kymostudio 0.2.3 → 0.2.5
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 +20 -0
- package/dist/alignment.d.ts +18 -0
- package/dist/alignment.d.ts.map +1 -0
- package/dist/alignment.js +436 -0
- package/dist/alignment.js.map +1 -0
- package/dist/dsl.d.ts +38 -0
- package/dist/dsl.d.ts.map +1 -0
- package/dist/dsl.js +538 -0
- package/dist/dsl.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/layout.d.ts +57 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +393 -0
- package/dist/layout.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,6 +9,26 @@ Diagram-as-code: turn a declarative `.diagram` DSL — or a standard BPMN 2.0
|
|
|
9
9
|
npm install kymostudio
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
+
## Render a `.diagram` DSL file
|
|
13
|
+
|
|
14
|
+
`parseDiagram(src)` runs the full front-end pipeline — parse the declarative
|
|
15
|
+
DSL, then position everything (grid / Figma-style auto-layout, parent/child
|
|
16
|
+
alignment, auto-bounded regions, auto-canvas sizing) — returning a positioned
|
|
17
|
+
Diagram. Equivalent to the Python `kymo` CLI's `.diagram` path.
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { parseDiagram, renderSVG } from "kymostudio";
|
|
21
|
+
import { readFileSync } from "node:fs";
|
|
22
|
+
|
|
23
|
+
const svg = await renderSVG(parseDiagram(readFileSync("arch.diagram", "utf8")));
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
For finer control the stages are exported individually — `parse(src)` returns
|
|
27
|
+
`{ diagram, layout, external }` (unresolved), then `layout(diagram, …)` and
|
|
28
|
+
`resolveAlignments(diagram)` mutate it into place. See
|
|
29
|
+
[`docs/DSL.md`](https://github.com/kymostudio/kymostudio/blob/main/docs/DSL.md)
|
|
30
|
+
for the grammar.
|
|
31
|
+
|
|
12
32
|
## Convert a BPMN file
|
|
13
33
|
|
|
14
34
|
`parseBpmn(xml)` reads a standard `.bpmn` file (from bpmn.io / Camunda /
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local alignment — JS port of `packages/python/src/kymo/alignment.py`.
|
|
3
|
+
*
|
|
4
|
+
* The post-parse resolver that turns declared relationships into absolute
|
|
5
|
+
* geometry. Six passes, run in order by {@link resolveAlignments}:
|
|
6
|
+
* 1. auto-layouts — Figma-style: regions with a `layout` direction
|
|
7
|
+
* position every child along that axis.
|
|
8
|
+
* 2. component alignments — pairwise parent/child anchoring (`@ parent side`).
|
|
9
|
+
* 3. region bounds — bounding boxes from the enclosed components.
|
|
10
|
+
* 4. fan-in / fan-out — stagger shared-anchor ports so arrows fan out.
|
|
11
|
+
* 5. trunk lanes — channel-route parallel Z-edges into lanes.
|
|
12
|
+
* 6. auto-size canvas — derive width/height + snap to an 8px grid.
|
|
13
|
+
*
|
|
14
|
+
* Independent implementation kept at parity with the Python algorithm.
|
|
15
|
+
*/
|
|
16
|
+
import { type Diagram } from "./model.js";
|
|
17
|
+
export declare function resolveAlignments(diagram: Diagram): void;
|
|
18
|
+
//# sourceMappingURL=alignment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alignment.d.ts","sourceRoot":"","sources":["../src/alignment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAEW,KAAK,OAAO,EAC7B,MAAM,YAAY,CAAC;AAuDpB,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAOxD"}
|
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local alignment — JS port of `packages/python/src/kymo/alignment.py`.
|
|
3
|
+
*
|
|
4
|
+
* The post-parse resolver that turns declared relationships into absolute
|
|
5
|
+
* geometry. Six passes, run in order by {@link resolveAlignments}:
|
|
6
|
+
* 1. auto-layouts — Figma-style: regions with a `layout` direction
|
|
7
|
+
* position every child along that axis.
|
|
8
|
+
* 2. component alignments — pairwise parent/child anchoring (`@ parent side`).
|
|
9
|
+
* 3. region bounds — bounding boxes from the enclosed components.
|
|
10
|
+
* 4. fan-in / fan-out — stagger shared-anchor ports so arrows fan out.
|
|
11
|
+
* 5. trunk lanes — channel-route parallel Z-edges into lanes.
|
|
12
|
+
* 6. auto-size canvas — derive width/height + snap to an 8px grid.
|
|
13
|
+
*
|
|
14
|
+
* Independent implementation kept at parity with the Python algorithm.
|
|
15
|
+
*/
|
|
16
|
+
import { LABEL_HEIGHT, componentHalf, regionHalf, anchor, resolveAnchors, getComponent, } from "./model.js";
|
|
17
|
+
const NAME_CHAR_W = 7; // 14px bold sans ≈ 7 px/char
|
|
18
|
+
const SUB_CHAR_W = 6; // 11.5px regular sans ≈ 6 px/char
|
|
19
|
+
/** Round half-to-even, matching Python's built-in `round()` — so grid snapping
|
|
20
|
+
* and lane offsets land on the same pixels as the Python implementation
|
|
21
|
+
* (`Math.round` differs only at exact .5 boundaries, where it rounds up). */
|
|
22
|
+
function pyRound(x) {
|
|
23
|
+
const f = Math.floor(x);
|
|
24
|
+
const diff = x - f;
|
|
25
|
+
if (diff < 0.5)
|
|
26
|
+
return f;
|
|
27
|
+
if (diff > 0.5)
|
|
28
|
+
return f + 1;
|
|
29
|
+
return f % 2 === 0 ? f : f + 1; // exactly .5 → nearest even
|
|
30
|
+
}
|
|
31
|
+
function isRegion(n) {
|
|
32
|
+
return "bounds" in n;
|
|
33
|
+
}
|
|
34
|
+
function halfOf(n) {
|
|
35
|
+
return isRegion(n) ? regionHalf(n) : componentHalf(n);
|
|
36
|
+
}
|
|
37
|
+
/** Geometric centre of a node — components carry it as `pos`, regions derive
|
|
38
|
+
* it from `bounds` (Python sorts fan-in/out by the other endpoint's pos). */
|
|
39
|
+
function centerOf(n) {
|
|
40
|
+
return isRegion(n) ? anchor(n, "center") : n.pos;
|
|
41
|
+
}
|
|
42
|
+
function labelHalfWidth(c) {
|
|
43
|
+
if (c.shape === "annotation" || c.shape === "badge")
|
|
44
|
+
return 0;
|
|
45
|
+
const nameW = c.name.length * NAME_CHAR_W;
|
|
46
|
+
const subW = c.subtitle.length * SUB_CHAR_W;
|
|
47
|
+
return Math.floor(Math.max(nameW, subW) / 2);
|
|
48
|
+
}
|
|
49
|
+
function effectiveHalf(c) {
|
|
50
|
+
const [hw, hh] = componentHalf(c);
|
|
51
|
+
return [Math.max(hw, labelHalfWidth(c)), hh];
|
|
52
|
+
}
|
|
53
|
+
function isZeroBounds(b) {
|
|
54
|
+
return b[0] === 0 && b[1] === 0 && b[2] === 0 && b[3] === 0;
|
|
55
|
+
}
|
|
56
|
+
function buildNodeMap(diagram) {
|
|
57
|
+
const m = new Map();
|
|
58
|
+
for (const r of diagram.regions)
|
|
59
|
+
m.set(r.id, r);
|
|
60
|
+
for (const c of diagram.components)
|
|
61
|
+
m.set(c.id, c); // components win on collision
|
|
62
|
+
return m;
|
|
63
|
+
}
|
|
64
|
+
export function resolveAlignments(diagram) {
|
|
65
|
+
resolveAutoLayouts(diagram);
|
|
66
|
+
resolveComponentAlignments(diagram);
|
|
67
|
+
resolveRegionBounds(diagram);
|
|
68
|
+
staggerFaninEdges(diagram);
|
|
69
|
+
staggerTrunkLanes(diagram);
|
|
70
|
+
autoSizeCanvas(diagram);
|
|
71
|
+
}
|
|
72
|
+
// ── Pass 5: trunk-lane channel routing ─────────────────────────────────
|
|
73
|
+
function staggerTrunkLanes(diagram, minStep = 8, maxStep = 16) {
|
|
74
|
+
const byId = buildNodeMap(diagram);
|
|
75
|
+
const horiz = new Map();
|
|
76
|
+
const vert = new Map();
|
|
77
|
+
const push = (m, key, entry) => {
|
|
78
|
+
const arr = m.get(key);
|
|
79
|
+
if (arr)
|
|
80
|
+
arr.push(entry);
|
|
81
|
+
else
|
|
82
|
+
m.set(key, [entry]);
|
|
83
|
+
};
|
|
84
|
+
for (const e of diagram.edges) {
|
|
85
|
+
if (e.via.length)
|
|
86
|
+
continue; // explicit routing wins
|
|
87
|
+
const src = byId.get(e.src);
|
|
88
|
+
const dst = byId.get(e.dst);
|
|
89
|
+
if (!src || !dst)
|
|
90
|
+
continue;
|
|
91
|
+
const [sa, da] = resolveAnchors(e, src, dst);
|
|
92
|
+
const sp = anchor(src, sa);
|
|
93
|
+
const dp = anchor(dst, da);
|
|
94
|
+
if (sp[0] === dp[0] || sp[1] === dp[1])
|
|
95
|
+
continue; // already axis-aligned
|
|
96
|
+
if (sa === "left" || sa === "right") {
|
|
97
|
+
push(horiz, `${pyRound(sp[0] / 8) * 8},${pyRound(dp[0] / 8) * 8}`, { e, sp, dp });
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
push(vert, `${pyRound(sp[1] / 8) * 8},${pyRound(dp[1] / 8) * 8}`, { e, sp, dp });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const assign = (entries, sortIdx, channelWidth) => {
|
|
104
|
+
const n = entries.length;
|
|
105
|
+
if (n <= 1)
|
|
106
|
+
return;
|
|
107
|
+
const overlaps = (t1, t2) => {
|
|
108
|
+
const r1 = [t1.sp[sortIdx], t1.dp[sortIdx]].sort((a, b) => a - b);
|
|
109
|
+
const r2 = [t2.sp[sortIdx], t2.dp[sortIdx]].sort((a, b) => a - b);
|
|
110
|
+
return Math.max(r1[0], r2[0]) < Math.min(r1[1], r2[1]);
|
|
111
|
+
};
|
|
112
|
+
let any = false;
|
|
113
|
+
for (let i = 0; i < n && !any; i++) {
|
|
114
|
+
for (let j = i + 1; j < n; j++) {
|
|
115
|
+
if (overlaps(entries[i], entries[j])) {
|
|
116
|
+
any = true;
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (!any)
|
|
122
|
+
return;
|
|
123
|
+
const step = Math.max(minStep, Math.min(maxStep, Math.floor(channelWidth / (n + 1))));
|
|
124
|
+
entries.sort((a, b) => (a.sp[sortIdx] - b.sp[sortIdx]) || (a.dp[sortIdx] - b.dp[sortIdx]));
|
|
125
|
+
const mid = (n - 1) / 2;
|
|
126
|
+
entries.forEach((t, i) => { t.e.trunkOffset = pyRound((i - mid) * step); });
|
|
127
|
+
};
|
|
128
|
+
for (const [key, entries] of horiz) {
|
|
129
|
+
const [srcX, dstX] = key.split(",").map(Number);
|
|
130
|
+
assign(entries, 1, Math.abs(dstX - srcX));
|
|
131
|
+
}
|
|
132
|
+
for (const [key, entries] of vert) {
|
|
133
|
+
const [srcY, dstY] = key.split(",").map(Number);
|
|
134
|
+
assign(entries, 0, Math.abs(dstY - srcY));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function staggerFaninEdges(diagram) {
|
|
138
|
+
const byId = buildNodeMap(diagram);
|
|
139
|
+
const fanin = new Map();
|
|
140
|
+
const fanout = new Map();
|
|
141
|
+
const push = (m, key, entry) => {
|
|
142
|
+
const arr = m.get(key);
|
|
143
|
+
if (arr)
|
|
144
|
+
arr.push(entry);
|
|
145
|
+
else
|
|
146
|
+
m.set(key, [entry]);
|
|
147
|
+
};
|
|
148
|
+
for (const e of diagram.edges) {
|
|
149
|
+
const src = byId.get(e.src);
|
|
150
|
+
const dst = byId.get(e.dst);
|
|
151
|
+
if (!src || !dst)
|
|
152
|
+
continue;
|
|
153
|
+
const [sa, da] = resolveAnchors(e, src, dst);
|
|
154
|
+
const entry = { e, src, dst, sa, da };
|
|
155
|
+
push(fanin, `${e.dst}|${da}`, entry);
|
|
156
|
+
push(fanout, `${e.src}|${sa}`, entry);
|
|
157
|
+
}
|
|
158
|
+
const STEP = 16;
|
|
159
|
+
const spread = (entriesIn, anchorSide, attr, nodeOf, otherOf, minCount) => {
|
|
160
|
+
let entries = entriesIn;
|
|
161
|
+
let n = entries.length;
|
|
162
|
+
if (n < minCount)
|
|
163
|
+
return;
|
|
164
|
+
if (attr === "srcOffset") {
|
|
165
|
+
entries = entries.filter((t) => !t.e.sharedPort); // shared-port edges opt out
|
|
166
|
+
if (entries.length < 1)
|
|
167
|
+
return;
|
|
168
|
+
n = entries.length;
|
|
169
|
+
}
|
|
170
|
+
const node = nodeOf(entries[0]);
|
|
171
|
+
if (anchorSide === "left" || anchorSide === "right") {
|
|
172
|
+
const crossSpan = halfOf(node)[1] * 2;
|
|
173
|
+
entries.sort((a, b) => centerOf(otherOf(a))[1] - centerOf(otherOf(b))[1]);
|
|
174
|
+
const spreadTotal = Math.min(crossSpan - 16, STEP * (n - 1));
|
|
175
|
+
const mid = (n - 1) / 2;
|
|
176
|
+
entries.forEach((t, i) => {
|
|
177
|
+
const dy = pyRound(((i - mid) / Math.max(mid, 1)) * (spreadTotal / 2));
|
|
178
|
+
const cur = t.e[attr];
|
|
179
|
+
t.e[attr] = [cur[0], cur[1] + dy];
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
else if (anchorSide === "top" || anchorSide === "bottom") {
|
|
183
|
+
const crossSpan = halfOf(node)[0] * 2;
|
|
184
|
+
entries.sort((a, b) => centerOf(otherOf(a))[0] - centerOf(otherOf(b))[0]);
|
|
185
|
+
const spreadTotal = Math.min(crossSpan - 16, STEP * (n - 1));
|
|
186
|
+
const mid = (n - 1) / 2;
|
|
187
|
+
entries.forEach((t, i) => {
|
|
188
|
+
const dx = pyRound(((i - mid) / Math.max(mid, 1)) * (spreadTotal / 2));
|
|
189
|
+
const cur = t.e[attr];
|
|
190
|
+
t.e[attr] = [cur[0] + dx, cur[1]];
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
for (const [key, entries] of fanin) {
|
|
195
|
+
const da = key.split("|")[1];
|
|
196
|
+
spread(entries, da, "dstOffset", (t) => t.dst, (t) => t.src, 2);
|
|
197
|
+
}
|
|
198
|
+
for (const [key, entries] of fanout) {
|
|
199
|
+
const sa = key.split("|")[1];
|
|
200
|
+
spread(entries, sa, "srcOffset", (t) => t.src, (t) => t.dst, 3);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// ── Pass 6: auto-size canvas + snap to grid ────────────────────────────
|
|
204
|
+
function autoSizeCanvas(diagram, margin = 30) {
|
|
205
|
+
if (diagram.width > 0 && diagram.height > 0)
|
|
206
|
+
return;
|
|
207
|
+
let minX = 1e9, minY = 1e9, maxX = -1e9, maxY = -1e9;
|
|
208
|
+
for (const c of diagram.components) {
|
|
209
|
+
const effHw = Math.max(componentHalf(c)[0], labelHalfWidth(c));
|
|
210
|
+
const lh = (c.name || c.subtitle) ? (LABEL_HEIGHT[c.shape] ?? 0) : 0;
|
|
211
|
+
minX = Math.min(minX, c.pos[0] - effHw);
|
|
212
|
+
maxX = Math.max(maxX, c.pos[0] + effHw);
|
|
213
|
+
minY = Math.min(minY, c.pos[1] - componentHalf(c)[1]);
|
|
214
|
+
maxY = Math.max(maxY, c.pos[1] + componentHalf(c)[1] + lh);
|
|
215
|
+
}
|
|
216
|
+
for (const r of diagram.regions) {
|
|
217
|
+
if (isZeroBounds(r.bounds))
|
|
218
|
+
continue;
|
|
219
|
+
const [x, y, w, h] = r.bounds;
|
|
220
|
+
minX = Math.min(minX, x);
|
|
221
|
+
minY = Math.min(minY, y);
|
|
222
|
+
maxX = Math.max(maxX, x + w);
|
|
223
|
+
maxY = Math.max(maxY, y + h);
|
|
224
|
+
}
|
|
225
|
+
for (const e of diagram.edges) {
|
|
226
|
+
for (const [vx, vy] of e.via) {
|
|
227
|
+
minX = Math.min(minX, vx);
|
|
228
|
+
minY = Math.min(minY, vy);
|
|
229
|
+
maxX = Math.max(maxX, vx);
|
|
230
|
+
maxY = Math.max(maxY, vy);
|
|
231
|
+
}
|
|
232
|
+
if (e.labelPos) {
|
|
233
|
+
minX = Math.min(minX, e.labelPos[0]);
|
|
234
|
+
minY = Math.min(minY, e.labelPos[1]);
|
|
235
|
+
maxX = Math.max(maxX, e.labelPos[0]);
|
|
236
|
+
maxY = Math.max(maxY, e.labelPos[1]);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (minX > maxX)
|
|
240
|
+
return; // nothing to size against
|
|
241
|
+
const dx = minX < margin ? margin - minX : 0;
|
|
242
|
+
const dy = minY < margin ? margin - minY : 0;
|
|
243
|
+
if (dx || dy) {
|
|
244
|
+
for (const c of diagram.components)
|
|
245
|
+
c.pos = [c.pos[0] + dx, c.pos[1] + dy];
|
|
246
|
+
for (const r of diagram.regions) {
|
|
247
|
+
if (isZeroBounds(r.bounds))
|
|
248
|
+
continue;
|
|
249
|
+
const [x, y, w, h] = r.bounds;
|
|
250
|
+
r.bounds = [x + dx, y + dy, w, h];
|
|
251
|
+
}
|
|
252
|
+
for (const e of diagram.edges) {
|
|
253
|
+
e.via = e.via.map(([vx, vy]) => [vx + dx, vy + dy]);
|
|
254
|
+
if (e.labelPos)
|
|
255
|
+
e.labelPos = [e.labelPos[0] + dx, e.labelPos[1] + dy];
|
|
256
|
+
}
|
|
257
|
+
maxX += dx;
|
|
258
|
+
maxY += dy;
|
|
259
|
+
}
|
|
260
|
+
if (diagram.width === 0)
|
|
261
|
+
diagram.width = maxX + margin;
|
|
262
|
+
if (diagram.height === 0)
|
|
263
|
+
diagram.height = maxY + margin;
|
|
264
|
+
// Enforce min 4:3 landscape aspect: pad width and re-centre horizontally.
|
|
265
|
+
if (diagram.width * 3 < diagram.height * 4) {
|
|
266
|
+
const newW = Math.floor((diagram.height * 4) / 3);
|
|
267
|
+
const shift = Math.floor((newW - diagram.width) / 2);
|
|
268
|
+
for (const c of diagram.components)
|
|
269
|
+
c.pos = [c.pos[0] + shift, c.pos[1]];
|
|
270
|
+
for (const r of diagram.regions) {
|
|
271
|
+
if (isZeroBounds(r.bounds))
|
|
272
|
+
continue;
|
|
273
|
+
const [x, y, w, h] = r.bounds;
|
|
274
|
+
r.bounds = [x + shift, y, w, h];
|
|
275
|
+
}
|
|
276
|
+
for (const e of diagram.edges) {
|
|
277
|
+
e.via = e.via.map(([vx, vy]) => [vx + shift, vy]);
|
|
278
|
+
if (e.labelPos)
|
|
279
|
+
e.labelPos = [e.labelPos[0] + shift, e.labelPos[1]];
|
|
280
|
+
}
|
|
281
|
+
diagram.width = newW;
|
|
282
|
+
}
|
|
283
|
+
snapToGrid(diagram);
|
|
284
|
+
}
|
|
285
|
+
function snapToGrid(diagram, grid = 8) {
|
|
286
|
+
const s = (v) => pyRound(v / grid) * grid;
|
|
287
|
+
const sUp = (v) => Math.floor((v + grid - 1) / grid) * grid;
|
|
288
|
+
for (const c of diagram.components)
|
|
289
|
+
c.pos = [s(c.pos[0]), s(c.pos[1])];
|
|
290
|
+
for (const e of diagram.edges) {
|
|
291
|
+
e.via = e.via.map(([vx, vy]) => [s(vx), s(vy)]);
|
|
292
|
+
if (e.labelPos)
|
|
293
|
+
e.labelPos = [s(e.labelPos[0]), s(e.labelPos[1])];
|
|
294
|
+
}
|
|
295
|
+
const byId = new Map(diagram.components.map((c) => [c.id, c]));
|
|
296
|
+
for (const r of diagram.regions) {
|
|
297
|
+
if (isZeroBounds(r.bounds) || !r.contains.length)
|
|
298
|
+
continue;
|
|
299
|
+
const cells = r.contains.map((cid) => byId.get(cid)).filter((c) => !!c);
|
|
300
|
+
if (!cells.length)
|
|
301
|
+
continue;
|
|
302
|
+
const [padX, padY] = r.padding;
|
|
303
|
+
const padB = r.paddingBottom ?? padY;
|
|
304
|
+
const xsLeft = cells.map((c) => c.pos[0] - Math.max(componentHalf(c)[0], labelHalfWidth(c)));
|
|
305
|
+
const xsRight = cells.map((c) => c.pos[0] + Math.max(componentHalf(c)[0], labelHalfWidth(c)));
|
|
306
|
+
const ysTop = cells.map((c) => c.pos[1] - componentHalf(c)[1]);
|
|
307
|
+
const ysBot = cells.map((c) => c.pos[1] + componentHalf(c)[1] + ((c.name || c.subtitle) ? (LABEL_HEIGHT[c.shape] ?? 0) : 0));
|
|
308
|
+
const x = Math.min(...xsLeft) - padX;
|
|
309
|
+
const y = Math.min(...ysTop) - padY;
|
|
310
|
+
r.bounds = [x, y, Math.max(...xsRight) - x + padX, Math.max(...ysBot) - y + padB];
|
|
311
|
+
}
|
|
312
|
+
diagram.width = sUp(diagram.width);
|
|
313
|
+
diagram.height = sUp(diagram.height);
|
|
314
|
+
}
|
|
315
|
+
// ── Pass 1: Figma-style auto-layouts ───────────────────────────────────
|
|
316
|
+
function resolveAutoLayouts(diagram) {
|
|
317
|
+
for (const r of diagram.regions) {
|
|
318
|
+
const dir = r.layout;
|
|
319
|
+
if (dir == null)
|
|
320
|
+
continue;
|
|
321
|
+
if (r.pos == null)
|
|
322
|
+
continue;
|
|
323
|
+
if (!r.contains.length)
|
|
324
|
+
continue;
|
|
325
|
+
const children = r.contains.map((cid) => getComponent(diagram, cid));
|
|
326
|
+
const [padX, padY] = r.padding;
|
|
327
|
+
const [ox, oy] = r.pos;
|
|
328
|
+
let cursorX = ox + padX;
|
|
329
|
+
let cursorY = oy + padY;
|
|
330
|
+
const effs = children.map(effectiveHalf);
|
|
331
|
+
if (dir === "horizontal") {
|
|
332
|
+
const maxH = Math.max(...effs.map(([, eh]) => eh));
|
|
333
|
+
children.forEach((c, i) => {
|
|
334
|
+
const [ew] = effs[i];
|
|
335
|
+
const ch = componentHalf(c)[1];
|
|
336
|
+
let cy;
|
|
337
|
+
if (r.align === "start")
|
|
338
|
+
cy = cursorY + ch;
|
|
339
|
+
else if (r.align === "end")
|
|
340
|
+
cy = cursorY + 2 * maxH - ch;
|
|
341
|
+
else
|
|
342
|
+
cy = cursorY + maxH;
|
|
343
|
+
c.pos = [cursorX + ew, cy];
|
|
344
|
+
cursorX += ew * 2 + r.gap;
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
const maxW = Math.max(...effs.map(([ew]) => ew));
|
|
349
|
+
children.forEach((c, i) => {
|
|
350
|
+
const [, eh] = effs[i];
|
|
351
|
+
const cw = componentHalf(c)[0];
|
|
352
|
+
let cx;
|
|
353
|
+
if (r.align === "start")
|
|
354
|
+
cx = cursorX + cw;
|
|
355
|
+
else if (r.align === "end")
|
|
356
|
+
cx = cursorX + 2 * maxW - cw;
|
|
357
|
+
else
|
|
358
|
+
cx = cursorX + maxW;
|
|
359
|
+
c.pos = [cx, cursorY + eh];
|
|
360
|
+
cursorY += eh * 2 + r.gap;
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
// ── Pass 2: parent/child alignment ─────────────────────────────────────
|
|
366
|
+
function resolveComponentAlignments(diagram) {
|
|
367
|
+
const resolved = new Set();
|
|
368
|
+
const resolve = (cid, path) => {
|
|
369
|
+
if (resolved.has(cid))
|
|
370
|
+
return;
|
|
371
|
+
if (path.includes(cid)) {
|
|
372
|
+
throw new Error(`alignment cycle: ${[...path, cid].join(" → ")}`);
|
|
373
|
+
}
|
|
374
|
+
const comp = getComponent(diagram, cid);
|
|
375
|
+
if (comp.parent === null) {
|
|
376
|
+
resolved.add(cid);
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
resolve(comp.parent, [...path, cid]);
|
|
380
|
+
const parent = getComponent(diagram, comp.parent);
|
|
381
|
+
if (comp.align === null) {
|
|
382
|
+
throw new Error(`component ${JSON.stringify(cid)} has parent=${JSON.stringify(comp.parent)} but no align side`);
|
|
383
|
+
}
|
|
384
|
+
comp.pos = alignTo(parent, comp, comp.align, comp.alignGap, comp.alignOffset);
|
|
385
|
+
resolved.add(cid);
|
|
386
|
+
};
|
|
387
|
+
for (const c of diagram.components)
|
|
388
|
+
resolve(c.id, []);
|
|
389
|
+
}
|
|
390
|
+
// ── Pass 3: region bounds from contents ────────────────────────────────
|
|
391
|
+
function resolveRegionBounds(diagram) {
|
|
392
|
+
for (const r of diagram.regions) {
|
|
393
|
+
if (!r.contains.length)
|
|
394
|
+
continue;
|
|
395
|
+
const cells = r.contains.map((cid) => getComponent(diagram, cid));
|
|
396
|
+
const [padX, padY] = r.padding;
|
|
397
|
+
const padB = r.paddingBottom ?? padY;
|
|
398
|
+
const effHws = cells.map((c) => Math.max(componentHalf(c)[0], labelHalfWidth(c)));
|
|
399
|
+
const xsLeft = cells.map((c, i) => c.pos[0] - effHws[i]);
|
|
400
|
+
const xsRight = cells.map((c, i) => c.pos[0] + effHws[i]);
|
|
401
|
+
const ysTop = cells.map((c) => c.pos[1] - componentHalf(c)[1]);
|
|
402
|
+
const ysBot = cells.map((c) => c.pos[1] + componentHalf(c)[1] + ((c.name || c.subtitle) ? (LABEL_HEIGHT[c.shape] ?? 0) : 0));
|
|
403
|
+
const x = Math.min(...xsLeft) - padX;
|
|
404
|
+
const y = Math.min(...ysTop) - padY;
|
|
405
|
+
r.bounds = [x, y, Math.max(...xsRight) - x + padX, Math.max(...ysBot) - y + padB];
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
function alignTo(parent, child, side, gap, offset) {
|
|
409
|
+
const [px, py] = parent.pos;
|
|
410
|
+
const [pHw, pHh] = componentHalf(parent);
|
|
411
|
+
const pLabel = LABEL_HEIGHT[parent.shape] ?? 0;
|
|
412
|
+
const [cHw, cHh] = componentHalf(child);
|
|
413
|
+
const [ox, oy] = offset;
|
|
414
|
+
let cx, cy;
|
|
415
|
+
switch (side) {
|
|
416
|
+
case "right":
|
|
417
|
+
cx = px + pHw + gap + cHw;
|
|
418
|
+
cy = py;
|
|
419
|
+
break;
|
|
420
|
+
case "left":
|
|
421
|
+
cx = px - pHw - gap - cHw;
|
|
422
|
+
cy = py;
|
|
423
|
+
break;
|
|
424
|
+
case "bottom":
|
|
425
|
+
cx = px;
|
|
426
|
+
cy = py + pHh + pLabel + gap + cHh;
|
|
427
|
+
break;
|
|
428
|
+
case "top":
|
|
429
|
+
cx = px;
|
|
430
|
+
cy = py - pHh - gap - cHh;
|
|
431
|
+
break;
|
|
432
|
+
default: throw new Error(`unknown align side: ${JSON.stringify(side)}`);
|
|
433
|
+
}
|
|
434
|
+
return [cx + ox, cy + oy];
|
|
435
|
+
}
|
|
436
|
+
//# sourceMappingURL=alignment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alignment.js","sourceRoot":"","sources":["../src/alignment.ts"],"names":[],"mappings":"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"}
|
package/dist/dsl.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D2-style DSL parser — JS port of `packages/python/src/kymo/dsl.py`.
|
|
3
|
+
*
|
|
4
|
+
* Line-based, brace-delimited surface for {@link Diagram}. There is no
|
|
5
|
+
* `component` / `region` keyword — lines are disambiguated by shape:
|
|
6
|
+
*
|
|
7
|
+
* • line ending in `{`, second token ∈ outer|inner|cluster → region
|
|
8
|
+
* • line ending in `{`, second token ∈ horizontal|vertical → layout frame
|
|
9
|
+
* • `id arrow id …` → edge
|
|
10
|
+
* • `id shape/icon/accent "Name" "Sub" [@ …]` → leaf component
|
|
11
|
+
* • bare ids (inside a container body) → membership refs
|
|
12
|
+
* • `row id1 id2 …` (inside a region body) → grid row
|
|
13
|
+
*
|
|
14
|
+
* `parse()` returns the unresolved diagram plus the grid-layout / external
|
|
15
|
+
* specs (mirroring the Python tuple). `parseDiagram()` runs the full CLI
|
|
16
|
+
* pipeline (parse → layout → resolveAlignments) and returns a positioned
|
|
17
|
+
* {@link Diagram} ready for {@link renderSVG}.
|
|
18
|
+
*
|
|
19
|
+
* Independent implementation kept at parity with the Python parser, which
|
|
20
|
+
* remains the normative reference alongside `docs/DSL.md`.
|
|
21
|
+
*/
|
|
22
|
+
import { type Diagram, type Region } from "./model.js";
|
|
23
|
+
import { type LayoutNode, type RegionLayout, type ExternalSpec } from "./layout.js";
|
|
24
|
+
export interface ParseResult {
|
|
25
|
+
diagram: Diagram;
|
|
26
|
+
layout: RegionLayout | null;
|
|
27
|
+
external: ExternalSpec | null;
|
|
28
|
+
}
|
|
29
|
+
export declare function parse(dsl: string): ParseResult;
|
|
30
|
+
/** Full front-end pipeline: parse → grid layout → alignment resolution.
|
|
31
|
+
* Returns a positioned {@link Diagram} ready for `renderSVG`. */
|
|
32
|
+
export declare function parseDiagram(dsl: string): Diagram;
|
|
33
|
+
export declare function parseLayoutTree(expr: string, lineNo: number): LayoutNode;
|
|
34
|
+
/** Replace a leaf whose id matches a directional region with a sub-tree built
|
|
35
|
+
* from that region's `contains` + `layout` direction, so the layout DSL stays
|
|
36
|
+
* flat. Regions without a direction stay opaque (a single leaf). */
|
|
37
|
+
export declare function inlineRegionLeaves(tree: LayoutNode, regionsById: Map<string, Region>): LayoutNode;
|
|
38
|
+
//# sourceMappingURL=dsl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dsl.d.ts","sourceRoot":"","sources":["../src/dsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAEW,KAAK,OAAO,EAAa,KAAK,MAAM,EACrD,MAAM,YAAY,CAAC;AACpB,OAAO,EAEL,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EACtD,MAAM,aAAa,CAAC;AA0CrB,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;CAC/B;AAGD,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAQ9C;AAED;kEACkE;AAClE,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAKjD;AA8VD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,CAQxE;AAwDD;;qEAEqE;AACrE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,UAAU,CAWjG"}
|