14 Oct 2020

When transmitting complex information I find having some kind of diagram extremely helpful. Sometimes they are there just to have something to look at and point, sometimes they are key to following a complex flow.

Over the years of trying lots of different tools, still seems to me that what I would call 'hand drawn' diagrams are best - but I don't mean actually hand drawn, I'm quite bad at whiteboard drawing but give me a tool like Omnigraffle and I'll make the nicest diagrams. I'll throw in some pastel colors even.

The issue is that integrating that with documentation when most of the documentation is in markdown is getting very annoying: you have to export the diagram as an image, save it somewhere and then insert a reference to it inside the markdown document.

It's pretty much impossible to do a decent version control on those, other than replacing a binary blow by another binary blob.

WARNING: If you read this post in an RSS reader it's not going to look pretty - diagrams are rendered client-side, you'll need to go to the website.

Mermaid

Many times all I want is to draw a small simple figure to help the narrative or to more effectively highlight some point, something that belongs to the document. Enter mermaidjs, that lets you embed diagrams by writing a description of them. Here is a simple example diagram, you will have to enclose it in three backticks and the word mermaid (I can't seem to be able to escape that in a way that works in jekyll):

sequenceDiagram
    Mobile Device->>Server: Request
    Server->>Cache: get [x-something]
    Cache-->>Server: null || contents

Renders:

sequenceDiagram Mobile Device->>Server: Request Server->>Cache: get [x-something] Cache-->>Server: null || contents

The great thing about this is that now I can edit the source file for this post and open a preview in Visual Studio Code (by installing the extension Markdown Preview Mermaid Support) that shows me what it would look like.

Here are some more examples, there is a ton of diagram types:

pie title When to use a pie chart "Never" : 235 "When lying about your data" : 85 "When hungry" : 15

I can see myself writing a quick gantt diagram that I can store as part of my project's code, and then export as PDF when needed with the "Markdown PDF: Export (pdf)" command of the Markdown PDF plugin.

gantt title A Gantt Diagram: This is not how things work in reality but you need something dateFormat YYYY-MM-DD section Governing Planning :done, planning, 2013-12-21, 5d Budget allocation :done, budget, after planning, 5d section Backend API definition :active, api-interface, 2014-01-01, 5d API implementation :api-implementation, after api-interface, 10d E2E testing :e2e, after api-implementation, 3d Announcing it's all done and leaving the company: after api-interface, 3d section Frontend Implementation :fe-implementation, after api-interface branding, 12d Implementation extension : fe-again, after fe-implementation we-didnt-think-about-that, 12d section Design Branding :active, branding, after budget, 12d We didn't think about that : we-didnt-think-about-that, after api-implementation, 24d

You can do pretty interesting things in the gantt charts, multiple dependencies etc

erDiagram CUSTOMER ||--o{ ORDER : places ORDER ||--|{ LINE-ITEM : contains CUSTOMER }|..|{ DELIVERY-ADDRESS : uses

You can have class diagrams

classDiagram
      Animal <|-- Duck
      Animal <|-- Fish
      Animal <|-- Zebra
      class Duck{
          +String beakColor
          +swim()
          +quack()
      }
      ...
classDiagram Animal <|-- Duck Animal <|-- Fish Animal <|-- Zebra Animal : +int age Animal : +String gender Animal: +isMammal() Animal: +mate() class Duck{ +String beakColor +swim() +quack() } class Fish{ -int sizeInFeet -canEat() } class Zebra{ +bool is_wild +run() }

You can have nice state diagrams

stateDiagram
    [*] --> State1
    State3 --> State4
    State1 --> State2
    State3 --> [*]
    State2 --> State4
    State2 --> State3: Conked

or with the newer plugin:

stateDiagram-v2
    [*] --> State1
    state fork_state <<fork>>
        [*] --> fork_state
        fork_state --> State1
        fork_state --> State3
    ...
stateDiagram-v2 [*] --> State1 state fork_state <> [*] --> fork_state fork_state --> State1 fork_state --> State3 State3 --> State4 State1: The state with a note note right of State1 Important information! You can write notes. end note State1 --> State2 note left of State2 : This is the note to the left. State2 --> Active state Active { [*] --> NumLockOff NumLockOff --> NumLockOn : EvNumLockPressed NumLockOn --> NumLockOff : EvNumLockPressed -- [*] --> ScrollLockOff ScrollLockOff --> ScrollLockOn : EvCapsLockPressed ScrollLockOn --> ScrollLockOff : EvCapsLockPressed } state join_state <> State4 --> join_state Active --> join_state join_state --> [*]
stateDiagram [*] --> State1 State3 --> State4 State1 --> State2 State3 --> [*] State2 --> State4 State2 --> State3: Conked

Entity relationship diagrams:

graph LR A[Hard edge] -->|Link text| B(Round edge) B --> C{Decision} C -->|One| D[Result one] C -->|Two| E[Result two]

Caveats

One thing to note is the different diagram plugins are almost independent applications and have subtle syntax differences: for instance you must use quotes in pie charts, but not in gantt.

The "Markdown: Open preview to the side" command on visual studio code right now works but has a very annoying refresh effect on the document you are typing in making it mostly unusable. You will be better of just opening previews that refresh only when you focus them using the "Markdown: Open Preview" command.

Integration with Jekyll

There's no real integration with Jekyll, you just add the library to your layout and then embed a <div> which automatically gets expanded client-side by the library:

<div class="mermaid">
sequenceDiagram
    Mobile Device->>Server: Request
    Server->>Cache: get [x-something]
    Cache-->>Server: null || contents
</div>

To add the library (quite a hefty library at 800K for the minified version, but for a site like this it's acceptable):

mkdir lib
cd lib
curl -O https://raw.githubusercontent.com/mermaid-js/mermaid/develop/dist/mermaid.min.js

To add it to your layout, edit for instance _layouts/default.html:

...
<body>
...
<script src="/yay/lib/mermaid.min.js"></script>
</body>

Customization

One of the greatest things about mermaid is that you can tweak most of it using just CSS and you can add event listeners to make the diagrams more interactive. Check the excellent documentation


(Follow me on Twitter, on Facebook or add this RSS feed) (Sígueme en Twitter, on Facebook o añade mi feed RSS)
details

Comments