🧜‍♀️

GitHub Pages Jekyll で Mermaid を表示

2024/09/21に公開

はじめに

GitHub の Repository に Push した Markdown ファイルを GitHub Pages でドキュメントを公開したい場合があります。
そのとき、GitHub Repository の Code で表示されたものと同じように GitHub Pages に表示されることを期待しましたが、Mermaid は対応していませんでした。
そこで、Mermaid が表示できるようにできるように対応した方法を紹介します。

Mermaid とは

https://mermaid.js.org/intro/

Mermaid lets you create diagrams and visualizations using text and code.

Mermaid を使用すると、テキストとコードを使用して図や視覚化を作成できます。

GitHub の Mermaid について

https://docs.github.com/ja/get-started/writing-on-github/working-with-advanced-formatting/creating-diagrams

Markdown では、Mermaid、geoJSON と topoJSON、ASCII STL の 3 つの異なる構文を使用してダイアグラムを作成できます。 ダイアグラムのレンダリングは、GitHub Issues、GitHub Discussions、pull request、Wiki、Markdown ファイルで利用できます。

GitHub Pages で Mermaid を表示

GitHub Pages へのデプロイ方法

GitHub Pages へのデプロイは、いくつかの方法があります。

  1. GitHub Repository の Setting Pages で公開する Branch を指定
  2. GitHub Actions で actions/jekyll-build-pages で Markdown ファイルを HTML ファイルに変換し、actions/upload-pages-artifact, actions/deploy-pages でデプロイ
  3. GitHub Actions で独自に HTML ファイルを生成し、actions/upload-pages-artifact, actions/deploy-pages でデプロイ

ここでは、 2. の方法で Mermaid の表示に対応します。

GitHub Actions 設定

.github/workflows/deploy_github_pages.yml

---
name: Deploy GitHub Pages

on:
  push:
    branches:
      - main

concurrency:
  group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
  cancel-in-progress: true

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    permissions:
      contents: read
    steps:
      - name: Checkout
        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - name: Build with Jekyll
        uses: actions/jekyll-build-pages@44a6e6beabd48582f863aeeb6cb2151cc1716697 # v1.0.13
        with:
          source: ./
          destination: ./_site

      - name: Add Mermaid
        env:
          MERMAID_HTML_TAG: |
            <script type='module'>
              import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
              mermaid.initialize({ startOnLoad: false });
              await mermaid.run({
                querySelector: 'pre > code.language-mermaid',
              });
            </script>
        run: |
          MERMAID_HTML_TAG="${MERMAID_HTML_TAG//$'\n'/}"
          grep -rl "language-mermaid" _site | while IFS= read -r file; do
            echo "Adding Mermaid to $file"
            sudo sed -i "s|</head>|$MERMAID_HTML_TAG\n</head>|" "$file"
          done

      - name: Upload artifact
        uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1
        with:
          path: _site/

  deploy:
    runs-on: ubuntu-latest
    needs: build
    timeout-minutes: 10
    permissions:
      contents: read
      pages: write
      id-token: write
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - name: Deploy
        id: deployment
        uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5

Mermaid への対応

- name: Add Mermaid
  env:
    MERMAID_HTML_TAG: |
      <script type='module'>
        import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
        mermaid.initialize({ startOnLoad: false });
        await mermaid.run({
          querySelector: 'pre > code.language-mermaid',
        });
      </script>
  run: |
    MERMAID_HTML_TAG="${MERMAID_HTML_TAG//$'\n'/}"
    grep -rl "language-mermaid" _site | while IFS= read -r file; do
      echo "Adding Mermaid to $file"
      sudo sed -i "s|</head>|$MERMAID_HTML_TAG\n</head>|" "$file"
    done

対応内容

Jekyll によって Markdown ファイルから HTML ファイルに変換されたとき、以下のように変換されます。

<pre>
  <code class="language-mermaid">
    ...
  </code>
</pre>

このままでは、コードブロックとして表示されるので、以下のように対応します。

  • language-mermaid が含まれる HTML ファイルを対象に以下の処理を実施
  • コードブロックを Mermaid で表示できるように、<script>〜</script>を HTML ファイルに追加

<script>〜</script>の内容は以下のようになっています。

  • CDN からmermaid.esm.min.mjsをインポート
  • mermaid.initialize({ startOnLoad: false });で初期化
    • startOnLoad: falseを指定し、ロード時に処理しないようにする
  • await mermaid.run({querySelector: 'pre > code.language-mermaid',}); で Mermaid を表示
    • 'pre > code.language-mermaid'<pre><code class="language-mermaid">...</code></pre>のセレクター

まとめ

GitHub Pages Jekyll で Mermaid を表示することができました。
Mermaid が表示されることを期待している場合は、上記のように対応してみてはいかがでしょうか。

Discussion