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.
“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
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:-->

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
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:-->
