Introducing Markdown Babel: a Universal Tool to Make Markdown Files Executable

md-babel is a cross-platform (Linux, macOS) command line utility that enables text editors to execute code blocks and then show the result.

https://md-babel.org/

“Enables text editors to” actually means you can use it from VSCode or Emacs or Neovim. Others to come.

“Execute code blocks” currently means e.g.

  • run shell scripts to perform tasks, e.g. from tutorials;
  • run Python/Ruby/… script snippets, then insert the result into the document;
  • run image graph generators like Graphviz or PlantUML or Mermaid to create images.

Again, more to come, but this is the basic use case I wanted to cover as quickly as possible.

Use It for Notes

Add illustrations to your Zettelkasten notes via PlantUML and generate images on the fly. md-babel will skip image generation if the code block’s content hasn’t changed, so you could run it on ever save, or git commit hook, or whatever, without a noticable performance hit.

For your programming notes, embed snippets and execute them right there to verify the output. Works with everything that can be evaluated from standard input. (There’s no built-in support for compiled languages to build something, first, but you could write a script to do that for you and execute that.)

Use It for Documentation

Confluence, shmonfluence.

Any Markdown file can be self-documenting, and documentation becomes code, and code becomes documentation.

Roadmap

  • Literate programming. Don’t just execute individual code blocks on the fly, but tangle the Markdown file into source files. Write the code from your documentation. Run the whole Markdown file.
  • Table formulae. Spreadsheets in Markdown files, basically. Working on that; we’re getting there, but it’ll take some time.

Examples

Here are some examples of script execution and image generation.

I executed all code blocks from this post’s Markdown source. The following is what you get in VSCode’s preview or via Marked as well.

Ruby

p 1*2*3
6

Created from this code:

```ruby
p 1*2*3
```

<!--Result:-->
```
6
```

PlantUML

actor User
control RequestConfirmationPresenter
control DeleteNotes
control RemoveFile
collections Store

User -> Store                 : DeletingSelectedNotes(identifiers)
Store -> DeletionConfirmation : set .pending(identifiers)

alt Confirmation
    DeletionConfirmation --> RequestConfirmationPresenter : newState .pending
    RequestConfirmationPresenter --> User  : present dialog

    User -> RequestConfirmationPresenter  : confirm
    RequestConfirmationPresenter -> Store : ConfirmingNoteDeletion
    Store -> DeletionConfirmation         : set .confirmed(identifiers)

    DeletionConfirmation --> DeleteNotes : newState .confirmed

    alt Found notes to recreate
        DeleteNotes -> Store : undoable(RemovingFiles, RecreatingNotes)
        Store -> PendingFileChangesState : set remove
        PendingFileChangesState --> RemoveFile : newState bulkFileRemoval
        alt Deletion error
            RemoveFile -> Store : HandlingError
        end
        RemoveFile -> Store : CompletingBulkFileRemoval
        Store -> Store : RemovingNotesFromWorkspace
    else Note read error
        DeleteNotes -> Store : HandlingError
    end

    DeleteNotes -> Store : CompletingNoteDeletion
else Canceling
    DeletionConfirmation --> RequestConfirmationPresenter : newState .pending
    RequestConfirmationPresenter --> User : present dialog

    User -> RequestConfirmationPresenter : cancel
    RequestConfirmationPresenter -> Store : CancelingNoteDeletion
    Store -> DeletionConfirmation : set nil
end

b0fac3a68478b49d555526b5347e714928365a3aaffb6e8c61fe3784550a8a59

Created from this code:

```plantuml
actor User
control RequestConfirmationPresenter
control DeleteNotes
control RemoveFile
collections Store

User -> Store                 : DeletingSelectedNotes(identifiers)
Store -> DeletionConfirmation : set .pending(identifiers)

alt Confirmation
    DeletionConfirmation --> RequestConfirmationPresenter : newState .pending
    RequestConfirmationPresenter --> User  : present dialog

    User -> RequestConfirmationPresenter  : confirm
    RequestConfirmationPresenter -> Store : ConfirmingNoteDeletion
    Store -> DeletionConfirmation         : set .confirmed(identifiers)

    DeletionConfirmation --> DeleteNotes : newState .confirmed

    alt Found notes to recreate
        DeleteNotes -> Store : undoable(RemovingFiles, RecreatingNotes)
        Store -> PendingFileChangesState : set remove
        PendingFileChangesState --> RemoveFile : newState bulkFileRemoval
        alt Deletion error
            RemoveFile -> Store : HandlingError
        end
        RemoveFile -> Store : CompletingBulkFileRemoval
        Store -> Store : RemovingNotesFromWorkspace
    else Note read error
        DeleteNotes -> Store : HandlingError
    end

    DeleteNotes -> Store : CompletingNoteDeletion
else Canceling
    DeletionConfirmation --> RequestConfirmationPresenter : newState .pending
    RequestConfirmationPresenter --> User : present dialog

    User -> RequestConfirmationPresenter : cancel
    RequestConfirmationPresenter -> Store : CancelingNoteDeletion
    Store -> DeletionConfirmation : set nil
end
```

<!--Result:-->
![b0fac3a68478b49d555526b5347e714928365a3aaffb6e8c61fe3784550a8a59](images/20250425134254--index__b0fac3a68478b49d555526b5347e714928365a3aaffb6e8c61fe3784550a8a59.svg)

Mermaid

Using the mermaid-cli node package to wrap the Mermaid JavaScript renderer library in an executable:

npm install -g --loglevel=error mermaid-cli
changed 123 packages in 855ms

4 packages are looking for funding
  run `npm fund` for details

Then try a Mermaid example graph:

gitGraph
  commit
  commit
  branch develop
  commit
  commit
  commit
  checkout main
  commit
  commit

b9698c45d60afdd4b5e8b54984bed7cc9141e614058342aa66bc1a2f775d6163

Created from this code:

```sh
npm install -g --loglevel=error mermaid-cli
```

<!--Result:-->
```
changed 123 packages in 855ms

4 packages are looking for funding
  run `npm fund` for details
```

Then try a Mermaid example graph:

```mermaid
gitGraph
  commit
  commit
  branch develop
  commit
  commit
  commit
  checkout main
  commit
  commit
```

<!--Result:-->
![b9698c45d60afdd4b5e8b54984bed7cc9141e614058342aa66bc1a2f775d6163](images/20250425151005--index__b9698c45d60afdd4b5e8b54984bed7cc9141e614058342aa66bc1a2f775d6163.svg)