I learned about Mermaid in 2021 while trying to find a way to better see changes in diagrams at work. Being able to look through a revision history of images was tolerable but only slightly better than the proverbial needle and the unexplained presence of a nearby haystack.
But Mermaid resolves my complaints by rendering text/code into fairly nice-looking diagrams and visualizations. Some are too plain for my liking (looking at you, state diagram), but they convey information graphically. That’s all I’m really looking to get here.
Complicating It All; Let’s Make a Website
Mermaid files are just fine when used in a README (GitHub supports Mermaid already in its markdown) or project documentation. If I want to also post them on here, we have a problem.
```mermaid
graph LR
A{do you need a panflute?} -->|yes| B[no you don't]
B --> C[no panflute]
A -->|no| C
```
Ok, an inconvenience, at the least. Hugo doesn’t know about Mermaid. Not in the slightest. I guess it’s time to figure out how to get that working.
Adding Mermaid to Hugo
One option is to change my theme to something that has Mermaid built-in. Docsy is an example of this, but that isn’t something I want to consider for the site right now. I could also compile the image with Mermaid’s live editor (or use their CLI locally), but again, the intent is to keep everything together. Cats and dogs; living together.
What I really want is a shortcode like {{< code [...] >}}
that will let me do it inline. Following the directions from satoru.dev, I expected that I’d found the perfect example and implementation. Nope. Does nothing.
I checked to make sure I had spelled things correctly and placed them in the right place… Oh. Rereading the article, I see that I needed to put the shortcode in layouts/shortcodes/mermaid.html
, but where the site had said,
Find somewhere in your theme that’s suitable for adding a […]
I had not really done the ‘suitable’ part of it – and would continue to fail at this part. Clues on the Hugo Discourse, RTFM, RTF(Theme)M, and investigation of the layouts/partial/extended_footer.html
file got me a bit closer. Nope. RTFM again and look at the example theme with Mermaid included… and a little bit at the end of Alexandra Souly’s article.
I am convinced at this point that I have fully grokked the situation. I am a god amongst men (actually, no, my self-esteem would never get there…). Update. Refresh.
Frak.
Time to look at the raw page source. Hmm, there isn’t one iota of reference to the mermaid.min.js script. Time for an equivalent form of print statement debugging. Adding TESTING_FOOTER
right after the script should do the trick. And its absence is deafening. Some debugging, some tea, and a last-ditch effort to look for any bugs in the theme that would cause this, and I see it.
I want you to know that I could have deleted all of this. I could have. Do you remember that foreshadowing about failing to find a suitable place for things?
2022-06-24 00:38:05 EDT in blog on main [⇡!?]
➜ tree layouts
layouts
└── shortcodes
├── mermaid.html
└── partials
├── comments.html
└── extended_footer.html
Yes, I failed to pay attention and created layouts/shortcodes/partials
instead of layouts/partials
. The first resource was correct, and I have it working.
That’s great. Seriously. I’m happy now and tired and a little thirsty. This should take the typical person a few minutes to get this working.
tl;dr
First, create a shortcode in layouts/shortcodes/mermaid.html
. I added some extra sugar here so that I can center it and make it look just right.
<div class="mermaid" style="text-align: {{ .Get 0 }}">
{{.Inner}}
</div>
Then update layouts/partials/extended_footer.html
to call the script that will look for the mermaid class and render it. If the file doesn’t already exist, you can create it or copy the example from themes/layouts/partials/extended_footer.html
(which is a file that only contains a comment saying that you should create the file).
{{ if (.Params.mermaid) }}
<!-- MermaidJS support -->
<script async src="https://unpkg.com/mermaid/dist/mermaid.min.js"></script>
{{ end }}
This is wrapped in a check for frontmatter on the page that lets you choose which pages get that loaded. Generally a good idea to only load on pages that need it. Saves a bit of loading time and data transfer. We’re doing this all to have a zippy site, right? So the last setup bit is to update the page frontmatter.
title: "Mermaid + Hugo"
author: "Ben"
tags:
- mermaid
mermaid: true
That’s it. You can use it as so:
```mermaid
graph LR
A{do you need a panflute?} -->|yes| B[no you don't]
B --> C[no panflute]
A -->|no| C
```
<div class="mermaid" style="text-align: center">
graph LR
A{do you need a panflute?} -->|yes| B[no you don't]
B --> C[no panflute]
A -->|no| C
</div>