Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add symbolator #1566

Merged
merged 11 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ jobs:
- name: Install GraphViz
run: sudo apt-get install graphviz -y

- name: Install Symbolator
run: |
wget https://github.com/zebreus/symbolator/releases/download/v1.2.2/symbolator.AppImage
chmod +x symbolator.AppImage
mv symbolator.AppImage /usr/local/bin/symbolator

ggrossetie marked this conversation as resolved.
Show resolved Hide resolved
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
Expand Down
2 changes: 1 addition & 1 deletion DOCKERHUB.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Convert plain text diagrams to images !

Kroki provides a unified API with support for BlockDiag (BlockDiag, SeqDiag, ActDiag, NwDiag, PacketDiag, RackDiag), BPMN, Bytefield, C4 (with PlantUML), D2, DBML, Ditaa, Erd, Excalidraw, GraphViz, Mermaid, Nomnoml, Pikchr, PlantUML, SvgBob, UMLet, Vega, Vega-Lite, WaveDrom... and more to come!
Kroki provides a unified API with support for BlockDiag (BlockDiag, SeqDiag, ActDiag, NwDiag, PacketDiag, RackDiag), BPMN, Bytefield, C4 (with PlantUML), D2, DBML, Ditaa, Erd, Excalidraw, GraphViz, Mermaid, Nomnoml, Pikchr, PlantUML, SvgBob, Symbolator, UMLet, Vega, Vega-Lite, WaveDrom... and more to come!

## Getting Started

Expand Down
2 changes: 1 addition & 1 deletion README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ image:https://github.com/yuzutech/kroki/workflows/CI/badge.svg?branch=master[Git
image:https://img.shields.io/badge/zulip-join_chat-brightgreen.svg[Zulip chat, link=https://kroki.zulipchat.com/]
endif::[]

{uri-kroki}[Kroki] provides a unified API with support for BlockDiag (BlockDiag, SeqDiag, ActDiag, NwDiag, PacketDiag, RackDiag), BPMN, Bytefield, C4 (with PlantUML), D2, DBML, Diagrams.net (experimental), Ditaa, Erd, Excalidraw, GraphViz, Mermaid, Nomnoml, Pikchr, PlantUML, SvgBob, UMLet, Vega, Vega-Lite, WaveDrom and WireViz... and more to come!
{uri-kroki}[Kroki] provides a unified API with support for BlockDiag (BlockDiag, SeqDiag, ActDiag, NwDiag, PacketDiag, RackDiag), BPMN, Bytefield, C4 (with PlantUML), D2, DBML, Diagrams.net (experimental), Ditaa, Erd, Excalidraw, GraphViz, Mermaid, Nomnoml, Pikchr, PlantUML, SvgBob, Symbolator, UMLet, Vega, Vega-Lite, WaveDrom and WireViz... and more to come!

== Quickstart

Expand Down
22 changes: 22 additions & 0 deletions blockdiag/examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,28 @@ def sample(service, source):

sample('ditaa', ditaa)

# Symbolator
section('Symbolator')
symbolator = """
module demo_device #(
//# {{}}
parameter SIZE = 8,
parameter RESET_ACTIVE_LEVEL = 1
) (
//# {{clocks|Clocking}}
input wire clock,
//# {{control|Control signals}}
input wire reset,
input wire enable,
//# {{data|Data ports}}
input wire [SIZE-1:0] data_in,
output wire [SIZE-1:0] data_out
);
// ...
endmodule
"""

sample('symbolator', symbolator)

section('C4 PlantUML')
context_bigbank = """
Expand Down
35 changes: 29 additions & 6 deletions ci/tasks/update-versions.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,18 @@ const require = createRequire(import.meta.url)
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
const rootDir = ospath.join(__dirname, '..', '..')
const krokiServicePath = ospath.join(rootDir, 'server', 'src', 'main', 'java', 'io', 'kroki', 'server', 'service')
const githubActionsPath = ospath.join(rootDir, '.github', 'workflows')
ggrossetie marked this conversation as resolved.
Show resolved Hide resolved

const diagramLibraryVersions = {}

function getDependencyVersion (pkg, name) {
function getDependencyVersion(pkg, name) {
if (name in pkg.dependencies) {
return pkg.dependencies[name]
}
return pkg.devDependencies[name]
}

async function updateServiceGetVersion (javaServiceFileName, version) {
async function updateServiceGetVersion(javaServiceFileName, version) {
ggrossetie marked this conversation as resolved.
Show resolved Hide resolved
const servicePath = ospath.join(krokiServicePath, javaServiceFileName)
const javaContent = await fs.readFile(servicePath, 'utf8')
const versionFound = javaContent.match(/(?<= +public String getVersion\(\) {\n\s+return ")(?<version>[0-9.]+)(?=";\n\s+})/)
Expand All @@ -34,7 +35,20 @@ async function updateServiceGetVersion (javaServiceFileName, version) {
}
}

async function updateVegaServiceGetVersion (vegaVersion, vegaLiteVersion) {
async function updateSymbolatorAppImageVersion(githubActionFileName, version) {
const actionPath = ospath.join(githubActionsPath, githubActionFileName)
const githubActionContent = await fs.readFile(actionPath, 'utf8')
const versionFound = githubActionContent.match(/(?<=symbolator\/releases\/download\/v)(?<version>[0-9.]+)(?=\/symbolator\.AppImage)/)
if (versionFound) {
const currentVersion = versionFound.groups.version
if (currentVersion !== version) {
const updatedGithubActionContent = githubActionContent.replace(/(?<=symbolator\/releases\/download\/v)(?<version>[0-9.]+)(?=\/symbolator\.AppImage)/, version)
await fs.writeFile(actionPath, updatedGithubActionContent, 'utf8')
}
}
}

ggrossetie marked this conversation as resolved.
Show resolved Hide resolved
async function updateVegaServiceGetVersion(vegaVersion, vegaLiteVersion) {
// update vega version
const servicePath = ospath.join(krokiServicePath, 'Vega.java')
let javaContent = await fs.readFile(servicePath, 'utf8')
Expand All @@ -56,7 +70,7 @@ async function updateVegaServiceGetVersion (vegaVersion, vegaLiteVersion) {
await fs.writeFile(servicePath, javaContent, 'utf8')
}

async function mvnEvaluateExpression (expression, pomRootRelativePath) {
async function mvnEvaluateExpression(expression, pomRootRelativePath) {
if (pomRootRelativePath === undefined) {
pomRootRelativePath = ospath.join('server', 'pom.xml')
}
Expand All @@ -83,7 +97,7 @@ async function mvnEvaluateExpression (expression, pomRootRelativePath) {
})
}

function addDiagramLibraryPackageVersion (diagramName, dependencyName, directoryName) {
function addDiagramLibraryPackageVersion(diagramName, dependencyName, directoryName) {
if (directoryName === undefined) {
directoryName = diagramName
}
Expand Down Expand Up @@ -118,6 +132,7 @@ const diagramLibraryNames = [
'seqdiag',
'structurizr',
'svgbob',
'symbolator',
'umlet',
'vega',
'vegalite',
Expand Down Expand Up @@ -187,6 +202,12 @@ try {
const { version } = pikchrVersionFound.groups
diagramLibraryVersions.pikchr = version.slice(0, 10)
}

const symbolatorVersionFound = line.match(/^ARG SYMBOLATOR_VERSION=(?<version>.+)$/)
if (symbolatorVersionFound) {
const { version } = symbolatorVersionFound.groups
diagramLibraryVersions.symbolator = version
}
const umletVersionFound = line.match(/^ARG UMLET_VERSION="(?<version>.+)"$/)
if (umletVersionFound) {
const { version } = umletVersionFound.groups
Expand Down Expand Up @@ -234,7 +255,7 @@ try {
for (let line of antoraComponentContent.split('\n')) {
const found = line.match(/^\s+(?<name>[a-z0-9]+)-version: '?(?<version>[^']+)'?$/)
if (found) {
const { name, version : versionFound } = found.groups
const { name, version: versionFound } = found.groups
const version = diagramLibraryVersions[name]
if (versionFound !== version) {
line = line.replace(/(?<=^\s+(?<name>[a-z0-9]+)-version: '?)(?<version>[^']+)/, version)
Expand All @@ -258,10 +279,12 @@ try {
await updateServiceGetVersion('Plantuml.java', diagramLibraryVersions.plantuml)
await updateServiceGetVersion('Structurizr.java', diagramLibraryVersions.structurizr)
await updateServiceGetVersion('Svgbob.java', diagramLibraryVersions.svgbob)
await updateServiceGetVersion('Symbolator.java', diagramLibraryVersions.symbolator)
await updateServiceGetVersion('Umlet.java', diagramLibraryVersions.umlet)
await updateServiceGetVersion('Wavedrom.java', diagramLibraryVersions.wavedrom)
await updateServiceGetVersion('Wireviz.java', diagramLibraryVersions.wireviz)
await updateVegaServiceGetVersion(diagramLibraryVersions.vega, diagramLibraryVersions.vegalite)
await updateSymbolatorAppImageVersion("main.yaml", diagramLibraryVersions.symbolator)
ggrossetie marked this conversation as resolved.
Show resolved Hide resolved

} catch (err) {
console.error(err)
Expand Down
16 changes: 16 additions & 0 deletions ci/tests/diagrams/component.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module demo_device #(
//# {{}}
parameter SIZE = 8,
parameter RESET_ACTIVE_LEVEL = 1
) (
//# {{clocks|Clocking}}
input wire clock,
//# {{control|Control signals}}
input wire reset,
input wire enable,
//# {{data|Data ports}}
input wire [SIZE-1:0] data_in,
output wire [SIZE-1:0] data_out
);
// ...
endmodule
111 changes: 56 additions & 55 deletions ci/tests/smoke.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,42 @@ import * as url from 'url'
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))

const tests = [
{engine: 'graphviz', file: 'hello.dot', options: {}, outputFormat: ['svg', 'jpeg']},
{engine: 'dot', file: 'hello.dot', options: {}, outputFormat: ['svg', 'jpeg']},
{engine: 'blockdiag', file: 'kroki.diag', options: {}, outputFormat: ['svg', 'png']},
{engine: 'seqdiag', file: 'sequence.diag', options: {}, outputFormat: ['svg', 'png']},
{engine: 'actdiag', file: 'actions.diag', options: {}, outputFormat: ['svg', 'png']},
{engine: 'nwdiag', file: 'network.diag', options: {}, outputFormat: ['svg', 'png']},
{engine: 'c4plantuml', file: 'banking-system.puml', options: {}, outputFormat: ['svg', 'pdf', 'png', 'txt']},
{engine: 'dbml', file: 'dbml.dbml', options: {}, outputFormat: ['svg']},
{engine: 'ditaa', file: 'components.ditaa', options: {}, outputFormat: ['svg']},
{engine: 'erd', file: 'schema.erd', options: {}, outputFormat: ['svg']},
{engine: 'mermaid', file: 'contribute.mmd', options: {}, outputFormat: ['svg']},
{engine: 'bpmn', file: 'example.bpmn', options: {}, outputFormat: ['svg']},
{engine: 'plantuml', file: 'architecture.puml', options: {}, outputFormat: ['svg', 'pdf', 'png', 'txt']},
{engine: 'svgbob', file: 'cloud.bob', options: {}, outputFormat: ['svg']},
{engine: 'nomnoml', file: 'pirate.nomnoml', options: {}, outputFormat: ['svg']},
{engine: 'packetdiag', file: 'packet.diag', options: {}, outputFormat: ['svg', 'png']},
{engine: 'rackdiag', file: 'rack.diag', options: {}, outputFormat: ['svg', 'png']},
{engine: 'vega', file: 'bar-chart.vega', options: {}, outputFormat: ['svg', 'png', 'pdf']},
{engine: 'vegalite', file: 'discretizing-scale.vlite', options: {}, outputFormat: ['svg', 'png', 'pdf']},
{engine: 'wavedrom', file: 'wavedrom.json5', options: {}, outputFormat: ['svg']},
{engine: 'wavedrom', file: 'bitfield.json5', options: {}, outputFormat: ['svg']},
{engine: 'bytefield', file: 'bytefield.bf', options: {}, outputFormat: ['svg']},
{engine: 'umlet', file: 'umlet.xml', options: {}, outputFormat: ['svg']},
{engine: 'excalidraw', file: 'venn.excalidraw', options: {}, outputFormat: ['svg']},
{engine: 'pikchr', file: 'sqlite-architecture.pikchr', options: {}, outputFormat: ['svg']},
{engine: 'structurizr', file: 'gettingstarted.structurizr', options: {}, outputFormat: ['svg']},
{engine: 'diagramsnet', file: 'diagramsnet-infography.xml', options: {}, outputFormat: ['svg', 'png']},
{engine: 'diagramsnet', file: 'diagramsnet-mindmap.xml', options: {}, outputFormat: ['svg', 'png']},
{engine: 'diagramsnet', file: 'diagramsnet-network.xml', options: {}, outputFormat: ['svg', 'png']},
{engine: 'diagramsnet', file: 'diagramsnet-ui.xml', options: {}, outputFormat: ['svg', 'png']},
{engine: 'diagramsnet', file: 'diagramsnet-venn.xml', options: {}, outputFormat: ['svg', 'png']},
{engine: 'd2', file: 'connections.d2', options: {}, outputFormat: ['svg']},
{engine: 'd2', file: 'connections.d2', options: {sketch: 'true'}, outputFormat: ['svg']},
{engine: 'wireviz', file: 'wireviz.yaml', options: {}, outputFormat: ['svg', 'png']},
{engine: 'tikz', file: 'periodic-table.tex', options: {}, outputFormat: ['jpeg', 'pdf', 'png', 'svg']}
{ engine: 'graphviz', file: 'hello.dot', options: {}, outputFormat: ['svg', 'jpeg'] },
{ engine: 'dot', file: 'hello.dot', options: {}, outputFormat: ['svg', 'jpeg'] },
{ engine: 'blockdiag', file: 'kroki.diag', options: {}, outputFormat: ['svg', 'png'] },
{ engine: 'seqdiag', file: 'sequence.diag', options: {}, outputFormat: ['svg', 'png'] },
{ engine: 'actdiag', file: 'actions.diag', options: {}, outputFormat: ['svg', 'png'] },
{ engine: 'nwdiag', file: 'network.diag', options: {}, outputFormat: ['svg', 'png'] },
{ engine: 'c4plantuml', file: 'banking-system.puml', options: {}, outputFormat: ['svg', 'pdf', 'png', 'txt'] },
{ engine: 'dbml', file: 'dbml.dbml', options: {}, outputFormat: ['svg'] },
{ engine: 'ditaa', file: 'components.ditaa', options: {}, outputFormat: ['svg'] },
{ engine: 'symbolator', file: 'component.sv', options: {}, outputFormat: ['svg', 'png'] },
{ engine: 'erd', file: 'schema.erd', options: {}, outputFormat: ['svg'] },
{ engine: 'mermaid', file: 'contribute.mmd', options: {}, outputFormat: ['svg'] },
{ engine: 'bpmn', file: 'example.bpmn', options: {}, outputFormat: ['svg'] },
{ engine: 'plantuml', file: 'architecture.puml', options: {}, outputFormat: ['svg', 'pdf', 'png', 'txt'] },
{ engine: 'svgbob', file: 'cloud.bob', options: {}, outputFormat: ['svg'] },
{ engine: 'nomnoml', file: 'pirate.nomnoml', options: {}, outputFormat: ['svg'] },
{ engine: 'packetdiag', file: 'packet.diag', options: {}, outputFormat: ['svg', 'png'] },
{ engine: 'rackdiag', file: 'rack.diag', options: {}, outputFormat: ['svg', 'png'] },
{ engine: 'vega', file: 'bar-chart.vega', options: {}, outputFormat: ['svg', 'png', 'pdf'] },
{ engine: 'vegalite', file: 'discretizing-scale.vlite', options: {}, outputFormat: ['svg', 'png', 'pdf'] },
{ engine: 'wavedrom', file: 'wavedrom.json5', options: {}, outputFormat: ['svg'] },
{ engine: 'wavedrom', file: 'bitfield.json5', options: {}, outputFormat: ['svg'] },
{ engine: 'bytefield', file: 'bytefield.bf', options: {}, outputFormat: ['svg'] },
{ engine: 'umlet', file: 'umlet.xml', options: {}, outputFormat: ['svg'] },
{ engine: 'excalidraw', file: 'venn.excalidraw', options: {}, outputFormat: ['svg'] },
{ engine: 'pikchr', file: 'sqlite-architecture.pikchr', options: {}, outputFormat: ['svg'] },
{ engine: 'structurizr', file: 'gettingstarted.structurizr', options: {}, outputFormat: ['svg'] },
{ engine: 'diagramsnet', file: 'diagramsnet-infography.xml', options: {}, outputFormat: ['svg', 'png'] },
{ engine: 'diagramsnet', file: 'diagramsnet-mindmap.xml', options: {}, outputFormat: ['svg', 'png'] },
{ engine: 'diagramsnet', file: 'diagramsnet-network.xml', options: {}, outputFormat: ['svg', 'png'] },
{ engine: 'diagramsnet', file: 'diagramsnet-ui.xml', options: {}, outputFormat: ['svg', 'png'] },
{ engine: 'diagramsnet', file: 'diagramsnet-venn.xml', options: {}, outputFormat: ['svg', 'png'] },
{ engine: 'd2', file: 'connections.d2', options: {}, outputFormat: ['svg'] },
{ engine: 'd2', file: 'connections.d2', options: { sketch: 'true' }, outputFormat: ['svg'] },
{ engine: 'wireviz', file: 'wireviz.yaml', options: {}, outputFormat: ['svg', 'png'] },
{ engine: 'tikz', file: 'periodic-table.tex', options: {}, outputFormat: ['jpeg', 'pdf', 'png', 'svg'] }
]

chai.use(chaiHttp)
Expand Down Expand Up @@ -95,7 +96,7 @@ describe('Diagrams', function () {
describe('PlantUML native image', function () {
this.timeout(15000)
it('plantuml (native image) should convert class diagram (issue#1546)', async () => {
const testCase = {engine: 'plantuml', file: 'class.puml'}
const testCase = { engine: 'plantuml', file: 'class.puml' }
const response = await sendRequest(testCase, 'svg')
try {
expect(response.status).to.equal(200)
Expand All @@ -109,7 +110,7 @@ describe('PlantUML native image', function () {
describe('CJK font', function () {
this.timeout(15000)
it('plantuml should compute correct text length (issue#574)', async () => {
const testCase = {engine: 'plantuml', file: 'chinese.puml'}
const testCase = { engine: 'plantuml', file: 'chinese.puml' }
const response = await sendRequest(testCase, 'svg')
try {
expect(response.body.toString('utf8')).to.include('textLength="56"')
Expand All @@ -119,7 +120,7 @@ describe('CJK font', function () {
}
})
it('mermaid should compute correct text length (issue#1167)', async () => {
const testCase = {engine: 'mermaid', file: 'japanese.mermaid'}
const testCase = { engine: 'mermaid', file: 'japanese.mermaid' }
const response = await sendRequest(testCase, 'svg')
try {
const data = response.body.toString('utf8')
Expand All @@ -137,23 +138,23 @@ describe('CJK font', function () {

describe('Health', function () {
this.timeout(15000)
;['/health', '/healthz', '/v1/health'].forEach((endpoint) => {
it(`should return health status from ${endpoint}`, async () => {
const response = await chai.request('localhost:8000')
.get(endpoint)
.set('Accept', 'application/health+json')
.send()
;['/health', '/healthz', '/v1/health'].forEach((endpoint) => {
it(`should return health status from ${endpoint}`, async () => {
const response = await chai.request('localhost:8000')
.get(endpoint)
.set('Accept', 'application/health+json')
.send()

try {
expect(response.status).to.equal(200)
expect(response.body.status).to.equal('pass')
const engines = Array.from(new Set(tests.map((it) => it.engine)))
engines.push('kroki')
expect(response.body.version).to.have.keys(engines)
} catch (err) {
console.log('response:', response.text)
throw err
}
try {
expect(response.status).to.equal(200)
expect(response.body.status).to.equal('pass')
const engines = Array.from(new Set(tests.map((it) => it.engine)))
engines.push('kroki')
expect(response.body.version).to.have.keys(engines)
} catch (err) {
console.log('response:', response.text)
throw err
}
})
})
})
})
1 change: 1 addition & 0 deletions docs/antora.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ asciidoc:
seqdiag-version: 3.0.0
structurizr-version: 1.30.1
svgbob-version: 0.7.0
symbolator-version: 1.2.2
umlet-version: 15.1
vega-version: 5.24.0
vegalite-version: 5.7.0
Expand Down
4 changes: 4 additions & 0 deletions docs/modules/ROOT/pages/architecture.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ The `yuzutech/kroki` Docker image contains the following diagrams libraries out-
|{svgbob-version}
//|Binary `/rust/bin/svgbob`

|https://hdl.github.io/symbolator/[Symbolator]
|{symbolator-version}
//|Binary `/usr/bin/symbolator`

|https://github.com/umlet/umlet[UMlet]
|{umlet-version}
//|Java library
Expand Down
1 change: 1 addition & 0 deletions docs/modules/ROOT/pages/diagram-types.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Diagram::
* Digital Timing diagram (waveform)
* BPMN diagram
* Bytefield diagram
* HDL Component diagram
* Excalidraw
* https://www.diagrams.net/[diagrams.net] (experimental)
* WireViz
Expand Down
4 changes: 2 additions & 2 deletions docs/modules/ROOT/pages/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
=== Convert plain text diagrams to images !

Kroki provides a unified HTTP API with support for BlockDiag (BlockDiag, SeqDiag, ActDiag, NwDiag, PacketDiag, RackDiag),
BPMN, Bytefield, C4 (with PlantUML), Diagrams.net (experimental), Ditaa, Erd, Excalidraw, GraphViz, Mermaid, Nomnoml, PlantUML, Structurizr, SvgBob, UMLet,
Vega, Vega-Lite, WaveDrom and WireViz... and more to come!
BPMN, Bytefield, C4 (with PlantUML), Diagrams.net (experimental), Ditaa, Erd, Excalidraw, GraphViz, Mermaid, Nomnoml, PlantUML, Structurizr, SvgBob,
Symbolator, UMLet, Vega, Vega-Lite, WaveDrom and WireViz... and more to come!

Kroki is available as a Self-Managed instance. +
We are also _actively_ looking for sponsors to provide Kroki as a free service:
Expand Down
1 change: 1 addition & 0 deletions docs/modules/setup/pages/configuration.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ you can override its location manually using an environment variable or a Java s
`KROKI_PIKCHR_BIN_PATH`:: Path to `pikchr` binary (defaults: `/usr/bin/pikchr`)
`KROKI_PLANTUML_BIN_PATH`:: Path to `plantuml` binary (defaults: `/usr/bin/plantuml`)
`KROKI_SVGBOB_BIN_PATH`:: Path to `svgbob` binary (defaults: `/usr/bin/svgbob`)
`KROKI_SYMBOLATOR_BIN_PATH`:: Path to `symbolator` binary (defaults: `/usr/bin/symbolator`)
`KROKI_TIKZ2SVG_BIN_PATH`:: Path to `tikz2svg` binary (defaults: `/usr/bin/tikz2svg`)
`KROKI_UMLET_BIN_PATH`:: Path to `umlet` binary (defaults: `/usr/bin/umlet`)
`KROKI_VEGA_BIN_PATH`:: Path to `vega` binary which supports both Vega and Vega-Lite grammar (defaults: `/usr/bin/bytefield`)
Expand Down
Loading