@diagrammo/dgmo 0.84.0 → 0.86.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/dist/advanced.d.ts +74 -9
- package/dist/advanced.js +70 -52
- package/dist/block.js +9 -9
- package/dist/chart-meta.js +4 -4
- package/dist/{chunk-LRNIYQ6Y.js → chunk-33FQ6HNV.js} +1 -1
- package/dist/{chunk-REUEU5PU.js → chunk-3CQS3CIO.js} +2 -2
- package/dist/{chunk-LQSNWE3W.js → chunk-4ELXLATB.js} +1 -1
- package/dist/{chunk-QZRYCRT7.js → chunk-4YA5XW43.js} +40 -40
- package/dist/{chunk-23RWHHI5.js → chunk-5NU7NII2.js} +14 -2
- package/dist/{chunk-HMWZQ53A.js → chunk-7WGCQE2E.js} +1 -1
- package/dist/{chunk-NSS2EF5B.js → chunk-AAMCXQPP.js} +1 -1
- package/dist/{chunk-XD7XL3SF.js → chunk-AGO3PFGS.js} +1 -1
- package/dist/{chunk-ECIXBEG2.js → chunk-AQIBKTPG.js} +2 -2
- package/dist/{chunk-ITLPDLBH.js → chunk-BF7JAFJI.js} +1 -1
- package/dist/{chunk-RMAJIB6S.js → chunk-BHZE36F7.js} +3 -3
- package/dist/{chunk-6HOVLE3H.js → chunk-BT2WH2XT.js} +1 -1
- package/dist/{chunk-3MXJMZAN.js → chunk-BV6PKJUS.js} +105 -28
- package/dist/{chunk-PSH5DT26.js → chunk-C6FZZFYD.js} +2 -2
- package/dist/{chunk-7256EOAE.js → chunk-CFBY77QJ.js} +129 -10
- package/dist/{chunk-VKGQX6P2.js → chunk-D4M25W6R.js} +1 -1
- package/dist/{chunk-A4PHPKNR.js → chunk-DAX42XVH.js} +1 -1
- package/dist/{chunk-V3LJIPS4.js → chunk-E6S2K6O2.js} +1 -1
- package/dist/{chunk-BIQYWWJ2.js → chunk-ERYHC4KJ.js} +1 -1
- package/dist/{chunk-JLGN6S4B.js → chunk-EWSESGC2.js} +32 -3
- package/dist/{chunk-MIZ46MOF.js → chunk-GYORDNOM.js} +1 -1
- package/dist/{chunk-D7D5YK4J.js → chunk-H6AFNCN3.js} +14 -2
- package/dist/{chunk-PEFPTQ3Z.js → chunk-HUMQIRJK.js} +1 -1
- package/dist/{chunk-XXAZ5C4K.js → chunk-IJ27L3R4.js} +1 -1
- package/dist/{chunk-VDMG3MM4.js → chunk-JD4RHBNX.js} +1 -1
- package/dist/{chunk-J2ICADUM.js → chunk-LHBMQJC3.js} +1 -1
- package/dist/{chunk-Y7FTHOMD.js → chunk-LIYWJ6DV.js} +32 -223
- package/dist/{chunk-HATTVAWX.js → chunk-LJFXC3IP.js} +1 -1
- package/dist/{chunk-KABGWUND.js → chunk-MSXRNVHB.js} +5 -3
- package/dist/{chunk-2QIGN7KL.js → chunk-MYHPRQHR.js} +6 -2
- package/dist/{chunk-UJRMARNX.js → chunk-NJIGYGZS.js} +19 -1
- package/dist/{chunk-RYZNNXUV.js → chunk-PKXKWHDW.js} +1 -1
- package/dist/{chunk-C5FEPGSJ.js → chunk-QJFT5MAH.js} +1 -1
- package/dist/{chunk-ULCB4BLF.js → chunk-QPE646M2.js} +1 -1
- package/dist/{chunk-UNSN56OJ.js → chunk-R2K5L4UA.js} +1 -1
- package/dist/{chunk-SLMAAJPE.js → chunk-RGI64U3A.js} +1 -1
- package/dist/chunk-TW6WMZFW.js +287 -0
- package/dist/{chunk-ZUUNTOMG.js → chunk-UIUXIDBX.js} +1 -1
- package/dist/{chunk-XIYVGO24.js → chunk-UMRZPRAN.js} +3 -3
- package/dist/{chunk-67USWFFE.js → chunk-UY6TEJJH.js} +1 -1
- package/dist/{chunk-YWHGWLY6.js → chunk-VEE777MD.js} +3 -3
- package/dist/{chunk-UGYZ5Q5Y.js → chunk-VJ2KROJ5.js} +1 -1
- package/dist/{chunk-6EV2F6W7.js → chunk-VPASQOR3.js} +68 -46
- package/dist/{chunk-OGKP2XGJ.js → chunk-VPVWG2GH.js} +1 -1
- package/dist/{chunk-IIEI7VK5.js → chunk-XCKNFFKM.js} +2 -0
- package/dist/{chunk-AYA6C64M.js → chunk-XFMQSFS4.js} +84 -27
- package/dist/cloud-reference.d.ts +11 -1
- package/dist/cloud-reference.js +1 -1
- package/dist/{dgmo-router-YW4SBNYB.js → dgmo-router-F2DSURTR.js} +5 -5
- package/dist/{dimensions-F3Y5T54V.js → dimensions-6QAWEGIR.js} +2 -2
- package/dist/{flowchart-renderer-TGQL4S4L.js → flowchart-renderer-H72L7BEC.js} +2 -2
- package/dist/index.js +9 -9
- package/dist/{layout-WZCXK7DF.js → layout-5NPBHV5F.js} +2 -2
- package/dist/{layout-WXVGMSI3.js → layout-5VSMZPMG.js} +2 -2
- package/dist/{layout-K6NI4VCS.js → layout-CUFA7XJD.js} +2 -2
- package/dist/{layout-NB7TKAWN.js → layout-LUQKAGGT.js} +2 -2
- package/dist/{layout-CFTB7GKV.js → layout-QIPCNUSB.js} +2 -2
- package/dist/{layout-PT7IKVCV.js → layout-QX5T6ZNE.js} +2 -2
- package/dist/layout-T6TAB5OI.js +10 -0
- package/dist/{layout-search-GRJEBAUF.js → layout-search-AW5VBDCV.js} +13 -8
- package/dist/live-link-resolve.d.ts +21 -3
- package/dist/live-link-resolve.js +47 -17
- package/dist/{parser-6PHQJO42.js → parser-PVIWHVGY.js} +1 -1
- package/dist/{parser-6TXNMXNB.js → parser-XYY5NHP4.js} +2 -2
- package/dist/{renderer-FXX3XSNW.js → renderer-2BWRW23Z.js} +2 -2
- package/dist/{renderer-OV3GUJRR.js → renderer-36JH4OMC.js} +4 -4
- package/dist/{renderer-EU27D4S6.js → renderer-425QUIYO.js} +2 -2
- package/dist/{renderer-HV6ZYJMC.js → renderer-4NZZ5J2F.js} +2 -2
- package/dist/{renderer-UGA5DGKR.js → renderer-5JVVJBAS.js} +2 -2
- package/dist/{renderer-YSH5EX54.js → renderer-AI2MD52D.js} +1 -1
- package/dist/{renderer-HWEGM72C.js → renderer-BICLPGAH.js} +2 -2
- package/dist/{renderer-XS42HEXW.js → renderer-CZJ4AMYV.js} +2 -2
- package/dist/{renderer-WUDVV363.js → renderer-E7WF75GY.js} +2 -2
- package/dist/{renderer-3XRDFNYF.js → renderer-EWJS2RAZ.js} +3 -3
- package/dist/{renderer-5YOF2AHJ.js → renderer-JEEGPLMM.js} +2 -2
- package/dist/{renderer-OXSLLQQC.js → renderer-KVAQE7PQ.js} +2 -2
- package/dist/{renderer-TF3NTKP3.js → renderer-NX4YKWCJ.js} +2 -2
- package/dist/{renderer-P7LQBDU2.js → renderer-QM23SWAM.js} +2 -2
- package/dist/{renderer-FBAFYSIQ.js → renderer-RAATRF6W.js} +3 -3
- package/dist/{renderer-X4KFEKUK.js → renderer-RH4U3UVM.js} +3 -3
- package/dist/{renderer-G72GMBKA.js → renderer-RLSR7N6I.js} +4 -4
- package/dist/{renderer-3F4K2X57.js → renderer-RMGN3Q7D.js} +2 -2
- package/dist/{renderer-OVDVFPAI.js → renderer-RUGMKHX5.js} +3 -3
- package/dist/{renderer-GWNSV76V.js → renderer-UUWR7NGF.js} +3 -3
- package/dist/{renderer-J3O2KVTL.js → renderer-V6LLASGN.js} +2 -2
- package/dist/{renderer-FQAZ3KNU.js → renderer-VKAJ52UO.js} +2 -2
- package/dist/{renderer-WRWVFEX7.js → renderer-XRALFCIN.js} +6 -4
- package/dist/{renderer-QZW4RCZW.js → renderer-YIZ7G4HU.js} +6 -6
- package/dist/{state-renderer-B4ZF6ESS.js → state-renderer-DDVJ43HR.js} +2 -2
- package/docs/language-reference.md +24 -12
- package/gallery/fixtures/sequence-groups-nested.dgmo +50 -0
- package/package.json +2 -2
- package/dist/chunk-WTTIODDV.js +0 -9
- package/dist/layout-JQ3IPJYR.js +0 -9
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import {
|
|
2
|
+
measureText,
|
|
3
|
+
truncateText,
|
|
4
|
+
wrapTextToWidth
|
|
5
|
+
} from "./chunk-KAO7JL4I.js";
|
|
6
|
+
|
|
7
|
+
// src/boxes-and-lines/node-metrics.ts
|
|
8
|
+
var PHI = 1.618;
|
|
9
|
+
var NODE_HEIGHT = 60;
|
|
10
|
+
var NODE_WIDTH = Math.round(NODE_HEIGHT * PHI);
|
|
11
|
+
|
|
12
|
+
// src/boxes-and-lines/label-placement.ts
|
|
13
|
+
var EDGE_LABEL_FONT_SIZE = 11;
|
|
14
|
+
var LABEL_MAX_WIDTH = 160;
|
|
15
|
+
var MAX_LABEL_LINES = 3;
|
|
16
|
+
var LABEL_LINE_HEIGHT = 1.3;
|
|
17
|
+
var H_PAD = 6;
|
|
18
|
+
var V_PAD = 3;
|
|
19
|
+
var BOX_CLEAR_PAD = 4;
|
|
20
|
+
var PERP_STEP = 8;
|
|
21
|
+
var LABEL_REACH_NEAR = 40;
|
|
22
|
+
var LABEL_REACH_WIDE = 56;
|
|
23
|
+
var SLIDE_SAMPLES = 9;
|
|
24
|
+
function measureEdgeLabel(label, fontSize = EDGE_LABEL_FONT_SIZE, maxWidth = LABEL_MAX_WIDTH) {
|
|
25
|
+
let lines = wrapTextToWidth(label, fontSize, maxWidth, { hardBreak: true });
|
|
26
|
+
if (lines.length > MAX_LABEL_LINES) {
|
|
27
|
+
const kept = lines.slice(0, MAX_LABEL_LINES - 1);
|
|
28
|
+
const rest = lines.slice(MAX_LABEL_LINES - 1).join(" ");
|
|
29
|
+
kept.push(truncateText(rest, fontSize, maxWidth));
|
|
30
|
+
lines = kept;
|
|
31
|
+
}
|
|
32
|
+
let textW = 0;
|
|
33
|
+
for (const ln of lines) {
|
|
34
|
+
const w = measureText(ln, fontSize);
|
|
35
|
+
if (w > textW) textW = w;
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
lines,
|
|
39
|
+
width: textW + 2 * H_PAD,
|
|
40
|
+
height: lines.length * fontSize * LABEL_LINE_HEIGHT + 2 * V_PAD
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function edgePolylineMidpoint(points) {
|
|
44
|
+
return pointAtArcFraction(points, 0.5).p;
|
|
45
|
+
}
|
|
46
|
+
function pointAtArcFraction(points, t) {
|
|
47
|
+
if (points.length === 0) return { p: { x: 0, y: 0 }, nx: 0, ny: 1 };
|
|
48
|
+
if (points.length === 1)
|
|
49
|
+
return { p: { x: points[0].x, y: points[0].y }, nx: 0, ny: 1 };
|
|
50
|
+
const segLen = [];
|
|
51
|
+
let total = 0;
|
|
52
|
+
for (let k = 1; k < points.length; k++) {
|
|
53
|
+
const len = Math.hypot(
|
|
54
|
+
points[k].x - points[k - 1].x,
|
|
55
|
+
points[k].y - points[k - 1].y
|
|
56
|
+
);
|
|
57
|
+
segLen.push(len);
|
|
58
|
+
total += len;
|
|
59
|
+
}
|
|
60
|
+
let want = total * Math.max(0, Math.min(1, t));
|
|
61
|
+
for (let k = 1; k < points.length; k++) {
|
|
62
|
+
const len = segLen[k - 1];
|
|
63
|
+
if (want <= len || k === points.length - 1) {
|
|
64
|
+
const f = len === 0 ? 0 : Math.min(1, want / len);
|
|
65
|
+
const ax = points[k - 1].x;
|
|
66
|
+
const ay = points[k - 1].y;
|
|
67
|
+
const bx = points[k].x;
|
|
68
|
+
const by = points[k].y;
|
|
69
|
+
const dx = bx - ax;
|
|
70
|
+
const dy = by - ay;
|
|
71
|
+
const dlen = Math.hypot(dx, dy) || 1;
|
|
72
|
+
return {
|
|
73
|
+
p: { x: ax + dx * f, y: ay + dy * f },
|
|
74
|
+
nx: -dy / dlen,
|
|
75
|
+
ny: dx / dlen
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
want -= len;
|
|
79
|
+
}
|
|
80
|
+
const last = points[points.length - 1];
|
|
81
|
+
return { p: { x: last.x, y: last.y }, nx: 0, ny: 1 };
|
|
82
|
+
}
|
|
83
|
+
function rectFromCenter(cx, cy, w, h) {
|
|
84
|
+
return {
|
|
85
|
+
minX: cx - w / 2,
|
|
86
|
+
minY: cy - h / 2,
|
|
87
|
+
maxX: cx + w / 2,
|
|
88
|
+
maxY: cy + h / 2
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function overlapsAny(cx, cy, w, h, obstacles, pad) {
|
|
92
|
+
const minX = cx - w / 2 - pad;
|
|
93
|
+
const minY = cy - h / 2 - pad;
|
|
94
|
+
const maxX = cx + w / 2 + pad;
|
|
95
|
+
const maxY = cy + h / 2 + pad;
|
|
96
|
+
for (const o of obstacles) {
|
|
97
|
+
if (minX < o.maxX && maxX > o.minX && minY < o.maxY && maxY > o.minY)
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
function slideFractions() {
|
|
103
|
+
const out = [0.5];
|
|
104
|
+
for (let k = 1; k <= SLIDE_SAMPLES; k++) {
|
|
105
|
+
const off = k * 0.08;
|
|
106
|
+
if (0.5 - off >= 0.12) out.push(0.5 - off);
|
|
107
|
+
if (0.5 + off <= 0.88) out.push(0.5 + off);
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
function findClearPosition(w, h, points, obstacles, perpMax) {
|
|
112
|
+
const ts = slideFractions();
|
|
113
|
+
for (const t of ts) {
|
|
114
|
+
const { p } = pointAtArcFraction(points, t);
|
|
115
|
+
if (!overlapsAny(p.x, p.y, w, h, obstacles, BOX_CLEAR_PAD)) return p;
|
|
116
|
+
}
|
|
117
|
+
for (let mag = PERP_STEP; mag <= perpMax; mag += PERP_STEP) {
|
|
118
|
+
for (const t of ts) {
|
|
119
|
+
const { p, nx, ny } = pointAtArcFraction(points, t);
|
|
120
|
+
for (const sign of [-1, 1]) {
|
|
121
|
+
const x = p.x + nx * mag * sign;
|
|
122
|
+
const y = p.y + ny * mag * sign;
|
|
123
|
+
if (!overlapsAny(x, y, w, h, obstacles, BOX_CLEAR_PAD)) return { x, y };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
function buildGroupContainers(groups) {
|
|
130
|
+
const byLabel = new Map(groups.map((g) => [g.label, g]));
|
|
131
|
+
const parent = /* @__PURE__ */ new Map();
|
|
132
|
+
for (const g of groups)
|
|
133
|
+
for (const c of g.children) if (byLabel.has(c)) parent.set(c, g.label);
|
|
134
|
+
for (const g of groups) if (g.parentGroup) parent.set(g.label, g.parentGroup);
|
|
135
|
+
const chainOf = (label) => {
|
|
136
|
+
const out = [];
|
|
137
|
+
const seen = /* @__PURE__ */ new Set();
|
|
138
|
+
let cur = label;
|
|
139
|
+
while (cur !== void 0 && byLabel.has(cur) && !seen.has(cur)) {
|
|
140
|
+
seen.add(cur);
|
|
141
|
+
out.push(cur);
|
|
142
|
+
cur = parent.get(cur);
|
|
143
|
+
}
|
|
144
|
+
return out;
|
|
145
|
+
};
|
|
146
|
+
const containers = /* @__PURE__ */ new Map();
|
|
147
|
+
for (const g of groups) containers.set(g.label, new Set(chainOf(g.label)));
|
|
148
|
+
for (const g of groups) {
|
|
149
|
+
const chain = chainOf(g.label);
|
|
150
|
+
for (const c of g.children) {
|
|
151
|
+
if (byLabel.has(c)) continue;
|
|
152
|
+
let set = containers.get(c);
|
|
153
|
+
if (!set) {
|
|
154
|
+
set = /* @__PURE__ */ new Set();
|
|
155
|
+
containers.set(c, set);
|
|
156
|
+
}
|
|
157
|
+
for (const a of chain) set.add(a);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return containers;
|
|
161
|
+
}
|
|
162
|
+
function resolveLabelOverlaps(boxes) {
|
|
163
|
+
const MAX_PASSES = 8;
|
|
164
|
+
const PAD = 4;
|
|
165
|
+
for (let pass = 0; pass < MAX_PASSES; pass++) {
|
|
166
|
+
let moved = false;
|
|
167
|
+
for (let i = 0; i < boxes.length; i++) {
|
|
168
|
+
for (let j = i + 1; j < boxes.length; j++) {
|
|
169
|
+
const a = boxes[i];
|
|
170
|
+
const b = boxes[j];
|
|
171
|
+
const dx = Math.abs(a.cx - b.cx);
|
|
172
|
+
const dy = Math.abs(a.cy - b.cy);
|
|
173
|
+
const overlapX = (a.w + b.w) / 2 + PAD - dx;
|
|
174
|
+
const overlapY = (a.h + b.h) / 2 + PAD - dy;
|
|
175
|
+
if (overlapX > 0 && overlapY > 0) {
|
|
176
|
+
const shift = overlapY / 2 + 1;
|
|
177
|
+
if (a.cy < b.cy) {
|
|
178
|
+
a.cy -= shift;
|
|
179
|
+
b.cy += shift;
|
|
180
|
+
} else {
|
|
181
|
+
a.cy += shift;
|
|
182
|
+
b.cy -= shift;
|
|
183
|
+
}
|
|
184
|
+
moved = true;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (!moved) break;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function placeEdgeLabels(layout, opts) {
|
|
192
|
+
const fontSize = opts?.fontSize ?? EDGE_LABEL_FONT_SIZE;
|
|
193
|
+
const maxWidth = opts?.maxWidth ?? LABEL_MAX_WIDTH;
|
|
194
|
+
const perpMax = opts?.perpMax ?? LABEL_REACH_NEAR;
|
|
195
|
+
const baseObstacles = [];
|
|
196
|
+
for (const n of layout.nodes)
|
|
197
|
+
baseObstacles.push(rectFromCenter(n.x, n.y, n.width, n.height));
|
|
198
|
+
const expandedGroups = [];
|
|
199
|
+
for (const g of layout.groups) {
|
|
200
|
+
const r = rectFromCenter(g.x, g.y, g.width, g.height);
|
|
201
|
+
if (g.collapsed) baseObstacles.push(r);
|
|
202
|
+
else expandedGroups.push({ label: g.label, rect: r });
|
|
203
|
+
}
|
|
204
|
+
const containers = buildGroupContainers(opts?.groups ?? []);
|
|
205
|
+
const noContainers = /* @__PURE__ */ new Set();
|
|
206
|
+
const obstacleCache = /* @__PURE__ */ new Map();
|
|
207
|
+
const obstaclesFor = (edgeIdx) => {
|
|
208
|
+
const cached = obstacleCache.get(edgeIdx);
|
|
209
|
+
if (cached !== void 0) return cached;
|
|
210
|
+
let out = baseObstacles;
|
|
211
|
+
if (expandedGroups.length > 0) {
|
|
212
|
+
const e = layout.edges[edgeIdx];
|
|
213
|
+
const src = containers.get(e.source) ?? noContainers;
|
|
214
|
+
const tgt = containers.get(e.target) ?? noContainers;
|
|
215
|
+
const foreign = expandedGroups.filter((g) => !(src.has(g.label) && tgt.has(g.label))).map((g) => g.rect);
|
|
216
|
+
if (foreign.length > 0) out = [...baseObstacles, ...foreign];
|
|
217
|
+
}
|
|
218
|
+
obstacleCache.set(edgeIdx, out);
|
|
219
|
+
return out;
|
|
220
|
+
};
|
|
221
|
+
const boxes = [];
|
|
222
|
+
layout.edges.forEach((e, idx) => {
|
|
223
|
+
if (!e.label || e.points.length < 2) return;
|
|
224
|
+
const m = measureEdgeLabel(e.label, fontSize, maxWidth);
|
|
225
|
+
const mid = edgePolylineMidpoint(e.points);
|
|
226
|
+
let cy = mid.y;
|
|
227
|
+
if (e.parallelCount > 1 && e.yOffset !== 0)
|
|
228
|
+
cy += (e.yOffset < 0 ? -1 : 1) * (m.height / 2);
|
|
229
|
+
boxes.push({
|
|
230
|
+
edgeIdx: idx,
|
|
231
|
+
cx: mid.x,
|
|
232
|
+
cy,
|
|
233
|
+
w: m.width,
|
|
234
|
+
h: m.height,
|
|
235
|
+
lines: m.lines,
|
|
236
|
+
resolved: true
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
for (const box of boxes) {
|
|
240
|
+
const obstacles = obstaclesFor(box.edgeIdx);
|
|
241
|
+
if (!overlapsAny(box.cx, box.cy, box.w, box.h, obstacles, BOX_CLEAR_PAD))
|
|
242
|
+
continue;
|
|
243
|
+
const e = layout.edges[box.edgeIdx];
|
|
244
|
+
const clear = findClearPosition(box.w, box.h, e.points, obstacles, perpMax) ?? findClearPosition(box.w, box.h, e.points, baseObstacles, perpMax);
|
|
245
|
+
if (clear) {
|
|
246
|
+
box.cx = clear.x;
|
|
247
|
+
box.cy = clear.y;
|
|
248
|
+
}
|
|
249
|
+
if (overlapsAny(box.cx, box.cy, box.w, box.h, obstacles, BOX_CLEAR_PAD))
|
|
250
|
+
box.resolved = false;
|
|
251
|
+
}
|
|
252
|
+
resolveLabelOverlaps(boxes);
|
|
253
|
+
for (const box of boxes) {
|
|
254
|
+
const obstacles = obstaclesFor(box.edgeIdx);
|
|
255
|
+
if (overlapsAny(box.cx, box.cy, box.w, box.h, obstacles, BOX_CLEAR_PAD))
|
|
256
|
+
box.resolved = false;
|
|
257
|
+
}
|
|
258
|
+
const boxByIdx = /* @__PURE__ */ new Map();
|
|
259
|
+
for (const b of boxes) boxByIdx.set(b.edgeIdx, b);
|
|
260
|
+
const edges = layout.edges.map((e, idx) => {
|
|
261
|
+
const b = boxByIdx.get(idx);
|
|
262
|
+
if (!b) return e;
|
|
263
|
+
return {
|
|
264
|
+
...e,
|
|
265
|
+
labelX: b.cx,
|
|
266
|
+
labelY: b.cy,
|
|
267
|
+
labelWidth: b.w,
|
|
268
|
+
labelHeight: b.h,
|
|
269
|
+
labelLines: b.lines,
|
|
270
|
+
labelResolved: b.resolved
|
|
271
|
+
};
|
|
272
|
+
});
|
|
273
|
+
return {
|
|
274
|
+
layout: { ...layout, edges },
|
|
275
|
+
unresolved: boxes.filter((b) => !b.resolved).map((b) => b.edgeIdx)
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export {
|
|
280
|
+
NODE_HEIGHT,
|
|
281
|
+
NODE_WIDTH,
|
|
282
|
+
EDGE_LABEL_FONT_SIZE,
|
|
283
|
+
BOX_CLEAR_PAD,
|
|
284
|
+
LABEL_REACH_WIDE,
|
|
285
|
+
measureEdgeLabel,
|
|
286
|
+
placeEdgeLabels
|
|
287
|
+
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
layoutOrg
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-33FQ6HNV.js";
|
|
4
4
|
import {
|
|
5
5
|
renderCollapseBar,
|
|
6
6
|
renderNodeCard
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-R2K5L4UA.js";
|
|
8
8
|
import {
|
|
9
9
|
ScaleContext
|
|
10
10
|
} from "./chunk-24YPR5EH.js";
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
META_LINE_HEIGHT,
|
|
25
25
|
NODE_STROKE_WIDTH,
|
|
26
26
|
SEPARATOR_GAP
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-XCKNFFKM.js";
|
|
28
28
|
import {
|
|
29
29
|
extractExportSvg,
|
|
30
30
|
runInExportContainer
|
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
} from "./chunk-WMIKC5XO.js";
|
|
4
4
|
import {
|
|
5
5
|
renderNodeCard
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-R2K5L4UA.js";
|
|
7
7
|
import {
|
|
8
8
|
renderInlineText
|
|
9
9
|
} from "./chunk-FWNJDD4U.js";
|
|
10
10
|
import {
|
|
11
11
|
formatDateLabel
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-QPE646M2.js";
|
|
13
13
|
import {
|
|
14
14
|
CARD_RADIUS,
|
|
15
15
|
HAIRLINE_DASH,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
LABEL_FONT_SIZE,
|
|
18
18
|
NODE_STROKE_WIDTH,
|
|
19
19
|
SEPARATOR_GAP
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-XCKNFFKM.js";
|
|
21
21
|
import {
|
|
22
22
|
layoutInlineHeader
|
|
23
23
|
} from "./chunk-3DOQOXXI.js";
|
|
@@ -41,6 +41,22 @@ import {
|
|
|
41
41
|
suggest
|
|
42
42
|
} from "./chunk-BYU54C3S.js";
|
|
43
43
|
|
|
44
|
+
// src/sequence/diagnostics.ts
|
|
45
|
+
var SEQUENCE_DIAGNOSTIC_CODES = {
|
|
46
|
+
GROUP_DEPTH: "E_SEQ_GROUP_DEPTH"
|
|
47
|
+
};
|
|
48
|
+
var SEQUENCE_DIAGNOSTICS = [
|
|
49
|
+
{
|
|
50
|
+
code: SEQUENCE_DIAGNOSTIC_CODES.GROUP_DEPTH,
|
|
51
|
+
severity: "error",
|
|
52
|
+
chartType: "sequence",
|
|
53
|
+
title: "Group nested too deep",
|
|
54
|
+
message: (p) => `Group "${String(p.label ?? "?")}" is nested ${String(p.depth ?? "?")} levels deep \u2014 participant groups nest to depth ${String(p.max ?? "?")}; its participants join the group above it`,
|
|
55
|
+
hint: "Move the inner [Group] up a level \u2014 two levels of bracket is the bound.",
|
|
56
|
+
example: "sequence\n[Monolith]\n [Linux]\n [Container]\n App"
|
|
57
|
+
}
|
|
58
|
+
];
|
|
59
|
+
|
|
44
60
|
// src/sequence/parser.ts
|
|
45
61
|
var KNOWN_SEQ_OPTIONS = /* @__PURE__ */ new Set(["active-tag"]);
|
|
46
62
|
var KNOWN_SEQ_BOOLEANS = /* @__PURE__ */ new Set([
|
|
@@ -70,6 +86,7 @@ function isSequenceNote(el) {
|
|
|
70
86
|
}
|
|
71
87
|
var IS_A_PATTERN = /^([^:]+?)\s+is\s+an?\s+(\w+)(?:\s+(.+))?$/i;
|
|
72
88
|
var COLORED_PARTICIPANT_PATTERN = /^(\S+?)\((red|orange|yellow|green|blue|purple|teal|cyan|gray|black|white)\)\s*$/;
|
|
89
|
+
var MAX_GROUP_DEPTH = 2;
|
|
73
90
|
var GROUP_HEADING_PATTERN = /^\[([^\]|]+?)(?:\(([^)]+)\))?\]\s*(.*)$/;
|
|
74
91
|
var GROUP_HEADING_FALLBACK = /^\[([^\]]+)\]\s*(.*)$/;
|
|
75
92
|
var SECTION_PATTERN = /^==\s+(.+?)(?:\s*==)?\s*$/;
|
|
@@ -218,8 +235,8 @@ function parseSequenceDgmo(content, palette) {
|
|
|
218
235
|
return nameAliasMap.resolve(trimmed) ?? trimmed;
|
|
219
236
|
};
|
|
220
237
|
const fail = makeFail(result);
|
|
221
|
-
const pushError = (line, message) => {
|
|
222
|
-
const diag = makeDgmoError(line, message);
|
|
238
|
+
const pushError = (line, message, code) => {
|
|
239
|
+
const diag = makeDgmoError(line, message, "error", code);
|
|
223
240
|
result.diagnostics.push(diag);
|
|
224
241
|
if (!result.error) result.error = formatDgmoError(diag);
|
|
225
242
|
};
|
|
@@ -249,7 +266,31 @@ function parseSequenceDgmo(content, palette) {
|
|
|
249
266
|
}
|
|
250
267
|
break;
|
|
251
268
|
}
|
|
252
|
-
|
|
269
|
+
const groupStack = [];
|
|
270
|
+
const activeGroup = () => groupStack.length > 0 ? groupStack[groupStack.length - 1].group : null;
|
|
271
|
+
const closeGroupsTo = (indent) => {
|
|
272
|
+
while (groupStack.length > 0 && groupStack[groupStack.length - 1].indent >= indent) {
|
|
273
|
+
groupStack.pop();
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
const joinActiveGroup = (key, id, lineNumber) => {
|
|
277
|
+
const innermost = activeGroup();
|
|
278
|
+
if (!innermost || innermost.participantIds.includes(key)) return;
|
|
279
|
+
const existingGroup = participantGroupMap.get(key);
|
|
280
|
+
if (existingGroup) {
|
|
281
|
+
pushError(
|
|
282
|
+
lineNumber,
|
|
283
|
+
`Participant '${id}' is already in group '${existingGroup}' \u2014 participants can only belong to one group`
|
|
284
|
+
);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
for (const frame of groupStack) {
|
|
288
|
+
if (!frame.group.participantIds.includes(key)) {
|
|
289
|
+
frame.group.participantIds.push(key);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
participantGroupMap.set(key, innermost.name);
|
|
293
|
+
};
|
|
253
294
|
const participantIds = /* @__PURE__ */ new Set();
|
|
254
295
|
const idByKey = /* @__PURE__ */ new Map();
|
|
255
296
|
const addParticipant = (name, lineNumber, extras) => {
|
|
@@ -364,7 +405,7 @@ function parseSequenceDgmo(content, palette) {
|
|
|
364
405
|
const lineNumber = i + 1;
|
|
365
406
|
nameAliasMap.at(lineNumber);
|
|
366
407
|
if (!trimmed) {
|
|
367
|
-
|
|
408
|
+
closeGroupsTo(0);
|
|
368
409
|
currentTagGroup = null;
|
|
369
410
|
continue;
|
|
370
411
|
}
|
|
@@ -407,14 +448,29 @@ function parseSequenceDgmo(content, palette) {
|
|
|
407
448
|
);
|
|
408
449
|
}
|
|
409
450
|
contentStarted = true;
|
|
410
|
-
|
|
451
|
+
const headingIndent = measureIndent(raw);
|
|
452
|
+
closeGroupsTo(headingIndent);
|
|
453
|
+
const depth = groupStack.length;
|
|
454
|
+
if (depth >= MAX_GROUP_DEPTH) {
|
|
455
|
+
pushError(
|
|
456
|
+
lineNumber,
|
|
457
|
+
`Group '${groupName}' is nested ${String(depth + 1)} levels deep \u2014 participant groups nest to depth ${String(MAX_GROUP_DEPTH)}; its participants join the group above it`,
|
|
458
|
+
SEQUENCE_DIAGNOSTIC_CODES.GROUP_DEPTH
|
|
459
|
+
);
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
const parentGroup = activeGroup();
|
|
463
|
+
const group = {
|
|
411
464
|
name: groupName,
|
|
412
465
|
participantIds: [],
|
|
413
466
|
lineNumber,
|
|
467
|
+
depth,
|
|
468
|
+
...parentGroup ? { parent: parentGroup.name } : {},
|
|
414
469
|
...groupMeta ? { metadata: groupMeta } : {},
|
|
415
470
|
...isCollapsed ? { collapsed: true } : {}
|
|
416
471
|
};
|
|
417
|
-
result.groups.push(
|
|
472
|
+
result.groups.push(group);
|
|
473
|
+
groupStack.push({ group, indent: headingIndent });
|
|
418
474
|
continue;
|
|
419
475
|
}
|
|
420
476
|
if (trimmed.startsWith("[")) {
|
|
@@ -431,9 +487,7 @@ function parseSequenceDgmo(content, palette) {
|
|
|
431
487
|
continue;
|
|
432
488
|
}
|
|
433
489
|
}
|
|
434
|
-
|
|
435
|
-
activeGroup = null;
|
|
436
|
-
}
|
|
490
|
+
closeGroupsTo(measureIndent(raw));
|
|
437
491
|
if (trimmed.startsWith("//")) continue;
|
|
438
492
|
if (trimmed.startsWith("#")) {
|
|
439
493
|
pushError(lineNumber, "Use // for comments");
|
|
@@ -623,18 +677,7 @@ function parseSequenceDgmo(content, palette) {
|
|
|
623
677
|
...position !== void 0 && { position },
|
|
624
678
|
...isAMeta !== void 0 && { metadata: isAMeta }
|
|
625
679
|
});
|
|
626
|
-
|
|
627
|
-
const existingGroup = participantGroupMap.get(key);
|
|
628
|
-
if (existingGroup) {
|
|
629
|
-
pushError(
|
|
630
|
-
lineNumber,
|
|
631
|
-
`Participant '${id}' is already in group '${existingGroup}' \u2014 participants can only belong to one group`
|
|
632
|
-
);
|
|
633
|
-
} else {
|
|
634
|
-
activeGroup.participantIds.push(key);
|
|
635
|
-
participantGroupMap.set(key, activeGroup.name);
|
|
636
|
-
}
|
|
637
|
-
}
|
|
680
|
+
joinActiveGroup(key, id, lineNumber);
|
|
638
681
|
continue;
|
|
639
682
|
}
|
|
640
683
|
const { core: colorCore, meta: colorMeta } = splitPipe(trimmed, lineNumber);
|
|
@@ -650,18 +693,7 @@ function parseSequenceDgmo(content, palette) {
|
|
|
650
693
|
const key = addParticipant(id, lineNumber, {
|
|
651
694
|
...colorMeta !== void 0 && { metadata: colorMeta }
|
|
652
695
|
});
|
|
653
|
-
|
|
654
|
-
const existingGroup = participantGroupMap.get(key);
|
|
655
|
-
if (existingGroup) {
|
|
656
|
-
pushError(
|
|
657
|
-
lineNumber,
|
|
658
|
-
`Participant '${id}' is already in group '${existingGroup}' \u2014 participants can only belong to one group`
|
|
659
|
-
);
|
|
660
|
-
} else {
|
|
661
|
-
activeGroup.participantIds.push(key);
|
|
662
|
-
participantGroupMap.set(key, activeGroup.name);
|
|
663
|
-
}
|
|
664
|
-
}
|
|
696
|
+
joinActiveGroup(key, id, lineNumber);
|
|
665
697
|
continue;
|
|
666
698
|
}
|
|
667
699
|
{
|
|
@@ -670,7 +702,7 @@ function parseSequenceDgmo(content, palette) {
|
|
|
670
702
|
meta: bareMeta,
|
|
671
703
|
alias: bareAlias
|
|
672
704
|
} = splitPipe(trimmed, lineNumber);
|
|
673
|
-
const inGroup = activeGroup && measureIndent(raw) > 0;
|
|
705
|
+
const inGroup = activeGroup() !== null && measureIndent(raw) > 0;
|
|
674
706
|
if (/^\S+$/.test(bareCore) && !ARROW_PATTERN.test(bareCore) && (inGroup || !bodyStarted || bareMeta)) {
|
|
675
707
|
contentStarted = true;
|
|
676
708
|
const id = bareCore;
|
|
@@ -682,18 +714,7 @@ function parseSequenceDgmo(content, palette) {
|
|
|
682
714
|
...position !== void 0 && { position },
|
|
683
715
|
...bareMeta !== void 0 && { metadata: bareMeta }
|
|
684
716
|
});
|
|
685
|
-
|
|
686
|
-
const existingGroup = participantGroupMap.get(key);
|
|
687
|
-
if (existingGroup) {
|
|
688
|
-
pushError(
|
|
689
|
-
lineNumber,
|
|
690
|
-
`Participant '${id}' is already in group '${existingGroup}' \u2014 participants can only belong to one group`
|
|
691
|
-
);
|
|
692
|
-
} else {
|
|
693
|
-
activeGroup.participantIds.push(key);
|
|
694
|
-
participantGroupMap.set(key, activeGroup.name);
|
|
695
|
-
}
|
|
696
|
-
}
|
|
717
|
+
joinActiveGroup(key, id, lineNumber);
|
|
697
718
|
continue;
|
|
698
719
|
}
|
|
699
720
|
}
|
|
@@ -1066,6 +1087,7 @@ function looksLikeSequence(content) {
|
|
|
1066
1087
|
}
|
|
1067
1088
|
|
|
1068
1089
|
export {
|
|
1090
|
+
SEQUENCE_DIAGNOSTICS,
|
|
1069
1091
|
isSequenceBlock,
|
|
1070
1092
|
isSequenceSection,
|
|
1071
1093
|
isSequenceNote,
|
|
@@ -5,6 +5,7 @@ var CARD_RADIUS = 6;
|
|
|
5
5
|
var CONTAINER_RADIUS = 8;
|
|
6
6
|
var COLLAPSE_BAR_INSET = 0;
|
|
7
7
|
var EDGE_LABEL_KNOCKOUT_OPACITY = 0.9;
|
|
8
|
+
var EDGE_LABEL_UNRESOLVED_KNOCKOUT_OPACITY = 1;
|
|
8
9
|
var ARROWHEAD_WIDTH = 10;
|
|
9
10
|
var ARROWHEAD_HEIGHT = 7;
|
|
10
11
|
var EDGE_DASH = "6 3";
|
|
@@ -31,6 +32,7 @@ export {
|
|
|
31
32
|
CONTAINER_RADIUS,
|
|
32
33
|
COLLAPSE_BAR_INSET,
|
|
33
34
|
EDGE_LABEL_KNOCKOUT_OPACITY,
|
|
35
|
+
EDGE_LABEL_UNRESOLVED_KNOCKOUT_OPACITY,
|
|
34
36
|
ARROWHEAD_WIDTH,
|
|
35
37
|
ARROWHEAD_HEIGHT,
|
|
36
38
|
EDGE_DASH,
|