A Python-Markdown Extension for Embedding Graphviz
Two of the tools I use most frequently in my writing (both public writing on this blog and notes I jot down for personal consumption) are graphviz and markdown. The last few days I've been tossing around the idea of embedding Graphviz graphs into Markdown, and today I had a couple of hours to quickly throw it together.
The proof of concept, python-markdown-graphviz, is available on Github.
I chose to extend Python-Markdown because that is how I implemented my custom (and some have claimed, arbitrary) Markdown extensions I use for this blog.
The syntax for writing documents is straightforward: enclose the Graphviz graphs
in a tag whose type corresponds with the Graphviz executable to render
the snippet (dot
, neato
, lefty
, dotty
).
* hi
* there
<dot>
digraph a {
b -> c -> d
}
</dot>
## And a title
<neato>
digraph a {
b -> c -> d
}
</neato>
This is some text
A simple example of usage is (requiring that mdx_graphviz.py
be in the Python path):
import markdown
txt = "* this is some\n<dot>\ndigraph a {\n a -> b;\n}\n</dot>\nhi\n"
md = markdown.Markdown(extensions=['graphviz'])
print md.convert(txt)
You can customize a few settings:
BINARY_PATH
is the path to thedot
,neato
, etc executables (defaults to no path, i.e. assumes will be in$PATH
).FORMAT
is the format for images created by Graphviz (defaults to png).WRITE_IMGS_DIR
is the directory to write images into (defaults to local directory).BASE_IMG_LINK_DIR
is the base directory for the links to the generated images (defaults to local directory).
An example of changing the defaults settings:
import markdown
txt = "* this is some\n<dot>\ndigraph a {\n a -> b;\n}\n</dot>\nhi\n"
md = markdown.Markdown(
extensions=['graphviz'],
extension_configs={'graphviz':
{'FORMAT':'gif'}
},
)
print md.convert(txt)
There is a lot of room for improvement, in particular a few ideas:
- use the name of the graph (extracted from the graphviz syntax) for the filename instead of numeric filenames.
- option to specify dimensions of graphs, or at least specify the width and auto-calculate the height.
That's all there really is to it. I'll probably make some improvements as I keep using it, but would always be glad to have others build on it as well if it's useful.