Function Repository Resource:

MermaidInk

Source Notebook

Get an image corresponding to a Mermaid-JS specification via the web Mermaid-Ink interface of Mermaid-JS

Contributed by: Anton Antonov

ResourceFunction["MermaidInk"][s]

retrieves an image defined by the spec s from Mermaid's Ink Web interface.

Details and Options

Mermaid lets you create diagrams and visualizations using text and code.
Mermaid has different types of diagrams: Flowchart, Sequence Diagram, Class Diagram, State Diagram, Entity Relationship Diagram, User Journey, Gantt, Pie Chart, Requirement Diagram, and others. It is a JavaScript based diagramming and charting tool that renders Markdown-inspired text definitions to create and modify diagrams dynamically.
ResourceFunction["MermaidInk"] uses the Mermaid's functionalities via the Web interface "https://mermaid.ink/img".
The first argument can be a string (that is, a Mermaid-JS specification) or a Graph object.
The option "MermaidDirectives" can be used to control the layout of Mermaid diagrams if the first argument is a Graph object. The accepted orientations are given below:
"TB"top-to-bottom
"TD"top-down
"BT"bottom-to-top
"RL"right-to-left
"LR"left-to-right
ResourceFunction["MermaidInk"] produces images.

Examples

Basic Examples (2) 

Generate a flowchart from a Mermaid specification:

In[1]:=
ResourceFunction["MermaidInk"]["
graph TD
    WL --> |ZMQ|Python --> |ZMQ|WL
"]
Out[1]=

Create a Graphics expression from a class diagram:

In[2]:=
ResourceFunction["MermaidInk"]["
classDiagram
    Animal <|-- Duck
    Animal <|-- Fish
    Animal <|-- Zebra
    Animal : +int age
    Animal : +String gender
    Animal: +isMammal()
    Animal: +mate()
    class Duck{
        +String beakColor
        +swim()
        +quack()
    }
    class Fish{
        -int sizeInFeet
        -canEat()
    }
    class Zebra{
        +bool is_wild
        +run()
    }
"]
Out[2]=

Scope (9) 

The first argument can be a Graph object -- the corresponding Mermaid-JS graph is produced. Here is a random graph that has both directed and undirected edges (some edges have tags):

In[3]:=
SeedRandom[45];
gr = GraphUnion[RandomGraph[{3, 2}, DirectedEdges -> True], RandomGraph[{4, 4}, DirectedEdges -> False]];
gr = Graph[
   Map[RandomChoice[{#, Append[#, RandomWord[]]}] &, EdgeList[gr]], VertexLabels -> "Name", EdgeLabels -> "EdgeTag"];
gr
Out[6]=

Here is the corresponding Mermaid-JS image:

In[7]:=
ResourceFunction["MermaidInk"][gr]
Out[7]=

Here is a left-to-right version:

In[8]:=
ResourceFunction["MermaidInk"][gr, "MermaidDirectives" -> "LR"]
Out[8]=

Very often Large Language Models (LLMs) produce Mermaid-JS code as a Markdown fenced code block. By default the fences are removed. Here we define a Mermaid-JS specification:

In[9]:=
spec = LLMSynthesize[{"Give a concise Mermaid-JS diagram of continents' land connections.", LLMPrompt["NothingElse"]["Mermaid-JS"]}]
Out[9]=

Here we generate the corresponding diagram:

In[10]:=
ResourceFunction["MermaidInk"][spec]
Out[10]=

Create a Sequence Diagram:

In[11]:=
ResourceFunction["MermaidInk"]["sequenceDiagram
    Alice->>John: Hello John, how are you?
    John-->>Alice: Great!
    Alice-)John: See you later!"]
Out[11]=

State diagram:

In[12]:=
ResourceFunction["MermaidInk"]["
stateDiagram-v2
    [*] --> Still
    Still --> [*] Still --> Moving
    Moving --> Still
    Moving --> Crash
    Crash --> [*]
"]
Out[12]=

Entity Relationship Diagram:

In[13]:=
ResourceFunction["MermaidInk"]["
erDiagram
    CUSTOMER ||--o{ ORDER : places
    ORDER ||--|{ LINE-ITEM : contains
    CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
"]
Out[13]=

User Journey -- PNG image is obtained and cropped:

In[14]:=
ResourceFunction["MermaidInk"]["
journey
    title My working day
    section Go to work
      Make tea: 5: Me
      Go upstairs: 3: Me
      Do work: 1: Me, Cat
    section Go home
      Go downstairs: 5: Me
      Sit down: 5: Me
"]
Out[14]=

Gantt chart:

In[15]:=
ResourceFunction["MermaidInk"]["
gantt
    title A Gantt Diagram
    dateFormat  YYYY-MM-DD
    section Section
    A task           :a1, 2014-01-01, 30d
    Another task     :after a1  , 20d
    section Another
    Task in sec      :2014-01-12  , 12d
    another task      : 24d
"]
Out[15]=

Pie chart:

In[16]:=
ResourceFunction["MermaidInk"]["pie title Pets adopted by volunteers
    \"Dogs\" : 386
    \"Cats\" : 85
    \"Rats\" : 15"]
Out[16]=

Requirement Diagram:

In[17]:=
ResourceFunction["MermaidInk"]["
    requirementDiagram requirement test_req {
    id: 1
    text: the test text.
    risk: high
    verifymethod: test
    } element test_entity {
    type: simulation
    } test_entity - satisfies -> test_req"]
Out[17]=

Options (3) 

DropMarkdownFences (2) 

Very often Large Language Models (LLMs) produce Mermaid-JS code as a Markdown fenced code block. By default the fences are removed:

In[18]:=
ResourceFunction["MermaidInk"]["
```mermaid
graph LR
    Asia --- Europe
    Asia --- Africa
    North_America --- South_America
    Asia --- North_America
    Europe --- Africa
```"]
Out[18]=

Without dropping the Markdown code block fences we get an error:

In[19]:=
ResourceFunction["MermaidInk"]["
```mermaid
graph LR
    Asia --- Europe
    Asia --- Africa
    North_America --- South_America
    Asia --- North_America
    Europe --- Africa
```", "DropMarkdownFences" -> False]
Out[19]=

MermaidDirectives (1) 

The option "MermaidDirectives" is used when the first argument is a Graph object:

In[20]:=
SeedRandom[1];
Block[{gr = RandomGraph[{5, 6}]},
 Association[# -> ResourceFunction["MermaidInk"][gr, "MermaidDirectives" -> #] & /@ {"TB", "TD", "BT", "RL", "LR"}]
 ]
Out[21]=

Applications (2) 

Create a Markdown-related conversions flowchart:

In[22]:=
ResourceFunction["MermaidInk"]["
graph TD
    WL[Make a Mathematica notebook] --> E
    E[\"Examine notebook(s)\"] --> M2MD
    M2MD[\"Convert to Markdown with M2MD\"] --> MG
    MG[\"Convert to Mathematica with Markdown::Grammar\"] --> |Compare|E
"]
Out[22]=

Create a Sequence Diagram for a blogging app service communication:

In[23]:=
ResourceFunction["MermaidInk"]["
sequenceDiagram
    participant web as Web Browser
    participant blog as Blog Service
    participant account as Account Service
    participant mail as Mail Service
    participant db as Storage Note over web,db: The user must be logged in to submit blog posts
    web->>+account: Logs in using credentials
    account->>db: Query stored accounts
    db->>account: Respond with query result alt Credentials not found
        account->>web: Invalid credentials
    else Credentials found
        account->>-web: Successfully logged in Note over web,db: When the user is authenticated, they can now submit new posts
        web->>+blog: Submit new post
        blog->>db: Store post data par Notifications
            blog--)mail: Send mail to blog subscribers
            blog--)db: Store in-site notifications
        and Response
            blog-->>-web: Successfully posted
        end
    end
"]

Properties and Relations (3) 

There is a fairly straightforward correspondence between the edge specifications for Graph and Mermaid graph (or flowchart) specifications:

In[24]:=
gr = Graph[{DirectedEdge[A, B, MyTag], UndirectedEdge[A, C]}, VertexLabels -> "Name", EdgeLabels -> "EdgeTag"]
Out[24]=
In[25]:=
ResourceFunction["MermaidInk"][gr, "MermaidDirectives" -> "LR"]
Out[25]=
In[26]:=
ResourceFunction["MermaidInk"]["
graph LR
 A --> |MyTag|B A --- C  
"]
Out[26]=

A diagram that clarifies the execution of MermaidInk:

In[27]:=
ResourceFunction["MermaidInk"]["
graph TD
UI[/User input/]
MS{{Mermaid-Ink server}}
WL{{Wolfram Language}}
WLnb>Notebook]
WLIC[[Input cell]]
WLOC[[Output cell]]
MI[MermaidInk]
UI --> WLIC -.- WLnb
WLIC --> MI -.- WL
MI --> |spec|MS
MS --> |image|MI
MI --> WLOC -.- WLnb
WLnb -.- WL
"]
Out[27]=

For some textual content MermaidInk specifications should use quotes. Also, a new line character in text can be included using "<br/>":

In[28]:=
ResourceFunction["MermaidInk"]["
graph LR
	A[\"Complicated text <br/>(maybe)\"] --> S[Sink <br/> place]
"]
Out[28]=

Without the quotes for block "A" the specifications above does not work:

In[29]:=
ResourceFunction["MermaidInk"]["
graph LR
	A[Complicated text <br/>(maybe)] --> S[Sink <br/> place]
"]
Out[29]=

Neat Examples (2) 

Larger flowchart with some styling:

In[30]:=
ResourceFunction["MermaidInk"]["
graph TB
    sq[Square shape] --> ci((Circle shape)) subgraph A
        od>Odd shape]-- Two line<br/>edge comment --> ro
        di{Diamond with <br/> line break} -.-> ro(Rounded<br>square<br>shape)
        di==>ro2(Rounded square shape)
    end %% Notice that no text in shape are added here instead that is appended further down
    e --> od3>Really long text with linebreak<br>in an Odd shape] %% Comments after double percent signs
    e((Inner / circle<br>and some odd <br>special characters)) --> f(,.?!+-*ز) cyr[Cyrillic]-->cyr2((Circle shape Начало)); classDef green fill:#9f6,stroke:#333,stroke-width:2px;
     classDef orange fill:#f96,stroke:#333,stroke-width:4px;
     class sq,e green
     class di orange
"] // ImageCrop
Out[30]=

Some interesting interaction:

In[31]:=
ResourceFunction["MermaidInk"]["
sequenceDiagram
    participant Alice
    participant Bob
    Alice->>John: Hello John, how are you?
    loop Healthcheck
        John->>John: Fight against hypochondria
    end
    Note right of John: Rational thoughts <br/>prevail!
    John-->>Alice: Great!
    John->>Bob: How about you?
    Bob-->>John: Jolly good!
"]
Out[31]=

Publisher

Anton Antonov

Requirements

Wolfram Language 13.0 (December 2021) or above

Version History

  • 1.0.0 – 19 April 2023

Related Resources

License Information