Vivliostyle-CLI v4.6.0から使えるようになったJavaScriptで、近頃話題のmermaid.jsが使えるか試してみました。
表示例
VFMファイル
VFMのFrontmatterのscriptプロパティにmermaid.jsと、後述のvs-mermaid.jsを記述します。
VFMのcode表記のファイル種別に"mermaid-render"を指定するとレンダリングの対象になります。
注意点
- mermaid.jsはローカルにあるファイルを指定しても動作します。
- vivliostyle.config.jsでworkspaceDirを指定すると作業ディレクトリにローカルのJavaScriptファイルがコピーされないため正しく処理されません。
- vs-mermaid.jsにdeferを付けて遅延読み込みするのがポイントで、deferが無いとレンダリング対象の要素を見つけられないことがあります。
---
script:
- type: 'text/javascript'
src: 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js'
- type: 'text/javascript'
src: './vs-mermaid.js'
defer: true
---
```mermaid-render
stateDiagram
状態1: ノート付き状態
note right of 状態1
日本語も扱えます
end note
状態1 --> 状態2
note left of 状態2 : こちらにもノート
```
```mermaid-render:キャプション付き
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
```
JavaScript
デフォルトのレンダリング(onLoadイベントで.mermaidの要素を対象)をせずに、VFMの書き出す要素を選択してレンダリングを行ないます。
vs-mermaid.js
mermaid.initialize({
startOnLoad:false
});
function renderGraph(){
// VFMが作るcode要素に付けられるクラスを指定したセレクタ
const codeSelector = "code.language-mermaid-render";
// レンダリング対象になる要素のリストを取得する
const mermaidElements = document.querySelectorAll(codeSelector);
let i = 1;
for(let src of mermaidElements) {
const dist = src.parentNode;
const svg = mermaid.render('mermaid-graph-'+i, src.textContent, undefined);
const div = document.createElement('div');
div.innerHTML = svg;
div.classList.add('language-mermaid-render');
// code要素の親要素であるpre要素をdiv.language-mermaid-render > svg#mermaid-grahp-*に置き換える
dist.replaceWith(div);
i++;
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', renderGraph);
} else {
renderGraph();
}
CSS
div.language-mermaid-render内のsvgを中央に表示するためにtext-alignを設定しています。
.language-mermaid-render {
width: 100%;
text-align: center;
}
figcaption {
width: 100%;
text-align: center;
}