Function Resource

Function Repository Resource:

MermaidJS

Source Notebook

Returns an image corresponding to a mermaid-js specification via the command line interface of mermaid-js

Contributed by: Anton Antonov

ResourceFunction["MermaidJS"][s]

invokes Mermaid's Command Line Interface (CLI) with the spec s and imports the result.

ResourceFunction["MermaidJS"][s,t]

specifies Mermaid's CLI output to be of type t.

ResourceFunction["MermaidJS"][s,t,copts]

invokes Mermaid's CLI with the options copts.

Details and Options

Mermaid lets you create diagrams and visualizations using text and code.
It is a JavaScript based diagramming and charting tool that renders Markdown-inspired text definitions to create and modify diagrams dynamically.
ResourceFunction["MermaidJS"] uses the Command Line Interface (CLI) to Mermaid's functionalities via the Shell function mmdc.
This means that mmdc (aka "mermaid-cli") have to be installed on the computer executing ResourceFunction["MermaidJS"].
ResourceFunction["MermaidJS"] passes a Mermaid spec to mmdc.
The script mmdc generates a PNG, PDF, of SVG file, that file is placed in a temporary directory, and it is imported by ResourceFunction["MermaidJS"].
By default ResourceFunction["MermaidJS"] requets mmdc with to generate a PNG image.
If a PDF type is specified, them ResourceFunction["MermaidJS"] imports the resulting PDF file as a graphics expression. (Using Import[__,"PageGraphics"].)
The first argument can be a string (that is a mermaid-js specification) or a Graph object.

Examples

Basic Examples (2) 

Here is flowchart generate with a Mermaid specification:

In[1]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]]["
graph TD
    WL --> |ZMQ|Python --> |ZMQ|WL
"]
Out[1]=

Here is class diagram that is a Graphics expression:

In[2]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]]["
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()
    }
", "PDF", ImageSize -> Large]
Out[2]=

Scope (11) 

Additional options can be passed to mmdc with the third argument of MermaidJS. For example, if the PNG images are with too low resolution then the mmdc"--scale" option can be used:

In[3]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]]["
graph LR
    WL --> |ZMQ|Python --> |ZMQ|WL
", "PNG", "MermaidOptions" -> "--scale 2"]
Out[3]=

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[4]:=
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[5]=

Here is the corresponding mermaid-js image:

In[6]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]][gr]
Out[6]=

Here is a left-to-right version:

In[7]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]][gr, "MermaidDirectives" -> "LR"]
Out[7]=

Mermaid has a different type of diagrams: Flowchart, Sequence Diagram, Class Diagram, State Diagram, Entity Relationship Diagram, User Journey, Gantt, Pie Chart, Requirement Diagram, and others.


Sequence Diagram:

In[8]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]]["sequenceDiagram
    Alice->>John: Hello John, how are you?
    John-->>Alice: Great!
    Alice-)John: See you later!"]
Out[8]=

Here is Graphics expression of a Class Diagram obtained via a PDF file additionally tweaked to have large image size:

In[9]:=
ResourceFunction[
CloudObject[
   "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]]["
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()
    }
", "PDF"] // Append[#, ImageSize -> Large] &
Out[9]=

State diagram:

In[10]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]]["
stateDiagram-v2
    [*] --> Still
    Still --> [*] Still --> Moving
    Moving --> Still
    Moving --> Crash
    Crash --> [*]
"]
Out[10]=

Entity Relationship Diagram:

In[11]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]]["
erDiagram
    CUSTOMER ||--o{ ORDER : places
    ORDER ||--|{ LINE-ITEM : contains
    CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
"]
Out[11]=

User Journey -- PNG image is obtained and cropped:

In[12]:=
ResourceFunction[
CloudObject[
   "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]]["
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
"] // ImageCrop
Out[12]=

Gantt chart:

In[13]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]]["
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[13]=

Pie chart:

In[14]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]]["pie title Pets adopted by volunteers
    \"Dogs\" : 386
    \"Cats\" : 85
    \"Rats\" : 15"]
Out[14]=

Requirement Diagram:

In[15]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]]["
    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[15]=

Options (5) 

Graphics

MermaidJS takes all options of Graphics. Those options are used when the second, type argument is "PDF".

MermaidDirectives (1) 

The option "MermaidDirectives" is used when the first argument is a Graph object. The value of that option is concatenated to the Mermaid graph specification prefix "graph". Here is an example:

In[16]:=
SeedRandom[1];
Block[{gr = RandomGraph[{5, 6}]},
 Association[# -> ResourceFunction[
CloudObject[
       "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]][gr, "MermaidDirectives" -> #] & /@ {"LR", "TD"}]
 ]
Out[2]=

MermaidOptions (2) 

The value of the option "MermaidOptions" is given to the CLI script "mmds". Here are the CLI options:

Here is examples with using different values for the theme option:

In[17]:=
spec = "sequenceDiagram
    Alice->>John: Hello John, how are you?
    John-->>Alice: Great!
    Alice-)John: See you later!";
Association@Map[# -> ResourceFunction[
CloudObject[
      "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]][spec, "PDF", "MermaidOptions" -> "--theme " <> #] &, {"default", "forest", "dark", "neutral"}]
Out[2]=

Prolog (2) 

The option "Prolog" can be used to used to specify code to be executed before the mermaid-js command. (The default value of the option "source ~/.zshrc".) The option value is passed to the option "Prolog" of ExternalEvaluate. Here is an example:

In[18]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]]["graph LR
A-->B-->C
A-.-D-.-B
", "Prolog" -> "echo 'This is it!'; source ~/.zshrc"]
Out[18]=

Note that "source ~/.zshrc" makes mermaid-js (the program "mmdc") reachable. if "mmdc" is unreachable, then the last image generated by MermaidJS will be returned (if the corresponding temporary file still exists):

In[19]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]]["graph TD
a-->b<--c
", "Prolog" -> ""]
Out[19]=

ShellSession

This option allows the specification of shell session to be used by MermaidJS. Its values are external sessions objects (ExternalSessionObject) or "Shell".

Applications (2) 

Markdown-related conversions flowchart:

In[20]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]]["
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
", "PDF"]
Out[20]=

Sequence Diagram: Blogging app service communication:

In[21]:=
ResourceFunction[
CloudObject[
   "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]]["
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
", "PDF"] // Append[#, ImageSize -> 1000] &
Out[21]=

Properties and Relations (1) 

There is a fairly straightforward correspondence between the edge specifications for Graph and Mermaid's graph (and flowchart) specifications. Here are illustrating examples:

In[22]:=
gr = Graph[{DirectedEdge[A, B, MyTag], UndirectedEdge[A, C]}, VertexLabels -> "Name", EdgeLabels -> "EdgeTag"]
Out[22]=
In[23]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]][gr, "MermaidDirectives" -> "LR"]
Out[23]=
In[24]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]]["
graph LR
 A --> |MyTag|B A --- C  
"]
Out[24]=

Possible Issues (2) 

Make sure mermaid-cli is installed and accessible in WL. It mermaid-cli but cannot be found then (i) set up Shell's path variable(s) in a shell session and use the option "ShellSession" to pass that session to MermaidJS, or (ii) use appropriate Shell command to give to the option "Prolog". Consider using SetOptions. For example, here we use "ShellSession":

SetOptions[MermaidJS, "ShellSession" -> ExternalSessions[][[1]]]

Here we use "Prolog":

SetOptions[MermaidJS, "Prolog" -> "source ~/.bashrc"]

Neat Examples (2) 

Larger flowchart with some styling:

In[25]:=
ResourceFunction[
CloudObject[
   "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]]["
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
", Automatic, "MermaidOptions" -> "--scale 3"] // ImageCrop
Out[25]=

Some interesting interaction:

In[26]:=
ResourceFunction[
CloudObject[
  "https://www.wolframcloud.com/obj/antononcube/DeployedResources/Function/MermaidJS"]]["
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[26]=

Author Notes

In order this repository function to work mermaid-cli has to be installed. Follow the instructions at https://github.com/mermaid-js/mermaid-cli.