目的
krokiが動かない時に 自前で bytefields の画像を生成する
事前準備
nodejsをインストールする
fedoraの場合は
sudo yum install -y nodejs
手順
bytefield-svgを取ってきて webサーバとかの node_modules
をインストールする
ちなみに bytefield-svg
はリポジトリ内に lib.js
が無いので結局インストールしないといけない
git clone --depth=1 https://github.com/Deep-Symmetry/bytefield-svg.git
cd bytefield-svg
npm install bytefield-svg express
プロジェクトルートの cli.js
を修正する
diff --git a/cli.js b/cli.js
index 6c98f95..18c7d04 100755
--- a/cli.js
+++ b/cli.js
@@ -3,7 +3,7 @@
// A simple command line interface for rendering diagrams from standard input or a file,
// to standard output or a file.
-const generate = require('./lib.js'); // The bytefield-svg DSL interpreter and diagram generator
+const generate = require('bytefield-svg/lib.js'); // The bytefield-svg DSL interpreter and diagram generator
const fs = require('fs'); // Used to read and write files if needed.
const commandLineArgs = require('command-line-args');
const commandLineUsage = require('command-line-usage');
@@ -66,4 +66,4 @@ if (options.help) {
} else { // Write to standard out.
process.stdout.write(diagram);
}
-}
\ No newline at end of file
+}
Webサーバを立てる
server.js
const express = require('express');
const { spawn } = require('child_process');
const path = require('path');
const app = express();
const port = 3000;
app.use(express.static('public'));
app.use(express.json());
app.post('/render', (req, res) => {
const input = req.body.source || '';
const cliPath = 'cli.js';
let output = '';
let error = '';
const proc = spawn('node', [cliPath], { stdio: ['pipe', 'pipe', 'pipe'] });
proc.stdin.write(input);
proc.stdin.end();
proc.stdout.on('data', data => output += data.toString());
proc.stderr.on('data', data => error += data.toString());
proc.on('close', code => {
if (code === 0) {
res.type('image/svg+xml').send(output);
} else {
res.status(500).send(`Error: ${error}`);
}
});
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
htmlを作成する
public/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Bytefield Live Editor</title>
<style>
body { display: flex; height: 100vh; margin: 0; font-family: sans-serif; }
textarea { width: 50%; padding: 1rem; font-family: monospace; }
iframe { flex: 1; border: none; }
</style>
</head>
<body>
<textarea id="input" placeholder="# Enter bytefield here..."></textarea>
<div id="preview"></div>
<script>
const input = document.getElementById('input');
const preview = document.getElementById('preview');
async function render() {
const res = await fetch('/render', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ source: document.getElementById('input').value })
});
const svg = await res.text();
const svg_data = svg.replace(/^<\?xml[^>]*\?>/, '');
preview.innerHTML = svg_data;
}
input.addEventListener('input', () => {
clearTimeout(input._timer);
input._timer = setTimeout(render, 500); // debounce
});
</script>
</body>
</html>
package.jsonにコマンドを作成する
scripts
内に "server": "node server.js"
を追加する
それ以外は npm install
したら勝手に追加される
diff --git a/package.json b/package.json
index 1ba4ac9..3e88437 100644
--- a/package.json
+++ b/package.json
@@ -5,13 +5,15 @@
"main": "lib.js",
"bin": "cli.js",
"dependencies": {
+ "bytefield-svg": "^1.11.0",
"command-line-args": "^5.1.1",
- "command-line-usage": "^6.1.3"
+ "command-line-usage": "^6.1.3",
+ "express": "^5.1.0"
},
"devDependencies": {
"@antora/cli": "3.1.2",
- "@antora/site-generator": "3.1.2",
"@antora/lunr-extension": "^1.0.0-alpha.8",
+ "@antora/site-generator": "3.1.2",
"@djencks/asciidoctor-mathjax": "0.0.8",
"shadow-cljs": "^2.21.0",
"source-map-support": "^0.5.21"
@@ -20,7 +22,8 @@
"build": "shadow-cljs compile lib",
"release": "shadow-cljs release lib",
"local-docs": "npx antora --fetch doc/local.yml",
- "test": "./cli.js test.edn >test.svg"
+ "test": "./cli.js test.edn >test.svg",
+ "server": "node server.js"
},
"repository": {
"type": "git",
実行
npm run server
編集と確認
ブラウザで http://localhost:3000/
にアクセスして
画像を生成する
こんな感じ
全部入り
dockerでやるのが一番楽なことに気づいた
sudo yum install -y docker
sudo systemctl start docker
sudo docker run -p8000:8000 yuzutech/kroki
例えば以下のようなファイル(example.bf)を用意して
example.bf
(defattrs :bg-green {:fill "#a0ffa0"})
(defattrs :bg-yellow {:fill "#ffffa0"})
(defattrs :bg-pink {:fill "#ffb0a0"})
(defattrs :bg-cyan {:fill "#a0fafa"})
(defattrs :bg-purple {:fill "#e4b5f7"})
(defn draw-group-label-header
[span label]
(draw-box (text label [:math {:font-size 12}]) {:span span :borders #{} :height 14}))
(defn draw-remotedb-header
[kind args]
(draw-column-headers)
(draw-group-label-header 5 "start")
(draw-group-label-header 5 "TxID")
(draw-group-label-header 3 "type")
(draw-group-label-header 2 "args")
(draw-group-label-header 1 "tags")
(next-row 18)
(draw-box 0x11 :bg-green)
(draw-box 0x872349ae [{:span 4} :bg-green])
(draw-box 0x11 :bg-yellow)
(draw-box (text "TxID" :math) [{:span 4} :bg-yellow])
(draw-box 0x10 :bg-pink)
(draw-box (hex-text kind 4 :bold) [{:span 2} :bg-pink])
(draw-box 0x0f :bg-cyan)
(draw-box (hex-text args 2 :bold) :bg-cyan)
(draw-box 0x14 :bg-purple)
(draw-box (text "0000000c" :hex [[:plain {:font-weight "light" :font-size 16}] " (12)"]) [{:span 4} :bg-purple])
(draw-box (hex-text 6 2 :bold) [:box-first :bg-purple])
(doseq [val [6 6 3 6 6 6 6 3]]
(draw-box (hex-text val 2 :bold) [:box-related :bg-purple]))
(doseq [val [0 0]]
(draw-box val [:box-related :bg-purple]))
(draw-box 0 [:box-last :bg-purple]))
(draw-remotedb-header 0x4702 9)
(draw-box 0x11)
(draw-box 0x2104 {:span 4})
(draw-box 0x11)
(draw-box 0 {:span 4})
(draw-box 0x11)
(draw-box (text "length" [:math] [:sub 1]) {:span 4})
(draw-box 0x14)
(draw-box (text "length" [:math] [:sub 1]) {:span 4})
(draw-gap "Cue and loop point bytes")
(draw-box nil :box-below)
(draw-box 0x11)
(draw-box 0x36 {:span 4})
(draw-box 0x11)
(draw-box (text "num" [:math] [:sub "hot"]) {:span 4})
(draw-box 0x11)
(draw-box (text "num" [:math] [:sub "cue"]) {:span 4})
(draw-box 0x11)
(draw-box (text "length" [:math] [:sub 2]) {:span 4})
(draw-box 0x14)
(draw-box (text "length" [:math] [:sub 2]) {:span 4})
(draw-gap "Unknown bytes" {:min-label-columns 6})
(draw-bottom)
こんなコマンドで svgファイルが取得出来る
curl -X POST http://localhost:8000/bytefield -H "Content-Type: text/plain" -H "Accept: image/svg+xml" --data-binary "@example.bf" -o diagram.svg
/
以降の部分を変更することで例えば以下のようにplantumlも取ってこれる
curl -X POST http://localhost:8000/plantuml -H "Content-Type: text/plain" -H "Accept: image/svg+xml" --data-binary "@example.puml" -o diagram.svg
--data-binary
で指定する場合 @
+ ファイル名 となるようにする