0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

krokiが使用出来ない時に自前でbytefieldを変換する

Last updated at Posted at 2025-04-18

目的

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/ にアクセスして
画像を生成する

こんな感じ

image.png

全部入り

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 で指定する場合 @ + ファイル名 となるようにする

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?