Open6

Mermaidに慣れたいためにMarpでMermaidを利用できるようにする備忘録

KidoYutaKidoYuta

フローチャートなどを作る際にGoogleスライドやらFigmaやらで図を作ってはスクショコピーしてMarpに貼り付けという手順を踏んでいるわけですが、フローチャートに変更が入るとツールを切り替える手間をなんとかしたいというところ、これを機会にMermaidに慣れておこうというのがきっかけ。

メリットとしては他ツールを使わずにチャート図とかを作れるのはもちろん、Gitなどで管理するなら画像よりも何が変更されたのか分かりやすくなるので良い。
デメリットとしては、Mermaidを知らない人には編集するのは大変になるかもという点ぐらいでしょうか。
知らなくても図さえ視覚化できていればOKなら良いのかなと思ってます。

今回Marpを使っている理由については、基本技術的な資料についてはMarpで作ることが多いためです。
Marpはマークダウンでスライド資料が作れてVSCode拡張機能もありプレビューしながら編集できるので重宝しています。CSSでテーマをカスタムできますし、PDFやPPTなどにエクスポートできるのも良いですね。
Marp: https://marp.app/

今回はVSCodeでMarpを使用する際にMermaidを扱うための手順を試しながら、備忘録的に連ねます。

KidoYutaKidoYuta

まず、VSCodeにはMarpの環境が備えます。

VSCode拡張機能があるのでインストールします。
Marp for VS Code: https://marketplace.visualstudio.com/items?itemName=marp-team.marp-vscode

インストールしたらMarp for VS CodeでHTMLを有効にします。

Shift + Ctrl(Cmd) + P でコマンドパレットから、>Preferences: Open User Settingsからmarkdown.marp.enableHtmlをTrueにします。

setttings.jsonから設定するなら"markdown.marp.enableHtml": trueを追記します。

デフォルトではHTMLを記載してもコードが表示されるだけなのでこれを有効にしてmermaidを囲う要素を用意しています。

KidoYutaKidoYuta

実際にMermaidをMarpに書いてみます。

---
marp: true
---
<!-- Marpと認識させるおまじない -->

## Basic Pie Chart
<!-- class名をmermaidとした要素タグ内に出力するMermaidコードを記載 -->
<pre class="mermaid">
pie title What Voldemort doesn't have?
  "FRIENDS" : 2
  "FAMILY" : 3
  "NOSE" : 45
</pre>

<!-- Mermaidを読み込み -->
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11.4.1/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>

プレビューにMermaidが表示されなければ、コマンドパレットから>markdown: Change Preview Security Settingsで無効(Disabled)を選択してみるとJavaScriptが読み込まれ表示されます。

また、囲う要素タグは<pre>じゃないと変更した際に再リロードした際に正しくプレビューされなくなるようなので必ず<pre>を使う必要があるようです。

KidoYutaKidoYuta

図が大きくなるとスライドからはみ出たりしますが、MarpのStyleを編集すれば対応は可能です。
とりあえずスライド一枚に大きく載せたい場合はこんな感じとか。

<style>
  .mermaid {
    width: 100%;
    height: 100%;
    background: none; // preタグの装飾消し
    border: none // preタグの装飾消し
  }
  .mermaid svg {
    display: block;
    min-width: 100%;
    max-width: 100%;
    max-height: 100%;
    margin: 0 auto
  }
</style>
KidoYutaKidoYuta

試しにMermaidのExampleを全て試してみました。

コピペでは表示されないものもありましたが、改行などが空いていると認識しないようですね。
あとはテキストサイズなど調整が必要かもしれないです。

---
marp: true
headingDivider: 2
---

<style>
  .mermaid {
    width: 100%;
    height: 100%;
    background: none;
    border: none
  }
  .mermaid svg {
    display: block;
    min-width: 100%;
    max-width: 100%;
    max-height: 100%;
    margin: 0 auto
  }
</style>

# MarpでMermaidを扱いたい

Write: キド

## Basic Pie Chart
<pre class="mermaid">
pie title What Voldemort doesn't have?
  "FRIENDS" : 2
  "FAMILY" : 3
  "NOSE" : 45
</pre>

## Basic sequence diagram
<pre class="mermaid">
sequenceDiagram
  Alice ->> Bob: Hello Bob, how are you?
  Bob-->>John: How about you John?
  Bob--x Alice: I am good thanks!
  Bob-x John: I am good thanks!
  Note right of John: Bob thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row.
  Bob-->Alice: Checking with John...
  Alice->John: Yes... John, how are you?
</pre>

## Basic flowchart
<pre class="mermaid">
graph LR
  A[Square Rect] -- Link text --> B((Circle))
  A --> C(Round Rect)
  B --> D{Rhombus}
  C --> D
</pre>

## Larger flowchart with some styling
<pre class="mermaid">
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
</pre>

## SequenceDiagram: Loops, alt and opt
<pre class="mermaid">
sequenceDiagram
  loop Daily query
    Alice->>Bob: Hello Bob, how are you?
    alt is sick
      Bob->>Alice: Not so good :(
    else is well
      Bob->>Alice: Feeling fresh like a daisy
    end
    opt Extra response
      Bob->>Alice: Thanks for asking
    end
  end
</pre>

## SequenceDiagram: Message to self in loop
<pre class="mermaid">
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!
</pre>

## Sequence Diagram: Blogging app service communication
<pre class="mermaid">
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
</pre>

## A commit flow diagram.
<pre class="mermaid">
gitGraph:
  commit "Ashish"
  branch newbranch
  checkout newbranch
  commit id:"1111"
  commit tag:"test"
  checkout main
  commit type: HIGHLIGHT
  commit
  merge newbranch
  commit
  branch b2
  commit
</pre>

<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11.4.1/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
KidoYutaKidoYuta

Marp以外でMermaid使いならMarkdown Preview Mermaid Supportがあるのでこっちを使えます。

Markdown Preview Mermaid Support(以降、MPMS)を有効にしたままMarpのMermaidをみるとプレビューがMPMSでプレビューされてしまいます。
見た目的にはMPMSの方が綺麗なのですが、MarpでExportする際はMarp側で設定されたスタイルでエクスポートされるので差異が発生してしまうようです。
この場合は、Marp側とMPMS側のMermaidのスタイルを合わせる必要があります。

Marp

<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11.4.1/dist/mermaid.esm.min.mjs';
mermaid.initialize({
  startOnLoad: true,
  theme: 'dark' // 使用するテーマを指定
});
</script>

MPMS(Markdown Preview Mermaid Support)

設定から使用するテーマを設定

Mermaidはいくつかテーマ用意されているので気に入ったものを使えそうです。
https://mermaid.js.org/config/theming.html