Cloudflare のアーキテクチャ図を mermaid で書く

# Cloudflare のアイコン集
以下の npm パッケージで公開されている React コンポーネントから `svg` を取り出すことができます。

- [@cloudflare/component-logo - npm](https://www.npmjs.com/package/@cloudflare/component-logo)
- [@cloudflare/component-icon - npm](https://www.npmjs.com/package/@cloudflare/component-icon)

以下のようなサイトでアイコン集が確認できます。

https://cfdata.lol/icons/

実際に Cloudflare Pages と React を使って確認・ダウンロードできるようにしました。

https://cf-icons.pages.dev/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/adebeccc-9d62-ebee-e871-1f88582c4bcc.png)

サイトの中身は以下の GitHub にあります。

https://github.com/kyouheicf/cf-icons

# mermaid でアイコンを使う
以下の記事を参考にして `<img src='svg_url_link'>` を挿入する形式とします。

- [【mermaid.js】フローチャートに画像を表示する | noitaro.github.io](https://noitaro.github.io/mermaid-js-flowchart-in-image/)

ローカルエディタは Visual Studio Code と以下のプラグインを使って `.mmd` をハイライト＆プレビューできます。

- [Mermaid Editor - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=tomoyukim.vscode-mermaid-editor)
- [Mermaid Markdown Syntax Highlighting - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=bpruitt-goddard.mermaid-markdown-syntax-highlighting)

```md:cf-icons.mmd
graph LR
User[User<br><img src='https://cf-icons.pages.dev/user.svg' width='48' height='48'>] --> |Static page|Functions[Pages Functions<br><img src='https://cf-icons.pages.dev/workers-pages.svg' width='48' height='48'/>]
mermaid[mermaid<br><img src='https://cf-icons.pages.dev/file.svg' width='48' height='48'>] --> |"img src = https://cf-icons.pages.dev/*.svg"|Functions
Functions --> |Static page|Pages[Cloudflare Pages<img src='https://cf-icons.pages.dev/pages-logo.svg' width='48' height='48'/>]

Pages --> |Render<br>SVG|Icons[React<br>Component]
Pages -.->|Save All SVG|SVG[SVG icons<br><img src='https://cf-icons.pages.dev/image.svg' width='48' height='48'>]
SVG --> |Upload with<br>Custom ID|Images

Functions --> |"img src = https://imagedelivery.net/ACCOUNT_HASH/*/svg"|Images[Cloudflare<br>Images<br><img src='https://cf-icons.pages.dev/r2.svg' width='48' height='48'>]
```

今のところ、~~Qiita や~~ Google Slide には、このように `png` に変換して表示させるのが良さそうです。

```shell:
mmdc -i cf-icons.mmd -o cf-icons.png --scale 3
```

実装には Cloudflare Pages Functions `functions/_middleware.js` を使って、`https://cf-icons.pages.dev/*.svg` は Cloudflare Images から SVG 画像を配信します。

![cf-icons.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/38aa3b4c-c232-1326-1189-fbde9a699379.png)

~~以下のディスカッションが実装されれば、きっと Qiita でも画像付きでレンダリングできるようになるでしょう :pray:~~

- ~~[Mermaid 内で画像が表示されるようにしてほしい · increments/qiita-discussions · Discussion #547](https://github.com/increments/qiita-discussions/discussions/547)~~

2024年4月3日追記
Qiita でも `mermaid` 内の `img` タグが正しく表示されるようになりました！

ただ `img` タグでのサイズ指定が効いていない :thinking: ので、 `themeCSS` を使って `%%{init: {'themeCSS': 'img {width: 48px; height:48px;}'}}%%` のように指定することでサイズ指定が適用されました。

```mermaid
%%{init: {'themeCSS': 'img {width: 48px;height:48px;}'}}%%

graph LR
  b[<img src='https://cf-icons.pages.dev/internet-browser.svg' width='48' height='48'/><br>Browser] --> |GET html|p
  subgraph Cloudflare[<div style='text-align:center'><img src='https://cf-icons.pages.dev/logo-cloud.svg' width='100'/><br>Cloudflare]
    p[<img src='https://cf-icons.pages.dev/pages-logo.svg' width='48' height='48'/><br>Pages]
    cw --> |<img src='https://cf-icons.pages.dev/timer.svg' width='48' height='48'/><br>Cron Trigger|cw[<img src='https://cf-icons.pages.dev/edgeworker.svg' width='48' height='48'/><br>Cron Workers</div>]
    fw --> |"READ"|d["<img src='https://cf-icons.pages.dev/d1.svg' width='48' height='48'/><br>D1</br>(Table 'WaitPeople')"]
  end
  cw --> |"<img src='https://cf-icons.pages.dev/browser-rendering.svg' width='48' height='48'/><br>GET html</br>(Browser Rendering)"|q[<img src='https://cf-icons.pages.dev/applications.svg' width='48' height='48'/><br>www.qbhouse.co.jp]
  cw --> |"WRITE"|d
  b --> |"ajax Request</br>(drawChart)"|fw[<img src='https://cf-icons.pages.dev/edgeworker.svg' width='48' height='48'/><br>Fetch Workers]
```

このリリースで mermaid バージョンがアップデートされた影響かも？

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">📝リリースノート <br>マイページのピックアップ記事を編集するモーダルの「保存する」ボタンを常に見えるように修正しました🚀<br><br>Mermaidのバージョンを10.2.4から10.9.0に変更しました🚀 <a href="https://t.co/6nMuk3gBwO">https://t.co/6nMuk3gBwO</a></p>&mdash; Qiita (キータ) 公式 (@Qiita) <a href="https://twitter.com/Qiita/status/1767451407580561903?ref_src=twsrc%5Etfw">March 12, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# サンプル図
`mermaid` コードの可読性は落ちますが、ベースのロジックができあがった後に、アイコンを追加してわかりやすくしておくと、パッと見たときの印象が変わってきます。

他人に見せるときや自分でも後から見返す際には助かります。

- [Cloudflare スタックを駆使してQBハウスの待ち人数推移を眺める #cloudflare - Qiita](https://qiita.com/khayama/items/38130a208a4dd2ab9ab7)

```markdown:busy-qbhouse.mmd
graph LR
  b[<img src='https://cf-icons.pages.dev/internet-browser.svg' width='48' height='48'/><br>Browser] --> |GET html|p
  subgraph Cloudflare[<div style='text-align:center'><img src='https://cf-icons.pages.dev/logo-cloud.svg' width='100'/><br>Cloudflare]
    p[<img src='https://cf-icons.pages.dev/pages-logo.svg' width='48' height='48'/><br>Pages]
    cw --> |<img src='https://cf-icons.pages.dev/timer.svg' width='48' height='48'/><br>Cron Trigger|cw[<img src='https://cf-icons.pages.dev/edgeworker.svg' width='48' height='48'/><br>Cron Workers</div>]
    fw --> |"READ"|d["<img src='https://cf-icons.pages.dev/d1.svg' width='48' height='48'/><br>D1</br>(Table 'WaitPeople')"]
  end
  cw --> |"<img src='https://cf-icons.pages.dev/security-bots.svg' width='48' height='48'/><br>GET html</br>(Browser Rendering)"|q[www.qbhouse.co.jp]
  cw --> |"WRITE"|d
  b --> |"ajax Request</br>(drawChart)"|fw[<img src='https://cf-icons.pages.dev/edgeworker.svg' width='48' height='48'/><br>Fetch Workers]
```

↓デフォルトテーマ

```shell:
mmdc -i busy-qbhouse.mmd -o busy-qbhouse-default.png --scale 3
```

![busy-qbhouse-default.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/28004993-9064-fab1-7d6e-6b7ba87f4092.png)

↓ニュートラルテーマ

```shell:
mmdc -i busy-qbhouse.mmd -o busy-qbhouse-neutral.png --scale 3 -t neutral
```

![busy-qbhouse-neutral.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/3c0e018d-a0db-9d53-1359-8dac15068124.png)

# 参考：PNG 画像生成コマンドのエイリアス

```zsh:~/.zshrc
function md2png() {
    mmdc -i $1 -o $(basename $1 .mmd).png --scale 3
}
alias md2png=md2png

# % md2png busy-qbhouse.mmd 
# Generating single mermaid chart
```

# まとめ
しばらくはこの方法で描いていきたいと思います。

- やはり図は mermaid で書くに限る！
- やはりアイコンがあった方が映える！
- やはり `svg` だと図がきれい！

余談ですが、最近の流行は AI が `mermaid` を書いてくれるようになってきたようなので、駆使していければと思います。

- [Mermaid Chart’s ChatGPT Plugin Combines Generative AI and Smart Diagramming For Users · MermaidChart Blog](https://www.mermaidchart.com/blog/posts/mermaid-chart-chatgpt-plugin-combines-generative-ai-and-smart-diagramming)
- [New AI chatbot now available on Mermaid Chart to simplify text-based diagram creation · MermaidChart Blog](https://www.mermaidchart.com/blog/posts/ai-chatbot-now-available-on-mermaid-chart-to-simplify-text-based-diagram-creation)