Use Mermaid diagrams with images inside your documentation using GitHub

3 minute read

Writing documentation is a burden in a lot of software projects. Besides the fact that it is often done afterward and gets outdated soon, it is not directly coupled with the source code most of the time. You have to use systems like Confluence or other third-party tools and work in a different rhythm to produce the needed documentation.

So I m a big fan of storing your documentation next to your source code. In the most simple form, this is a set of folders and markdown files, where changes go through the same process as regular source code; you make a (feature) branch, apply changes, and offer this as a Pull Request for review. Documentation can certainly be combined with the code itself when it documents new or changed features. This way of working gives you a complete history of versions, reviews, and approvals and a one-to-one relation to the source code that it refers to.

However, as part of the documentation effort, you might need to create diagrams, like state, flow, class, etc. There are many tools available that let you draw nice pictures, but that brings back the original issue; the input for those diagrams is inside another system and thus difficult to make changes to. It is more efficient to have the source inside/alongside your markdown and render the diagram based on that source.

Luckily there is an excellent solution in the form of Mermaid. The Mermaid syntax defines various structures to create different types of diagrams.

For example, you can create a flowchart using the below syntax, which is stored perfectly inside a markdown file.

flowchart TD
    A[Christmas] -->|Get money| B(Go shopping)
    B --> C{Let me think}
    C -->|One| D[Laptop]
    C -->|Two| E[iPhone]
    C -->|Three| F[fa:fa-car Car]

The code is readable, but a picture is more accessible, so we can render it to an image:

There are various kinds of editors for this Mermaid syntax, either VS Code or the live editor. These tools allow for exporting the graph data to an image. However, that is manual work we do not want, so let’s make sure that we always generate the correct images based on the Mermaid in the markdown files and that this does not only work on my machine.

GitHub to the rescue

To make sure we all benefit from the generated diagrams, we will use a GitHub workflow that scans for changed markdown files, convert the Mermaid to images and append the link to the picture above the Mermaid code.

name: 'Compile Mermaid'

on:
  push:
    paths:
      - '**/*.mermaid'
      - '**/*.mmd'
      - '**/*.md'
    branches-ignore:
      - main
      
jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/[email protected]
        with:
          fetch-depth: 2

      - name: get changed files
        id: getfile
        run: |
          echo "::set-output name=files::$(git diff-tree --no-commit-id --name-only -r $ | grep -e '.*\.md$' -e '.*\.mmd$' -e '.*\.mermaid$' | xargs)"

      - name: mermaid files changed
        run: |
          echo $

      - name: compile mermaid
        uses: neenjaw/[email protected]
        with:
          files: $
          output: 'docs/images'
        env:
          HIDE_CODEBLOCKS: 1
          ABSOLUTE_IMAGE_LINKS: 1
          OUTPUT_FILE_TYPE: "svg"

      - name: show changes
        run: |
          git status

      - name: Create Pull Request
        id: cpr
        uses: peter-evans/[email protected]
        with:
          token: $
          commit-message: Add compiled mermaid
          title: '[MMDC] New mermaid files compiled'
          body: |
            - Auto-generated by [create-pull-request][1]

            [1]: https://github.com/peter-evans/create-pull-request
          labels: report, automated pr
          assignees: $
          reviewers: $

This workflow will trigger on pushes to GitHub for files with specific extensions. The neenjaw/compile-mermaid-markdown-action action performs the actual work and produces a set of images and alterations to the markdown files. It will offer those changes to you using a PR to your feature branch. So merge those into your branch when you are okay with them.

Note; make sure your output path (like docs/images) does exist. Create an empty folder with a .keep file inside and commit this as well.

The resulting markdown will look like this:

## Context diagram

<!-- generated by mermaid compile action - START -->
![~mermaid diagram 1~](/docs/images/docs_architecture_readme-md-1.svg)
<details>
  <summary>Mermaid markup</summary>

'''mermaid
graph LR
    A[SystemA] -->|Raw transaction| B(SystemB)
    C[SystemC] -->|Relations| B
    B -->|Transaction| D(SystemD)
    D -->|Status change| B
'''

</details>
<!-- generated by mermaid compile action - END -->

When you browse your documentation on GitHub, the image will be shown, and the original Mermaid code is collapsed.

Conclusion

For me, this is an ideal way to keep documentation close to my source code and use similar tools while at the same time offering diagrams to explain concepts better. Everybody can keep these diagrams up to date without having to resort to using a third-party tool.

Offcourse, it would be even better if GitHub would render the Mermaid automatically. This is a feature a lot of people are looking for, is already available in GitLab and even in Azure DevOps this works natively (in a basic form).

Tags:

Updated:

Leave a comment