WordPress の Gutenberg ブロックエディタで Mermaid 図表をレンダリングするプラグインを開発中、classDef スタイリングを使った図表がエディタプレビューで正しく表示されない問題が発生しました。フロントエンド(投稿表示)では正常に動作するのに、エディタ内のプレビューでのみ失敗する状況です。
## 症状
次のような Mermaid コードがエディタプレビューでレンダリングされませんでした。
```text
flowchart LR
classDef highlight fill:#f9f,stroke:#333,stroke-width:2px
A[Start] --> B[Process]
B:::highlight --> C[End]
```
- エラーメッセージなし
- Mermaid ブロックとして検出されない
- コードブロックのまま表示される
## 原因
Mermaid コンテンツ検出ロジックで、SVG(レンダリング済み図表)を除外するためのパターンに `stroke-width:` が含まれていました。
```javascript
// 問題のあったコード
const SVG_EXCLUSION_PATTERNS = [
'#gfmr-mermaid-',
'font-family:',
'stroke-width:', // ← これが原因
'<svg',
'</svg>'
];
```
classDef で `stroke-width` を指定すると、正当な Mermaid ソースコードなのに「すでにレンダリング済みの SVG」と誤判定されてスキップされていました。
## 直し方
`stroke-width:` を SVG 除外パターンから削除します。
```javascript
// 修正後
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 コードを入力:
```text
flowchart LR
classDef highlight fill:#f9f,stroke:#333,stroke-width:2px
A[Start]:::highlight --> B[End]
```
4. プレビューモードに切り替え
5. 図表が正しくレンダリングされることを確認
## 追加で実施したリファクタリング
問題調査中に発見した重複コードを整理しました。
- ヘルパー関数の抽出: `isMermaidContent()`, `buildMermaidErrorHTML()`, `getMermaidContainerStyle()`
- 定数の抽出: `MERMAID_START_PATTERNS`, `MERMAID_CLASS_SELECTORS` など
- レガシーフォールバック処理の削除(約 95 行)
- 結果: 967 行 → 805 行(162 行削減)
---
これは [Markdown Renderer for GitHub](/markdown-renderer-for-github/) に実装されています。
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 検出パターンも追加しました。
学び
- 除外パターンは慎重に設計する: 「レンダリング済み SVG にしか現れないパターン」と「ソースコードにも現れうるパターン」を区別する必要がある。
- stroke-width は CSS プロパティ: SVG 内でよく使われるが、Mermaid classDef でも普通に使われる正当な記法。
- リファクタリングの副次効果: 問題調査の過程で重複コードを発見。ヘルパー関数・定数への抽出により 162 行(17%)削減を達成。
確認手順
- Gutenberg エディタで新規投稿を作成
- Markdown ブロックを追加
- 次の Mermaid コードを入力:
flowchart LR
classDef highlight fill:#f9f,stroke:#333,stroke-width:2px
A[Start]:::highlight --> B[End]
- プレビューモードに切り替え
- 図表が正しくレンダリングされることを確認
追加で実施したリファクタリング
問題調査中に発見した重複コードを整理しました。
- ヘルパー関数の抽出:
isMermaidContent(), buildMermaidErrorHTML(), getMermaidContainerStyle()
- 定数の抽出:
MERMAID_START_PATTERNS, MERMAID_CLASS_SELECTORS など
- レガシーフォールバック処理の削除(約 95 行)
- 結果: 967 行 → 805 行(162 行削減)
これは Markdown Renderer for GitHub に実装されています。