My first Mermaid contributions
Last week, I was excited to see contributions I made to the Mermaid code repository finally go live.
What’s Mermaid?
Mermaid is a tool for creating diagrams using plain-text. Like Markdown for writing prose, it’s a “no-code” or “low-code” tool but for visuals. And like Markdown it’s a simple set of conventions that, once you know how to use them, allow you to capture and represent ideas quickly.
I’ve been an advocate of using plain-text methods for a while, whether it’s for documentation or for content management systems. It’s particularly helpful in places WYSIWYG (“what you see is what you get”) editors can be a distraction from focusing on what you want to say. My own blog (this one!) is built by compiling Markdown files.
I’ve been playing around with data visualisation tools like D3.js and Observable for quite a while too.
So when I found out about a tool that combined these two interests, plain text and visualisation, I was immediately sold.
The idea that you can create a Gantt chart or a flow chart with just a few words within the text file for a blog post appeals to me. It hugely expands the toolkit and reduces the friction for creating explanatory content. And it does so at very little cost: Mermaid itself is free. The only overhead is setting it up in whatever environment you’re using.
On top of that Mermaid is open source. If you can code, you contribute directly towards the development. The impetus for me to get involved was when I saw the library pop up on the list for Hacktoberfest 2023.
I thought I’d take a look at the issues users had raised and see how I could help out.
What’s up, docs?
Learning about the workings of a new codebase can be daunting at first, especially in your free time.
Fortunately, code isn’t the only way to contribute to an open source repository. Non-code efforts like documentation are often accepted and useful too. Reading documentation is one way to understand a tool as a whole, especially if you’re looking to improve it.
I found an issue reporting broken “Git graph” examples in the documentation. Looking at it myself, I could see there were a couple of different ways to interpret the section in question. That suggested to me that it needed rewriting for clarity. So rewriting is what I did in my first pull request for Mermaid.
Having tested the waters and got my first light-touch low-stakes changes accepted, I was keen to get stuck into the code itself.
Diving in…
Mermaid offers a lot of different graph types, which I’ve been playing around with. But since I’d started by updating the documentation for the gitGraph
type this seemed as good a place as any to start.
Git is the most popular versioning tool in the world for code, although it’s very powerful for non-code uses too.
Mermaid’s GitGraph visualisation is a way of sketching out different strategies for branching, merging, and cherry-picking in Git. By writing a list of shorthand Git commands like branch develop
, commit
and merge develop
, you can quickly create a visualisation of how your codebase or content might change over time and through a workflow.
One issue pointed out that the way that branches merged didn’t always look right. The path connection the branches was the wrong colour and had a weird bend to it
Having had experience of writing SVG and thinking that it was probably a buggy if
condition or ternary somewhere, I figured it’d be an easy fix…
Phase 1: Part of my world
Initially I thought I’d found the problem pretty quickly.
The variable being used for colouring a path was wrong so that would be a straightforward change.
And the strange bend in the path was actually a feature – just not one needed in this particular case.
When behaving normally, there’s no need for the strange bending arrow.
I found some logic and a function called hasOverlappingCommits
. This was supposed to act as guard against arrows crossing over commits they had nothing to do with.
Normally, when a branch is merged into another branch, there’s a simple arrow that comes out of the first branch and goes into a new commit on the second.
But when, for example, a commit is cherry-picked from a branch, the path that joins that commit to the selecting branch needs to dodge out of the way of any of other commits that might have come after it.
This avoids the arrow or path being over the rest of the branch which would the graph harder to read.
So I fixed this logic (or thought I had fixed it…) and then submitted my fix for the issue as a pull request.
Phase 2: In deep
When my pull request was reviewed, it transpired there was some cases when my fix and the new logic didn’t work or wasn’t enough.
Unfortunately I hadn’t spotted it because these edge cases were not in any of the existing integration tests.
So I found myself writing a bunch of tests for Cypress to pick these up and then trying to figure out how to fix the edge cases. And then of course doing that exposed some other issues, which were picked up in review.
Eventually, I added 6 new snapshot tests, and a long demo page showing what was possible. (The original demo page only had one example graph on it.)
In the process, I renamed hasOverlappingCommits
to shouldRerouteArrow
as I thought that was a more accurate description of what was being asked.
I also raised a separate issue about different configurations of branches in the graph after someone else spotted it – I wanted to make sure that I didn’t get bogged down in scope creep.
In doing that, I still found myself overthinking the simple issue of when a normal arrow was appropriate and when the bending branch should come in. I thought there was some semantic reasoning that I was missing and that perhaps it was even missing from Mermaid itself. But I came to realise it was simply about positioning.
I eventually reasoned: arrows should curve emerge straight from parent branches and curve gracefully into child branches unless there was something in the way. And on merging they should curve out of the child branches and into the parent. This probably still needs work though…
Phase 3: Resisting the siren’s call
At points, I had a huge temptation to rewrite the whole thing. This was partly based on reviews I was getting.
But I also knew that would not only broaden the scope of what I was trying to do, but also broaden the scope of any review and raise many more questions. If I was going to get the issue fixed it was better to focus on that and raise a separate issue or PR with any further changes I wanted to make, as I had before with the branch configuration issue.
So I resisted the temptation.
I did that, by creating another local branch (which I periodically rebase with changes in the main branch I was working on) and use that to scratch the itch of exploration and improvement. And in doing so, I learned more about the code I was working on and fed the ideas back into the fix. At some point, I would refine that and raise it as a separate pull request. But not before I’d finished this job first.
Thoughts
There’s certainly more I could say about the experience of getting stuck into a codebase that was totally new to me. Some of that I may write up another time.
My main thought from all this has been that, when time allows, I want to do more.
It was hugely satisfying getting feedback, both positive and constructive, from the repository maintainers. It felt like we were working as a remote team, albeit voluntarily.
(I should probably call out for thanks here Ian J Mitchell, who raised the original issue, and those who took the time to review, feed back on, and approve my pull request, Sidharth Vinod, Matheus Braga and Nikolay Rozhkov.)
It’s also satisfying because I believe Mermaid presents such a useful tool for coding and content creation alike. Contributing to something that thousands, perhaps even millions will use, is its own reward.
Check out Mermaid yourself and have a play.