Marpにいれたmermaid記法をVSCodeでPreviewとExport

Marpでmermaid記法を使いたい
ゴール設定
PDFや諸々出力でも問題が出ないように調整したい
MARPを使う、ということで調べていたら、いまはMarpitに集約されていると
Marpitをmarkdown内で書く
---
marp: true
---
参考サイト
Marpit
v10からmermaid.init()はdeprecated---
marp: true
---
<pre class="mermaid">
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
</pre>
<!-- Put this script at the end of Markdown file. -->
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
mermaid記法を入れるための試作
参考サイト
呼び出し
mermaid.esm.mjsまたはmermaid.esm.min.mjsを介して Mermaid ライブラリをインポートしmermaid.initialize()呼び出します。
これにより、ダイアグラムの外観が決定され、レンダリング プロセスが始まる。
呼び出し時のパラメータ指定ではどうかな
フローチャートの指定
nodeの余白を調整できるか
テーマの指定
フォント周りを調整できるか
mermaid内に書く
%%{init:{'theme':'base','themeCSS':" .cluster .label {font-size:32px;font-weight:bold;} .output {font-size:24px;}",'flowchart':{'nodeSpacing':80}}}%%
marpでstyle指定
---
marp: true
style: |
section {
background-color: #ccc;
}
.mermaid svg {
display: block;
min-width: 100%;
max-width: 100%;
max-height: 100%;
margin: 0 auto
}
---
実践
- フォントが表示し切れない問題
- previewの方の色が実際と違う
preview
export

Mermaid + 日本語 + 絵文字対応
Marp / PDF出力で安定動作させるための最終まとめ
問題の発端
-
Mermaid記法がそのまま出力される / 描画エラーになる
- PDF化では
<script>
実行が制限される -
btoa()
が 非ASCII(日本語・絵文字) を処理できずエラー - Markdownやエディタ経由で NBSP(\u00A0) や ゼロ幅スペース(\u200B) が混入
- PDF化では
改善アプローチと修正点
対策 | 内容 | 効果 |
---|---|---|
NBSP除去処理 | (el.textContent ?? '').replace(/\u00A0/g, ' ').trim(); |
ソース中の不可視文字による構文エラー防止 |
encodeURIComponent方式 | 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svg) |
絵文字・日本語含むSVGの安全なエンコード |
一意IDの付与 | m-${crypto.randomUUID()} |
SVG内部のmarker / defs衝突を防止 |
フォント指定除去/SVGテキスト対策 | inline SVG+overflow: visible +htmlLabels: true
|
フォント見切れや行間切れを防止 |
PDF出力時はHTML許可 | VSCode: Enable HTML / CLI: --html
|
<script> 実行を有効化 |
サンプル
---
marp: true
size: 16:9
paginate: true
---
<!-- Use: marp --html --watch <this file> -->
<style>
/* 画像にして埋め込む前提のサイズ調整用クラス */
img.mermaid-100h { max-height: 100%; }
</style>
<!-- Mermaid v11 を ESM import で読み込み、<pre.mermaid> を画像に差し替え -->
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
mermaid.initialize({
startOnLoad: false,
theme: 'default'
});
// btoaは非ASCII(日本語・絵文字)で失敗するため、URIエンコードでdata URL化
const svgToDataURL = (svg) =>
'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svg);
window.addEventListener('DOMContentLoaded', async () => {
const mermaidEls = document.querySelectorAll('pre.mermaid');
let n = 0;
for (const el of mermaidEls) {
// NBSP(\u00A0)混入を通常スペース化し、前後空白を除去
const code = ((el.textContent ?? '').replace(/\u00A0/g, ' ')).trim();
if (!code) continue;
// 一意ID(数字始まり回避&再描画でも衝突しにくい)
const id = (crypto?.randomUUID ? `m-${crypto.randomUUID()}` : `m-${Date.now()}-${n++}`);
try {
const { svg } = await mermaid.render(id, code);
const img = document.createElement('img');
img.src = svgToDataURL(svg);
img.className = el.className; // 既存クラスを引き継ぐ(例: mermaid-100h)
const style = el.getAttribute('style');
if (style) img.setAttribute('style', style); // インラインstyleも引き継ぐ
el.replaceWith(img);
} catch (e) {
// フォールバック:エラー内容をスライド上に表示
const warn = document.createElement('div');
warn.style.cssText = 'padding:.75rem 1rem;border-left:6px solid #e53935;background:#fdecea;color:#b71c1c;border-radius:.5rem;';
warn.textContent = `Mermaid描画エラー: ${e?.message || e}`;
el.replaceWith(warn);
}
}
});
</script>
### Flowchart test (日本語/絵文字対応・フォント指定なし)
<pre class="mermaid mermaid-100h">
flowchart LR
A["開始 😃"] --> B["処理中 🔧(日本語OK)"]
B --> C["完了 🎉"]
B --> D["要確認 ❓"]
style A fill:#e0f7fa,stroke:#006064,stroke-width:2px
style C fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px
style D fill:#fff3e0,stroke:#e65100,stroke-width:2px
</pre>
Preview
コードとVSCodeのプレビューを並べた
PDFとVSCodeのプレビューを並べた。
差があるのは色の指定のないクラス。そこも調整できた方がよいな。

不可視文字(ZWSPなど)への対応について
MermaidやMarkdownを扱う際に、コピー&ペーストやエディタの自動変換によってゼロ幅スペース(ZWSP)やノーブレークスペース(NBSP)などの不可視文字が混入することがあります。これらは見た目には分かりませんが、Mermaidの構文解析を壊す原因になります。
// 不可視文字を除去する関数
const sanitize = (s) =>
s.replace(/\u00A0/g, ' ') // NBSPを通常のスペースに
.replace(/[\u200B-\u200D\uFEFF]/g, '') // ZWSP, ZWNJ, ZWJ, FEFFを削除
.trim();
なぜ必要か
- 文字の間に「見えない文字」があると、Mermaidがノードやエッジを正しく認識できない
- 「Syntax Error」「Unexpected character」といった曖昧なエラーの原因になりがち
- ZennやVSCodeでは、HTMLコピーなどで自動的に混入することもある
影響
-
日本語・英語の文章、Markdown、Mermaidコードでは削除しても表示や意味に影響なし
-
絵文字の結合(👨👩👧👦 など) や アラビア語・インド系文字 では、ZWJ/ZWNJを削除すると表記が崩れることがあります
-
そのため、用途によっては以下のように“軽めの除去”:
s.replace(/[\u200B\uFEFF]/g, '')
普通のスライドやMermaid図では削除して問題なし。
ただし、絵文字や特殊言語を多く使う資料では慎重に扱う。

theme: gaia
で文字サイズが崩れる件
MarpでMermaidを使うとき、状況
Marpで theme: gaia
(または uncover
)を指定しているとき、Mermaid内の文字サイズやフォントが崩れることを確認。
- 文字が異常に大きくなる
- ノード内の文字がはみ出す
- PDFではさらにズレが目立つ
原因は MarpテーマのCSSリセット が、MermaidのSVG内にまで影響しているため。
原因の整理
要因 | 内容 |
---|---|
Marpテーマの section スコープ |
font-size , color , line-height などが全要素に継承される |
Mermaidが em 基準でノードサイズを計算 |
Marp側のfont-size に引きずられる |
Mermaidの themeVariables がCSSに負ける |
Marpテーマが後勝ちになる |
PDF出力時のフォント差 | Marpテーマのフォント指定がSVGに反映される |
対策
SVGを独立スコープにする
Mermaidのrender()
で生成したSVGに、CSS継承をリセットする。
const inline = new DOMParser().parseFromString(svg, 'image/svg+xml').documentElement;
inline.style.all = 'initial'; // Marpテーマの影響をリセット
これで theme: gaia
や theme: uncover
を使っても、文字の崩れが解消される。
Mermaidのフォントを明示的に指定
mermaid.initialize({
startOnLoad: false,
theme: 'base',
themeVariables: {
fontFamily: 'Arial, "Noto Sans JP", sans-serif',
fontSize: '18px',
},
});
theme: base
を指定すると、Marpテーマとの競合が最小化される。
Marp側でSVG内の文字をリセット
MarpスライドのCSSで、SVG内テキストを強制的に指定し直す方法も有効。
<style>
svg.mermaid text {
font-size: 18px !important;
font-family: "Noto Sans JP", sans-serif !important;
fill: #333 !important;
}
</style>
実測メモ
Marpテーマ | 結果 | 備考 |
---|---|---|
gaia |
かなり大きく崩れる | 確認 |
まとめ
-
theme:
はスライド装飾に優れるが、Mermaidの文字サイズを上書きしてしまう -
安定させるには
-
inline.style.all = 'initial'
を追加 - または
theme: base
+themeVariables
明示
-
-
どうしてもズレる場合は
theme: none
を選ぶのが無難
補足
この挙動はMermaidのバグではなく、MarpテーマCSSの継承によるもの。
Marpのテーマはスライド本文を対象として設計されており、SVGの中身まで制御対象に入ってしまう。