reladraw 0.2.0 → 0.4.0
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.
- package/README.md +30 -22
- package/SYNTAX.md +465 -214
- package/dist/ast.d.ts +204 -61
- package/dist/ast.js +190 -51
- package/dist/constants.d.ts +64 -49
- package/dist/constants.js +91 -71
- package/dist/grammar.d.ts +17 -4
- package/dist/grammar.js +53 -7
- package/dist/icons.d.ts +53 -35
- package/dist/icons.js +81 -43
- package/dist/lexer.js +6 -5
- package/dist/measure.d.ts +3 -3
- package/dist/measure.js +3 -3
- package/dist/model.d.ts +87 -16
- package/dist/parser.js +584 -220
- package/dist/render.d.ts +1 -1
- package/dist/render.js +347 -281
- package/dist/resolve.js +1223 -294
- package/dist/text.d.ts +48 -0
- package/dist/text.js +196 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# reladraw
|
|
2
2
|
|
|
3
|
-
A text language for diagrams where **
|
|
3
|
+
A text language for diagrams where **you say where things go**.
|
|
4
4
|
|
|
5
5
|
**[Try it in your browser →](https://reladraw.github.io/reladraw/)** — edit the source on the left, watch the layout re-solve on the right. Nothing to install.
|
|
6
6
|
|
|
@@ -8,11 +8,11 @@ A diagram drawn by hand in draw.io:
|
|
|
8
8
|
|
|
9
9
|

|
|
10
10
|
|
|
11
|
-
And the same diagram written down in reladraw and rendered from the text — [`examples/arch.reladraw`](examples/arch.reladraw),
|
|
11
|
+
And the same diagram written down in reladraw and rendered from the text — [`examples/arch.reladraw`](examples/arch.reladraw), 44 statements, no coordinates anywhere in it:
|
|
12
12
|
|
|
13
13
|

|
|
14
14
|
|
|
15
|
-
Every distance in the second picture was worked out from statements like `above-left of
|
|
15
|
+
Every distance in the second picture was worked out from statements like `above-left of cluster.hub` and `between cluster.desktop1 and cluster.laptop1`. Nothing chose the arrangement; the file states it.
|
|
16
16
|
|
|
17
17
|
## The gap
|
|
18
18
|
|
|
@@ -25,13 +25,13 @@ On the other end of the spectrum are the absolute-positioning tools — draw.io,
|
|
|
25
25
|
reladraw aims at the middle. Every position is stated relative to something else, and nothing in the file is a coordinate:
|
|
26
26
|
|
|
27
27
|
```
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
node app "Web app"
|
|
29
|
+
node app.ui "Interface"
|
|
30
|
+
node app.api "API" below app.ui
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
node store "Database" right of app level with app
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
edge app.api -> store "queries" from: right to: left
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
Nothing is nested, so no line depends on another line's position or indentation.
|
|
@@ -44,7 +44,7 @@ The common case is not drawing a diagram, it is changing one. Ask for the auth s
|
|
|
44
44
|
|
|
45
45
|
Writing has the same shape. An agent emitting Mermaid is guessing at a layout that an algorithm settles later, and its only way to find out is to render and look — a round trip that comes back as a picture rather than as a list of what is wrong.
|
|
46
46
|
|
|
47
|
-
Intent is confirmable, outcomes are not, and the difference is worth being precise about. An agent can re-read its own file and see that the database is under the API and all four machines hang off
|
|
47
|
+
Intent is confirmable, outcomes are not, and the difference is worth being precise about. An agent can re-read its own file and see that the database is under the API and all four machines hang off the sync hub. It cannot see that two clusters anchored to different things now overlap, that a text overflowed its node, or that an edge crosses four others — those are resolved from the statements rather than stated, so they need the diagnostics in the scope section below.
|
|
48
48
|
|
|
49
49
|
### Using it with an agent
|
|
50
50
|
|
|
@@ -56,11 +56,19 @@ npx skills add reladraw/reladraw -g
|
|
|
56
56
|
|
|
57
57
|
That installs it for whichever agent you use — Claude Code, Codex, Cursor, Copilot and others — each into its own skills directory. Drop the `-g` to install it into the current project instead.
|
|
58
58
|
|
|
59
|
+
To install it for one agent rather than all of them, name it with `-a`:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
npx skills add reladraw/reladraw -g -a claude-code
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Re-run whichever command you used after a release that changes the syntax. The skill is a copy taken at install time, not a live link, so nothing refreshes it on its own.
|
|
66
|
+
|
|
59
67
|
It is [plain Markdown](.claude/skills/reladraw/SKILL.md) with the syntax reference beside it, so it is worth reading whatever you use, and copying the directory by hand works just as well.
|
|
60
68
|
|
|
61
69
|
## Status
|
|
62
70
|
|
|
63
|
-
Version 0.
|
|
71
|
+
Version 0.4.0. Early, but it runs: a parser, resolver and SVG renderer in TypeScript with no runtime dependencies, and a command-line tool that takes a text file and writes a standalone SVG. The comparison at the top of this page is that pipeline run on [`examples/arch.reladraw`](examples/arch.reladraw). What is still visibly off there is typography, not placement.
|
|
64
72
|
|
|
65
73
|
```
|
|
66
74
|
npm install -g reladraw
|
|
@@ -77,18 +85,18 @@ node dist/cli.js examples/arch.reladraw -o out.svg
|
|
|
77
85
|
Not built yet, roughly in the order they are missed:
|
|
78
86
|
|
|
79
87
|
- **The diagnostics report.** The scope section below says what it is for. Today the tool either renders or fails; it will not tell you what is wrong with a picture it drew successfully.
|
|
80
|
-
- **Edge routing around
|
|
81
|
-
- **More
|
|
88
|
+
- **Edge routing around nodes.** An edge can be told which side of a node to leave and arrive on, and which gap to run down on the way. An edge that says none of that is a straight line between two centers, and it will cut through whatever stands in the way.
|
|
89
|
+
- **More pictures.** Icons and shapes are closed sets drawn from path data inside the tool, so a diagram wanting one that is not there has nowhere to go.
|
|
82
90
|
|
|
83
91
|
The language is not stable. Expect the syntax to change.
|
|
84
92
|
|
|
85
93
|
## How it works
|
|
86
94
|
|
|
87
|
-
A gap is a *minimum* distance, never an exact one. Say two things sit side by side, then say a third goes between them, and the first two are pushed apart by exactly what the third needs; delete the third and they close back up. That is the step an author otherwise does by hand — shove things apart to make room, then drag everything back so the diagram is not full of holes — and no number goes stale when a
|
|
95
|
+
A gap is a *minimum* distance, never an exact one. Say two things sit side by side, then say a third goes between them, and the first two are pushed apart by exactly what the third needs; delete the third and they close back up. That is the step an author otherwise does by hand — shove things apart to make room, then drag everything back so the diagram is not full of holes — and no number goes stale when a text grows.
|
|
88
96
|
|
|
89
97
|
So the resolver solves a system rather than walking a chain. Each axis is a set of minimum distances, and the tightest arrangement satisfying all of them is found by longest paths: one answer, no search, no arrangement ever tried and rejected. The engine works out distances; which side of what a thing sits on came from the file.
|
|
90
98
|
|
|
91
|
-
That is also what makes non-overlap affordable, so it holds for every pair of
|
|
99
|
+
That is also what makes non-overlap affordable, so it holds for every pair of nodes without anyone writing it down. On its own "these two must not overlap" is a choice among four directions, which is the search this design refuses — but the file has usually settled it already: if your arrangement lets one node travel away from another and offers no way back, that is the only separation it permits. Where the file orders a pair on neither axis, the tool names them rather than guessing; where it orders them on both, the tie breaks toward the axis of least overlap, which is the smallest movement and the one place the tool decides something nobody wrote.
|
|
92
100
|
|
|
93
101
|
Nothing is nudged. Each round derives the separations the file already implied, adds them as ordinary minimum distances, and solves the whole thing again from scratch — repairing a solved layout in place is the thing being avoided.
|
|
94
102
|
|
|
@@ -98,22 +106,22 @@ Nothing is nudged. Each round derives the separations the file already implied,
|
|
|
98
106
|
- Deterministic resolver: minimum distances in, tightest arrangement out *(done)*
|
|
99
107
|
- Static SVG renderer *(done)*
|
|
100
108
|
- A command-line tool: text file in, SVG out *(done)*
|
|
101
|
-
- A placement grammar that can say what a real diagram needs: several placements on one
|
|
102
|
-
-
|
|
103
|
-
- Minimal
|
|
109
|
+
- A placement grammar that can say what a real diagram needs: several placements on one node, one thing between two others, exact side-to-side alignment *(done)*
|
|
110
|
+
- Nodes that do not overlap by default, with the separation direction derived from the stated arrangement *(done)*
|
|
111
|
+
- Minimal node-avoiding edge routing
|
|
104
112
|
- Machine-readable diagnostics from the solved geometry
|
|
105
113
|
|
|
106
|
-
Diagnostics are a real output rather than a debugging aid. What they cannot do is stand in for the grammar: a check catches only what the language genuinely leaves open, and "these must not overlap" rules arrangements out without naming one, so it can never place anything. Everything the source cannot tell you is computable once the geometry is solved, with no image involved: overlapping
|
|
114
|
+
Diagnostics are a real output rather than a debugging aid. What they cannot do is stand in for the grammar: a check catches only what the language genuinely leaves open, and "these must not overlap" rules arrangements out without naming one, so it can never place anything. Everything the source cannot tell you is computable once the geometry is solved, with no image involved: overlapping nodes, crossed edges, text exceeding its container, anything off-canvas, large dead regions. So the tool reports `hub overlaps laptop1` and `edge auth->db crosses 4 edges`, and the fix is written in the same vocabulary as the source. An agent working this way reads a report about a text file it wrote and edits that text file — no rendering, no vision model, no pixel arithmetic.
|
|
107
115
|
|
|
108
|
-
A diagnostic never repairs a solved layout in place. That is the line the design holds: a checker allowed to nudge
|
|
116
|
+
A diagnostic never repairs a solved layout in place. That is the line the design holds: a checker allowed to nudge nodes is a layout algorithm with a bad search strategy, fixing one overlap into the next with no view of the whole. Deriving a constraint the file already implied and solving the whole system again is a different thing, and is how non-overlap works. What is left over — anything the source genuinely does not settle — is reported, naming the statement that was broken, and the author edits the source. Open, and it decides how far this goes: may a diagnostic describe a fix in words, or only name the symptom? Describing one means the tool has an opinion about layout, which is the auto-layout instinct coming back in through the side door.
|
|
109
117
|
|
|
110
118
|
Three design problems decide how much machinery this needs, and the first outranks the other two:
|
|
111
119
|
|
|
112
|
-
**Saying enough.** The benchmark contains arrangements the grammar cannot express at all, which is why some
|
|
120
|
+
**Saying enough.** The benchmark contains arrangements the grammar cannot express at all, which is why some nodes land in the wrong place no matter how the file is written. So the work is adding statements, not restricting them. Expressiveness is not the danger; the engine *choosing* an arrangement is.
|
|
113
121
|
|
|
114
|
-
**What the engine is allowed to decide.** Auto-layout is refused, because a picture chosen by an algorithm is not predictable from its source, and that predictability is the entire point. Working out coordinates from an arrangement the author stated is a different thing and is simply the job. The test between them: the engine's freedom may affect distances and never relationships. If a default can change which side of something a
|
|
122
|
+
**What the engine is allowed to decide.** Auto-layout is refused, because a picture chosen by an algorithm is not predictable from its source, and that predictability is the entire point. Working out coordinates from an arrangement the author stated is a different thing and is simply the job. The test between them: the engine's freedom may affect distances and never relationships. If a default can change which side of something a node sits on, the language was short a statement and the tool should say so rather than guess.
|
|
115
123
|
|
|
116
|
-
**Overlap and edge routing.** Relative placement with default spacing collides as soon as two clusters grow toward each other. Stating placement and then routing edges afterward with no influence on them reproduces the exact failure this is meant to avoid, so minimal
|
|
124
|
+
**Overlap and edge routing.** Relative placement with default spacing collides as soon as two clusters grow toward each other. Stating placement and then routing edges afterward with no influence on them reproduces the exact failure this is meant to avoid, so minimal node-avoiding orthogonal routing belongs in the first version. Routing and diagnostics are complements, not substitutes: routing fixes what it can, and the diagnostics report what it could not.
|
|
117
125
|
|
|
118
126
|
## Prior art
|
|
119
127
|
|