d2
svugy reads d2 v0.9.0 so existing d2 files render without a rewrite.
svugy render my.d2renders the file as it is;svugy import my.d2 -o my.mdconverts it to Markdown.- d2 input gets no features beyond this page: what d2 can’t say, write in Markdown.
The editor holds the Quickstart’s web app written in d2; the SVG re-renders as you type.
What maps
| d2 | svugy |
|---|---|
a: { b } | b nested in a |
a -> b: text, a -> b -> c | a labelled edge; one edge per hop |
a <- b | an edge from b to a |
_.x | x in the parent scope |
link | link |
tooltip on a shape or an edge | its description, stored as Markdown |
style.fill, style.stroke, style.stroke-dash | fill, stroke, dash |
shape: rectangle, shape: square | a box |
shape: cylinder | a cylinder |
shape: circle, shape: oval | a disc |
direction: right | the layered layout, already the default |
the root’s label | the title, drawn top-left; d2 itself never draws it |
- Keys match case-insensitively, repeated keys merge with the last write winning, and an edge to an undeclared name declares it, as in d2.
- d2’s 17 other style keys (
opacity,font-size,shadow, …) are accepted and not drawn. A misspelt style key is a warning.
Ignored, with a warning
- variables other than
vars.svugy,${…}substitutions, imports (@…),class,classes,layers,scenarios,steps - globs and filters (
*,&,!&), edge references ((a -> b)[0]), block strings (|md … |), arrays outside the carrier,nulldeletions icon,constraint,near,width,height,top,left,grid-rows,grid-columns,grid-gap,vertical-gap,horizontal-gap,source-arrowhead,target-arrowhead- sub-keyed fields such as
label.nearora.vars.svugy.caption - shapes other than those above;
sql_table,sequence_diagram,classandhierarchyincluded directionother thanright, since svugy’s layered layout ranks along one axis- the arrowheads of
<->and--: the edge is kept, drawn from left operand to right shape,directionandlinkon an edge; declarations inside an edge’s map- fields on the root other than
label,directionandvars
The vars: { svugy: { … } } carrier
d2 has no syntax for what svugy draws beyond 2D boxes, and vars is the only map d2 accepts extra keys in: an unknown style.* key is a d2 compile error, and a dotted name like iso.depth declares child shapes.
On a shape:
| Key | Value | Why not plain d2 |
|---|---|---|
caption | text | d2 has no caption |
shape | box, slab, cylinder, disc, any case | d2 has no slab or explicit box; overrides d2’s shape |
height | number, plan units | d2’s height is a 2D size in pixels, and is ignored |
position: { x; y } | numbers, negative allowed | d2’s top and left take non-negative integers, and only the TALA layout reads them |
badge | true or false | d2 has no badges; true badges every edge into this leaf from a leaf |
On the root:
| Key | Value |
|---|---|
subtitle | text |
legend.title | text |
legend.entries | list of lines: ["① …"; "② …"] |
legend.dashes | map of stroke-dash value to description: { 5: data; 2: build time } |
legend.badges | map of a badge target’s path to description: { data.cache: looks up the cache } |
- Any other key in the carrier is an error, with its location; d2 itself drops
varsunread, so it never catches a typo there. positionneedsxandyin onevarsmap, although d2 mergesvarsacross statements.- d2’s own
vars.d2-legenddraws sample shapes, not text: it is ignored like any other variable. - A
varsmap on an edge is an error, even one withoutsvugy, as d2 rejects it (“does not accept composite”).
What d2 can’t say
| Feature | In d2 | In Markdown |
|---|---|---|
| travelers | impossible: an edge can’t hold vars | traveler= |
| one badge per edge | badge: true badges every edge into the leaf; on a container it is ignored with a warning | line=badge on each edge |
grid, row, column layouts | grid-rows, grid-columns are ignored | layout, columns |
| detail panel lines | no place for them | meta.NAME |
| shared styles | classes are ignored, so each shape repeats its style.fill | frontmatter styles |
Import to Markdown
svugy import my.d2 -o my.md
- The model keeps no named styles, so every property is written out and fills repeat as in d2. Factor them into frontmatter
stylesby hand. - If any part can’t be written as Markdown, import lists every such part, writes nothing and exits
1. Examples:- a key that isn’t a Markdown ID, e.g. one holding a space or a dot
- a
stroke-dashother than0(line=solid),5(line=dashed) or2(line=dotted) - any style key other than
fill,strokeandstroke-dash - a label with a line break or leading or trailing whitespace
Next: Rust