Improving ExDocs with PlantUML (and GraphViz)

Not sure if I’m the only one, but I often find myself designing Elixir projects using AsciiDoctor - because I find the embedded PlantUML drawings very useful to model graphically processes, supervision trees and messages flowing between multiple GenServers.

I think that it would be useful to have such drawings as a part of the “standard” documentation that comes with an Elixir project, as generated by ExDocs - I used to do it with a JS library that does it at runtime, but it would be just as easy to leverage a local PlantUML or a webserver, generate the SVG for once, and add it to the documentation.

So I’m starting to play around with these ideas - had a couple of free hours and was able to generate and embed them, and add two functions to my SayCheezEx to allow easy generation - if you are curios, this is what I got: SayCheezEx — say_cheez_ex v0.3.0 . It’s interesting how PlantUML has actually a huge number of drawings, and a lot of them could be useful to improve documentation.

Am I the only one toying with these ideas? How could they be made better? Is there a way to make them easier to use than just

module Foo do
    import SayCheezEx, only: [uml: 1, graphviz: 1]

    @moduledoc """
    Here goes a Graphviz graph:

    #{graphviz("digraph { Sup -> GenServ }")}

    Here a PlantUML graph:

      Bob -> Alice : I do love UML in documentation
      Alice -> Bob : me too!



(those functions can be massively improved - I’d like to use a local install and if not available to fall back on a webservice - and caching is not complete yet. But it’s a start…)

I have done something similar with mermaid js.

Yes that’s what I used to do - but I like the idea of having an image generated just once, and not at runtime. And PlantUML is a powerhouse of graphs.


The benefit of this idea is also a drawback of it. Such approach significantly increases compilation times.

Well, yes and no, Yes - of course - when you have new or modified graphs, but the images can be cached effectively, so the difference - in practice - is unnoticeable.

Ideally that could be done only during documentation generation. Unfortunately there is no way to have backward compatible way to extend Markdown/CommonMark that would allow to implement such thing.

If you cache the results based on the actual graph recipe, it’s technically executed every time, but you don’t care because it does not slow you down. (Come to think of it: under which environment is documentation generated?)

Though it is executed every time when you compile project, which puts compile-time dependency on PlantUMl being available in your system. That can be pretty painful for CI or if your project is a library.

1 Like

Actually, PlantUML is also available as a webservice, or you can even host your own, so I was thinking of trying a local version first, and going for the webservice if not installed. In the library as it is today, it uses the webservice.

Then you have requirement on being on-line and that you can reach given website. That also make your compilation non idempotent, which also can be not desirable, especially in corporate environments, CIs, and other environments where you want to control/disallow networks during builds.


If you need strong idempotency, you add the PlantUML binary to your local build environment, or run a local server. But my feeling is that online will be “good enough” for most of us :grinning: