This is a demonstration of the demonic project, specifically by running editable code snippets from a markdown-converted document.

demonic was inspired by mdbook, which is a great Rust documentation project. In mdbook, you can edit and run Rust code right from the document (e.g. Hello World)! I really liked this feature, but wanted to be able to send input back to the running process.

demonic-web allows one to do this, and demonic-docs integrates it with html-ized markdown documents. Go ahead and play around and edit any of the code blocks below, and click on the ‘▶’ button to run them!


#include <stdio.h>

int main(int argc, char** argv) {
    fprintf(stderr, "%s", "Enter your name: ");
    char name[100];
    scanf("%s", name);

    fprintf(stderr, "Hello %s!\n", name);
    return 0;


#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::string;

int main(int argc, char** argv) {
    string name;
    cout << "What is your name? ";
    cin >> name;
    cout << "Hello " << name << "!" << endl;


package main

import (

func main() {
    fmt.Print("What is your name? ")
    reader := bufio.NewReader(os.Stdin)
    name,_ := reader.ReadString('\n')
    name = strings.Replace(name, "\n", "", -1);
    fmt.Printf("Hello %s!\n", name)


import java.util.Scanner;

public class Hello {
    public static void main(String[] args) {
        Scanner reader = new Scanner(;
        System.out.print("What is your name? ");
        String name = reader.nextLine();
        System.out.println("Hello " + name + "!");

JavaScript (Node.js)

const readline = require('readline');

const readline_interface = readline.createInterface({
    input: process.stdin,
    output: process.stdout,

readline_interface.question('What is your name? ', name => {
    console.log(`Hello ${name}!`);



def greet():
    name = input('Enter your name: ')
    print('Hello', name)

if __name__ == '__main__':


#lang racket

(define (greet)
  (display "Enter your name: ")
  (printf "Hello, ~a!\n"
          (read-line (current-input-port) 'any)))



def greet()
  print 'What is your name ? '
  name = gets
  name = name.chomp
  puts 'Hello ' + name + '!'



use std::io::stdin;
use std::io::stdout;
use std::io::Write;

fn greet() {
    let mut name = String::new();
    print!("What is your name? ");
    let _ = stdout().flush();
    stdin().read_line(&mut name)
           .expect("Error in reading stdin.");

    if let Some('\n') = name.chars().next_back() {
    println!("Hello {}!", name);

fn main() {



greet() {
    read -p "What is your name? " name
    echo "Hello $name"


Support and Roadmap

This project aims to allow unmodified markdown files to have editable and runnable code blocks. But there needs to be a way for users to tell which program blocks they want to run and which they don’t. Unfortunately, this requires a modification to the markdown files! In this instance, the following markdown code had a “.norun” class addition, which tells demonic not to add a “▶” button to the code block.

    {: .norun}
    print("Don't run me!")
print("Don't run me!")

Markdown files converted by Pandoc are the only supported format currently, but I’d like to add lots of others! I’d like to add the following features:

Adding support requires playing around with the resulting DOM structure of each converter and file type, and being able to extract the language and code of each code block.