Creating Mermaid diagrams in markdown using vscode

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

Wrapping Up

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.

References

#mtfbwy



Recent Posts