29 releases (17 breaking)
new 0.18.0 | Feb 2, 2025 |
---|---|
0.16.0 | Dec 31, 2024 |
0.14.0 | Nov 18, 2024 |
0.10.0 | Jul 4, 2024 |
0.1.0 | Dec 25, 2023 |
#76 in Images
367 downloads per month
Used in 2 crates
610KB
10K
SLoC
svgdx - create SVG diagrams easily
svgdx is a diagrams-as-code format extending SVG, as well as a library and tools to convert this SVG superset into an SVG image.
The goal of svgdx is to allow (1) arbitrary (2) diagrams to be (3) directly written as code:
- arbitrary, rather than restricted to a set of specific use-cases
- diagrams, rather than free-form images, because some constraint is useful
- directly written, rather than requiring an image editor
Why another diagram-as-code language?
(or, why svgdx might not be for you)
There are many diagram-as-code ('DaC') languages and tools, including Graphviz, PlantUML, Mermaid, and D2.
What these have in common is they tend to be high level, automating the leap from the represented domain to a visual representation. The trade-off of being high-level is sacrificing some level of control over diagram layout. In many cases this is worthwhile, or even desirable - the language and tooling might be intended to reveal layout (e.g. traditional Graphviz applications), rather than encode it.
There are cases where a specific layout (or other aspects) is already intended. If "the medium is the message", then in diagrams structure and layout can provide clarity which an automated translation cannot always provide.
Consider a diagram scribbled on a napkin. How should that be encoded for computer use?
Option 1: Just take a photo
Option 2: Use something like Inkscape, Dia, draw.io or Visio to "draw" the diagram on a computer
Option 3: Quickly code it using svgdx!
Selected feature highlights
- Relative positioning of SVG shapes
- Template-like fragment re-use
- Variables, expressions, conditionals and loops
- Web-based editor, pandoc and mdBook plugins available
Most importantly, svgdx
is a superset of SVG, so any valid SVG is also valid as input to an svgdx processor.
This distinguishes svgdx
from many other diagrams-as-code languages, which are typically use-case driven.
These other tools are typically easier to use when 'going with the grain', but sacrifice control and flexibility.
In contrast, anything possible in SVG is (by definition) also possible in svgdx
.
One big caveat first:
This project is in active pre-v1.0 development, with known issues and frequent changes.
In particular, the input format is not stable at this point, lacking even an informal specification.
Stability and backwards compatibility will become much higher priority once the project reaches v1.0.0. Check CHANGELOG.md for more info.
and a smaller caveat:
svgdx
benefits from a basic knowledge of SVG and XML. This will help avoid surprises when everything seems to work fine until you want an ampersand in your text...
Try svgdx online
Try svgdx in the online editor at svgdx.net, where svgdx can be explored without installing anything. This repository includes a local server implementing the same editor, allowing fully offline use.
note that the svgdx.net editor is whenever a new version of svgdx is tagged, so be aware that breaking changes may affect your diagrams.
Integrations with mdBook and pandoc are supported via the plugins mdbook-svgdx and svgdx-pandoc respectively;
these both provide support for Markdown documents containing svgdx
-fenced code-blocks, which are processed and rendered as inline SVG images.
Installation
For now installation requires a working Rust toolchain, e.g. installed from rustup.rs.
Install svgdx
as follows:
cargo install svgdx
Usage
After installation, two binaries are available:
svgdx
svgdx [INPUT] [-o OUTPUT] [-w]
By default, svgdx
reads from stdin and writes to standard output, so if run without any
arguments it simply waits for input.
The -w
argument (which requires a non-stdin input file) 'watches' the input,
regenerating the output whenever it changes. This is particularly useful alongside
an SVG viewer / preview which also refreshes the view when the underlying file changes.
svgdx-server & editor
svgdx-server --open
Running svgdx-server
starts an HTTP server on localhost port 3003.
This provides an /api/transform
endpoint; when a valid svgdx document is POSTed to this (as application/xml
),
the generated svg+xml
response will be returned.
More immediately useful, the --open
argument causes a browser to open serving the same editor as running on https://svgdx.net.
There are minor differences, in that the hosted version uses WASM rather than a backend server to perform conversion in the browser,
but the entire web app (including vendored third-party libraries) is included within the svgdx-server
binary.
Example
Input
Prepare an input file (examples/simple.xml):
<svg>
<rect id="in" wh="20 10" text="input" />
<rect id="proc" xy="^|h 10" wh="^" text="process" />
<rect id="out" xy="^|h 10" wh="^" text="output" />
<line start="#in" end="#proc" class="d-arrow"/>
<line start="#proc" end="#out" class="d-arrow"/>
</svg>
Processing
Process the input with svgdx
:
$ svgdx examples/simple.svg -o examples/simple.svg
Output
Output file (examples/simple.svg):
which is a rendering of the following generated SVG:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="96mm" height="22mm" viewBox="-8 -6 96 22">
<defs>
<marker id="d-arrow" refX="1" refY="0.5" orient="auto-start-reverse" markerWidth="5" markerHeight="5" viewBox="0 0 1 1">
<path d="M 0 0 1 0.5 0 1" style="stroke-width: 0.2; stroke: context-stroke; fill: context-fill; stroke-dasharray: none;"/>
</marker>
</defs>
<style>
rect, circle, ellipse, line, polyline, polygon, path { stroke-width: 0.5; stroke: black; fill: none; }
text { font-family: sans-serif; font-size: 3px; }
text.d-text, text.d-text * { text-anchor: middle; dominant-baseline: central; }
line.d-arrow, polyline.d-arrow, path.d-arrow { marker-end: url(#d-arrow); }
</style>
<rect id="in" width="20" height="10"/>
<text x="10" y="5" class="d-text">input</text>
<rect id="proc" x="30" y="0" width="20" height="10"/>
<text x="40" y="5" class="d-text">process</text>
<rect id="out" x="60" y="0" width="20" height="10"/>
<text x="70" y="5" class="d-text">output</text>
<line x1="20" y1="5" x2="30" y2="5" class="d-arrow"/>
<line x1="50" y1="5" x2="60" y2="5" class="d-arrow"/>
</svg>
This example shows just a few of svgdx
's features:
- shortcut attributes, e.g. the use of
wh
rather than having to specifywidth
andheight
separately. - relative positioning, either by reference to an id (e.g.
#in
), or to the previous element using the caret (^
) symbol. - new attributes providing additional functionality -
text
within shapes, orstart
andend
points on<line>
elements to define connectors. - automatic calculation of root
<svg>
elementwidth
,height
andviewBox
derived from the bounding box of all elements. - automatic styles added to provide sensible defaults for 'box and line' diagrams.
Many more features are provided by svgdx, with the goal of making a diagram something you can write, rather than draw.
See more examples
Background
An important principle is that raw SVG can be included directly at any point in the input. This is analogous to Markdown, which provides the 'escape hatch' of using inline HTML tags (used in this very README!). Markdown has been incredibly successful as a text based format allowing simple text files to carry both semantic and simple style information. Being able to do both of those in a single workflow - just by typing - allows a flow which would otherwise not be achievable.
Can the same be done for drawing - specifically for diagrams? That's what svgdx aims to deliver.
Text files provide a number of advantages over other document formats:
- Clear compatibility with version control - meaningful diffs
- Self-describing - text files are easy to (at least approximately) reverse engineer even in the absence of a clear spec or other tools
- Application independence - additional tools can be written to deal with the format
- Easy editing - at least for simple changes
Why 'svgdx'?
Project naming is hard.
I could write about how this tool is provides a set of svg diagram extensions. But primarily and originally, the dx
in svgdx
is intended to refer to a delta of SVG.
This is explicitly an SVG tool, not some generic diagamming tool. It is most useful when combined with some experience of SVG. While the SVG standards progress slowly, this tool allows keeping everything good from SVG and adding just that little bit more.
Dependencies
~3–16MB
~215K SLoC