Diagrams (ob-mermaid, ob-dot, ob-plantuml)
Stability: experimental (org-extensions-stability)
diagrams renders diagram source blocks to images: mermaid (with mermaid-cli's mmdc, like the third-party ob-mermaid), dot (Graphviz, like Emacs's ob-dot) and the built-in plantuml port (org-babel-languages):
require("org").setup({
extensions = { diagrams = { render_on_save = true } },
})
C-c C-c on a block writes the diagram to its :file and inserts a [[file:...]] result, as for any babel language (both languages default to :results file :exports results):
#+begin_src mermaid :file flow.png :theme dark
flowchart LR
A --> B
#+end_src
#+begin_src dot :file deps.svg :var color="red"
digraph { a [color=$color]; a -> b }
#+end_src
mermaid takes ob-mermaid's header arguments :theme, :background-color, :width, :height, :scale, :mermaid-config-file, :css-file and :puppeteer-config-file (ob-mermaid's spelling :pupeteer-config-file also works). dot runs CMD IN CMDLINE -o OUT like ob-dot: :cmd (default dot), :cmdline (default -T plus the extension of :file) and $NAME replaced by :var NAME. plantuml keeps its own options in babel.languages.plantuml; when no jar_path is set but a plantuml command is installed, that command is used.
Beyond Emacs
- A block without
:filegetsoutput_dir/LANG-HASH8.EXT(HASH8 starts the content hash; EXT is:file-extorformat), relative to the org file's directory or:dir. Emacs errors instead; setauto_file = falsefor that. - Rendered diagrams are cached in
cache_dirby a hash of the language, the command and options, the output format and the expanded body. An unchanged diagram is copied from the cache instead of being rendered again. For plantuml the key also covers the files the text pulls in with!include(!include_once,!include_many,!includesub; local files, four levels deep), so editing one renders again.:Org diagrams_rerenderrenders the block at point without the cache and:Org diagrams_clear_cacheempties it. At startup the cache drops entries unused forcache_max_agedays, then the least recently used beyondcache_max_sizemegabytes. Both only touch cache entries (files named by the hash); other files incache_dirare left alone. - With
auto_preview(the default) the result image is shown inline after the block runs, when an image backend is available (org-images; SVG needs ImageMagick). - With
render_on_saveevery diagram block of an org buffer is rendered after the buffer is written, one block after another in the background, so Neovim stays responsive while mmdc or dot run. When they are done and nothing but the results changed, the buffer is written again, so the file on disk has the new results; when you edited it meanwhile, the buffer is left modified for you to save. Blocks run without the evaluation prompt, except those with:eval no,neverorquery, which are skipped. Unchanged diagrams come from the cache at once. :Org diagrams_cleandeletes the generated files (LANG-HASH8.EXT) in the current file'soutput_dirthat no org file of that directory links to or names (open buffers count with their unsaved text), after asking;:Org diagrams_clean dryonly lists them. Files you named yourself with:fileare never touched.- The tools run without a shell (an argument list) unless the command is a shell fragment (a string of several words) or the block sets
:cmdor:cmdline, which are shell text as in ob-dot.
Actions
diagrams_renderrender the diagram block at point (whatC-c C-cdoes there); not applicable elsewherediagrams_rerenderthe same, ignoring the cachediagrams_render_bufferrender every diagram block of the bufferdiagrams_clear_cachedelete the cached rendersdiagrams_cleandelete generated diagrams nothing links to No default keys; use:Org <action>or bind them inmappings.org.
Options (defaults in parentheses)
languageshandled languages ({ "mermaid", "dot", "plantuml" }); a language left out keeps its core behaviourmermaid{command("mmdc"; a string runs through the shell, so "npx -y @mermaid-js/mermaid-cli" works, or a list of words),args({}),theme,background,config_file,puppeteer_config} (defaults for the header arguments above)dot{command("dot"),args({}) }auto_filegenerate a:filewhen there is none (true)output_dirdirectory of generated names ("diagrams")formatextension of generated names ("png")cacheuse the cache (true)cache_dirstdpath("cache") .. "/org/diagrams"auto_previewpreview the result image (true)render_on_saverender diagram blocks after writing (false)cache_max_agedays an unused cache entry is kept (90; false: ever)cache_max_sizemegabytes the cache is pruned to (200; false: no limit)
:checkhealth org shows which renderers (mmdc, dot, plantuml or the jar and java) are installed, whether results can be previewed, and the cache directory. None of the tools is needed to load the extension; a block whose tool is missing reports it and inserts no result.
Limits
- Generated names change with the body, so an edited diagram leaves its old file behind in
output_diruntildiagrams_clean. - Only plantuml includes are followed: a mermaid config or CSS file, and dot's
image=orimagepathfiles, are not part of the cache key; usediagrams_rerenderafter changing them. - Without Graphviz installed only fake tools were run in the tests; the argument order follows ob-dot (
dot IN -TEXT [args] -o OUT). - Only file results are cached. plantuml's text output (
:results verbatim, no:file) is left to the core port.