大晦日に何をやっているのか
言わないで…
言わないで…
さよならは…(これ以上は、●ASRAC に怒られる)
概要
GitBucket用のプラグイン GitBucket Markdown Enhanced Pluginを開発しています。
GitBucket Markdown Enhanced Plugin は、GitBucket 標準のマークダウンレンダリングエンジンを置き換えるプラグインです。
目標は、Visual Studio Code の Markdown Preview Enhanced 向けの markdown ファイルを軽易に Web で共有できる環境です。
しばらく別のプラグインの開発をしていたため、久しぶりの更新です。
今回は、Markdown Preview Enhanced が対応している Vega and Vega-lite サポートを追加した話です。
前回の記事
機能の説明
vega あるいは vega-lite 用のコードブロックに専用の JSON を書くとグラフが表示されます。
以下のコードブロックが、上の画像に変換されます。
サンプルコード
```vega-lite
{
"$schema": "https://vega.github.io/schema/vega-lite/v6.json",
"description": "A simple bar chart with embedded data.",
"data": {
"values": [
{
"a": "A",
"b": 28
},
{
"a": "B",
"b": 55
},
{
"a": "C",
"b": 43
},
{
"a": "D",
"b": 91
},
{
"a": "E",
"b": 81
},
{
"a": "F",
"b": 53
},
{
"a": "G",
"b": 19
},
{
"a": "H",
"b": 87
},
{
"a": "I",
"b": 52
}
]
},
"mark": "bar",
"encoding": {
"x": {
"field": "a",
"type": "ordinal"
},
"y": {
"field": "b",
"type": "quantitative"
}
}
}
```
JSON オブジェクトではなく、JSON 文字列を書くことに注意してください。プロパティ名をダブルクォーテーション等で囲む必要があります。
vega 関連のスクリプトファイルを LICENSE とともに同梱
専用のディレクトリ src/main/resources/gme/assets/vegaを掘り、以下のスクリプトを LICENSE とともに配置しました。
Plugin クラスの javaScripts メソッドに上記ファイルを読み込むための記述を追加
src/main/scala/Plugin.scala に以下の記述を追加しました。
|<script src="${jsPath}/vega/vega-6.2.0.js" type="text/javascript">
|</script>
|<script src="${jsPath}/vega/vega-lite-6.4.1.js" type="text/javascript">
|</script>
|<script src="${jsPath}/vega/vega-embed-7.0.2.js" type="text/javascript">
|</script>
MarkdownEnhancedNodeRenderer に処理を追加
src/main/scala/io/github/yasumichi/gme/MarkdownEnhancedNodeRenderer.scala に専用のメソッドを追加しました。
private def renderVega(
html: HtmlWriter,
node: FencedCodeBlock,
context: NodeRendererContext,
language: String
): Unit = {
html.withAttr().attr("id", s"vega-${vegaId}").tag("div")
html.tag("/div")
html.withAttr().attr("type", language).attr("class", "vega").attr("data-target", s"#vega-${vegaId}").tag("script")
vegaId = vegaId + 1;
html.rawIndentedPre(node.getContentChars())
html.tag("/script")
}
グラフを埋め込むための <div> タグと JSON を埋め込むための <script> タグを出力しています。
JavaScript として処理されないように type 属性を vage または vega-lite にしています。(WaveDrom 方式)
また、グラフを埋め込むための <div> タグを決定するために data-target 属性にセレクターを付与しています。
vegaId はクラスの private フィールドです。
このメソッドをコードブロックの処理を振り分けるところから、呼び出しています。
最終的に描画を行うスクリプト
src/main/resources/gme/assets/gme.js に最終的な描画を行う関数を追加しました。
var renderVega = function() {
return new Promise((resolve, reject) => {
let vegaList = document.querySelectorAll('.vega');
vegaList.forEach((node, index) => {
let vegaId = node.getAttribute('data-target');
try {
let vegaData = JSON.parse(node.textContent);
vegaEmbed(vegaId, vegaData);
} catch (error) {
let node = document.querySelector(vegaId)
if (node) {
node.textContent = error.message;
}
}
});
resolve();
});
}
一応、Promise を使って非同期処理にしています。
主な処理は以下の通りです。
-
class 属性が
vegaであるノードを探し、forEach で走査- ノードの data-target 属性の値を取得
- ノードの textContent プロパティを JSON.parse() でオブジェクトに変換
- vegaEmbed でターゲットノードにグラフを埋め込み
この関数を以下のそれぞれで呼び出しています。
- DOMContentLoaded が発火した時(閲覧時)
- リポジトリビューアーでファイル編集時にプレビューされた時
- issue コメントなどを編集時にプレビューされた時
最後までお読みいただきありがとうございました。
今年も最後までお付き合いいただきありがとうございました。
それでは、よいお年を。
-
YAML Ain't Markup Language (← Yet Another Markup Language) - YAML Ain’t Markup Language (YAML™) revision 1.2.2 ↩
-
JavaScript Object Notation - RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format ↩
