TLDR

  • Hugo out of box does not set up mermaid.js
  • Multiple ways to set up mermaid.js
  • Overview on how set up mermaid.js

At this point I’ll just assume everyone knows mermaid and how it works. This post is a reference post for future me who might get asked on how I set up mermaid.js for this blog.

Mermaid.js

I only discovered mermaid.js when GitHub made the announcement that they were going to natively support Mermaid as part of their Markdown rendering for README or any Markdown files in GitHub and it would render as it was intended to be rendered.

All you have to know is to create a mermaid code block in your Markdown file and it will render as a diagram. No additional installation was required, no additonal config was required, it was like magic. Not so much the case for VSCode, but an extension was available for that, which would use the same rendering engine as GitHub.

From that point on, I got addicted to using mermaid as my tool to illustrate my ideas and diagrams, before turning to draw.io.

Hugo the missing piece

Turns out, Hugo does not support mermaid.js out of the box. It does not have the mermaid.js library included in the default theme and no update to hugo.toml to enable the mermaid code bocks.

There have been multiple posts and articles on how to enable mermaid is Hugo, including the official documentation. But none of them worked easily for me.

THE SETUP

So I did turn to Vide Coding Magic to enable this change, let me breakdown the changes involved in it. 4 Changes were introduced to overall codebase:

  1. U - hugo.toml
  2. A - layouts/_default/_markup/render-codeblock-mermaid.html
  3. A - layouts/_default/baseof.html
  4. A - layouts/partials/extend_footer.html

The changes aren’t huge, but they finally enabled mermaid blocks in the markdown content. Let dive into each of the changes.

Update - hugo.toml

    [markup.goldmark.renderer]
      unsafe = true

Add - layouts/_default/_markup/render-codeblock-mermaid.html

<div class="mermaid">{{- .Inner | safeHTML }}</div>
{{ .Page.Store.Set "hasMermaid" true }}

Add - layouts/_default/baseof.html


<!DOCTYPE html>
<html lang="{{ site.Language }}" dir="{{ .Language.LanguageDirection | default "auto" }}">

<head>
    {{- partial "head.html" . }}
</head>

<body class="
{{- if (or (ne .Kind `page` ) (eq .Layout `archives`) (eq .Layout `search`)) -}}
{{- print "list" -}}
{{- end -}}
{{- if eq site.Params.defaultTheme `dark` -}}
{{- print " dark" }}
{{- end -}}
" id="top">
    {{- partialCached "header.html" . .Page -}}
    <main class="main">
        {{- block "main" . }}{{ end }}
    </main>
    {{ partialCached "footer.html" . .Layout .Kind (.Param "hideFooter") (.Param "ShowCodeCopyButtons") -}}
    {{ partial "extend_footer.html" . }}
</body>

</html>

Add - layouts/partials/extend_footer.html

{{ if .Store.Get "hasMermaid" }}
<script type="module">
  import mermaid from "https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs";
  mermaid.initialize({ startOnLoad: true });
</script>
{{ end }}

Testing Diagrams

So lets test out the setup with an example diagram.

'''mermaid
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]
'''

This should render as a diagram in the markdown file.

--- title: " Test Diagram" description: "Test Diagram to show to add mermaid.js to hugo" config: theme: dark --- 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]