Mermaid code to a diagram you can edit

Published . By the DiagramDesk team.

Mermaid describes a diagram in a few lines of text, which is why it turns up in READMEs, wikis and chat answers. DiagramDesk reads that text, works out where every shape should go, and opens the result as ordinary shapes: you can drag them, recolour them, add to them and export the finished picture.

A worked example

Here is a password-reset flow as someone might write it in Mermaid. Two of its decisions are worth noticing, because they are the kind a diagram exists to make visible. When no account matches the address, the page shows exactly the message it shows when one does, which is why that box appears twice: the form cannot be used to find out who has an account. And the emailed link works once and then runs out. Both follow the advice in the OWASP Forgot Password Cheat Sheet, which asks for "a consistent message for both existent and non-existent accounts" and for reset tokens that are "single use and expire after an appropriate period".

flowchart TD
  A([Reset requested]) --> B[/Email address entered/]
  B --> C{Account found?}
  C -->|Yes| E[Email a one-time link]
  E --> M1[Show the usual message]
  C -->|No| M2[Show the usual message]
  M2 --> Z([Request handled])
  M1 --> F{Link unused and under an hour old?}
  F -->|Yes| G[/New password entered/]
  G --> I([Password changed])
  F -->|No| H[Say the link has expired]
  H --> B

Pasted into the importer, those 12 lines become 11 shapes and 11 connectors, placed like this. The way back from the expired link to the email step is drawn up the side, clear of everything it passes, rather than straight through the middle of the chart.

The password-reset flow, as the importer lays it out.YesNoYesNoResetrequestedEmail addressenteredAccountfound?Email a one-timelinkShow the usualmessageShow the usualmessageRequesthandledLink unusedand under anhour old?New passwordenteredPasswordchangedSay the link hasexpired
The password-reset flow, as the importer lays it out.Open in the editor

How the layout is worked out

Mermaid code says what joins to what, never where anything goes, so the importer has to decide. It uses the layered method, often called Sugiyama-style layout after a 1981 paper by Sugiyama, Tagawa and Toda. Their paper drew a hierarchy in layers, cut down the crossings by reordering one layer at a time and sweeping up and down until nothing improved, and then placed each shape close to the ones it is linked to. The method has since settled into four steps, as the survey chapter by Healy and Nikolov in the Handbook of Graph Drawing and Visualization describes it, and this is how the importer takes them.

  1. Any loop is broken by treating one link in it as pointing backwards, so the rest of the chart has a direction to flow in.
  2. Every shape is given a row, far enough down that each link runs from a higher row to a lower one. A link that skips rows gets a reserved lane on each row it passes, so it never has to cut through a shape.
  3. The shapes in each row are reordered, a sweep at a time, to reduce the number of links that cross. The best order found is kept.
  4. Each shape is moved as close as it can get to the shapes it is linked to, without overlapping its neighbours.

Subgraphs are laid out on their own first and then placed as one block, which is why a group's contents stay together inside their frame. Sequence diagrams are simpler: one column per participant, and the messages in the order they were written.

The result is a starting point, not a verdict. Move any shape and its connectors find a new route; the bends the layout chose are dropped as soon as a shape they belong to is moved off its line.

What the importer reads

Four of Mermaid's diagram types have matching shapes in the editor, and those are the four it reads. The syntax is the one set out in Mermaid's own documentation, including the named shapes written A@{ shape: doc } that arrived in version 11.3.0.

Flowcharts flowchart or graph

  • All four directions: TD or TB, BT, LR and RL, and a direction of their own inside a subgraph
  • The node shapes: rectangle, rounded, stadium, subroutine, cylinder, circle, double circle, rhombus, hexagon, both parallelograms and both trapezoids, and the named shapes written A@{ shape: … } (one with no DiagramDesk equivalent is drawn as a rectangle, with a note)
  • Links: arrows, open lines, dotted and thick lines, circle and cross ends, arrows at both ends, chains (A --> B --> C) and & (A & B --> C)
  • Link labels, written either way: -- text --> or -->|text|
  • Subgraphs, nested, and links to a subgraph
  • Colours from style, classDef, class and :::, for nodes and subgraphs: fill, stroke and text colour, the stroke width and dashes
  • Quoted labels, <br> line breaks, entity codes such as #quot; and #35;, and HTML 4 character names such as #hearts;

Left out, with a note saying so: click actions and hyperlinks: a diagram here never holds a link; linkStyle, classes on links, link lengths (extra dashes), edge ids, and edge settings such as e1@{ animate: true } or e1@{ curve: linear }; invisible links (~~~); icons, images, and Markdown or HTML formatting inside labels (the words are kept); configuration: front matter settings, %%{init}%% directives and the ELK renderer; any other style, such as a named colour or a font size.

Sequence diagrams sequenceDiagram

  • participant and actor, with aliases (participant A as Alice)
  • Messages ->, -->, ->>, -->>, -x, --x, -), --), <<->> and <<-->>
  • Notes left of, right of or over one or two participants
  • loop, alt and else, opt, par and and, critical and option, and break frames
  • autonumber, with a start and a step (autonumber 10 5), and title

Left out, with a note saying so: activations (+, -, activate, deactivate); boxes, background rectangles, create and destroy; half arrowheads, and participant types other than actor, which are drawn as boxes; central connections written with (), drawn as ordinary messages; participant menus and links.

Class diagrams classDiagram

  • Classes with members, in braces or written Class : member, with methods told apart by their brackets
  • Visibility markers (+ - # ~) as written, generics written ~T~, and annotations such as <<interface>>
  • Relationships: inheritance <|--, composition *--, aggregation o--, association -->, link --, dependency ..>, realization ..|> and dashed link ..
  • Multiplicities ("1" --> "*") and relationship labels
  • Notes (note for Class) and namespace groups

Left out, with a note saying so: lollipop interfaces; click, link and callback; styles, cssClass, classDef and :::.

ER diagrams erDiagram

  • Entities, including aliases (p[Person]) and quoted names
  • Attributes with type, name, keys (PK, FK, UK) and a comment
  • All four cardinalities at either end, in symbols (||, |o, }o, }|) or in words (only one, zero or more…)
  • Identifying (--) and non-identifying (..) relationships, and their labels
  • direction

Left out, with a note saying so: styles, classDef, class and :::.

What happens to the rest

Nothing is dropped quietly. When a line cannot be used, the import still goes ahead with everything else, and the dialog then lists what was left out, by line number: "Line 12 was not understood and was left out", followed by the line itself. A line is read whole or not at all, so nothing half-read from it turns up in the drawing. Whatever is read but has no use here, such as a style DiagramDesk has no equivalent for or a link's animation, gets a note of its own. Click actions and hyperlinks are always refused, with a reason, because a diagram here never contains a link.

A diagram type the editor has no shapes for, such as a state diagram, a Gantt chart or a mind map, is refused by name ("This is a state diagram…") rather than half-read into something misleading. Code copied with its ```mermaid fence, as it comes out of a chat window, is fine: the fence is removed first.

Crow's foot from Mermaid's symbols

ER diagrams are where the translation matters most, because Mermaid writes cardinality as pairs of characters and the editor draws them as crow's foot marks. Each pair is read from the outside in: the outer character is the maximum, the inner one the minimum. The table follows Mermaid's own list of the four values.

Left of the lineRight of the lineMeansDrawn as
|oo|Zero or oneA ring and a bar
||||Exactly oneTwo bars
}oo{Zero or moreA ring and a crow's foot
}||{One or moreA bar and a crow's foot

Two hyphens between the pairs mean an identifying relationship, drawn solid; two dots mean a non-identifying one, drawn dashed. A relationship is identifying when the parent's key is part of the child's key, as an order line is "line 3 of order 1042", and non-identifying when the child has a key of its own, even if it cannot exist without its parent. The words Mermaid also accepts, such as only one to zero or more, are read the same way, with to for identifying and optionally to for non-identifying. A small lending library shows all four marks; every entity in it has an id of its own, so every line is dashed:

erDiagram
  AUTHOR }|..|{ BOOK : writes
  BOOK ||..|{ COPY : "is held as"
  COPY ||..o{ LOAN : "goes out on"
  MEMBER ||..o{ LOAN : takes
  MEMBER ||..o| CARD : holds
A book has one or more copies; a member may have no loans at all, and at most one card.writesis held asgoes out ontakesholdsAUTHORBOOKCOPYLOANMEMBERCARD
A book has one or more copies; a member may have no loans at all, and at most one card.Open in the editor

And back again

Export has a Mermaid option that writes the drawing back as text, as whichever of the four types it is: a diagram of entity boxes becomes an ER diagram, class boxes a class diagram, lifelines a sequence diagram, and anything else a flowchart. For the reset flow above it writes:

flowchart TD
  A(["Reset requested"])
  B[/"Email address entered"/]
  C{"Account found?"}
  E["Email a one-time link"]
  M1["Show the usual message"]
  M2["Show the usual message"]
  Z(["Request handled"])
  F{"Link unused and under an hour old?"}
  G[/"New password entered"/]
  I(["Password changed"])
  H["Say the link has expired"]
  A --> B
  B --> C
  C -->|"Yes"| E
  E --> M1
  C -->|"No"| M2
  M2 --> Z
  M1 --> F
  F -->|"Yes"| G
  G --> I
  F -->|"No"| H
  H --> B

Positions are not part of Mermaid, so whatever draws that text lays it out again. Labels, shapes, links, arrowheads, groups and the direction survive the trip, and so do a flowchart's colours, line widths and dashes; placed images do not, and shapes Mermaid has no word for are written as rectangles, with a note saying so. Import what export wrote and the same shapes, labels, links and groups come back, and exporting them again gives the same text. The site's tests check both on more than sixty samples of Mermaid across all four types, and check that every part of a sample the importer does not use is named in a note.

Questions

Is the code sent anywhere?

No. It is read by the page itself; the reading and the layout are part of the editor, which loads nothing from anyone else. The result is saved in your browser, like any other diagram.

Why not keep the diagram as code?

Often you should. Text is easy to review and to keep beside the thing it describes. A drawing is better when placement carries meaning (the happy path down the middle, errors off to one side), when it is going on a slide or into a printed document, or when the person who needs it will never open a code editor. Import when you need the picture, and export again if the text has to stay the master copy.

Can I share the result?

Yes: Share in the editor makes a link that carries the whole diagram inside it, or an embed code for a web page. Or export a PNG, SVG or PDF.

Paste some Mermaid

The importer opens in the editor, with an example to try.

Open the importer