Karan Engineering Blog
進捗状況
0%

2024-10-30

Mermaidプレビューを組み込む

Mermaidプレビューを組み込む

Mermaid Previewの構築

概要

  • プレビューで表示できる。
  • テーマの切り替えを行なっても別のテーマでのコントラストを作成できる。
graph TD A[ブログコンテンツ取得] --> B[Cheerioで解析] B --> C{コードブロックの種類} C -->|Mermaid| D[MermaidChartに変換] C -->|その他| E[Highlight.jsでハイライト] D --> F[Mermaidレンダリング] E --> F F --> G[Astroページ表示] G --> H[テーマ切替ボタンをクリック] H --> I{現在のテーマ} I -->|ライト| J[ダークモードに切替 & .darkクラス追加] I -->|ダーク| K[ライトモードに切替 & .darkクラス削除] J --> L[Mermaid再レンダリング] K --> L G --> M[ページ遷移時Mermaid初期化] M --> F

参考資料

Mermaidパッケージ

https://mermaid.js.org/intro/#deploying-mermaid

環境

  • Astro
  • microcms
    • cheerio
    • highlight.js

すでにコードでのシンタックスハイライトは実装できている状態。

構築

インストール

npm install mermaid

レスポンスからMermaid形式の部分を抽出

blog/id.astro (詳細ページ)

const $ = load(response.body);
$("pre code").each((_, elm) => {
  const className = $(elm).attr("class") || "";
  if (className.includes("language-mermaid")) {
    const mermaidCode = $(elm).text();

    $(elm)
      .parent("pre")
      .replaceWith(`<div class="mermaid">${mermaidCode}</div>`);
  } else {
    const result = hljs.highlightAuto($(elm).text());
    $(elm).html(result.value);
    $(elm).addClass("hljs");
  }
});

Mermaidの初期化とレンダリング

run()がないとView transitionを利用している場合は遷移後にプレビューが表示されないことがあるので注意。

initializeMermaid.js

import mermaid from "mermaid";

export function initializeMermaid() {
	mermaid.initialize({
		startOnLoad: true,
	});
	mermaid.run();
}

EventListenerの追加

DOMがロードした場合とview transitionに対応。

blog/id.astro (詳細ページ)

<script>
  import { initializeMermaid } from "target path";
  initializeMermaid();
  document.addEventListener("astro:after-swap", () => {
    initializeMermaid();
  });
</script>

スタイリング

モジュールとして切り出して利用するのでもいい。

元々用意されているテーマから上書きする形でスタイルを作成。

Mermaidプレビューにはさまざまなフォーマットがあるため、必要な時に都度修正スタイルをしていく。

blog/id.astro (詳細ページ)

<style is:inline>
/* mermaid format */
  .mermaid text {
    fill: #fff !important;
  }

  .mermaid line {
    fill: #fff !important;
    stroke: #fff !important;
  }

  .mermaid path {
    stroke: #fff !important;
  }

  .mermaid rect {
    fill: #fff !important;
    stroke: #fff !important;
  }

  .mermaid tspan {
    fill: #fff !important;
  }

  .mermaid marker path {
    fill: #fff !important;
    stroke: #fff !important;
  }

/* dark mode */
  .dark .mermaid text {
    fill: #ccc !important;
  }

/* etc ... */
</style>

大変だったこと

テーマの変更時の色の反映

Mermaid側でテーマの管理をしようと思ったが、テーマを切り替えても動的にプレビューのコントラストも変更されるわけではないので、他のスタイルと同様にCSSを利用して管理した。

const mermaidThemeVariables = {
	light: {
		background: "#fff",
	},
	dark: {
		background: "#ccc",
	},
};

const currentThemeVariables =
		theme === "dark"
			? mermaidThemeVariables.dark
			: mermaidThemeVariables.light;

mermaid.initialize({
	startOnLoad: true,
        themeVariables: currentThemeVariables,
});
© 2023 Karan. All Rights Reserved.