mermaid GitHub repo
mermaid - Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.
Online editor
https://mermaid-js.github.io/mermaid-live-editor/
Cheat sheet
Mermaid Cheat Sheet @ http://jojozhuang.github.io

Setup

docker image

I compiled this docker image myself as existing images on dockerhub were outdated.

https://github.com/matthewfeickert/mermaid-CLI

I bumped the mermaid version up from 8.2.6 to 8.4.4 because some of the examples were not working but I’m still not able to build some of the diagrams.

0.5.1 is the most up-to-date version of mermaid-cli.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
diff --git a/Dockerfile b/Dockerfile
index 95474fb..e48513c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -56,7 +56,7 @@ RUN apt-get -qq -y update && \
 # Pin at versions of Docker image build
 # FIXME: phantomjs is deprecated
 RUN yarn global add phantomjs-prebuilt@2.1.16 && \
-    yarn global add mermaid@8.2.6 && \
+    yarn global add mermaid@8.4.4 && \
     yarn global add mermaid.cli@0.5.1

 # Use C.UTF-8 locale to avoid issues with ASCII encoding
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Get the =mmdc= ve<rsion number
docker \
    run \
    --entrypoint "" \
    --rm \
    --name matthewfeickert-mermaid-cli-latest-acb1f60c-f9fb-4b79-9a66-573ad24e5c7e \
    matthewfeickert/mermaid-cli:latest \
    mmdc \
    -p /home/node/puppeteer-config.json \
    -V
0.5.1

emacs modes

Demonstration

What’s working

Flowcharts

graph TD
  A[Christmas] -->|Get money| B(Go shopping)
  B --> C{Let me think}
  C -->|One| D[Laptop]
  C -->|Two| E[iPhone]
  C -->|Three| F[fa:fa-car Car]

Sequence diagrams

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!

git graphs

gitGraph:
options
{
    "nodeSpacing": 150,
    "nodeRadius": 10
}
end
commit
branch newbranch
checkout newbranch
commit
commit
checkout master
commit
commit
merge newbranch

class diagrams

classDiagram
Class01 <|-- AveryLongClass : Cool
Class03 *-- Class04
Class05 o-- Class06
Class07 .. Class08
Class09 --> C2 : Where am i?
Class09 --* C3
Class09 --|> Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label

gantt charts

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

What’s not working for me

ER diagrams

1
2
3
4
5
6
7
8
9
erDiagram
        CUSTOMER }|..|{ DELIVERY-ADDRESS : has
        CUSTOMER ||--o{ ORDER : places
        CUSTOMER ||--o{ INVOICE : "liable for"
        DELIVERY-ADDRESS ||--o{ ORDER : receives
        INVOICE ||--|{ ORDER : covers
        ORDER ||--|{ ORDER-ITEM : includes
        PRODUCT-CATEGORY ||--|{ PRODUCT : contains
        PRODUCT ||--o{ ORDER-ITEM : "ordered in"

Pie charts

1
2
3
4
pie title Pets adopted by volunteers
  "Dogs" : 386
  "Cats" : 85
  "Rats" : 15

State diagrams

1
2
3
4
5
6
7
8
stateDiagram
        [*] --> Still
        Still --> [*]

        Still --> Moving
        Moving --> Still
        Moving --> Crash
        Crash --> [*]

Scripts and configuration

mmdc docker wrapper script

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/bin/bash
export TTY

( hs "$(basename "$0")" "$@" "#" "<==" "$(ps -o comm= $PPID)" 0</dev/null ) &>/dev/null

while [ $# -gt 0 ]; do opt="$1"; case "$opt" in
    "") { shift; }; ;;
    -i) {
        infile="$2"
        shift
        shift
    }
    ;;

    -o) {
        outfile="$2"
        shift
        shift
    }
    ;;

    *) break;
esac; done

stdin_exists() {
    ! [ -t 0 ] && ! test "$(readlink /proc/$$/fd/0)" = /dev/null
}

if stdin_exists; then
    infile="$(cat | tf txt)"
fi

fp="$infile"
rp="$(realpath "$fp")"
dn="$(dirname "$rp")"
bn="$(basename "$fp")"
ext="${bn##*.}"
fn="${bn%.*}"

td_mmdc="$(mktemp -t -d td_mmdcXXXXXX || echo /dev/null)"

test -n "$infile" || echo no input file 1>&2
test -n "$outfile" || echo no output file 1>&2

cp -a "$rp" "$td_mmdc"

docker run --entrypoint "" -v "$td_mmdc:/data2" -w /data2 matthewfeickert/mermaid-cli:latest mmdc -p /home/node/puppeteer-config.json -i "/data2/$bn" -o "/data2/mmdc_out.png"

cp -a "$td_mmdc/mmdc_out.png" "$outfile"

mermaid-mode emacs config

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
(require 'mermaid-mode)

(defun mermaid-compile ()
  "Compile the current mermaid file using mmdc."
  (interactive)
  (if (selection-p)
      (sh-notty "mermaid-show" (selection))
    (sh-notty "mermaid-show" (buffer-contents))))

(setq mermaid-mmdc-location "/home/shane/scripts/mmdc")
(setq ob-mermaid-cli-path "/home/shane/scripts/mmdc")

(provide 'my-mermaid)

mermaid-show script for displaying externally to emacs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/bash
export TTY

stdin_exists() {
    ! [ -t 0 ]
}

if stdin_exists && ! test -f "$1"; then
    input_fp="$(cat | tf mermaid)"
    set -- "$input_fp" "$@"
    exec <`tm-tty` `# see etty`
fi

( hs "$(basename "$0")" "$@" "#" "<==" "$(ps -o comm= $PPID)" 0</dev/null ) &>/dev/null

if test -f "$1"; then
    input_fp="$1"
else
    exit 1
fi

out_fp="$(odn tf png)"

# Sadly this usually hangs
timeout 4 mmdc -i "$input_fp" -o "$out_fp"
sps win ie "$out_fp"

Additional docker commands

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Obtain a shell
docker \
    run \
    --entrypoint "" \
    --rm \
    --name jnewland-mermaid-cli-latest-cd774805-2b43-4dfd-8b4c-07b7958d6d68 \
    -ti \
    matthewfeickert/mermaid-cli:latest \
    /bin/sh

# Usage
docker \
    run \
    --entrypoint "" \
    -v "$td_mmdc:/data2" \
    -w \
    /data2 \
    matthewfeickert/mermaid-cli:latest \
    mmdc \
    -p /home/node/puppeteer-config.json \
    -i "/data2/$bn" \
    -o "/data2/mmdc_out.png"

The error I’m seeing

1
mmdc -i /tmp/file_tempfile_iiRkcz_rand-4719_pid-10642.mermaid -o /tmp/file_tempfile_44Ee92_rand-10541_pid-10728.png
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
erDiagram    CUSTOM
^
Expecting 'NEWLINE', 'SPACE', 'GRAPH', got 'ALPHA'
    at Yt.parseError (file:///usr/local/share/.config/yarn/global/node_modules/mermaid.cli/mermaid.min.js:1:486512)
    at Yt.parse (file:///usr/local/share/.config/yarn/global/node_modules/mermaid.cli/mermaid.min.js:1:487678)
    at Object.e.getClasses (file:///usr/local/share/.config/yarn/global/node_modules/mermaid.cli/mermaid.min.js:1:749437)
    at Object.render (file:///usr/local/share/.config/yarn/global/node_modules/mermaid.cli/mermaid.min.js:1:759998)
    at s (file:///usr/local/share/.config/yarn/global/node_modules/mermaid.cli/mermaid.min.js:8:233)
    at Object.init (file:///usr/local/share/.config/yarn/global/node_modules/mermaid.cli/mermaid.min.js:8:318)
    at __puppeteer_evaluation_script__:17:20
    at ExecutionContext._evaluateInternal (/usr/local/share/.config/yarn/global/node_modules/puppeteer/lib/ExecutionContext.js:122:13)
    at process._tickCallback (internal/process/next_tick.js:68:7)
  -- ASYNC --
    at ExecutionContext.<anonymous> (/usr/local/share/.config/yarn/global/node_modules/puppeteer/lib/helper.js:111:15)
    at ElementHandle.evaluate (/usr/local/share/.config/yarn/global/node_modules/puppeteer/lib/JSHandle.js:55:42)
    at ElementHandle.<anonymous> (/usr/local/share/.config/yarn/global/node_modules/puppeteer/lib/helper.js:112:23)
    at ElementHandle.$eval (/usr/local/share/.config/yarn/global/node_modules/puppeteer/lib/JSHandle.js:478:40)
    at process._tickCallback (internal/process/next_tick.js:68:7)
  -- ASYNC --
    at ElementHandle.<anonymous> (/usr/local/share/.config/yarn/global/node_modules/puppeteer/lib/helper.js:111:15)
    at DOMWorld.$eval (/usr/local/share/.config/yarn/global/node_modules/puppeteer/lib/DOMWorld.js:156:21)
    at process._tickCallback (internal/process/next_tick.js:68:7)
  -- ASYNC --
    at Frame.<anonymous> (/usr/local/share/.config/yarn/global/node_modules/puppeteer/lib/helper.js:111:15)
    at Page.$eval (/usr/local/share/.config/yarn/global/node_modules/puppeteer/lib/Page.js:347:29)
    at Page.<anonymous> (/usr/local/share/.config/yarn/global/node_modules/puppeteer/lib/helper.js:112:23)
    at /usr/local/share/.config/yarn/global/node_modules/mermaid.cli/index.bundle.js:83:14
    at Generator.next (<anonymous>)
    at step (/usr/local/share/.config/yarn/global/node_modules/mermaid.cli/index.bundle.js:4:191)
    at /usr/local/share/.config/yarn/global/node_modules/mermaid.cli/index.bundle.js:4:361
    at process._tickCallback (internal/process/next_tick.js:68:7)
(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:1) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.