Menu

Mobile navigation

Mermaid を泳がせる

文字だけで見ると難しそうなことでも、図に起こしてみることで構造を単純化できることは多々ある。 そのため、頭で考えるだけではなく、思考を視覚化する癖をつけたい。

そんなときに有効なツールとして Mermaid がある。 フローチャートやシーケンス図など様々なダイアグラムの生成をサポートしている。

draw.io のような作図ツールとは違い、Markdown と同様にテキストからダイアグラムを生成できるのが特徴である。 もちろん、GUI で作図するのとは異なり、スタイルのリッチさでは劣るが抽象的に考えるにはそのほうがむしろ好都合なこともある。

Mermaid が何より素晴らしいのは、図を更新するために GUI を開いて、エクスポートしてといった煩わしい作業に時間を取られない点だろう。 テキストを数文字変えるだけで済む。 あとは、ちょっと線がずれたりしてストレスが溜まるといったこともない。

さて、このブログではロジカルな部分はできるだけ図や表にしてわかりやすくしたい。 そこで MDX ファイル内で Mermaid 記法を使えるようにした(v1.4.10)。

実装方法

rehype-mermaid というドンピシャなライブラリを使った。

このライブラリの良いところはインライン SVG の生成をビルド時に行ってくれることである。 内部的に Playwright のヘッドレスブラウザを使っているようだ。

Mermaid の描画は通常クライアント(ブラウザ)側で行われるが、その際にノードの数が多くなればなるほど負荷が高くなってしまう。 リンクカードのときもそうだったが、可能な限り SSG でページを生成してパフォーマンスを良くしたい。

とりあえず使うだけなら以下のように rehypePlugins に追加するだけで良い。 この際の注意点として、rehype-pretty-code などのシンタックスハイライト系のプラグインを使っている場合は、それよりも前に定義する必要がある。

contentlayer.config.ts

import rehypeMermaid from 'rehype-mermaid';
 
export default makeSource({
  mdx: {
    rehypePlugins: [
      [rehypeMermaid]
    ],
  },
});

デフォルトの機能だけでも十分だが、デザイン面で気に入らない部分があったので調整した。

rehype-mermaid の設定は変更していない。 変更したのは Mermaid 公式の設定のみ。

公式ドキュメントを見てもいまいちオプションが分からなかったが、幸いにも TypeScript の型定義がされていたのでそれを元に以下のように設定ファイルを書いた。

src/lib/mdx/rehype-mermaid.ts

import type { RehypeMermaidOptions } from 'rehype-mermaid';
 
const mermaidConfig = {
  theme: 'base',
  fontFamily:
    'ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"',
  fontSize: 13,
  themeVariables: {
    primaryColor: '#b0b0b0',
    secondaryColor: '#545480',
    primaryBorderColor: '#4c4c53',
    primaryTextColor: '#f4f4f5',
    secondaryTextColor: '#f4f4f5',
    lineColor: '#4c4c53',
    textColor: '#f4f4f5',
    ...
  },
} satisfies RehypeMermaidOptions['mermaidConfig'];
 
export const rehypeMermaidOptions = {
  mermaidConfig,
} satisfies RehypeMermaidOptions;

fontFamily には本当は Inter を使いたかったが、next/font を使っている都合上、レンダリングがうまくいかなかったため諦めた(文字がずれてしまう)。

themeVariables は図のスタイリングをするために使用している。 独自のスタイリングをする場合は themebase にしなければならない。

それぞれの色を指定していくのだが、ドキュメントにも乗っていないため 実際のテーマ を定義してあるファイルを参考にして書いた。

分量が多すぎるのと、それぞれのプロパティがどのパーツに紐づいているのか分からずに 1 つずつ確認したので骨が折れる作業であった。

途方もないのでひとまずは頻繁に使うであろうダイアグラムのみ色塗りした。

あとは、これはバグだと思うが、そのまま使うと文字がずれて描画されてしまうので全体に line-height: 1.1rem を指定してある。

Mermaid の例

前述したとおり、全てのダイアグラムをスタイリングするのは時間的に無理だったためスタイリングしたものだけ例示する。 今後使う機会があれば別のダイアグラムも追記していく。

Flowchart

```mermaid
flowchart TB
    c1 --> a2
 
    subgraph one
    a1 --> a2
    end
 
    subgraph two
    b1 --> b2
    end
 
    subgraph three
    c1 --> c2
    end
 
    one --> two
    three --> two
    two --> c2
```

three

one

two

b1

b2

c1

a2

a1

c2

Sequence diagrams

```mermaid
sequenceDiagram
    autonumber
 
    Alice ->> John: Hello John, how are you?
 
    loop Healthcheck
        John ->> John: Fight against hypochondria
    end
 
    Note right of John: Rational thoughts!
 
    John -->> Alice: Great!
    John ->> Bob: How about you?
    Bob -->> John: Jolly good!
```

BobJohnAliceBobJohnAliceloop[Healthcheck]Rational thoughts!Hello John, how are you?1Fight against hypochondria2Great!3How about you?4Jolly good!5

State diagrams

```mermaid
stateDiagram-v2
    state fork_state <<fork>>
        [*] --> fork_state
        fork_state --> State2
        fork_state --> State3
 
    state join_state <<join>>
        State2 --> join_state
        State3 --> join_state
        join_state --> State4
        State4 --> [*]
```

State2

State3

State4

Gitgraph Diagrams

```mermaid
gitGraph
    commit id: "ZERO"
    branch develop
    branch release
    commit id: "A"
    checkout main
    commit id: "ONE"
    checkout develop
    commit id: "B"
    checkout main
    merge develop id: "MERGE"
    commit id: "TWO"
    checkout release
    cherry-pick id: "MERGE" parent:"B"
    commit id: "THREE"
    checkout develop
    commit id: "C"
```

maindevelopreleaseZEROAONEBMERGETWOcherry-pick:MERGE|parent:BTHREEC

やってみたいことメモ

  • コードとプレビューを切り替えられるようにする
  • 拡大・縮小をできるようにする