reladraw 0.24.0 → 0.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,7 +15,7 @@ That matters here specifically. You can't see the SVG you produced. With auto-la
15
15
 
16
16
  ## Check it is installed, and the same version as this skill
17
17
 
18
- This skill teaches reladraw 0.24.0. Once per session, before the first render, run:
18
+ This skill teaches reladraw 0.25.1. Once per session, before the first render, run:
19
19
 
20
20
  ```
21
21
  reladraw --version
@@ -86,7 +86,7 @@ even with X top even with X bottom even with X left even with X right ev
86
86
  - **A gap is exact**: `none`, `tight`, `normal` (the default) or `wide`, in the placement's bracket, `right of a (gap: tight)`, or a number of the file's unit in front, `2 right of a`. A normal box is about 4 units tall.
87
87
  - **A lone direction also centers on its target.** `right of a` alone puts the box level with `a`. Another placement on that axis replaces the centering: `right of a even with b`.
88
88
  - **Each axis is stated once.** Two placements on one axis are refused. The one exception: `right of a left of b` centers the box in the space between them, and then something must say how high.
89
- - **Several targets are one region**: `below a and b` sits under the pair, centered between them.
89
+ - **Several targets are one region**: `below a and b` sits under the pair, centered between them. A distance and a direction after `and` start a second placement instead: `right of a and 2 above c top` is two placements. To use a point as a target, name it first with `point p 2 above c top-center`.
90
90
  - **Nothing moves a box.** Two boxes placed `right of a` both land on one spot and are reported. Chain them (`b right of a`, `c right of b`) or put them in a container with a layout.
91
91
 
92
92
  ### Containers
@@ -117,7 +117,7 @@ node grinder "Grinder / [dim]medium-fine[/dim]"
117
117
  node note "a longer remark that folds" (size: small, wrap: 30) shape: none below grinder (gap: tight)
118
118
  ```
119
119
 
120
- `[dim]…[/dim]` borrows a style's look for a stretch of text. A style hangs the bracket off a key: `style aside text: (size: small, color: theme-muted)`. **Always give bare text a `(wrap: n)`**, or a sentence is one long line across whatever is beside it.
120
+ `[dim]…[/dim]` borrows a style's text color and size for a stretch of text; a line that is all small is spaced as a small line. A style hangs the bracket off a key: `style aside text: (size: small, color: theme-muted)`. **Always give bare text a `(wrap: n)`**, or a sentence is one long line across whatever is beside it.
121
121
 
122
122
  ### Lines
123
123
 
@@ -170,7 +170,30 @@ node api_link "github.com/acme/api" shape: none right of api
170
170
  node api "API server" url: "https://github.com/acme/api"
171
171
  ```
172
172
 
173
- The address is never drawn; a reader follows it by clicking. A line with no text can't carry one, and neither can a style. Quote the value, since an unquoted `//` starts a comment.
173
+ The address is never drawn; a reader follows it by clicking. A line with no text can carry one too, but a style can't. Quote the value, since an unquoted `//` starts a comment.
174
+
175
+ When addresses are long, or one is used on several things, declare each once with its name and badge and use it by name, so the statements stay readable. A declaration can also list several links for things that share them:
176
+
177
+ ```
178
+ url orders-docs "https://docs.example.com/orders/v2/reference" (name: "Docs")
179
+ url orders-code "https://github.com/example/orders/tree/main/services/api" (name: "Code")
180
+ url orders-links orders-docs orders-code
181
+
182
+ node api "Orders API" url: orders-links
183
+ node worker "Worker" url: orders-docs
184
+ ```
185
+
186
+ ### Descriptions
187
+
188
+ ```
189
+ node proxy "Proxy" description: "Forwards each request by its path."
190
+
191
+ description for orders and to-orders """
192
+ Owns the order records. See [the docs](https://example.com/orders).
193
+ """
194
+ ```
195
+
196
+ **Notes about a thing go in its description, not in a box beside it.** A description is shown when the thing is selected on the `--page` page, and as hover text in an SVG; it is never drawn, so it can run to paragraphs and lists in Markdown. Write a short one on the statement, and a long one with `description for`, after the diagram's statements, so it doesn't crowd them. When several things share one text, name them all after `for`.
174
197
 
175
198
  **Offer links; don't add them unasked.** When the things in a diagram have real web addresses, such as the files of a pull request on GitHub, end your reply with one line offering to link each node to its file. Never guess an address, and don't link to files on the local machine.
176
199
 
@@ -1,4 +1,4 @@
1
- # Syntax reference — 0.24.0
1
+ # Syntax reference — 0.25.1
2
2
 
3
3
  What the language accepts. The changelog at the end lists what changed in each published version; 0.17.0's changes are large, and its entry has a table of every old spelling and what to write instead.
4
4
 
@@ -38,6 +38,7 @@ An indented line with nothing to continue, at the top of the file or after a bla
38
38
  | `default` | appearance every thing of one kind wears ([Defaults](#defaults)) |
39
39
  | `diagram` | settings for the whole drawing ([The diagram](#the-diagram)) |
40
40
  | `icon` | a picture of your own ([Your own icons](#your-own-icons)) |
41
+ | `description` | text about a box or a line, for the page's panel ([Descriptions](#descriptions)) |
41
42
 
42
43
  `box`, `link`, `note`, `deck`, `rect` and `arrow` at the start of a statement are refused by name, each quoting what to write instead.
43
44
 
@@ -71,7 +72,7 @@ A text is quoted. ` / `, a slash with whitespace on both sides, breaks the line,
71
72
 
72
73
  A node with no text shows its name, and a dotted name shows only its last part: `node server.docker` reads "docker". The name is never prettified. `""` says a node deliberately has none. A node drawn as a picture shows no text unless one is written.
73
74
 
74
- A `"""` string takes everything between its marks as written, quotes and line breaks included. It is accepted only for an icon's SVG.
75
+ A `"""` string takes everything between its marks as written, quotes and line breaks included. It is accepted only for an icon's SVG and a description's text ([Descriptions](#descriptions)).
75
76
 
76
77
  ### Numbers and the file's unit
77
78
 
@@ -258,7 +259,7 @@ node notes "notes" below resolver (gap: tight) shape: none
258
259
 
259
260
  ### Several targets at once
260
261
 
261
- A placement may name several targets, joined by `and` or commas: `right of a, b and c`. It places against the box bounding them all, a region nobody had to declare. A lone direction centers on that region, which is how one row is offset against another:
262
+ A placement may name several targets, joined by `and` or commas: `right of a, b and c`. It places against the box bounding them all, a region nobody had to declare. A distance and a direction after the `and` or comma start another placement instead: `right of a and 2 above c top` is `right of a 2 above c top`. To place against a point and a box together, name the point first: `point p 2 above c top-center`, then `right of a and p`. A lone direction centers on that region, which is how one row is offset against another:
262
263
 
263
264
  ```
264
265
  node a icon: cube
@@ -291,7 +292,7 @@ A fraction of the way across a box is written fraction first: `top even with 3/4
291
292
 
292
293
  `center 12 right of a center` puts the two centers exactly 12 apart, the even steps of a timeline whose boxes differ in width. `top 3 below a bottom` is the same for edges. The direction means what it always means, so with nothing else said the box also sits level with `a`'s center. A placement naming parts must give its distance: `center right of a center` is refused ("say how far").
293
294
 
294
- Two distances, one per axis, are accepted in any placement: `3 below and 2 right of a`, or `top-left 3 below and 2 right of a bottom-right`.
295
+ Two distances, one per axis, are accepted in any placement: `3 below and 2 right of a`, or `top-left 3 below and 2 right of a bottom-right`. A `left` or `right` that comes first may keep its `of`: `2 right of and 3 below a` is `2 right and 3 below a`.
295
296
 
296
297
  **How far along the side it faces.** `right of server 3/4 down` puts the box the usual gap right of `server`, its middle level with a spot three quarters of the way down `server`'s right side. `down` and `up` run along a left or right side, `across` along a top or bottom one. A word that doesn't run along the side the direction faces is refused, listing the words that do.
297
298
 
@@ -684,14 +685,16 @@ node rack.b "web-2"
684
685
 
685
686
  ### Markup
686
687
 
687
- A stretch of text can borrow a style's look:
688
+ A stretch of text can borrow a style's text color and size:
688
689
 
689
690
  ```
690
- style dim text: (color: theme-muted)
691
+ style dim text: (color: theme-muted, size: small)
691
692
  node files "shared folder / [dim]synced[/dim]"
692
693
  ```
693
694
 
694
- The opener names a style, never a color, so the marked words borrow a meaning the file already has. A name no style answers to is refused, and so is a style that says nothing about text. The closer repeats the name, so a mismatched close is refused by name. Marks don't nest, and a mark may cross a line break. A bare `[` is an error; write `\[` for a literal one.
695
+ The opener names a style, never a color, so the marked words borrow a meaning the file already has. A name no style answers to is refused, and so is a style that gives text neither a color nor a size.
696
+
697
+ **A line is as tall as its largest text.** A line that is all small is spaced as a small line, so the box is shorter. A small stretch mid-line, `"3 [dim]files[/dim] waiting"`, sits on the same baseline as the words around it, and the line keeps the normal spacing. With `wrap:`, a small character counts as less than a whole one, by the ratio of the two sizes. The closer repeats the name, so a mismatched close is refused by name. Marks don't nest, and a mark may cross a line break. A bare `[` is an error; write `\[` for a literal one.
695
698
 
696
699
  ## Lines
697
700
 
@@ -974,11 +977,19 @@ A line may carry several texts, one after another, each with its own bracket. **
974
977
 
975
978
  **Beside the line:** `(right of edge)`, `(left of edge)`, `(above edge)`, `(below edge)` move the text out the stated way until it is clear of the part of the line it landed on.
976
979
 
980
+ How far it moves can be said in front:
981
+
982
+ - `(at: 4/5, 1 above edge)`: one unit up from where it would sit on the line. If that is short of clear, the text still crosses the line and hides it there.
983
+ - `(at: 4/5, 1/2 clear above edge)`: half of the move that would clear the line. Any fraction or number works, `3/4 clear` or `1.5 clear`.
984
+ - `(at: 4/5, clear above edge)`: all the way clear, the same as `above edge`.
985
+
986
+ A distance is a number, `0.5 above edge`; `1/2 above edge` is refused, naming both forms. `edge-gap:` beside a distance is refused as said twice.
987
+
977
988
  **Lined up with a box on one axis:** `(left even with a right)` puts the left edge of the patch behind the text at `a`'s right side, and leaves its height where it would otherwise sit; `(x even with mid1)` centers the text across on `mid1`. Any `even with` a box takes works, one per axis, and the other axis comes from the line. On a level stretch it slides the text along the line; on an upright one, it moves the text off the line sideways. With a relation that already says the same axis, such as `right of edge`, it is refused. Separate it from the bracket's next item with a comma.
978
989
 
979
990
  **Which way it reads:** `reads: up` and `reads: down` turn it a quarter turn; `reads: along` takes the line's angle where it sits, never upside down.
980
991
 
981
- `gap:` is the distance from the box for `at: start`, `at: end` and the box relations; `edge-gap:` the distance off the line for a text beside it. Each defaults to half a unit, written in the text's own bracket.
992
+ `gap:` is the distance from the box for `at: start`, `at: end` and the box relations; `edge-gap:` the distance past clear for a text beside it, and part of the move that `1/2 clear` takes a fraction of. Each defaults to half a unit, written in the text's own bracket.
982
993
 
983
994
  ```
984
995
  node a
@@ -1052,7 +1063,7 @@ node nas "NAS" right of mirror
1052
1063
  edge mirror -> nas style: backup
1053
1064
  ```
1054
1065
 
1055
- A style is a named bundle of appearance, worn with `style:`. Color carries meaning through the style's name rather than being written per thing. A style takes `fill`, `border`, `line`, `text`, `badge`, `icon`, `shape`, `from-mark`, `to-mark`, `padding`, `corners` and a region's `opacity`, and a title's position inside `text: (…)`: `style zone text: (outside top, align: left)`. It never says where a thing goes, so it can't carry a placement, a `gap:`, a `depth:`, or a line's `from:` or `to:`, and it can't carry a `url:` or a deck's `cards:`.
1066
+ A style is a named bundle of appearance, worn with `style:`. Color carries meaning through the style's name rather than being written per thing. A style takes `fill`, `border`, `line`, `text`, `badge`, `icon`, `shape`, `from-mark`, `to-mark`, `padding`, `corners` and a region's `opacity`, and a title's position inside `text: (…)`: `style zone text: (outside top, align: left)`. It never says where a thing goes, so it can't carry a placement, a `gap:`, a `depth:`, or a line's `from:` or `to:`, and it can't carry a `url:`, a `description:` or a deck's `cards:`.
1056
1067
 
1057
1068
  - **A style may span kinds.** It gives each thing only the keys that thing has, so the style above gives nodes their border and lines their color.
1058
1069
  - **A style must give a thing at least one key it has.** A style that dresses a thing in nothing is on the wrong thing.
@@ -1118,7 +1129,7 @@ A default is a style every thing of one kind wears without naming it: `node`, `l
1118
1129
 
1119
1130
  A container inside another container is filled a shade further from the page than the one it sits in, so the two read as two backdrops. An invisible container (`shape: none`) doesn't count, and a stated `fill:` wins as always.
1120
1131
 
1121
- A default takes the words a style does and may wear a style of its own (`default edge style: quiet`), laid beneath its own words. It is strict about kind, since it names its kind: `default edge fill: red` is refused, pointing to `line:`. `icon:` is a leaf's alone. A default carries no `url:`. Each kind is written once, and `default leaf node` is refused, naming `default leaf`.
1132
+ A default takes the words a style does and may wear a style of its own (`default edge style: quiet`), laid beneath its own words. It is strict about kind, since it names its kind: `default edge fill: red` is refused, pointing to `line:`. `icon:` is a leaf's alone. A default carries no `url:` or `description:`. Each kind is written once, and `default leaf node` is refused, naming `default leaf`.
1122
1133
 
1123
1134
  ### The diagram
1124
1135
 
@@ -1156,6 +1167,70 @@ node api "Orders API"
1156
1167
 
1157
1168
  The same address twice in one `url:` is refused.
1158
1169
 
1170
+ A link can be declared once, with its name and badge, and used by name. A quoted value after `url:` is an address and an unquoted one is a declared link, and the two mix in one list in the order written:
1171
+
1172
+ ```
1173
+ url orders-docs "https://docs.example.com/orders/v2/reference" (name: "Docs", icon: "D" (fill: #3a6ea5, text: white))
1174
+ url orders-code "https://github.com/example/orders/tree/main/services/api" (name: "Code")
1175
+
1176
+ node api "Orders API" url: orders-docs orders-code
1177
+ node worker "Worker" url: orders-docs "https://example.com/runbooks/worker" (name: "Runbook")
1178
+ ```
1179
+
1180
+ A declaration may list several links, each a quoted address or another declared name, and a use gives all of them in order:
1181
+
1182
+ ```
1183
+ url orders-links orders-docs orders-code "https://wiki.example.com/orders" (name: "Wiki")
1184
+
1185
+ node api "Orders API" url: orders-links
1186
+ ```
1187
+
1188
+ A declared link's name and badge are its own, so a bracket after its name in a `url:` is refused; to show it differently, declare another. A declaration may come before or after its use. Refused, each with a message: a name used but never declared, a name declared twice, a declaration that reaches itself through its own list, and a name that starts a placement, such as `below`, since a placement may follow a `url:` on the same statement.
1189
+
1190
+ ### Descriptions
1191
+
1192
+ A box or a line can carry a description: text a reader asks for, shown in the panel when it is selected on a page made with `--page`, and never drawn. It can be written three ways.
1193
+
1194
+ On the thing's own statement, quoted:
1195
+
1196
+ ```
1197
+ node proxy "Proxy" description: "Forwards each request by its path."
1198
+ ```
1199
+
1200
+ At a distance, for things already named, so a long text doesn't crowd the diagram's statements:
1201
+
1202
+ ```
1203
+ node proxy "Proxy"
1204
+ node orders "Orders" right of proxy
1205
+ edge to-orders proxy -> orders
1206
+
1207
+ description for orders and to-orders """
1208
+ Owns the order records.
1209
+
1210
+ - `/orders` lands here
1211
+ - see [the docs](https://example.com/orders)
1212
+ """
1213
+ ```
1214
+
1215
+ Or named, for any box or line to take by that name:
1216
+
1217
+ ```
1218
+ description replica """
1219
+ One of three identical replicas behind the proxy.
1220
+ """
1221
+
1222
+ node r1 "Replica 1" description: replica
1223
+ node r2 "Replica 2" description: replica below r1
1224
+ ```
1225
+
1226
+ `description:` takes the text quoted, or a description's name unquoted, as `icon:` takes letters quoted and a picture's name bare. `description for` names boxes and named lines, separated by commas or `and`; a name that is neither is refused. A long text goes between `"""` marks, where line breaks are kept and the indentation every line shares is taken off.
1227
+
1228
+ The text is Markdown, in part: paragraphs, lists (`-`, `*` or `1.`), `**bold**`, `*italic*` or `_italic_`, `` `code` `` and links, `[text](https://…)`. Anything else shows as written. A link goes to an `https:`, `http:` or `mailto:` address or a path; any other is refused.
1229
+
1230
+ **In an SVG**, the description is the thing's hover text, with the marks taken out and each link's address after its text. Writing one never moves anything in the drawing.
1231
+
1232
+ A thing has one description: two on one statement, or one there and another from `description for`, are refused. So is a name declared twice. A style and a default carry none.
1233
+
1159
1234
  ## Errors and findings
1160
1235
 
1161
1236
  An **error** means the file can't be drawn: an unknown key, two placements on one axis, a cycle. Nothing is drawn, and the message names what to write instead. A **finding** is about a picture that was drawn and may not read as meant. A render with findings succeeds.
@@ -1215,7 +1290,7 @@ reladraw render arch.reladraw --page
1215
1290
 
1216
1291
  `--page` writes `arch.html`: one self-contained file, for opening in a browser, attaching or committing, that needs nothing running and fetches nothing. The page is in the diagram's own colors, so a dark diagram doesn't sit on a white page, and it is headed with `diagram title:`, or the file's name when there is none. Under the title it says which file it was drawn from and when, such as "drawn from arch.reladraw, 2026-11-05 14:32": the page is a snapshot of the file, and is behind it once the file is edited, until it is rendered again. Drag to pan; scroll, pinch or double-click to zoom; Fit shows the whole diagram and 100% returns it to its own scale. The zoom is always shown, with "Fit" beside it while the whole diagram is in view. There is a full-screen button. The Save menu saves the page itself, as it was written rather than at its current zoom; the `.reladraw` source it was drawn from; or the picture as an SVG or a PNG, as `render` would draw it; or copies the SVG. Each is named after the source file: `arch.html`, `arch.reladraw`, `arch.svg`, `arch.png`. In Chrome and Edge it asks where to save; other browsers put the file with their downloads. The findings are listed beside it in a panel that folds away, and clicking one lights up what its line drew. A box's or a line's name shows under the pointer.
1217
1292
 
1218
- **A click on a box or a line selects it**, and never follows a link. The selection is amber; what feeds it is green and what it feeds is red, the lines dashed and moving the way they run; the rest dims. A line runs from the end without an arrowhead when only one end has one, and otherwise from the end written first. The panel beside the drawing names the selection and lists its links, each with its badge, and the boxes it comes from and goes to; a link opens in a new tab, and a box selects it. One line out lights by default, and the panel's button lights everything upstream and downstream. A box with links underlines its text under the pointer. A click on the background or Escape clears the selection.
1293
+ **A click on a box or a line selects it**, and never follows a link. The selection is amber; what feeds it is green and what it feeds is red, the lines dashed and moving the way they run; the rest dims. A line runs from the end without an arrowhead when only one end has one, and otherwise from the end written first. The panel beside the drawing names the selection and lists its links, each with its badge, and the boxes it comes from and goes to; a link opens in a new tab, and a box selects it. One line out lights by default, and the panel's button lights everything upstream and downstream. Its description, if it has one, comes last ([Descriptions](#descriptions)). A box with links underlines its text under the pointer. A click on the background or Escape clears the selection.
1219
1294
 
1220
1295
  Keys: `+` and `-` zoom, `0` fits, `1` is actual size, `f` is full screen, Escape clears the selection.
1221
1296
 
@@ -1290,6 +1365,7 @@ Every attribute, and what takes one. A node's kind is what its body is: a box (`
1290
1365
  | `gather-children` | ✓ | | ✓ | | where the children sit in spare room |
1291
1366
  | `heading` | ✓ | | ✓ | | the child that is the title |
1292
1367
  | `join-with` | ✓ | ✓ | ✓ | | the thing this moves with |
1368
+ | `description` | ✓ | ✓ | ✓ | ✓ | text for the page's panel ([Descriptions](#descriptions)) |
1293
1369
  | `padding` | ✓ | | ✓ | | room inside the edge |
1294
1370
  | `padding-top`, `-right`, `-bottom`, `-left` | ✓ | | ✓ | | one side's room, over `padding` |
1295
1371
  | `width`, `height`, `min-…`, `max-…` | ✓ | | ✓ | | a stated size |
@@ -1338,6 +1414,24 @@ Designed and absent from the code.
1338
1414
 
1339
1415
  Pre-1.0, so the minor number is where a breaking change goes. Every removal is refused by name with the replacement quoted, rather than dropped in silence: an older file stops with an error saying what to write instead.
1340
1416
 
1417
+ **0.25.1**
1418
+
1419
+ - The agent skill now says that a distance and a direction after `and` start a second placement, and how to name a point to use as a target. No change to what the tool accepts or draws.
1420
+
1421
+ **0.25.0**
1422
+
1423
+ - **A link can be declared once and used by name**: `url orders-docs "https://…" (name: "Docs", icon: "D")`, then `url: orders-docs`, so long addresses stay out of the statements that link to them. A declaration may list several links, declared names among them, and a `url:` mixes names and quoted addresses. See [Destinations](#destinations).
1424
+
1425
+ - **Marked text takes its style's size**: with `style dim text: (size: small)`, `"Some Node / [dim]something[/dim]"` draws the second line small, and a line that is all small is spaced as one. Markup used to take only a style's color, and a style with only a size was refused as saying nothing about text. See [Markup](#markup).
1426
+
1427
+ - **`2 right of and 3 below a`** is accepted, the same as `2 right and 3 below a`. It used to be refused with a message that took `and` for the name of a box.
1428
+
1429
+ - **A distance and a direction after `and` or a comma start a second placement**: `node b right of a and 2 above c top` puts `b` right of `a`, with its bottom 2 above `c`'s top. It used to take `2 above c top` as a point added to the targets, so `b` was placed right of the region covering `a` and that point, with no warning, and the second half looked ignored. To get that reading, name the point first: `point p 2 above c top-center`, then `node b right of a and p`.
1430
+
1431
+ - **A box or a line can have a description**, shown in the panel when it is selected on a `--page` page, and as hover text in an SVG. It is written on the thing, `description: "Forwards each request by its path."`; at a distance, `description for orders and to-orders """…"""`; or named, `description replica """…"""`, and taken with `description: replica`. The text is a small part of Markdown: paragraphs, lists, bold, italic, code and links.
1432
+
1433
+ - **A line's text can rise a stated amount off its line, or part of the way clear.** `above edge` and its kin always moved a text all the way clear, which on a slanted line can be well away from it. `(1 above edge)` now raises it one unit from its spot on the line, still crossing the line if that is short of clear, and `(1/2 clear above edge)` moves it half the way. `(1 above edge)` used to be refused, pointing to `edge-gap:`.
1434
+
1341
1435
  **0.24.0**
1342
1436
 
1343
1437
  - **`reladraw install-skill` installs for Claude Code, the `~/.agents` folder, or both, and asks which.** It used to pass everything on to `skills`, which, given no agent, put a copy in the folder of every agent it knows, more than fifty of them, and in the current project unless `-g` was written. It now always installs for every project, in the places `--claude` and `--agents` name; `-a` and the other `skills` options are refused with the `skills` command that does the same, and `-g` is still accepted.
package/README.md CHANGED
@@ -94,7 +94,7 @@ To install the skill from the main branch instead, which can run ahead of the re
94
94
 
95
95
  ## Status
96
96
 
97
- Version 0.24.0. Early stage, but works. The parser, layout engine, and SVG renderer are written in TypeScript, with zero runtime dependencies. There is a command-line tool that turns a .reladraw text file into an SVG, and an element that does the same inside a web page.
97
+ Version 0.25.1. Early stage, but works. The parser, layout engine, and SVG renderer are written in TypeScript, with zero runtime dependencies. There is a command-line tool that turns a .reladraw text file into an SVG, and an element that does the same inside a web page.
98
98
 
99
99
  ## License
100
100
 
package/SYNTAX.md CHANGED
@@ -1,4 +1,4 @@
1
- # Syntax reference — 0.24.0
1
+ # Syntax reference — 0.25.1
2
2
 
3
3
  What the language accepts. The changelog at the end lists what changed in each published version; 0.17.0's changes are large, and its entry has a table of every old spelling and what to write instead.
4
4
 
@@ -38,6 +38,7 @@ An indented line with nothing to continue, at the top of the file or after a bla
38
38
  | `default` | appearance every thing of one kind wears ([Defaults](#defaults)) |
39
39
  | `diagram` | settings for the whole drawing ([The diagram](#the-diagram)) |
40
40
  | `icon` | a picture of your own ([Your own icons](#your-own-icons)) |
41
+ | `description` | text about a box or a line, for the page's panel ([Descriptions](#descriptions)) |
41
42
 
42
43
  `box`, `link`, `note`, `deck`, `rect` and `arrow` at the start of a statement are refused by name, each quoting what to write instead.
43
44
 
@@ -71,7 +72,7 @@ A text is quoted. ` / `, a slash with whitespace on both sides, breaks the line,
71
72
 
72
73
  A node with no text shows its name, and a dotted name shows only its last part: `node server.docker` reads "docker". The name is never prettified. `""` says a node deliberately has none. A node drawn as a picture shows no text unless one is written.
73
74
 
74
- A `"""` string takes everything between its marks as written, quotes and line breaks included. It is accepted only for an icon's SVG.
75
+ A `"""` string takes everything between its marks as written, quotes and line breaks included. It is accepted only for an icon's SVG and a description's text ([Descriptions](#descriptions)).
75
76
 
76
77
  ### Numbers and the file's unit
77
78
 
@@ -258,7 +259,7 @@ node notes "notes" below resolver (gap: tight) shape: none
258
259
 
259
260
  ### Several targets at once
260
261
 
261
- A placement may name several targets, joined by `and` or commas: `right of a, b and c`. It places against the box bounding them all, a region nobody had to declare. A lone direction centers on that region, which is how one row is offset against another:
262
+ A placement may name several targets, joined by `and` or commas: `right of a, b and c`. It places against the box bounding them all, a region nobody had to declare. A distance and a direction after the `and` or comma start another placement instead: `right of a and 2 above c top` is `right of a 2 above c top`. To place against a point and a box together, name the point first: `point p 2 above c top-center`, then `right of a and p`. A lone direction centers on that region, which is how one row is offset against another:
262
263
 
263
264
  ```
264
265
  node a icon: cube
@@ -291,7 +292,7 @@ A fraction of the way across a box is written fraction first: `top even with 3/4
291
292
 
292
293
  `center 12 right of a center` puts the two centers exactly 12 apart, the even steps of a timeline whose boxes differ in width. `top 3 below a bottom` is the same for edges. The direction means what it always means, so with nothing else said the box also sits level with `a`'s center. A placement naming parts must give its distance: `center right of a center` is refused ("say how far").
293
294
 
294
- Two distances, one per axis, are accepted in any placement: `3 below and 2 right of a`, or `top-left 3 below and 2 right of a bottom-right`.
295
+ Two distances, one per axis, are accepted in any placement: `3 below and 2 right of a`, or `top-left 3 below and 2 right of a bottom-right`. A `left` or `right` that comes first may keep its `of`: `2 right of and 3 below a` is `2 right and 3 below a`.
295
296
 
296
297
  **How far along the side it faces.** `right of server 3/4 down` puts the box the usual gap right of `server`, its middle level with a spot three quarters of the way down `server`'s right side. `down` and `up` run along a left or right side, `across` along a top or bottom one. A word that doesn't run along the side the direction faces is refused, listing the words that do.
297
298
 
@@ -684,14 +685,16 @@ node rack.b "web-2"
684
685
 
685
686
  ### Markup
686
687
 
687
- A stretch of text can borrow a style's look:
688
+ A stretch of text can borrow a style's text color and size:
688
689
 
689
690
  ```
690
- style dim text: (color: theme-muted)
691
+ style dim text: (color: theme-muted, size: small)
691
692
  node files "shared folder / [dim]synced[/dim]"
692
693
  ```
693
694
 
694
- The opener names a style, never a color, so the marked words borrow a meaning the file already has. A name no style answers to is refused, and so is a style that says nothing about text. The closer repeats the name, so a mismatched close is refused by name. Marks don't nest, and a mark may cross a line break. A bare `[` is an error; write `\[` for a literal one.
695
+ The opener names a style, never a color, so the marked words borrow a meaning the file already has. A name no style answers to is refused, and so is a style that gives text neither a color nor a size.
696
+
697
+ **A line is as tall as its largest text.** A line that is all small is spaced as a small line, so the box is shorter. A small stretch mid-line, `"3 [dim]files[/dim] waiting"`, sits on the same baseline as the words around it, and the line keeps the normal spacing. With `wrap:`, a small character counts as less than a whole one, by the ratio of the two sizes. The closer repeats the name, so a mismatched close is refused by name. Marks don't nest, and a mark may cross a line break. A bare `[` is an error; write `\[` for a literal one.
695
698
 
696
699
  ## Lines
697
700
 
@@ -974,11 +977,19 @@ A line may carry several texts, one after another, each with its own bracket. **
974
977
 
975
978
  **Beside the line:** `(right of edge)`, `(left of edge)`, `(above edge)`, `(below edge)` move the text out the stated way until it is clear of the part of the line it landed on.
976
979
 
980
+ How far it moves can be said in front:
981
+
982
+ - `(at: 4/5, 1 above edge)`: one unit up from where it would sit on the line. If that is short of clear, the text still crosses the line and hides it there.
983
+ - `(at: 4/5, 1/2 clear above edge)`: half of the move that would clear the line. Any fraction or number works, `3/4 clear` or `1.5 clear`.
984
+ - `(at: 4/5, clear above edge)`: all the way clear, the same as `above edge`.
985
+
986
+ A distance is a number, `0.5 above edge`; `1/2 above edge` is refused, naming both forms. `edge-gap:` beside a distance is refused as said twice.
987
+
977
988
  **Lined up with a box on one axis:** `(left even with a right)` puts the left edge of the patch behind the text at `a`'s right side, and leaves its height where it would otherwise sit; `(x even with mid1)` centers the text across on `mid1`. Any `even with` a box takes works, one per axis, and the other axis comes from the line. On a level stretch it slides the text along the line; on an upright one, it moves the text off the line sideways. With a relation that already says the same axis, such as `right of edge`, it is refused. Separate it from the bracket's next item with a comma.
978
989
 
979
990
  **Which way it reads:** `reads: up` and `reads: down` turn it a quarter turn; `reads: along` takes the line's angle where it sits, never upside down.
980
991
 
981
- `gap:` is the distance from the box for `at: start`, `at: end` and the box relations; `edge-gap:` the distance off the line for a text beside it. Each defaults to half a unit, written in the text's own bracket.
992
+ `gap:` is the distance from the box for `at: start`, `at: end` and the box relations; `edge-gap:` the distance past clear for a text beside it, and part of the move that `1/2 clear` takes a fraction of. Each defaults to half a unit, written in the text's own bracket.
982
993
 
983
994
  ```
984
995
  node a
@@ -1052,7 +1063,7 @@ node nas "NAS" right of mirror
1052
1063
  edge mirror -> nas style: backup
1053
1064
  ```
1054
1065
 
1055
- A style is a named bundle of appearance, worn with `style:`. Color carries meaning through the style's name rather than being written per thing. A style takes `fill`, `border`, `line`, `text`, `badge`, `icon`, `shape`, `from-mark`, `to-mark`, `padding`, `corners` and a region's `opacity`, and a title's position inside `text: (…)`: `style zone text: (outside top, align: left)`. It never says where a thing goes, so it can't carry a placement, a `gap:`, a `depth:`, or a line's `from:` or `to:`, and it can't carry a `url:` or a deck's `cards:`.
1066
+ A style is a named bundle of appearance, worn with `style:`. Color carries meaning through the style's name rather than being written per thing. A style takes `fill`, `border`, `line`, `text`, `badge`, `icon`, `shape`, `from-mark`, `to-mark`, `padding`, `corners` and a region's `opacity`, and a title's position inside `text: (…)`: `style zone text: (outside top, align: left)`. It never says where a thing goes, so it can't carry a placement, a `gap:`, a `depth:`, or a line's `from:` or `to:`, and it can't carry a `url:`, a `description:` or a deck's `cards:`.
1056
1067
 
1057
1068
  - **A style may span kinds.** It gives each thing only the keys that thing has, so the style above gives nodes their border and lines their color.
1058
1069
  - **A style must give a thing at least one key it has.** A style that dresses a thing in nothing is on the wrong thing.
@@ -1118,7 +1129,7 @@ A default is a style every thing of one kind wears without naming it: `node`, `l
1118
1129
 
1119
1130
  A container inside another container is filled a shade further from the page than the one it sits in, so the two read as two backdrops. An invisible container (`shape: none`) doesn't count, and a stated `fill:` wins as always.
1120
1131
 
1121
- A default takes the words a style does and may wear a style of its own (`default edge style: quiet`), laid beneath its own words. It is strict about kind, since it names its kind: `default edge fill: red` is refused, pointing to `line:`. `icon:` is a leaf's alone. A default carries no `url:`. Each kind is written once, and `default leaf node` is refused, naming `default leaf`.
1132
+ A default takes the words a style does and may wear a style of its own (`default edge style: quiet`), laid beneath its own words. It is strict about kind, since it names its kind: `default edge fill: red` is refused, pointing to `line:`. `icon:` is a leaf's alone. A default carries no `url:` or `description:`. Each kind is written once, and `default leaf node` is refused, naming `default leaf`.
1122
1133
 
1123
1134
  ### The diagram
1124
1135
 
@@ -1156,6 +1167,70 @@ node api "Orders API"
1156
1167
 
1157
1168
  The same address twice in one `url:` is refused.
1158
1169
 
1170
+ A link can be declared once, with its name and badge, and used by name. A quoted value after `url:` is an address and an unquoted one is a declared link, and the two mix in one list in the order written:
1171
+
1172
+ ```
1173
+ url orders-docs "https://docs.example.com/orders/v2/reference" (name: "Docs", icon: "D" (fill: #3a6ea5, text: white))
1174
+ url orders-code "https://github.com/example/orders/tree/main/services/api" (name: "Code")
1175
+
1176
+ node api "Orders API" url: orders-docs orders-code
1177
+ node worker "Worker" url: orders-docs "https://example.com/runbooks/worker" (name: "Runbook")
1178
+ ```
1179
+
1180
+ A declaration may list several links, each a quoted address or another declared name, and a use gives all of them in order:
1181
+
1182
+ ```
1183
+ url orders-links orders-docs orders-code "https://wiki.example.com/orders" (name: "Wiki")
1184
+
1185
+ node api "Orders API" url: orders-links
1186
+ ```
1187
+
1188
+ A declared link's name and badge are its own, so a bracket after its name in a `url:` is refused; to show it differently, declare another. A declaration may come before or after its use. Refused, each with a message: a name used but never declared, a name declared twice, a declaration that reaches itself through its own list, and a name that starts a placement, such as `below`, since a placement may follow a `url:` on the same statement.
1189
+
1190
+ ### Descriptions
1191
+
1192
+ A box or a line can carry a description: text a reader asks for, shown in the panel when it is selected on a page made with `--page`, and never drawn. It can be written three ways.
1193
+
1194
+ On the thing's own statement, quoted:
1195
+
1196
+ ```
1197
+ node proxy "Proxy" description: "Forwards each request by its path."
1198
+ ```
1199
+
1200
+ At a distance, for things already named, so a long text doesn't crowd the diagram's statements:
1201
+
1202
+ ```
1203
+ node proxy "Proxy"
1204
+ node orders "Orders" right of proxy
1205
+ edge to-orders proxy -> orders
1206
+
1207
+ description for orders and to-orders """
1208
+ Owns the order records.
1209
+
1210
+ - `/orders` lands here
1211
+ - see [the docs](https://example.com/orders)
1212
+ """
1213
+ ```
1214
+
1215
+ Or named, for any box or line to take by that name:
1216
+
1217
+ ```
1218
+ description replica """
1219
+ One of three identical replicas behind the proxy.
1220
+ """
1221
+
1222
+ node r1 "Replica 1" description: replica
1223
+ node r2 "Replica 2" description: replica below r1
1224
+ ```
1225
+
1226
+ `description:` takes the text quoted, or a description's name unquoted, as `icon:` takes letters quoted and a picture's name bare. `description for` names boxes and named lines, separated by commas or `and`; a name that is neither is refused. A long text goes between `"""` marks, where line breaks are kept and the indentation every line shares is taken off.
1227
+
1228
+ The text is Markdown, in part: paragraphs, lists (`-`, `*` or `1.`), `**bold**`, `*italic*` or `_italic_`, `` `code` `` and links, `[text](https://…)`. Anything else shows as written. A link goes to an `https:`, `http:` or `mailto:` address or a path; any other is refused.
1229
+
1230
+ **In an SVG**, the description is the thing's hover text, with the marks taken out and each link's address after its text. Writing one never moves anything in the drawing.
1231
+
1232
+ A thing has one description: two on one statement, or one there and another from `description for`, are refused. So is a name declared twice. A style and a default carry none.
1233
+
1159
1234
  ## Errors and findings
1160
1235
 
1161
1236
  An **error** means the file can't be drawn: an unknown key, two placements on one axis, a cycle. Nothing is drawn, and the message names what to write instead. A **finding** is about a picture that was drawn and may not read as meant. A render with findings succeeds.
@@ -1215,7 +1290,7 @@ reladraw render arch.reladraw --page
1215
1290
 
1216
1291
  `--page` writes `arch.html`: one self-contained file, for opening in a browser, attaching or committing, that needs nothing running and fetches nothing. The page is in the diagram's own colors, so a dark diagram doesn't sit on a white page, and it is headed with `diagram title:`, or the file's name when there is none. Under the title it says which file it was drawn from and when, such as "drawn from arch.reladraw, 2026-11-05 14:32": the page is a snapshot of the file, and is behind it once the file is edited, until it is rendered again. Drag to pan; scroll, pinch or double-click to zoom; Fit shows the whole diagram and 100% returns it to its own scale. The zoom is always shown, with "Fit" beside it while the whole diagram is in view. There is a full-screen button. The Save menu saves the page itself, as it was written rather than at its current zoom; the `.reladraw` source it was drawn from; or the picture as an SVG or a PNG, as `render` would draw it; or copies the SVG. Each is named after the source file: `arch.html`, `arch.reladraw`, `arch.svg`, `arch.png`. In Chrome and Edge it asks where to save; other browsers put the file with their downloads. The findings are listed beside it in a panel that folds away, and clicking one lights up what its line drew. A box's or a line's name shows under the pointer.
1217
1292
 
1218
- **A click on a box or a line selects it**, and never follows a link. The selection is amber; what feeds it is green and what it feeds is red, the lines dashed and moving the way they run; the rest dims. A line runs from the end without an arrowhead when only one end has one, and otherwise from the end written first. The panel beside the drawing names the selection and lists its links, each with its badge, and the boxes it comes from and goes to; a link opens in a new tab, and a box selects it. One line out lights by default, and the panel's button lights everything upstream and downstream. A box with links underlines its text under the pointer. A click on the background or Escape clears the selection.
1293
+ **A click on a box or a line selects it**, and never follows a link. The selection is amber; what feeds it is green and what it feeds is red, the lines dashed and moving the way they run; the rest dims. A line runs from the end without an arrowhead when only one end has one, and otherwise from the end written first. The panel beside the drawing names the selection and lists its links, each with its badge, and the boxes it comes from and goes to; a link opens in a new tab, and a box selects it. One line out lights by default, and the panel's button lights everything upstream and downstream. Its description, if it has one, comes last ([Descriptions](#descriptions)). A box with links underlines its text under the pointer. A click on the background or Escape clears the selection.
1219
1294
 
1220
1295
  Keys: `+` and `-` zoom, `0` fits, `1` is actual size, `f` is full screen, Escape clears the selection.
1221
1296
 
@@ -1290,6 +1365,7 @@ Every attribute, and what takes one. A node's kind is what its body is: a box (`
1290
1365
  | `gather-children` | ✓ | | ✓ | | where the children sit in spare room |
1291
1366
  | `heading` | ✓ | | ✓ | | the child that is the title |
1292
1367
  | `join-with` | ✓ | ✓ | ✓ | | the thing this moves with |
1368
+ | `description` | ✓ | ✓ | ✓ | ✓ | text for the page's panel ([Descriptions](#descriptions)) |
1293
1369
  | `padding` | ✓ | | ✓ | | room inside the edge |
1294
1370
  | `padding-top`, `-right`, `-bottom`, `-left` | ✓ | | ✓ | | one side's room, over `padding` |
1295
1371
  | `width`, `height`, `min-…`, `max-…` | ✓ | | ✓ | | a stated size |
@@ -1338,6 +1414,24 @@ Designed and absent from the code.
1338
1414
 
1339
1415
  Pre-1.0, so the minor number is where a breaking change goes. Every removal is refused by name with the replacement quoted, rather than dropped in silence: an older file stops with an error saying what to write instead.
1340
1416
 
1417
+ **0.25.1**
1418
+
1419
+ - The agent skill now says that a distance and a direction after `and` start a second placement, and how to name a point to use as a target. No change to what the tool accepts or draws.
1420
+
1421
+ **0.25.0**
1422
+
1423
+ - **A link can be declared once and used by name**: `url orders-docs "https://…" (name: "Docs", icon: "D")`, then `url: orders-docs`, so long addresses stay out of the statements that link to them. A declaration may list several links, declared names among them, and a `url:` mixes names and quoted addresses. See [Destinations](#destinations).
1424
+
1425
+ - **Marked text takes its style's size**: with `style dim text: (size: small)`, `"Some Node / [dim]something[/dim]"` draws the second line small, and a line that is all small is spaced as one. Markup used to take only a style's color, and a style with only a size was refused as saying nothing about text. See [Markup](#markup).
1426
+
1427
+ - **`2 right of and 3 below a`** is accepted, the same as `2 right and 3 below a`. It used to be refused with a message that took `and` for the name of a box.
1428
+
1429
+ - **A distance and a direction after `and` or a comma start a second placement**: `node b right of a and 2 above c top` puts `b` right of `a`, with its bottom 2 above `c`'s top. It used to take `2 above c top` as a point added to the targets, so `b` was placed right of the region covering `a` and that point, with no warning, and the second half looked ignored. To get that reading, name the point first: `point p 2 above c top-center`, then `node b right of a and p`.
1430
+
1431
+ - **A box or a line can have a description**, shown in the panel when it is selected on a `--page` page, and as hover text in an SVG. It is written on the thing, `description: "Forwards each request by its path."`; at a distance, `description for orders and to-orders """…"""`; or named, `description replica """…"""`, and taken with `description: replica`. The text is a small part of Markdown: paragraphs, lists, bold, italic, code and links.
1432
+
1433
+ - **A line's text can rise a stated amount off its line, or part of the way clear.** `above edge` and its kin always moved a text all the way clear, which on a slanted line can be well away from it. `(1 above edge)` now raises it one unit from its spot on the line, still crossing the line if that is short of clear, and `(1/2 clear above edge)` moves it half the way. `(1 above edge)` used to be refused, pointing to `edge-gap:`.
1434
+
1341
1435
  **0.24.0**
1342
1436
 
1343
1437
  - **`reladraw install-skill` installs for Claude Code, the `~/.agents` folder, or both, and asks which.** It used to pass everything on to `skills`, which, given no agent, put a copy in the folder of every agent it knows, more than fifty of them, and in the current project unless `-g` was written. It now always installs for every project, in the places `--claude` and `--agents` name; `-a` and the other `skills` options are refused with the `skills` command that does the same, and `-g` is still accepted.
package/dist/ast.d.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  * The shape a source file parses into. Nothing here knows about geometry —
3
3
  * these types are a faithful record of what the author wrote, and no more.
4
4
  */
5
+ import type { LinkEntry } from './links.js';
5
6
  export declare const DIRECTIONS: readonly ["above", "below", "left", "right", "above-left", "above-right", "below-left", "below-right"];
6
7
  export type Direction = (typeof DIRECTIONS)[number];
7
8
  export declare function isDirection(word: string): word is Direction;
@@ -443,6 +444,17 @@ export interface EdgeTextPlace {
443
444
  onLine?: boolean;
444
445
  /** `right of edge`: moved clear of the part of the line it landed on. */
445
446
  beside?: TextSide;
447
+ /**
448
+ * How far a text beside its line moves, from its spot on the line, the stated way:
449
+ * `2 above edge` a distance; `clear above edge` (1) or `1/2 clear above edge` a
450
+ * fraction of the move that clears the line, `edge-gap:` included. Unstated, it is
451
+ * `clear`. Either may leave the text across its line, and that is meant.
452
+ */
453
+ rise?: {
454
+ distance?: string;
455
+ clear?: number;
456
+ written: string;
457
+ };
446
458
  /**
447
459
  * `left even with x right`: one axis set by a box, at most one per axis; the
448
460
  * other stays where the text would otherwise sit (design.org 7.3).
@@ -812,7 +824,41 @@ export interface IconStmt {
812
824
  };
813
825
  line: number;
814
826
  }
815
- export type Stmt = NodeStmt | EdgeStmt | StyleStmt | DiagramStmt | DefaultStmt | IconStmt | PointStmt | RegionStmt | BundleStmt;
827
+ /** Where `description: notes` keeps the name until `resolve` swaps in the text. */
828
+ export declare const DESCRIPTION_NAME_KEY = "description.name";
829
+ /**
830
+ * `description for proxy, cache """…"""` attaches one text to things already
831
+ * named; `description notes """…"""` declares a named one, which a box or a
832
+ * line takes with `description: notes`. The text is a small Markdown subset,
833
+ * shown in the page's panel and, marks stripped, as an SVG's hover text.
834
+ */
835
+ export interface DescriptionStmt {
836
+ kind: 'description';
837
+ /** The declared name, for the named form. */
838
+ name?: string;
839
+ /** The boxes and lines named after `for`, for the at-a-distance form. */
840
+ targets?: string[];
841
+ text: string;
842
+ line: number;
843
+ }
844
+ /**
845
+ * Where a `url:` that names declared links keeps its list, declared names and
846
+ * quoted addresses in the order written, until `resolve` swaps each name for
847
+ * the links it declares.
848
+ */
849
+ export declare const LINK_NAMES_KEY = "url.names";
850
+ /**
851
+ * `url orders-docs "https://…" (name: "Docs", icon: "D")` declares a link once,
852
+ * with its name and badge, for `url: orders-docs`. A declaration may hold
853
+ * several links, each a quoted address or another declared name: a bundle.
854
+ */
855
+ export interface UrlStmt {
856
+ kind: 'url';
857
+ name: string;
858
+ entries: LinkEntry[];
859
+ line: number;
860
+ }
861
+ export type Stmt = NodeStmt | EdgeStmt | StyleStmt | DiagramStmt | DefaultStmt | IconStmt | PointStmt | RegionStmt | BundleStmt | DescriptionStmt | UrlStmt;
816
862
  export interface Document {
817
863
  statements: Stmt[];
818
864
  }
package/dist/ast.js CHANGED
@@ -462,10 +462,10 @@ export const PADDING_SIDE_KEYS = PADDING_SIDES.map((side) => `padding-${side}`);
462
462
  /** `right-edge-order: ae, ad, ac`: the lines on one side of a box, in reading order. */
463
463
  export const EDGE_ORDER_KEYS = ['top-edge-order', 'bottom-edge-order', 'left-edge-order', 'right-edge-order'];
464
464
  export const ATTR_KEYS = {
465
- shape: ['style', 'overlap', 'layout', 'gather-children', 'padding', ...PADDING_SIDE_KEYS, ...SIZE_KEY_NAMES, 'heading', 'join-with', 'badge', 'cards', 'shape', 'fill', 'border', 'corners', 'text', 'url', 'depth', ...EDGE_ORDER_KEYS],
466
- icon: ['style', 'overlap', 'icon', 'join-with', 'text', 'url', 'depth', ...EDGE_ORDER_KEYS],
467
- none: ['style', 'overlap', 'layout', 'gather-children', 'padding', ...SIZE_KEY_NAMES, 'heading', 'join-with', 'shape', 'text', 'url', 'depth', ...EDGE_ORDER_KEYS],
468
- edge: ['style', 'from', 'to', 'via', 'from-mark', 'to-mark', 'line', 'text', 'url', 'depth'],
465
+ shape: ['style', 'overlap', 'layout', 'gather-children', 'padding', ...PADDING_SIDE_KEYS, ...SIZE_KEY_NAMES, 'heading', 'join-with', 'badge', 'cards', 'shape', 'fill', 'border', 'corners', 'text', 'url', 'description', 'depth', ...EDGE_ORDER_KEYS],
466
+ icon: ['style', 'overlap', 'icon', 'join-with', 'text', 'url', 'description', 'depth', ...EDGE_ORDER_KEYS],
467
+ none: ['style', 'overlap', 'layout', 'gather-children', 'padding', ...SIZE_KEY_NAMES, 'heading', 'join-with', 'shape', 'text', 'url', 'description', 'depth', ...EDGE_ORDER_KEYS],
468
+ edge: ['style', 'from', 'to', 'via', 'from-mark', 'to-mark', 'line', 'text', 'url', 'description', 'depth'],
469
469
  };
470
470
  /**
471
471
  * What a node's `corners:` takes, the default first: a box is drawn rounded
@@ -488,3 +488,11 @@ export const NODE_CORNERS = ['rounded', 'sharp'];
488
488
  export const ALL_ATTR_KEYS = [
489
489
  ...new Set([...Object.values(ATTR_KEYS).flat(), ...DIAGRAM_KEYS, ...REGION_KEYS]),
490
490
  ];
491
+ /** Where `description: notes` keeps the name until `resolve` swaps in the text. */
492
+ export const DESCRIPTION_NAME_KEY = 'description.name';
493
+ /**
494
+ * Where a `url:` that names declared links keeps its list, declared names and
495
+ * quoted addresses in the order written, until `resolve` swaps each name for
496
+ * the links it declares.
497
+ */
498
+ export const LINK_NAMES_KEY = 'url.names';