cockscomblog?

cockscomb on hatena blog

ScrapboxでMermaidを使う

筆者の勤務先ではScrapboxというWiki的なツールが導入されていて、何でもそこに書いている。

そして筆者は以前からPlantUMLなどで作図するのが気に入っているが、最近は同様の目的を持ったMermaidがよく使われている様子がある。2021年12月にはNotionが、そして2022年2月にGitHubがそれぞれMermaidの機能を発表している。

いずれもドキュメント中にコードブロックを埋め込み、シンタックスとして「Mermaid」を設定すると、表示時には図に置き換わる。

特にソフトウェア開発に関連したツールでは、こういった機能は便利だ。ちょっとした図を載せたいときに、別なツールで作図して画像として貼り付けるのは手間だから、ひとつのツール内で閉じていると嬉しい。PlantUMLにしろMermaidにしろ、元がテキストなのもいい。

ある日仕事をしていて、どうしてもScrapbox上のドキュメントに図を入れたくなった。ScrapboxにMermaidが統合されていれば……。試しに別なツールで作図してSVGで出力して貼り付けて、とやったら1度で我慢の限界を迎えた。

ScrapboxのUserScriptを書く

ということでなんとかしていく。ScrapboxはUserScriptの機能を持っているので、危険を承知でこれを使う。

ということで書いてみたものがこちら。

UserScriptを有効にした上で、プロジェクト内の自分のページにscript.jsコードブロックを置いて読み込む。

code:script.js
    import '/api/code/cockscomb/Mermaid/script.js'
code:example.mmd
    graph LR
        Mermaid--makes y'all-->Happy

ブラウザをリロードしてから、適当なページに拡張子「mmd」のコードブロックを書くと、そのコードブロックの上に図が表示される。

f:id:cockscomb:20220221095309p:plain
Mermaidによって描画された図がコードブロック上に表示される

拡張子が「mmd」なのはmermaid-cliの例に倣った。

コードブロックを編集すれば図も更新される。複数人で同時に編集すると、図がリアルタイムにどんどん変化していって、おもしろい。

ScrapboxのUserScriptについて

現代のWebでUserScriptを書くことはなくなっていたので、Greasemonkeyを思い出したりして懐かしい。機能としてUserScript機能を持たせるのは胆力がある。利用者側としては便利だ。

ScrapboxのUserScriptを書くにあたって以下のようなテクニックを使った。

ライブラリの読み込み

Mermaidを読み込むのには、script要素を動的に追加した。

async function loadScript(src) {
   const script = document.createElement('script');
   script.src = src;
   const promise = new Promise(resolve => {
     script.addEventListener('load', resolve);
   });
   document.body.appendChild(script);
   return promise;
}

ScrapboxはContent-Security-Policyが設定されているので、許可されているcdnjs (cdnjs.cloudflare.com) を使った。

https://cdnjs.cloudflare.com/ajax/libs/mermaid/8.14.0/mermaid.min.js

ScrapboxAPI

UserScriptからグローバル変数scrapboxを介してページの情報を得られる。scrapbox.Page.linesで行の情報が得られるのでこれを使っている。

行が変更されたり、ページを移動したとき、イベントによってそれを検知できる。これでMermaidの図を再描画させたり、ページが変わったら後片付けしたりしている。

コードブロックの内容もAPIから取得できる。

DOM操作

図を表示させるのにDOM操作するしかなく躊躇した。DOM操作するのは乱暴だと思う。しかしScrapboxの開発者もUserScriptを提供している時点でDOM操作されるだろうと想像しているはずなので、諦める。

どうですか

ScrapboxでUserScriptを書いたことがなかったが、同僚がなんかやっているのを覗き見たりしてキャッチアップできた。ありがたい。そして社内で宣伝したら乗っかってくれる人が多くて、みんなで適当な図を共同編集できておもしろかった。PlantUMLもMermaidも行志向だから、Scrapboxと相性がいいと思う。

気をよくして、Scrapboxリニューアルされたはてなスターを設置しようとしたが、Content-Security-Policyで制約されており、iframeが読み込まれず挫折した。