WordPress の Gutenberg ブロックエディタで Mermaid 図表をレンダリングするプラグインを開発中、classDef スタイリングを使った図表がエディタプレビューで正しく表示されない問題が発生しました。フロントエンド(投稿表示)では正常に動作するのに、エディタ内のプレビューでのみ失敗する状況です。

症状

次のような Mermaid コードがエディタプレビューでレンダリングされませんでした。

flowchart LR
    classDef highlight fill:#f9f,stroke:#333,stroke-width:2px
    A[Start] --> B[Process]
    B:::highlight --> C[End]
  • エラーメッセージなし
  • Mermaid ブロックとして検出されない
  • コードブロックのまま表示される

原因

Mermaid コンテンツ検出ロジックで、SVG(レンダリング済み図表)を除外するためのパターンに stroke-width: が含まれていました。

// 問題のあったコード
const SVG_EXCLUSION_PATTERNS = [
  '#gfmr-mermaid-',
  'font-family:',
  'stroke-width:',  // ← これが原因
  '<svg',
  '</svg>'
];

classDef で stroke-width を指定すると、正当な Mermaid ソースコードなのに「すでにレンダリング済みの SVG」と誤判定されてスキップされていました。

直し方

stroke-width: を SVG 除外パターンから削除します。

// 修正後
const SVG_EXCLUSION_PATTERNS = [
  '#gfmr-mermaid-',
  'font-family:',
  '<svg',
  '</svg>'
];

加えて、検出ロジックの信頼性向上のために gitGraph 検出パターンも追加しました。

学び

  1. 除外パターンは慎重に設計する: 「レンダリング済み SVG にしか現れないパターン」と「ソースコードにも現れうるパターン」を区別する必要がある。
  2. stroke-width は CSS プロパティ: SVG 内でよく使われるが、Mermaid classDef でも普通に使われる正当な記法。
  3. リファクタリングの副次効果: 問題調査の過程で重複コードを発見。ヘルパー関数・定数への抽出により 162 行(17%)削減を達成。

確認手順

  1. Gutenberg エディタで新規投稿を作成
  2. Markdown ブロックを追加
  3. 次の Mermaid コードを入力:
flowchart LR
    classDef highlight fill:#f9f,stroke:#333,stroke-width:2px
    A[Start]:::highlight --> B[End]
  1. プレビューモードに切り替え
  2. 図表が正しくレンダリングされることを確認

追加で実施したリファクタリング

問題調査中に発見した重複コードを整理しました。

  • ヘルパー関数の抽出: isMermaidContent(), buildMermaidErrorHTML(), getMermaidContainerStyle()
  • 定数の抽出: MERMAID_START_PATTERNS, MERMAID_CLASS_SELECTORS など
  • レガシーフォールバック処理の削除(約 95 行)
  • 結果: 967 行 → 805 行(162 行削減)

これは Markdown Renderer for GitHub に実装されています。