Creating Mermaid diagrams in markdown using vscode
Table of Contents
Introduction
Exploring some of the unused features of my Hugo theme, I noticed that it supports mermaid. I have seen mermaid around the web and it has been on my list of things to try out. I thought I would have a little experiment with it as I do have some blog posts that I want to write where it could be useful. Here are my first few steps.
What is Mermaid?
The headline that originally caught my interest is:
Mermaid lets you create diagrams and visualizations using text and code.
That interests me because Visio is so bad. I do use other tools but the flaw with this can oftentimes be that not every organisation I work with permits those tools. Some details about it:
- It is a JavaScript based diagramming and charting tool
- It renders Markdown-inspired text definitions to create and modify diagrams dynamically
- It supports flowcharts, sequence diagrams, Gantt charts, and more
One of it’s big sells is that it is easy to embed in markdown and thus develop along with your code base.
How to install
Ummm…it’s built into my theme! I am not going to explore that this time round but if you want to get started quickly here is a live editor.
My very first attempt
Specifically in Hugo, you write the mermaid code in a code block with the language set to mermaid
. Whether that is how it works elsewhere I have yet to find out. Here is my first attempt at a flowchart:
flowchart LR; A[Fight with Luke] --> B[Disarm Luke...literally]; B --> C[Inform Luke I am his Father]; C --> D[Pause for Dramatic Screams];
That was pretty easy to write! Here is what the code looks like:
flowchart LR;
A[Fight with Luke] --> B[Disarm Luke (literally)];
B --> C[Inform Luke I am his Father];
C --> D[Pause for Dramatic Screams];
I am declaring the diagram type flowchart LR
at the start of the code block. This tells mermaid to draw a flowchart and to draw the flow from left to right.
Flowcharts are made up of nodes and edges. I have declared four nodes, A
, B
, C
, and D
. The edges are determined by the arrow type and the direction.
A node can have two parts, the first part is the node name and the second part is the node label. For ease of reading, once you have declared the label you only need to reference the node name. If you do however, write a label for a node more than once, the last one will be used.
Extending the flowchart
In the flowchart above, all of the nodes are rectangles. However, there are other shapes that you can use simply by altering the label. I am also going to change the direction of the flowchart.
flowchart TD;
A([Crash land on Dagobah]) --> B[Meet Yoda];
B --> C[Learn to Use the Force];
C --> F
D --> F{Am I ready?}
F --> |"No"|D[Face Fears in Cave];
F --> |"No but my friends need me"|G([Leave Dagobah]);
flowchart TD; A([Crash land on Dagobah]) --> B[Meet Yoda]; B --> C[Learn to Use the Force]; C --> F D --> F{Am I ready?} F --> |"No"|D[Face Fears in Cave]; F --> |"No but my friends need me"|G([Leave Dagobah]);
flowchart LR
is now flowchart TD
which tells mermaid to draw the flowchart from top to bottom. The first and last nodes are set to stadium-shape (??) nodes by using parentheses. I have drawn a decision point by using curly brackets. By adding the |No|
and |Yes|
ahead of the node relationship, it displays them as decision outcomes. I have added two edges to the decision node, one for each outcome. I can also change the appearance of the edge by using different syntax, here I used -.->
which is a dashed line.
Different diagram types
Mermaid supports a number of different diagram types, you do this by declare the. Here are a few examples:
Entity Relationship Diagram (ERD)
An entity relationship diagram is a visual representation of the relationships between tables in a database. This could be used for conceptual modelling or database design.
erDiagram
JEDI ||--|| LIGHTSABER : "wields"
JEDI }|--|| PLANET : "resides on"
JEDI }|--|| PLANET : "originates from"
erDiagram JEDI ||--|| LIGHTSABER : "wields" JEDI }|--|| PLANET : "resides on" JEDI }|--|| PLANET : "originates from"
The erDiagram
declaration tells mermaid to draw an entity relationship diagram. And the notation between nodes declares what sort of relationship it is and draws the relationship using crow’s foot notation. I can also describe the relationship between the nodes by using a colon one or more words (if more than one word it must be enclosed in quotes).
I can expand on this diagram by adding column names like this:
erDiagram
JEDI ||--|| LIGHTSABER : "wields"
JEDI }|--|| PLANET : "resides on"
JEDI }|--|| PLANET : "originates from"
JEDI {
int jediId
string name
string species
date dateOfBirth
}
LIGHTSABER {
int lightsaberId
string color
string crystal
}
PLANET {
int planetId
string name
string galaxy
}
erDiagram JEDI ||--|| LIGHTSABER : "wields" JEDI }|--|| PLANET : "resides on" JEDI }|--|| PLANET : "originates from" JEDI { int jediId string name string species date dateOfBirth } LIGHTSABER { int lightsaberId string color string crystal } PLANET { int planetId string name string galaxy }
Gitgraph
This is the one that led me to find mermaid! I was looking for a way to visualise git branching strategies and that is how I came across mermaid. Here is a simple example:
---
title: A very simple git diagram
---
gitGraph
commit
commit
branch develop
commit
commit
commit
checkout main
merge develop
--- title: A very simple git diagram --- gitGraph commit commit branch develop commit commit commit checkout main merge develop
I will be experimenting with this in future blog posts.
C4 Model
This one is interesting to me because I have been asked to create architecture diagrams using the C4 model. The C4 model is a way to visualise software architecture. It is a hierarchical model that describes the static structure of a software system. This one is under development right now, I pinched this example from the mermaid website:
C4Dynamic
title Dynamic diagram for Internet Banking System - API Application
ContainerDb(c4, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.")
Container(c1, "Single-Page Application", "JavaScript and Angular", "Provides all of the Internet banking functionality to customers via their web browser.")
Container_Boundary(b, "API Application") {
Component(c3, "Security Component", "Spring Bean", "Provides functionality Related to signing in, changing passwords, etc.")
Component(c2, "Sign In Controller", "Spring MVC Rest Controller", "Allows users to sign in to the Internet Banking System.")
}
Rel(c1, c2, "Submits credentials to", "JSON/HTTPS")
Rel(c2, c3, "Calls isAuthenticated() on")
Rel(c3, c4, "select * from users where username = ?", "JDBC")
C4Dynamic title Dynamic diagram for Internet Banking System - API Application ContainerDb(c4, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.") Container(c1, "Single-Page Application", "JavaScript and Angular", "Provides all of the Internet banking functionality to customers via their web browser.") Container_Boundary(b, "API Application") { Component(c3, "Security Component", "Spring Bean", "Provides functionality Related to signing in, changing passwords, etc.") Component(c2, "Sign In Controller", "Spring MVC Rest Controller", "Allows users to sign in to the Internet Banking System.") } Rel(c1, c2, "Submits credentials to", "JSON/HTTPS") Rel(c2, c3, "Calls isAuthenticated() on") Rel(c3, c4, "select * from users where username = ?", "JDBC")
Timeline
It’s really easy to construct a timeline, you simply list the entries using the notation {time period} : {event}
. Here is an example:
%%{init: { 'logLevel': 'debug', 'theme': 'dark' } }%%
timeline
title Star Wars Movie Release Dates
1977 : A New Hope
1980 : Empire Strikes Back
1983 : Return of the Jedi
%%{init: { 'logLevel': 'debug', 'theme': 'dark' } }%% timeline title Star Wars Movie Release Dates 1977 : A New Hope 1980 : Empire Strikes Back 1983 : Return of the Jedi
Conclusion
This was a fun little experiment. I am going to explore this futher in future blog posts. I can also see how this could be useful for visualising code and architecture which I will explore in the future.