@crazyhappyone/auto-graph 0.0.1 → 0.0.21
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 +2 -2
- package/README.zh-CN.md +2 -2
- package/dist/cli/index.cjs +907 -69
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +906 -69
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +846 -76
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +87 -1
- package/dist/index.d.ts +87 -1
- package/dist/index.js +844 -77
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/cli/index.cjs
CHANGED
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
|
|
4
4
|
var commander = require('commander');
|
|
5
5
|
var dagre = require('@dagrejs/dagre');
|
|
6
|
+
var module$1 = require('module');
|
|
7
|
+
var pretext = require('@chenglou/pretext');
|
|
6
8
|
var buffer = require('buffer');
|
|
7
9
|
var yaml = require('yaml');
|
|
8
10
|
var zod = require('zod');
|
|
9
11
|
var promises = require('fs/promises');
|
|
10
12
|
var path = require('path');
|
|
11
13
|
|
|
14
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
12
15
|
// src/dsl/diagnostics.ts
|
|
13
16
|
var SEVERITY_RANK = /* @__PURE__ */ new Map([
|
|
14
17
|
["error", 0],
|
|
@@ -196,11 +199,12 @@ function renderArrow(edge) {
|
|
|
196
199
|
height: box.height
|
|
197
200
|
}),
|
|
198
201
|
backgroundColor: "transparent",
|
|
202
|
+
strokeStyle: edge.style ?? "solid",
|
|
199
203
|
points: relativePoints,
|
|
200
204
|
startBinding: { elementId: `node:${edge.source.nodeId}`, focus: 0, gap: 0 },
|
|
201
205
|
endBinding: { elementId: `node:${edge.target.nodeId}`, focus: 0, gap: 0 },
|
|
202
206
|
startArrowhead: null,
|
|
203
|
-
endArrowhead:
|
|
207
|
+
endArrowhead: mapArrowhead(edge.arrowhead)
|
|
204
208
|
};
|
|
205
209
|
}
|
|
206
210
|
function renderText(id, label, box, containerId, groupIds) {
|
|
@@ -278,6 +282,16 @@ function mapShape(shape) {
|
|
|
278
282
|
return "cylinder";
|
|
279
283
|
}
|
|
280
284
|
}
|
|
285
|
+
function mapArrowhead(arrowhead) {
|
|
286
|
+
switch (arrowhead) {
|
|
287
|
+
case void 0:
|
|
288
|
+
return "arrow";
|
|
289
|
+
case "triangle":
|
|
290
|
+
return "triangle";
|
|
291
|
+
case "hollowTriangle":
|
|
292
|
+
return "triangle_outline";
|
|
293
|
+
}
|
|
294
|
+
}
|
|
281
295
|
function createGroupMembership(groups) {
|
|
282
296
|
const membership = /* @__PURE__ */ new Map();
|
|
283
297
|
for (const group of groups) {
|
|
@@ -344,19 +358,28 @@ function exportSvg(diagram, options = {}) {
|
|
|
344
358
|
`<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="${formatBoxViewBox(diagram.bounds)}">`,
|
|
345
359
|
...title === void 0 ? [] : [` <title>${escapeXml(title)}</title>`],
|
|
346
360
|
` <rect class="background" x="${formatNumber(diagram.bounds.x)}" y="${formatNumber(diagram.bounds.y)}" width="${formatNumber(diagram.bounds.width)}" height="${formatNumber(diagram.bounds.height)}" fill="#ffffff"/>`,
|
|
361
|
+
...diagram.frame === void 0 ? [] : [indent(renderFrame(diagram.frame))],
|
|
362
|
+
...(diagram.swimlanes ?? []).flatMap(
|
|
363
|
+
(swimlane) => renderSwimlane(swimlane)
|
|
364
|
+
),
|
|
347
365
|
...diagram.groups.map((group) => indent(renderGroup2(group))),
|
|
348
366
|
...diagram.edges.flatMap((edge) => {
|
|
349
|
-
const path = renderEdgePath(edge
|
|
367
|
+
const path = renderEdgePath(edge);
|
|
350
368
|
if (path === void 0) {
|
|
351
369
|
return [];
|
|
352
370
|
}
|
|
353
|
-
return [indent(path), indent(renderArrowhead(edge
|
|
371
|
+
return [indent(path), indent(renderArrowhead(edge))];
|
|
354
372
|
}),
|
|
355
373
|
...diagram.nodes.map((node) => indent(renderNode2(node))),
|
|
374
|
+
...diagram.nodes.flatMap((node) => renderCompartments(node)),
|
|
375
|
+
...diagram.nodes.flatMap((node) => renderPorts(node)),
|
|
356
376
|
...diagram.groups.flatMap(
|
|
357
377
|
(group) => renderLabel(group.label, group.box, group)
|
|
358
378
|
),
|
|
359
|
-
...diagram.nodes.flatMap(
|
|
379
|
+
...diagram.nodes.flatMap(
|
|
380
|
+
(node) => node.compartments === void 0 ? renderLabel(node.label, node.box, node) : []
|
|
381
|
+
),
|
|
382
|
+
...diagram.edges.flatMap((edge) => renderEdgeLabel(edge)),
|
|
360
383
|
"</svg>"
|
|
361
384
|
];
|
|
362
385
|
return `${lines.join("\n")}
|
|
@@ -366,7 +389,9 @@ function renderGroup2(group) {
|
|
|
366
389
|
return `<rect class="group" data-id="${escapeAttribute(group.id)}" x="${formatNumber(group.box.x)}" y="${formatNumber(group.box.y)}" width="${formatNumber(group.box.width)}" height="${formatNumber(group.box.height)}" fill="${GROUP_FILL}" stroke="${STROKE}" stroke-dasharray="6 4"/>`;
|
|
367
390
|
}
|
|
368
391
|
function renderNode2(node) {
|
|
369
|
-
const
|
|
392
|
+
const fill = node.style?.fill ?? NODE_FILL;
|
|
393
|
+
const stroke = node.style?.stroke ?? STROKE;
|
|
394
|
+
const common = `class="node node-${node.shape}" data-id="${escapeAttribute(node.id)}" fill="${escapeAttribute(fill)}" stroke="${escapeAttribute(stroke)}"`;
|
|
370
395
|
switch (node.shape) {
|
|
371
396
|
case "rectangle":
|
|
372
397
|
return renderRect(node.box, common);
|
|
@@ -382,16 +407,111 @@ function renderNode2(node) {
|
|
|
382
407
|
return `<path ${common} d="${formatCylinderPath(node.box)}"/>`;
|
|
383
408
|
}
|
|
384
409
|
}
|
|
410
|
+
function renderFrame(frame) {
|
|
411
|
+
const stroke = frame.style?.stroke ?? "#6b7280";
|
|
412
|
+
const fill = frame.style?.fill ?? "transparent";
|
|
413
|
+
return [
|
|
414
|
+
`<g class="sysml-frame" data-kind="${escapeAttribute(frame.kind)}">`,
|
|
415
|
+
` <rect class="sysml-frame-border" x="${formatNumber(frame.box.x)}" y="${formatNumber(frame.box.y)}" width="${formatNumber(frame.box.width)}" height="${formatNumber(frame.box.height)}" fill="${escapeAttribute(fill)}" stroke="${escapeAttribute(stroke)}"/>`,
|
|
416
|
+
` <path class="sysml-title-tab" d="M ${formatNumber(frame.titleBox.x)} ${formatNumber(frame.titleBox.y + frame.titleBox.height)} L ${formatNumber(frame.titleBox.x)} ${formatNumber(frame.titleBox.y)} L ${formatNumber(frame.titleBox.x + frame.titleBox.width - 16)} ${formatNumber(frame.titleBox.y)} L ${formatNumber(frame.titleBox.x + frame.titleBox.width)} ${formatNumber(frame.titleBox.y + frame.titleBox.height)} Z" fill="#f3f4f6" stroke="${escapeAttribute(stroke)}"/>`,
|
|
417
|
+
` <text class="sysml-title-tab-label" x="${formatNumber(frame.titleBox.x + 8)}" y="${formatNumber(frame.titleBox.y + frame.titleBox.height / 2)}" dominant-baseline="middle" font-family="${FONT_FAMILY}" font-size="12" fill="#111827">${escapeXml(frame.titleTab)}</text>`,
|
|
418
|
+
"</g>"
|
|
419
|
+
].join("\n");
|
|
420
|
+
}
|
|
421
|
+
function renderSwimlane(swimlane) {
|
|
422
|
+
if (swimlane.box === void 0) {
|
|
423
|
+
return [];
|
|
424
|
+
}
|
|
425
|
+
const lines = [
|
|
426
|
+
` <g class="swimlane" data-id="${escapeAttribute(swimlane.id)}">`,
|
|
427
|
+
` <rect class="swimlane-frame" x="${formatNumber(swimlane.box.x)}" y="${formatNumber(swimlane.box.y)}" width="${formatNumber(swimlane.box.width)}" height="${formatNumber(swimlane.box.height)}" fill="#ffffff" stroke="${STROKE}"/>`
|
|
428
|
+
];
|
|
429
|
+
for (const lane of swimlane.lanes) {
|
|
430
|
+
if (lane.box === void 0) {
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
433
|
+
lines.push(
|
|
434
|
+
` <rect class="swimlane-lane" data-lane="${escapeAttribute(`${swimlane.id}.${lane.id}`)}" x="${formatNumber(lane.box.x)}" y="${formatNumber(lane.box.y)}" width="${formatNumber(lane.box.width)}" height="${formatNumber(lane.box.height)}" fill="none" stroke="${STROKE}"/>`
|
|
435
|
+
);
|
|
436
|
+
if (lane.label?.text !== void 0) {
|
|
437
|
+
lines.push(
|
|
438
|
+
` <text class="swimlane-label" x="${formatNumber(lane.box.x + lane.box.width / 2)}" y="${formatNumber(lane.box.y + 16)}" text-anchor="middle" font-family="${FONT_FAMILY}" font-size="12" fill="#111827">${escapeXml(lane.label.text)}</text>`
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
lines.push(" </g>");
|
|
443
|
+
return lines;
|
|
444
|
+
}
|
|
445
|
+
function renderPorts(node) {
|
|
446
|
+
return (node.ports ?? []).flatMap((port) => [
|
|
447
|
+
` <rect class="port" data-kind="${escapeAttribute(port.kind)}" data-port="${escapeAttribute(`${node.id}.${port.id}`)}" x="${formatNumber(port.box.x)}" y="${formatNumber(port.box.y)}" width="${formatNumber(port.box.width)}" height="${formatNumber(port.box.height)}" fill="${escapeAttribute(port.style?.fill ?? "#d9ead3")}" stroke="${escapeAttribute(port.style?.stroke ?? STROKE)}"/>`,
|
|
448
|
+
...port.label?.text === void 0 ? [] : [
|
|
449
|
+
` <text class="port-label" data-for="${escapeAttribute(`${node.id}.${port.id}`)}" x="${formatNumber(portLabelX(port.anchor.x, port.side))}" y="${formatNumber(port.anchor.y - 8)}" text-anchor="${port.side === "left" ? "end" : "start"}" font-family="${FONT_FAMILY}" font-size="10" fill="#111827">${escapeXml(port.label.text)}</text>`
|
|
450
|
+
]
|
|
451
|
+
]);
|
|
452
|
+
}
|
|
453
|
+
function renderCompartments(node) {
|
|
454
|
+
const compartments2 = node.compartments;
|
|
455
|
+
if (compartments2 === void 0) {
|
|
456
|
+
return [];
|
|
457
|
+
}
|
|
458
|
+
const rows = [
|
|
459
|
+
...compartments2.stereotype === void 0 ? [] : [{ className: "stereotype", text: compartments2.stereotype }],
|
|
460
|
+
{
|
|
461
|
+
className: "name",
|
|
462
|
+
text: compartments2.name ?? node.label?.text ?? node.id
|
|
463
|
+
},
|
|
464
|
+
...(compartments2.properties ?? []).map((text) => ({
|
|
465
|
+
className: "properties",
|
|
466
|
+
text
|
|
467
|
+
})),
|
|
468
|
+
...(compartments2.constraints ?? []).map((text) => ({
|
|
469
|
+
className: "constraints",
|
|
470
|
+
text
|
|
471
|
+
}))
|
|
472
|
+
];
|
|
473
|
+
const lineHeight = 16;
|
|
474
|
+
const lines = [
|
|
475
|
+
` <g class="compartment" data-for="${escapeAttribute(node.id)}">`
|
|
476
|
+
];
|
|
477
|
+
for (let index = 0; index < rows.length; index += 1) {
|
|
478
|
+
const row = rows[index];
|
|
479
|
+
if (row === void 0) {
|
|
480
|
+
continue;
|
|
481
|
+
}
|
|
482
|
+
const y = node.box.y + 18 + index * lineHeight;
|
|
483
|
+
if (index > 1) {
|
|
484
|
+
lines.push(
|
|
485
|
+
` <line class="compartment-separator" x1="${formatNumber(node.box.x)}" y1="${formatNumber(y - 12)}" x2="${formatNumber(node.box.x + node.box.width)}" y2="${formatNumber(y - 12)}" stroke="${STROKE}"/>`
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
lines.push(
|
|
489
|
+
` <text class="compartment-${row.className}" x="${formatNumber(node.box.x + node.box.width / 2)}" y="${formatNumber(y)}" text-anchor="middle" font-family="${FONT_FAMILY}" font-size="11" fill="#111827">${escapeXml(row.text)}</text>`
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
lines.push(" </g>");
|
|
493
|
+
return lines;
|
|
494
|
+
}
|
|
495
|
+
function portLabelX(x, side) {
|
|
496
|
+
if (side === "left") {
|
|
497
|
+
return x - 8;
|
|
498
|
+
}
|
|
499
|
+
if (side === "right") {
|
|
500
|
+
return x + 8;
|
|
501
|
+
}
|
|
502
|
+
return x + 8;
|
|
503
|
+
}
|
|
385
504
|
function renderRect(box, attributes) {
|
|
386
505
|
return `<rect ${attributes} x="${formatNumber(box.x)}" y="${formatNumber(box.y)}" width="${formatNumber(box.width)}" height="${formatNumber(box.height)}"/>`;
|
|
387
506
|
}
|
|
388
507
|
function renderLabel(label, box, item) {
|
|
389
508
|
const labelLayout = item.labelLayout;
|
|
390
509
|
if (labelLayout?.lines !== void 0 && labelLayout.lines.length > 0) {
|
|
510
|
+
const offset = { x: box.x, y: box.y };
|
|
391
511
|
return [
|
|
392
512
|
` <text class="label" data-for="${escapeAttribute(item.id)}" font-family="${FONT_FAMILY}" font-size="${formatNumber(labelLayout.font.fontSize)}" fill="#111827">`,
|
|
393
513
|
...labelLayout.lines.map(
|
|
394
|
-
(line) => ` <tspan x="${formatNumber(line.box.x)}" y="${formatNumber(line.baselineY)}">${escapeXml(line.text)}</tspan>`
|
|
514
|
+
(line) => ` <tspan x="${formatNumber(offset.x + line.box.x)}" y="${formatNumber(offset.y + line.baselineY)}">${escapeXml(line.text)}</tspan>`
|
|
395
515
|
),
|
|
396
516
|
" </text>"
|
|
397
517
|
];
|
|
@@ -403,15 +523,88 @@ function renderLabel(label, box, item) {
|
|
|
403
523
|
` <text class="label" data-for="${escapeAttribute(item.id)}" x="${formatNumber(box.x + box.width / 2)}" y="${formatNumber(box.y + box.height / 2)}" text-anchor="middle" dominant-baseline="middle" font-family="${FONT_FAMILY}" font-size="14" fill="#111827">${escapeXml(label.text)}</text>`
|
|
404
524
|
];
|
|
405
525
|
}
|
|
406
|
-
function renderEdgePath(
|
|
407
|
-
if (points.length < 2) {
|
|
526
|
+
function renderEdgePath(edge) {
|
|
527
|
+
if (edge.points.length < 2) {
|
|
528
|
+
return void 0;
|
|
529
|
+
}
|
|
530
|
+
const dash = edge.style === "dashed" ? ' stroke-dasharray="6 4"' : "";
|
|
531
|
+
return `<path class="edge" data-id="${escapeAttribute(edge.id)}" d="${formatPath(pathPointsBeforeArrowhead(edge.points))}" fill="none" stroke="${EDGE_STROKE}" stroke-width="1.5"${dash}/>`;
|
|
532
|
+
}
|
|
533
|
+
function renderEdgeLabel(edge) {
|
|
534
|
+
if (edge.label?.text === void 0 || edge.points.length < 2) {
|
|
535
|
+
return [];
|
|
536
|
+
}
|
|
537
|
+
const placement = labelPlacementOnPolyline(edge.points);
|
|
538
|
+
if (placement === void 0) {
|
|
539
|
+
return [];
|
|
540
|
+
}
|
|
541
|
+
return [
|
|
542
|
+
` <text class="edge-label" data-for="${escapeAttribute(edge.id)}" x="${formatNumber(placement.x)}" y="${formatNumber(placement.y)}" text-anchor="middle" dominant-baseline="middle" font-family="${FONT_FAMILY}" font-size="12" fill="#111827">${escapeXml(edge.label.text)}</text>`
|
|
543
|
+
];
|
|
544
|
+
}
|
|
545
|
+
function renderArrowhead(edge) {
|
|
546
|
+
const arrowhead = computeArrowhead(edge.points);
|
|
547
|
+
const fill = edge.arrowhead === "hollowTriangle" ? "none" : EDGE_STROKE;
|
|
548
|
+
return `<polygon class="edge-arrowhead" data-edge="${escapeAttribute(edge.id)}" points="${formatPoints([arrowhead.tip, arrowhead.left, arrowhead.right])}" fill="${fill}" stroke="${EDGE_STROKE}"/>`;
|
|
549
|
+
}
|
|
550
|
+
function labelPlacementOnPolyline(points) {
|
|
551
|
+
const segments = nonZeroSegments(points);
|
|
552
|
+
const totalLength = segments.reduce(
|
|
553
|
+
(sum, segment) => sum + segment.length,
|
|
554
|
+
0
|
|
555
|
+
);
|
|
556
|
+
if (totalLength <= 0) {
|
|
408
557
|
return void 0;
|
|
409
558
|
}
|
|
410
|
-
|
|
559
|
+
let remaining = totalLength / 2;
|
|
560
|
+
for (const segment of segments) {
|
|
561
|
+
if (remaining <= segment.length) {
|
|
562
|
+
const ratio = remaining / segment.length;
|
|
563
|
+
const x = segment.start.x + (segment.end.x - segment.start.x) * ratio;
|
|
564
|
+
const y = segment.start.y + (segment.end.y - segment.start.y) * ratio;
|
|
565
|
+
const offset2 = labelOffset(segment);
|
|
566
|
+
return { x: x + offset2.x, y: y + offset2.y };
|
|
567
|
+
}
|
|
568
|
+
remaining -= segment.length;
|
|
569
|
+
}
|
|
570
|
+
const last = segments.at(-1);
|
|
571
|
+
if (last === void 0) {
|
|
572
|
+
return void 0;
|
|
573
|
+
}
|
|
574
|
+
const offset = labelOffset(last);
|
|
575
|
+
return { x: last.end.x + offset.x, y: last.end.y + offset.y };
|
|
576
|
+
}
|
|
577
|
+
function nonZeroSegments(points) {
|
|
578
|
+
const segments = [];
|
|
579
|
+
for (let index = 0; index < points.length - 1; index += 1) {
|
|
580
|
+
const start = points[index];
|
|
581
|
+
const end = points[index + 1];
|
|
582
|
+
if (start === void 0 || end === void 0) {
|
|
583
|
+
continue;
|
|
584
|
+
}
|
|
585
|
+
const length = Math.hypot(end.x - start.x, end.y - start.y);
|
|
586
|
+
if (length > 0) {
|
|
587
|
+
segments.push({ start, end, length });
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
return segments;
|
|
411
591
|
}
|
|
412
|
-
function
|
|
592
|
+
function labelOffset(segment) {
|
|
593
|
+
const offset = 10;
|
|
594
|
+
const dx = segment.end.x - segment.start.x;
|
|
595
|
+
const dy = segment.end.y - segment.start.y;
|
|
596
|
+
return {
|
|
597
|
+
x: -dy / segment.length * offset,
|
|
598
|
+
y: dx / segment.length * offset
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
function pathPointsBeforeArrowhead(points) {
|
|
413
602
|
const arrowhead = computeArrowhead(points);
|
|
414
|
-
|
|
603
|
+
const base = {
|
|
604
|
+
x: (arrowhead.left.x + arrowhead.right.x) / 2,
|
|
605
|
+
y: (arrowhead.left.y + arrowhead.right.y) / 2
|
|
606
|
+
};
|
|
607
|
+
return [...points.slice(0, -1), base];
|
|
415
608
|
}
|
|
416
609
|
function shapePoints(shape, box) {
|
|
417
610
|
const left = box.x;
|
|
@@ -1296,20 +1489,33 @@ function isValidDimension(value) {
|
|
|
1296
1489
|
// src/routing/routes.ts
|
|
1297
1490
|
function routeEdge(input) {
|
|
1298
1491
|
const diagnostics = [];
|
|
1492
|
+
const defaultAnchors = defaultAnchorsForGeometry(
|
|
1493
|
+
input.source.box,
|
|
1494
|
+
input.target.box,
|
|
1495
|
+
input.direction
|
|
1496
|
+
);
|
|
1299
1497
|
const source = getEdgePort(
|
|
1300
1498
|
input.source,
|
|
1301
1499
|
input.target.center,
|
|
1302
|
-
input.sourceAnchor
|
|
1500
|
+
input.sourceAnchor ?? defaultAnchors.sourceAnchor
|
|
1303
1501
|
);
|
|
1304
1502
|
const target = getEdgePort(
|
|
1305
1503
|
input.target,
|
|
1306
1504
|
input.source.center,
|
|
1307
|
-
input.targetAnchor
|
|
1505
|
+
input.targetAnchor ?? defaultAnchors.targetAnchor
|
|
1308
1506
|
);
|
|
1309
1507
|
if ((input.kind ?? "orthogonal") === "straight") {
|
|
1310
1508
|
return { points: simplifyRoute([source, target]), diagnostics };
|
|
1311
1509
|
}
|
|
1312
1510
|
const candidates = orthogonalCandidates(source, target, input.direction);
|
|
1511
|
+
candidates.push(
|
|
1512
|
+
...expandedObstacleCandidates(
|
|
1513
|
+
source,
|
|
1514
|
+
target,
|
|
1515
|
+
input.direction,
|
|
1516
|
+
input.obstacles ?? []
|
|
1517
|
+
)
|
|
1518
|
+
);
|
|
1313
1519
|
for (const candidate of candidates) {
|
|
1314
1520
|
if (!routeIntersectsObstacles(candidate, input.obstacles ?? [])) {
|
|
1315
1521
|
return { points: simplifyRoute(candidate), diagnostics };
|
|
@@ -1348,27 +1554,113 @@ function simplifyRoute(points) {
|
|
|
1348
1554
|
function orthogonalCandidates(source, target, direction) {
|
|
1349
1555
|
const midpointX = (source.x + target.x) / 2;
|
|
1350
1556
|
const midpointY = (source.y + target.y) / 2;
|
|
1351
|
-
const candidates = [
|
|
1352
|
-
[source, { x: target.x, y: source.y }, target],
|
|
1353
|
-
[source, { x: source.x, y: target.y }, target]
|
|
1354
|
-
];
|
|
1557
|
+
const candidates = [];
|
|
1355
1558
|
if (direction === "TB" || direction === "BT") {
|
|
1356
1559
|
candidates.push([
|
|
1357
1560
|
source,
|
|
1358
|
-
{ x:
|
|
1359
|
-
{ x:
|
|
1561
|
+
{ x: source.x, y: midpointY },
|
|
1562
|
+
{ x: target.x, y: midpointY },
|
|
1360
1563
|
target
|
|
1361
1564
|
]);
|
|
1362
1565
|
} else {
|
|
1363
1566
|
candidates.push([
|
|
1364
1567
|
source,
|
|
1365
|
-
{ x:
|
|
1366
|
-
{ x:
|
|
1568
|
+
{ x: midpointX, y: source.y },
|
|
1569
|
+
{ x: midpointX, y: target.y },
|
|
1367
1570
|
target
|
|
1368
1571
|
]);
|
|
1369
1572
|
}
|
|
1573
|
+
candidates.push(
|
|
1574
|
+
[source, { x: target.x, y: source.y }, target],
|
|
1575
|
+
[source, { x: source.x, y: target.y }, target]
|
|
1576
|
+
);
|
|
1577
|
+
return candidates;
|
|
1578
|
+
}
|
|
1579
|
+
function defaultSourceAnchor(direction) {
|
|
1580
|
+
switch (direction) {
|
|
1581
|
+
case "LR":
|
|
1582
|
+
return "right";
|
|
1583
|
+
case "RL":
|
|
1584
|
+
return "left";
|
|
1585
|
+
case "TB":
|
|
1586
|
+
return "bottom";
|
|
1587
|
+
case "BT":
|
|
1588
|
+
return "top";
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
function defaultAnchorsForGeometry(source, target, direction) {
|
|
1592
|
+
const dx = target.x + target.width / 2 - (source.x + source.width / 2);
|
|
1593
|
+
const dy = target.y + target.height / 2 - (source.y + source.height / 2);
|
|
1594
|
+
if (Math.abs(dy) > Math.abs(dx)) {
|
|
1595
|
+
return dy >= 0 ? { sourceAnchor: "bottom", targetAnchor: "top" } : { sourceAnchor: "top", targetAnchor: "bottom" };
|
|
1596
|
+
}
|
|
1597
|
+
if (Math.abs(dx) > 0) {
|
|
1598
|
+
return dx >= 0 ? { sourceAnchor: "right", targetAnchor: "left" } : { sourceAnchor: "left", targetAnchor: "right" };
|
|
1599
|
+
}
|
|
1600
|
+
return {
|
|
1601
|
+
sourceAnchor: defaultSourceAnchor(direction),
|
|
1602
|
+
targetAnchor: defaultTargetAnchor(direction)
|
|
1603
|
+
};
|
|
1604
|
+
}
|
|
1605
|
+
function defaultTargetAnchor(direction) {
|
|
1606
|
+
switch (direction) {
|
|
1607
|
+
case "LR":
|
|
1608
|
+
return "left";
|
|
1609
|
+
case "RL":
|
|
1610
|
+
return "right";
|
|
1611
|
+
case "TB":
|
|
1612
|
+
return "top";
|
|
1613
|
+
case "BT":
|
|
1614
|
+
return "bottom";
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
function expandedObstacleCandidates(source, target, direction, obstacles) {
|
|
1618
|
+
if (obstacles.length === 0) {
|
|
1619
|
+
return [];
|
|
1620
|
+
}
|
|
1621
|
+
const margin = 16;
|
|
1622
|
+
const candidates = [];
|
|
1623
|
+
if (direction === "TB" || direction === "BT") {
|
|
1624
|
+
const lanes = sortedUniqueLanes(
|
|
1625
|
+
obstacles.flatMap((obstacle) => [
|
|
1626
|
+
obstacle.x - margin,
|
|
1627
|
+
obstacle.x + obstacle.width + margin
|
|
1628
|
+
]),
|
|
1629
|
+
(source.x + target.x) / 2
|
|
1630
|
+
);
|
|
1631
|
+
for (const laneX of lanes) {
|
|
1632
|
+
candidates.push([
|
|
1633
|
+
source,
|
|
1634
|
+
{ x: laneX, y: source.y },
|
|
1635
|
+
{ x: laneX, y: target.y },
|
|
1636
|
+
target
|
|
1637
|
+
]);
|
|
1638
|
+
}
|
|
1639
|
+
} else {
|
|
1640
|
+
const lanes = sortedUniqueLanes(
|
|
1641
|
+
obstacles.flatMap((obstacle) => [
|
|
1642
|
+
obstacle.y - margin,
|
|
1643
|
+
obstacle.y + obstacle.height + margin
|
|
1644
|
+
]),
|
|
1645
|
+
(source.y + target.y) / 2
|
|
1646
|
+
);
|
|
1647
|
+
for (const laneY of lanes) {
|
|
1648
|
+
candidates.push([
|
|
1649
|
+
source,
|
|
1650
|
+
{ x: source.x, y: laneY },
|
|
1651
|
+
{ x: target.x, y: laneY },
|
|
1652
|
+
target
|
|
1653
|
+
]);
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1370
1656
|
return candidates;
|
|
1371
1657
|
}
|
|
1658
|
+
function sortedUniqueLanes(lanes, midpoint) {
|
|
1659
|
+
return [...new Set(lanes)].filter((lane) => Number.isFinite(lane)).sort((left, right) => {
|
|
1660
|
+
const distance = Math.abs(left - midpoint) - Math.abs(right - midpoint);
|
|
1661
|
+
return distance === 0 ? left - right : distance;
|
|
1662
|
+
});
|
|
1663
|
+
}
|
|
1372
1664
|
function routeIntersectsObstacles(points, obstacles) {
|
|
1373
1665
|
for (let index = 0; index < points.length - 1; index += 1) {
|
|
1374
1666
|
const a = points[index];
|
|
@@ -1447,12 +1739,17 @@ function solveDiagram(diagram, options = {}) {
|
|
|
1447
1739
|
options,
|
|
1448
1740
|
diagnostics
|
|
1449
1741
|
);
|
|
1742
|
+
const coordinatedSwimlanes = coordinateSwimlanes(
|
|
1743
|
+
diagram.swimlanes ?? [],
|
|
1744
|
+
constrained.boxes
|
|
1745
|
+
);
|
|
1450
1746
|
const groupBoxes = new Map(
|
|
1451
1747
|
coordinatedGroups.map((group) => [group.id, group.box])
|
|
1452
1748
|
);
|
|
1453
1749
|
const coordinatedEdges = coordinateEdges(
|
|
1454
1750
|
edges,
|
|
1455
1751
|
nodeGeometryById,
|
|
1752
|
+
coordinatedNodes,
|
|
1456
1753
|
[...nodeGeometryById.values()].map((geometry) => geometry.obstacleBox),
|
|
1457
1754
|
diagram.direction,
|
|
1458
1755
|
options,
|
|
@@ -1460,8 +1757,18 @@ function solveDiagram(diagram, options = {}) {
|
|
|
1460
1757
|
);
|
|
1461
1758
|
const allBoxes = [
|
|
1462
1759
|
...coordinatedNodes.map((node) => node.box),
|
|
1463
|
-
...
|
|
1760
|
+
...coordinatedNodes.flatMap(
|
|
1761
|
+
(node) => (node.ports ?? []).flatMap(
|
|
1762
|
+
(port) => port.label === void 0 ? [port.box] : [port.box, portLabelBox(port)]
|
|
1763
|
+
)
|
|
1764
|
+
),
|
|
1765
|
+
...groupBoxes.values(),
|
|
1766
|
+
...coordinatedSwimlanes.flatMap(
|
|
1767
|
+
(swimlane) => swimlane.box === void 0 ? [] : [swimlane.box]
|
|
1768
|
+
)
|
|
1464
1769
|
];
|
|
1770
|
+
const contentBounds = allBoxes.length === 0 ? { x: 0, y: 0, width: 0, height: 0 } : unionBoxes(allBoxes);
|
|
1771
|
+
const frame = diagram.frame === void 0 ? void 0 : coordinateFrame(diagram.frame, contentBounds);
|
|
1465
1772
|
return {
|
|
1466
1773
|
id: diagram.id,
|
|
1467
1774
|
...diagram.title === void 0 ? {} : { title: diagram.title },
|
|
@@ -1469,8 +1776,10 @@ function solveDiagram(diagram, options = {}) {
|
|
|
1469
1776
|
nodes: coordinatedNodes,
|
|
1470
1777
|
edges: coordinatedEdges,
|
|
1471
1778
|
groups: coordinatedGroups,
|
|
1779
|
+
...coordinatedSwimlanes.length === 0 ? {} : { swimlanes: coordinatedSwimlanes },
|
|
1472
1780
|
diagnostics,
|
|
1473
|
-
bounds:
|
|
1781
|
+
bounds: frame === void 0 ? contentBounds : unionBoxes([contentBounds, frame.box, frame.titleBox]),
|
|
1782
|
+
...frame === void 0 ? {} : { frame },
|
|
1474
1783
|
...diagram.metadata === void 0 ? {} : { metadata: diagram.metadata }
|
|
1475
1784
|
};
|
|
1476
1785
|
}
|
|
@@ -1496,6 +1805,9 @@ function coordinateNodes(nodes, boxes, options, diagnostics) {
|
|
|
1496
1805
|
coordinated.push({
|
|
1497
1806
|
id: node.id,
|
|
1498
1807
|
...node.label === void 0 ? {} : { label: node.label },
|
|
1808
|
+
...node.style === void 0 ? {} : { style: node.style },
|
|
1809
|
+
...node.ports === void 0 ? {} : { ports: coordinatePorts(node, box, options.portShifting) },
|
|
1810
|
+
...node.compartments === void 0 ? {} : { compartments: node.compartments },
|
|
1499
1811
|
...node.labelLayout === void 0 ? {} : { labelLayout: node.labelLayout },
|
|
1500
1812
|
shape: node.shape,
|
|
1501
1813
|
...node.metadata === void 0 ? {} : { metadata: node.metadata },
|
|
@@ -1506,6 +1818,142 @@ function coordinateNodes(nodes, boxes, options, diagnostics) {
|
|
|
1506
1818
|
}
|
|
1507
1819
|
return coordinated;
|
|
1508
1820
|
}
|
|
1821
|
+
function coordinatePorts(node, nodeBox, portShifting) {
|
|
1822
|
+
const portsBySide = /* @__PURE__ */ new Map();
|
|
1823
|
+
for (const port of node.ports ?? []) {
|
|
1824
|
+
const ports = portsBySide.get(port.side) ?? [];
|
|
1825
|
+
ports.push(port);
|
|
1826
|
+
portsBySide.set(port.side, ports);
|
|
1827
|
+
}
|
|
1828
|
+
const coordinated = [];
|
|
1829
|
+
for (const [side, ports] of portsBySide) {
|
|
1830
|
+
const sorted = [...ports ?? []].sort((a, b) => {
|
|
1831
|
+
const order = (a.order ?? 0) - (b.order ?? 0);
|
|
1832
|
+
return order === 0 ? a.id.localeCompare(b.id) : order;
|
|
1833
|
+
});
|
|
1834
|
+
for (let index = 0; index < sorted.length; index += 1) {
|
|
1835
|
+
const port = sorted[index];
|
|
1836
|
+
if (port === void 0) {
|
|
1837
|
+
continue;
|
|
1838
|
+
}
|
|
1839
|
+
const anchor = portAnchor(
|
|
1840
|
+
nodeBox,
|
|
1841
|
+
side,
|
|
1842
|
+
index,
|
|
1843
|
+
sorted.length,
|
|
1844
|
+
portShifting
|
|
1845
|
+
);
|
|
1846
|
+
const box = portBox(anchor);
|
|
1847
|
+
coordinated.push({ ...port, box, anchor });
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
return coordinated.sort((a, b) => a.id.localeCompare(b.id));
|
|
1851
|
+
}
|
|
1852
|
+
function portAnchor(nodeBox, side, index, count, portShifting) {
|
|
1853
|
+
const shiftingEnabled = portShifting?.enabled ?? true;
|
|
1854
|
+
const spacing = portShifting?.spacing ?? 24;
|
|
1855
|
+
const centeredOffset = shiftingEnabled ? (index - (count - 1) / 2) * spacing : 0;
|
|
1856
|
+
switch (side) {
|
|
1857
|
+
case "left":
|
|
1858
|
+
return {
|
|
1859
|
+
x: nodeBox.x,
|
|
1860
|
+
y: nodeBox.y + nodeBox.height / 2 + centeredOffset
|
|
1861
|
+
};
|
|
1862
|
+
case "right":
|
|
1863
|
+
return {
|
|
1864
|
+
x: nodeBox.x + nodeBox.width,
|
|
1865
|
+
y: nodeBox.y + nodeBox.height / 2 + centeredOffset
|
|
1866
|
+
};
|
|
1867
|
+
case "top":
|
|
1868
|
+
return {
|
|
1869
|
+
x: nodeBox.x + nodeBox.width / 2 + centeredOffset,
|
|
1870
|
+
y: nodeBox.y
|
|
1871
|
+
};
|
|
1872
|
+
case "bottom":
|
|
1873
|
+
return {
|
|
1874
|
+
x: nodeBox.x + nodeBox.width / 2 + centeredOffset,
|
|
1875
|
+
y: nodeBox.y + nodeBox.height
|
|
1876
|
+
};
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
function portBox(anchor) {
|
|
1880
|
+
const size = 10;
|
|
1881
|
+
return {
|
|
1882
|
+
x: anchor.x - size / 2,
|
|
1883
|
+
y: anchor.y - size / 2,
|
|
1884
|
+
width: size,
|
|
1885
|
+
height: size
|
|
1886
|
+
};
|
|
1887
|
+
}
|
|
1888
|
+
function portLabelBox(port) {
|
|
1889
|
+
const textWidth = Math.max(0, (port.label?.text.length ?? 0) * 6);
|
|
1890
|
+
const height = 12;
|
|
1891
|
+
const gap = 8;
|
|
1892
|
+
const x = port.side === "left" ? port.anchor.x - gap - textWidth : port.anchor.x + gap;
|
|
1893
|
+
return {
|
|
1894
|
+
x,
|
|
1895
|
+
y: port.anchor.y - 8 - height,
|
|
1896
|
+
width: textWidth,
|
|
1897
|
+
height
|
|
1898
|
+
};
|
|
1899
|
+
}
|
|
1900
|
+
function coordinateSwimlanes(swimlanes, nodeBoxes) {
|
|
1901
|
+
const titleSize = 28;
|
|
1902
|
+
const padding = 16;
|
|
1903
|
+
return swimlanes.map((swimlane) => {
|
|
1904
|
+
const laneBoxes = swimlane.lanes.flatMap((lane) => {
|
|
1905
|
+
const childBoxes = lane.children.map((child) => nodeBoxes.get(child)).filter((box) => box !== void 0);
|
|
1906
|
+
return childBoxes.length === 0 ? [] : [unionBoxes(childBoxes)];
|
|
1907
|
+
});
|
|
1908
|
+
const laneUnion = laneBoxes.length === 0 ? { x: 0, y: 0, width: 120, height: 80 } : unionBoxes(laneBoxes);
|
|
1909
|
+
const outer = expand(laneUnion, padding, titleSize);
|
|
1910
|
+
const laneCount = Math.max(1, swimlane.lanes.length);
|
|
1911
|
+
const lanes = swimlane.lanes.map((lane, index) => {
|
|
1912
|
+
const box = swimlane.orientation === "vertical" ? {
|
|
1913
|
+
x: outer.x + outer.width / laneCount * index,
|
|
1914
|
+
y: outer.y,
|
|
1915
|
+
width: outer.width / laneCount,
|
|
1916
|
+
height: outer.height
|
|
1917
|
+
} : {
|
|
1918
|
+
x: outer.x,
|
|
1919
|
+
y: outer.y + outer.height / laneCount * index,
|
|
1920
|
+
width: outer.width,
|
|
1921
|
+
height: outer.height / laneCount
|
|
1922
|
+
};
|
|
1923
|
+
return { ...lane, box };
|
|
1924
|
+
});
|
|
1925
|
+
return { ...swimlane, lanes, box: outer };
|
|
1926
|
+
});
|
|
1927
|
+
}
|
|
1928
|
+
function coordinateFrame(frame, contentBounds) {
|
|
1929
|
+
const padding = 32;
|
|
1930
|
+
const titleHeight = 28;
|
|
1931
|
+
const titleWidth = Math.max(180, frame.titleTab.length * 7);
|
|
1932
|
+
const box = {
|
|
1933
|
+
x: contentBounds.x - padding,
|
|
1934
|
+
y: contentBounds.y - padding - titleHeight,
|
|
1935
|
+
width: contentBounds.width + padding * 2,
|
|
1936
|
+
height: contentBounds.height + padding * 2 + titleHeight
|
|
1937
|
+
};
|
|
1938
|
+
return {
|
|
1939
|
+
...frame,
|
|
1940
|
+
box,
|
|
1941
|
+
titleBox: {
|
|
1942
|
+
x: box.x,
|
|
1943
|
+
y: box.y,
|
|
1944
|
+
width: Math.min(titleWidth, box.width * 0.8),
|
|
1945
|
+
height: titleHeight
|
|
1946
|
+
}
|
|
1947
|
+
};
|
|
1948
|
+
}
|
|
1949
|
+
function expand(box, padding, titleSize) {
|
|
1950
|
+
return {
|
|
1951
|
+
x: box.x - padding,
|
|
1952
|
+
y: box.y - padding - titleSize,
|
|
1953
|
+
width: box.width + padding * 2,
|
|
1954
|
+
height: box.height + padding * 2 + titleSize
|
|
1955
|
+
};
|
|
1956
|
+
}
|
|
1509
1957
|
function coordinateGroups(groups, nodeBoxes, options, diagnostics) {
|
|
1510
1958
|
const coordinated = [];
|
|
1511
1959
|
const groupBoxes = /* @__PURE__ */ new Map();
|
|
@@ -1554,8 +2002,11 @@ function coordinateGroups(groups, nodeBoxes, options, diagnostics) {
|
|
|
1554
2002
|
}
|
|
1555
2003
|
return coordinated;
|
|
1556
2004
|
}
|
|
1557
|
-
function coordinateEdges(edges, nodes, obstacles, direction, options, diagnostics) {
|
|
2005
|
+
function coordinateEdges(edges, nodes, coordinatedNodes, obstacles, direction, options, diagnostics) {
|
|
1558
2006
|
const coordinated = [];
|
|
2007
|
+
const coordinatedNodeById = new Map(
|
|
2008
|
+
coordinatedNodes.map((node) => [node.id, node])
|
|
2009
|
+
);
|
|
1559
2010
|
for (const edge of edges) {
|
|
1560
2011
|
const source = nodes.get(edge.source.nodeId);
|
|
1561
2012
|
const target = nodes.get(edge.target.nodeId);
|
|
@@ -1573,11 +2024,13 @@ function coordinateEdges(edges, nodes, obstacles, direction, options, diagnostic
|
|
|
1573
2024
|
});
|
|
1574
2025
|
continue;
|
|
1575
2026
|
}
|
|
2027
|
+
const sourcePort = coordinatedNodeById.get(edge.source.nodeId)?.ports?.find((port) => port.id === edge.source.portId);
|
|
2028
|
+
const targetPort = coordinatedNodeById.get(edge.target.nodeId)?.ports?.find((port) => port.id === edge.target.portId);
|
|
1576
2029
|
const route = routeEdge({
|
|
1577
2030
|
kind: options.routeKind ?? "orthogonal",
|
|
1578
2031
|
direction,
|
|
1579
|
-
source,
|
|
1580
|
-
target,
|
|
2032
|
+
source: portGeometry(source, sourcePort),
|
|
2033
|
+
target: portGeometry(target, targetPort),
|
|
1581
2034
|
...edge.source.anchor === void 0 ? {} : { sourceAnchor: edge.source.anchor },
|
|
1582
2035
|
...edge.target.anchor === void 0 ? {} : { targetAnchor: edge.target.anchor },
|
|
1583
2036
|
obstacles: obstacles.filter(
|
|
@@ -1597,6 +2050,21 @@ function coordinateEdges(edges, nodes, obstacles, direction, options, diagnostic
|
|
|
1597
2050
|
}
|
|
1598
2051
|
return coordinated;
|
|
1599
2052
|
}
|
|
2053
|
+
function portGeometry(nodeGeometry, port) {
|
|
2054
|
+
if (port === void 0) {
|
|
2055
|
+
return nodeGeometry;
|
|
2056
|
+
}
|
|
2057
|
+
return {
|
|
2058
|
+
...nodeGeometry,
|
|
2059
|
+
box: port.box,
|
|
2060
|
+
center: port.anchor,
|
|
2061
|
+
anchors: nodeGeometry.anchors.map((anchor) => ({
|
|
2062
|
+
name: anchor.name,
|
|
2063
|
+
point: port.anchor
|
|
2064
|
+
})),
|
|
2065
|
+
obstacleBox: port.box
|
|
2066
|
+
};
|
|
2067
|
+
}
|
|
1600
2068
|
function stableById(items) {
|
|
1601
2069
|
return [...items].sort((a, b) => a.id.localeCompare(b.id));
|
|
1602
2070
|
}
|
|
@@ -1626,34 +2094,34 @@ function assertFiniteNonNegative(value, label) {
|
|
|
1626
2094
|
throw new TypeError(`${label} must be a finite non-negative width`);
|
|
1627
2095
|
}
|
|
1628
2096
|
}
|
|
1629
|
-
function validateTextStyle(
|
|
1630
|
-
assertFinitePositive(
|
|
1631
|
-
if (
|
|
1632
|
-
assertFinitePositive(
|
|
2097
|
+
function validateTextStyle(style2) {
|
|
2098
|
+
assertFinitePositive(style2.fontSize, "fontSize");
|
|
2099
|
+
if (style2.lineHeight !== void 0) {
|
|
2100
|
+
assertFinitePositive(style2.lineHeight, "lineHeight");
|
|
1633
2101
|
}
|
|
1634
|
-
if (
|
|
2102
|
+
if (style2.letterSpacing !== void 0 && !Number.isFinite(style2.letterSpacing)) {
|
|
1635
2103
|
throw new TypeError("letterSpacing must be finite");
|
|
1636
2104
|
}
|
|
1637
2105
|
}
|
|
1638
|
-
function resolveLineHeight(
|
|
1639
|
-
validateTextStyle(
|
|
1640
|
-
return
|
|
2106
|
+
function resolveLineHeight(style2) {
|
|
2107
|
+
validateTextStyle(style2);
|
|
2108
|
+
return style2.lineHeight ?? style2.fontSize * 1.2;
|
|
1641
2109
|
}
|
|
1642
|
-
function toCanvasFont(
|
|
1643
|
-
validateTextStyle(
|
|
1644
|
-
const fontStyle =
|
|
1645
|
-
const fontWeight =
|
|
1646
|
-
return `${fontStyle}${fontWeight} ${
|
|
2110
|
+
function toCanvasFont(style2) {
|
|
2111
|
+
validateTextStyle(style2);
|
|
2112
|
+
const fontStyle = style2.fontStyle === "italic" ? "italic " : "";
|
|
2113
|
+
const fontWeight = style2.fontWeight ?? 400;
|
|
2114
|
+
return `${fontStyle}${fontWeight} ${style2.fontSize}px ${style2.fontFamily}`;
|
|
1647
2115
|
}
|
|
1648
2116
|
|
|
1649
2117
|
// src/text/fallback.ts
|
|
1650
2118
|
var DeterministicTextMeasurer = class {
|
|
1651
|
-
prepare(text,
|
|
1652
|
-
validateTextStyle(
|
|
2119
|
+
prepare(text, style2) {
|
|
2120
|
+
validateTextStyle(style2);
|
|
1653
2121
|
return {
|
|
1654
2122
|
text,
|
|
1655
|
-
font: toCanvasFont(
|
|
1656
|
-
style: { ...
|
|
2123
|
+
font: toCanvasFont(style2),
|
|
2124
|
+
style: { ...style2 },
|
|
1657
2125
|
backend: "deterministic"
|
|
1658
2126
|
};
|
|
1659
2127
|
}
|
|
@@ -1712,9 +2180,9 @@ var DeterministicTextMeasurer = class {
|
|
|
1712
2180
|
return output;
|
|
1713
2181
|
}
|
|
1714
2182
|
};
|
|
1715
|
-
function getCharacterWidth(
|
|
1716
|
-
const letterSpacing =
|
|
1717
|
-
return Math.max(0,
|
|
2183
|
+
function getCharacterWidth(style2) {
|
|
2184
|
+
const letterSpacing = style2.letterSpacing ?? 0;
|
|
2185
|
+
return Math.max(0, style2.fontSize * 0.6 + letterSpacing);
|
|
1718
2186
|
}
|
|
1719
2187
|
function createLine(text, width, segmentIndex, start, end) {
|
|
1720
2188
|
return {
|
|
@@ -1735,6 +2203,108 @@ function assertFinitePositiveLineHeight(lineHeight) {
|
|
|
1735
2203
|
throw new TypeError("lineHeight must be finite and positive");
|
|
1736
2204
|
}
|
|
1737
2205
|
}
|
|
2206
|
+
var require2 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
|
|
2207
|
+
function installNodeCanvasRuntime(loadNodeCanvasModule = loadDefaultNodeCanvasModule) {
|
|
2208
|
+
if (typeof globalThis.OffscreenCanvas === "function") {
|
|
2209
|
+
return true;
|
|
2210
|
+
}
|
|
2211
|
+
try {
|
|
2212
|
+
const canvasModule = loadNodeCanvasModule();
|
|
2213
|
+
const { createCanvas } = canvasModule;
|
|
2214
|
+
const NodeOffscreenCanvas = class {
|
|
2215
|
+
canvas;
|
|
2216
|
+
constructor(width, height) {
|
|
2217
|
+
this.canvas = createCanvas(width, height);
|
|
2218
|
+
}
|
|
2219
|
+
getContext(contextId) {
|
|
2220
|
+
return contextId === "2d" ? this.canvas.getContext("2d") : null;
|
|
2221
|
+
}
|
|
2222
|
+
};
|
|
2223
|
+
globalThis.OffscreenCanvas = NodeOffscreenCanvas;
|
|
2224
|
+
return true;
|
|
2225
|
+
} catch {
|
|
2226
|
+
return false;
|
|
2227
|
+
}
|
|
2228
|
+
}
|
|
2229
|
+
function loadDefaultNodeCanvasModule() {
|
|
2230
|
+
return require2("@napi-rs/canvas");
|
|
2231
|
+
}
|
|
2232
|
+
var RUNTIME_UNAVAILABLE = "text.pretext.runtime-unavailable";
|
|
2233
|
+
function isPretextRuntimeAvailable() {
|
|
2234
|
+
return typeof Intl.Segmenter === "function" && typeof globalThis.OffscreenCanvas === "function";
|
|
2235
|
+
}
|
|
2236
|
+
var PretextTextMeasurer = class {
|
|
2237
|
+
prepare(text, style2) {
|
|
2238
|
+
if (!isPretextRuntimeAvailable()) {
|
|
2239
|
+
throw new TypeError(RUNTIME_UNAVAILABLE);
|
|
2240
|
+
}
|
|
2241
|
+
validateTextStyle(style2);
|
|
2242
|
+
const font = toCanvasFont(style2);
|
|
2243
|
+
const options = {
|
|
2244
|
+
...style2.whiteSpace === void 0 ? {} : { whiteSpace: style2.whiteSpace },
|
|
2245
|
+
...style2.wordBreak === void 0 ? {} : { wordBreak: style2.wordBreak },
|
|
2246
|
+
...style2.letterSpacing === void 0 ? {} : { letterSpacing: style2.letterSpacing }
|
|
2247
|
+
};
|
|
2248
|
+
const prepared = pretext.prepareWithSegments(text, font, options);
|
|
2249
|
+
return {
|
|
2250
|
+
text,
|
|
2251
|
+
font,
|
|
2252
|
+
style: { ...style2 },
|
|
2253
|
+
backend: "pretext",
|
|
2254
|
+
pretextPrepared: prepared
|
|
2255
|
+
};
|
|
2256
|
+
}
|
|
2257
|
+
layout(prepared, maxWidth, lineHeight = resolveLineHeight(prepared.style)) {
|
|
2258
|
+
assertFiniteNonNegative(maxWidth, "maxWidth");
|
|
2259
|
+
if (!Number.isFinite(lineHeight) || lineHeight <= 0) {
|
|
2260
|
+
throw new TypeError("lineHeight must be finite and positive");
|
|
2261
|
+
}
|
|
2262
|
+
const result = pretext.layoutWithLines(
|
|
2263
|
+
toInternalPrepared(prepared),
|
|
2264
|
+
maxWidth,
|
|
2265
|
+
lineHeight
|
|
2266
|
+
);
|
|
2267
|
+
const width = result.lines.reduce(
|
|
2268
|
+
(current, line) => Math.max(current, line.width),
|
|
2269
|
+
0
|
|
2270
|
+
);
|
|
2271
|
+
return {
|
|
2272
|
+
width,
|
|
2273
|
+
height: result.height,
|
|
2274
|
+
lineHeight,
|
|
2275
|
+
lineCount: result.lineCount,
|
|
2276
|
+
lines: result.lines.map((line) => ({
|
|
2277
|
+
text: line.text,
|
|
2278
|
+
width: line.width,
|
|
2279
|
+
start: {
|
|
2280
|
+
segmentIndex: line.start.segmentIndex,
|
|
2281
|
+
graphemeIndex: line.start.graphemeIndex
|
|
2282
|
+
},
|
|
2283
|
+
end: {
|
|
2284
|
+
segmentIndex: line.end.segmentIndex,
|
|
2285
|
+
graphemeIndex: line.end.graphemeIndex
|
|
2286
|
+
}
|
|
2287
|
+
})),
|
|
2288
|
+
diagnostics: []
|
|
2289
|
+
};
|
|
2290
|
+
}
|
|
2291
|
+
naturalWidth(prepared) {
|
|
2292
|
+
return pretext.measureNaturalWidth(toInternalPrepared(prepared));
|
|
2293
|
+
}
|
|
2294
|
+
};
|
|
2295
|
+
function toInternalPrepared(prepared) {
|
|
2296
|
+
if (prepared.backend !== "pretext" || !("pretextPrepared" in prepared)) {
|
|
2297
|
+
throw new TypeError("prepared text was not created by PretextTextMeasurer");
|
|
2298
|
+
}
|
|
2299
|
+
return prepared.pretextPrepared;
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
// src/text/default.ts
|
|
2303
|
+
function createDefaultTextMeasurer(options = {}) {
|
|
2304
|
+
const installRuntime = options.installNodeCanvasRuntime ?? installNodeCanvasRuntime;
|
|
2305
|
+
installRuntime();
|
|
2306
|
+
return isPretextRuntimeAvailable() ? new PretextTextMeasurer() : new DeterministicTextMeasurer();
|
|
2307
|
+
}
|
|
1738
2308
|
|
|
1739
2309
|
// src/labels/fit.ts
|
|
1740
2310
|
function fitLabel(text, options, measurer) {
|
|
@@ -1793,6 +2363,7 @@ function computeLabelLayout(text, options, measurer) {
|
|
|
1793
2363
|
fittedSize,
|
|
1794
2364
|
padding,
|
|
1795
2365
|
font: { ...options.font },
|
|
2366
|
+
textBackend: prepared.backend,
|
|
1796
2367
|
lineHeight,
|
|
1797
2368
|
lines: buildLines(textLayout, contentBox2, lineHeight),
|
|
1798
2369
|
overflow,
|
|
@@ -1887,8 +2458,9 @@ function normalizeDiagramDsl(dslValue, options = {}) {
|
|
|
1887
2458
|
...outputResult(dsl)
|
|
1888
2459
|
};
|
|
1889
2460
|
}
|
|
1890
|
-
const measurer = options.textMeasurer ??
|
|
2461
|
+
const measurer = options.textMeasurer ?? createDefaultTextMeasurer();
|
|
1891
2462
|
const routeKind = dsl.routing?.kind ?? "orthogonal";
|
|
2463
|
+
const portShifting = normalizePortShifting(dsl.routing?.portShifting);
|
|
1892
2464
|
const diagram = {
|
|
1893
2465
|
id: options.id ?? dsl.id ?? "diagram",
|
|
1894
2466
|
...dsl.title === void 0 ? {} : { title: dsl.title },
|
|
@@ -1896,9 +2468,14 @@ function normalizeDiagramDsl(dslValue, options = {}) {
|
|
|
1896
2468
|
nodes: normalizeNodes(dsl, measurer),
|
|
1897
2469
|
edges: normalizeEdges(dsl),
|
|
1898
2470
|
groups: normalizeGroups(dsl, measurer),
|
|
2471
|
+
swimlanes: normalizeSwimlanes(dsl),
|
|
1899
2472
|
constraints: normalizeConstraints(dsl),
|
|
1900
2473
|
diagnostics: [],
|
|
1901
|
-
|
|
2474
|
+
...dsl.frame === void 0 ? {} : { frame: normalizeFrame(dsl.frame) },
|
|
2475
|
+
metadata: {
|
|
2476
|
+
routeKind,
|
|
2477
|
+
...portShifting === void 0 ? {} : { portShifting }
|
|
2478
|
+
}
|
|
1902
2479
|
};
|
|
1903
2480
|
return {
|
|
1904
2481
|
diagram,
|
|
@@ -1906,6 +2483,15 @@ function normalizeDiagramDsl(dslValue, options = {}) {
|
|
|
1906
2483
|
...outputResult(dsl)
|
|
1907
2484
|
};
|
|
1908
2485
|
}
|
|
2486
|
+
function normalizePortShifting(portShifting) {
|
|
2487
|
+
if (portShifting === void 0) {
|
|
2488
|
+
return void 0;
|
|
2489
|
+
}
|
|
2490
|
+
return {
|
|
2491
|
+
...portShifting.enabled === void 0 ? {} : { enabled: portShifting.enabled },
|
|
2492
|
+
...portShifting.spacing === void 0 ? {} : { spacing: portShifting.spacing }
|
|
2493
|
+
};
|
|
2494
|
+
}
|
|
1909
2495
|
function outputResult(dsl) {
|
|
1910
2496
|
return dsl.output?.format === void 0 ? {} : { output: { format: dsl.output.format } };
|
|
1911
2497
|
}
|
|
@@ -1915,15 +2501,24 @@ function normalizeNodes(dsl, measurer) {
|
|
|
1915
2501
|
const label = toLabel(node?.label);
|
|
1916
2502
|
const labelLayout = label === void 0 ? void 0 : fitDslLabel(label, measurer);
|
|
1917
2503
|
const fittedSize = labelLayout?.fittedSize;
|
|
2504
|
+
const nodeCompartments = node?.compartments === void 0 ? void 0 : compartments(node.compartments);
|
|
2505
|
+
const compartmentWidth = nodeCompartments === void 0 ? 0 : compartmentNaturalWidth(id, label, nodeCompartments, measurer);
|
|
1918
2506
|
return {
|
|
1919
2507
|
id,
|
|
1920
2508
|
...label === void 0 ? {} : { label },
|
|
1921
2509
|
shape: node?.shape ?? "rectangle",
|
|
1922
2510
|
...node?.position === void 0 ? {} : { position: point(node.position) },
|
|
2511
|
+
...node?.style === void 0 ? {} : { style: style(node.style) },
|
|
2512
|
+
...node?.ports === void 0 ? {} : { ports: normalizePorts(node.ports) },
|
|
2513
|
+
...nodeCompartments === void 0 ? {} : { compartments: nodeCompartments },
|
|
1923
2514
|
size: {
|
|
1924
|
-
width: Math.max(
|
|
2515
|
+
width: Math.max(
|
|
2516
|
+
DEFAULT_NODE_MIN_SIZE.width,
|
|
2517
|
+
fittedSize?.width ?? 0,
|
|
2518
|
+
compartmentWidth
|
|
2519
|
+
),
|
|
1925
2520
|
height: Math.max(
|
|
1926
|
-
DEFAULT_NODE_MIN_SIZE.height,
|
|
2521
|
+
nodeCompartments === void 0 ? DEFAULT_NODE_MIN_SIZE.height : compartmentHeight(nodeCompartments),
|
|
1927
2522
|
fittedSize?.height ?? 0
|
|
1928
2523
|
)
|
|
1929
2524
|
},
|
|
@@ -1932,11 +2527,42 @@ function normalizeNodes(dsl, measurer) {
|
|
|
1932
2527
|
};
|
|
1933
2528
|
});
|
|
1934
2529
|
}
|
|
2530
|
+
function compartmentHeight(value) {
|
|
2531
|
+
const rowCount = (value.stereotype === void 0 ? 0 : 1) + 1 + (value.properties?.length ?? 0) + (value.constraints?.length ?? 0);
|
|
2532
|
+
const rowHeight = 16;
|
|
2533
|
+
const verticalPadding = 20;
|
|
2534
|
+
return Math.max(
|
|
2535
|
+
DEFAULT_NODE_MIN_SIZE.height,
|
|
2536
|
+
rowCount * rowHeight + verticalPadding
|
|
2537
|
+
);
|
|
2538
|
+
}
|
|
2539
|
+
function compartmentNaturalWidth(id, label, value, measurer) {
|
|
2540
|
+
const rows = compartmentRows(id, label, value);
|
|
2541
|
+
const maxRowWidth = rows.reduce((width, row) => {
|
|
2542
|
+
const prepared = measurer.prepare(row, DEFAULT_FONT);
|
|
2543
|
+
return Math.max(width, measurer.naturalWidth(prepared));
|
|
2544
|
+
}, 0);
|
|
2545
|
+
return Math.ceil(
|
|
2546
|
+
maxRowWidth + DEFAULT_NODE_PADDING.left + DEFAULT_NODE_PADDING.right
|
|
2547
|
+
);
|
|
2548
|
+
}
|
|
2549
|
+
function compartmentRows(id, label, value) {
|
|
2550
|
+
return [
|
|
2551
|
+
...value.stereotype === void 0 ? [] : [value.stereotype],
|
|
2552
|
+
value.name ?? label?.text ?? id,
|
|
2553
|
+
...value.properties ?? [],
|
|
2554
|
+
...value.constraints ?? []
|
|
2555
|
+
];
|
|
2556
|
+
}
|
|
1935
2557
|
function normalizeEdges(dsl) {
|
|
1936
2558
|
const counts = /* @__PURE__ */ new Map();
|
|
1937
2559
|
return (dsl.edges ?? []).map((edge) => {
|
|
1938
|
-
const
|
|
1939
|
-
const
|
|
2560
|
+
const source = typeof edge === "string" ? void 0 : edge.source;
|
|
2561
|
+
const target = typeof edge === "string" ? void 0 : edge.target;
|
|
2562
|
+
const sourceId = typeof edge === "string" ? "" : edge.sourceId ?? endpointNodeId(source) ?? "";
|
|
2563
|
+
const targetId = typeof edge === "string" ? "" : edge.targetId ?? endpointNodeId(target) ?? "";
|
|
2564
|
+
const sourceEndpoint = typeof edge === "string" ? { nodeId: sourceId } : endpoint(source, edge.sourceId);
|
|
2565
|
+
const targetEndpoint = typeof edge === "string" ? { nodeId: targetId } : endpoint(target, edge.targetId);
|
|
1940
2566
|
const baseId = `${sourceId}-${targetId}`;
|
|
1941
2567
|
const count = counts.get(baseId) ?? 0;
|
|
1942
2568
|
counts.set(baseId, count + 1);
|
|
@@ -1944,9 +2570,96 @@ function normalizeEdges(dsl) {
|
|
|
1944
2570
|
const label = typeof edge === "string" ? void 0 : toLabel(edge.label);
|
|
1945
2571
|
return {
|
|
1946
2572
|
id,
|
|
1947
|
-
source:
|
|
1948
|
-
target:
|
|
1949
|
-
...label === void 0 ? {} : { label }
|
|
2573
|
+
source: sourceEndpoint,
|
|
2574
|
+
target: targetEndpoint,
|
|
2575
|
+
...label === void 0 ? {} : { label },
|
|
2576
|
+
...typeof edge === "string" || edge.style === void 0 ? {} : { style: edge.style },
|
|
2577
|
+
...typeof edge === "string" || edge.arrowhead === void 0 ? {} : { arrowhead: edge.arrowhead }
|
|
2578
|
+
};
|
|
2579
|
+
});
|
|
2580
|
+
}
|
|
2581
|
+
function normalizePorts(ports) {
|
|
2582
|
+
return Object.keys(ports ?? {}).sort().map((id) => {
|
|
2583
|
+
const port = ports?.[id];
|
|
2584
|
+
const label = toLabel(port?.label);
|
|
2585
|
+
return {
|
|
2586
|
+
id,
|
|
2587
|
+
...label === void 0 ? {} : { label },
|
|
2588
|
+
side: port?.side ?? "right",
|
|
2589
|
+
kind: port?.kind ?? "proxy",
|
|
2590
|
+
...port?.order === void 0 ? {} : { order: port.order },
|
|
2591
|
+
...port?.style === void 0 ? {} : { style: style(port.style) }
|
|
2592
|
+
};
|
|
2593
|
+
});
|
|
2594
|
+
}
|
|
2595
|
+
function endpoint(value, nodeIdOverride) {
|
|
2596
|
+
if (nodeIdOverride !== void 0) {
|
|
2597
|
+
return {
|
|
2598
|
+
nodeId: nodeIdOverride,
|
|
2599
|
+
...typeof value === "object" && value.node === nodeIdOverride && value.port !== void 0 ? { portId: value.port } : {}
|
|
2600
|
+
};
|
|
2601
|
+
}
|
|
2602
|
+
if (value === void 0) {
|
|
2603
|
+
return { nodeId: "" };
|
|
2604
|
+
}
|
|
2605
|
+
if (typeof value === "string") {
|
|
2606
|
+
return { nodeId: value };
|
|
2607
|
+
}
|
|
2608
|
+
return {
|
|
2609
|
+
nodeId: value.node,
|
|
2610
|
+
...value.port === void 0 ? {} : { portId: value.port }
|
|
2611
|
+
};
|
|
2612
|
+
}
|
|
2613
|
+
function style(value) {
|
|
2614
|
+
return {
|
|
2615
|
+
...value.fill === void 0 ? {} : { fill: value.fill },
|
|
2616
|
+
...value.stroke === void 0 ? {} : { stroke: value.stroke }
|
|
2617
|
+
};
|
|
2618
|
+
}
|
|
2619
|
+
function compartments(value) {
|
|
2620
|
+
return {
|
|
2621
|
+
...value.stereotype === void 0 ? {} : { stereotype: value.stereotype },
|
|
2622
|
+
...value.name === void 0 ? {} : { name: value.name },
|
|
2623
|
+
...value.properties === void 0 ? {} : { properties: value.properties.map(formatCompartmentEntry) },
|
|
2624
|
+
...value.constraints === void 0 ? {} : { constraints: [...value.constraints] }
|
|
2625
|
+
};
|
|
2626
|
+
}
|
|
2627
|
+
function normalizeFrame(frame) {
|
|
2628
|
+
return {
|
|
2629
|
+
kind: frame.kind,
|
|
2630
|
+
...frame.context === void 0 ? {} : { context: frame.context },
|
|
2631
|
+
...frame.name === void 0 ? {} : { name: frame.name },
|
|
2632
|
+
titleTab: frame.titleTab,
|
|
2633
|
+
...frame.style === void 0 ? {} : { style: style(frame.style) }
|
|
2634
|
+
};
|
|
2635
|
+
}
|
|
2636
|
+
function formatCompartmentEntry(value) {
|
|
2637
|
+
if (typeof value === "string") {
|
|
2638
|
+
return value;
|
|
2639
|
+
}
|
|
2640
|
+
const [entry] = Object.entries(value);
|
|
2641
|
+
if (entry === void 0) {
|
|
2642
|
+
return "";
|
|
2643
|
+
}
|
|
2644
|
+
return `${entry[0]}: ${entry[1]}`;
|
|
2645
|
+
}
|
|
2646
|
+
function normalizeSwimlanes(dsl) {
|
|
2647
|
+
return Object.keys(dsl.swimlanes ?? {}).sort().map((id) => {
|
|
2648
|
+
const swimlane = dsl.swimlanes?.[id];
|
|
2649
|
+
const label = toLabel(swimlane?.label);
|
|
2650
|
+
return {
|
|
2651
|
+
id,
|
|
2652
|
+
...label === void 0 ? {} : { label },
|
|
2653
|
+
orientation: swimlane?.orientation ?? "vertical",
|
|
2654
|
+
lanes: Object.keys(swimlane?.lanes ?? {}).sort().map((laneId) => {
|
|
2655
|
+
const lane = swimlane?.lanes[laneId];
|
|
2656
|
+
const laneLabel = toLabel(lane?.label);
|
|
2657
|
+
return {
|
|
2658
|
+
id: laneId,
|
|
2659
|
+
...laneLabel === void 0 ? {} : { label: laneLabel },
|
|
2660
|
+
children: [...lane?.children ?? []]
|
|
2661
|
+
};
|
|
2662
|
+
})
|
|
1950
2663
|
};
|
|
1951
2664
|
});
|
|
1952
2665
|
}
|
|
@@ -2020,14 +2733,28 @@ function validateReferences(dsl) {
|
|
|
2020
2733
|
if (typeof edge === "string") {
|
|
2021
2734
|
return;
|
|
2022
2735
|
}
|
|
2023
|
-
const sourceId = edge.sourceId ?? edge.source;
|
|
2024
|
-
const targetId = edge.targetId ?? edge.target;
|
|
2736
|
+
const sourceId = edge.sourceId ?? endpointNodeId(edge.source);
|
|
2737
|
+
const targetId = edge.targetId ?? endpointNodeId(edge.target);
|
|
2738
|
+
const sourceEndpoint = endpoint(edge.source, edge.sourceId);
|
|
2739
|
+
const targetEndpoint = endpoint(edge.target, edge.targetId);
|
|
2025
2740
|
if (sourceId !== void 0 && !nodeIds.has(sourceId)) {
|
|
2026
2741
|
diagnostics.push(referenceMissing(["edges", index, "source"], sourceId));
|
|
2027
2742
|
}
|
|
2028
2743
|
if (targetId !== void 0 && !nodeIds.has(targetId)) {
|
|
2029
2744
|
diagnostics.push(referenceMissing(["edges", index, "target"], targetId));
|
|
2030
2745
|
}
|
|
2746
|
+
validateEndpointPort(
|
|
2747
|
+
dsl,
|
|
2748
|
+
sourceEndpoint,
|
|
2749
|
+
["edges", index, "source"],
|
|
2750
|
+
diagnostics
|
|
2751
|
+
);
|
|
2752
|
+
validateEndpointPort(
|
|
2753
|
+
dsl,
|
|
2754
|
+
targetEndpoint,
|
|
2755
|
+
["edges", index, "target"],
|
|
2756
|
+
diagnostics
|
|
2757
|
+
);
|
|
2031
2758
|
});
|
|
2032
2759
|
for (const [groupId, group] of Object.entries(dsl.groups ?? {})) {
|
|
2033
2760
|
(group.nodes ?? []).forEach((nodeId, index) => {
|
|
@@ -2045,6 +2772,27 @@ function validateReferences(dsl) {
|
|
|
2045
2772
|
}
|
|
2046
2773
|
});
|
|
2047
2774
|
}
|
|
2775
|
+
for (const [swimlaneId, swimlane] of Object.entries(dsl.swimlanes ?? {})) {
|
|
2776
|
+
for (const [laneId, lane] of Object.entries(swimlane.lanes)) {
|
|
2777
|
+
(lane.children ?? []).forEach((child, childIndex) => {
|
|
2778
|
+
if (!nodeIds.has(child)) {
|
|
2779
|
+
diagnostics.push(
|
|
2780
|
+
referenceMissing(
|
|
2781
|
+
[
|
|
2782
|
+
"swimlanes",
|
|
2783
|
+
swimlaneId,
|
|
2784
|
+
"lanes",
|
|
2785
|
+
laneId,
|
|
2786
|
+
"children",
|
|
2787
|
+
childIndex
|
|
2788
|
+
],
|
|
2789
|
+
child
|
|
2790
|
+
)
|
|
2791
|
+
);
|
|
2792
|
+
}
|
|
2793
|
+
});
|
|
2794
|
+
}
|
|
2795
|
+
}
|
|
2048
2796
|
(dsl.constraints ?? []).forEach((constraint, index) => {
|
|
2049
2797
|
switch (constraint.kind) {
|
|
2050
2798
|
case "exact-position": {
|
|
@@ -2088,10 +2836,12 @@ function validateReferences(dsl) {
|
|
|
2088
2836
|
break;
|
|
2089
2837
|
case "containment": {
|
|
2090
2838
|
const container = constraint.containerId ?? constraint.container;
|
|
2091
|
-
if (container !== void 0
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2839
|
+
if (container !== void 0) {
|
|
2840
|
+
if (!nodeIds.has(container)) {
|
|
2841
|
+
diagnostics.push(
|
|
2842
|
+
referenceMissing(["constraints", index, "container"], container)
|
|
2843
|
+
);
|
|
2844
|
+
}
|
|
2095
2845
|
}
|
|
2096
2846
|
(constraint.childIds ?? constraint.children ?? []).forEach(
|
|
2097
2847
|
(child, childIndex) => {
|
|
@@ -2121,8 +2871,23 @@ function referenceMissing(path, id) {
|
|
|
2121
2871
|
hint: "Define the referenced node or group id, or update this reference."
|
|
2122
2872
|
};
|
|
2123
2873
|
}
|
|
2124
|
-
function hasNodeOrGroup(id, nodeIds, groupIds) {
|
|
2125
|
-
return nodeIds.has(id) || groupIds.has(id);
|
|
2874
|
+
function hasNodeOrGroup(id, nodeIds, groupIds, swimlaneLaneIds = /* @__PURE__ */ new Set()) {
|
|
2875
|
+
return nodeIds.has(id) || groupIds.has(id) || swimlaneLaneIds.has(id);
|
|
2876
|
+
}
|
|
2877
|
+
function endpointNodeId(endpointValue) {
|
|
2878
|
+
if (typeof endpointValue === "string" || endpointValue === void 0) {
|
|
2879
|
+
return endpointValue;
|
|
2880
|
+
}
|
|
2881
|
+
return endpointValue.node;
|
|
2882
|
+
}
|
|
2883
|
+
function validateEndpointPort(dsl, endpointValue, path, diagnostics) {
|
|
2884
|
+
if (endpointValue.portId === void 0) {
|
|
2885
|
+
return;
|
|
2886
|
+
}
|
|
2887
|
+
const node = dsl.nodes[endpointValue.nodeId];
|
|
2888
|
+
if (node !== void 0 && node.ports?.[endpointValue.portId] === void 0) {
|
|
2889
|
+
diagnostics.push(referenceMissing([...path, "port"], endpointValue.portId));
|
|
2890
|
+
}
|
|
2126
2891
|
}
|
|
2127
2892
|
function toLabel(value) {
|
|
2128
2893
|
if (value === void 0) {
|
|
@@ -2192,6 +2957,8 @@ function isValidEdgeId(value) {
|
|
|
2192
2957
|
var directionSchema = zod.z.enum(["TB", "LR", "BT", "RL"]);
|
|
2193
2958
|
var routeKindSchema = zod.z.enum(["orthogonal", "straight"]);
|
|
2194
2959
|
var outputFormatSchema = zod.z.enum(["svg", "excalidraw"]);
|
|
2960
|
+
var edgeStrokeStyleSchema = zod.z.enum(["solid", "dashed"]);
|
|
2961
|
+
var edgeArrowheadSchema = zod.z.enum(["triangle", "hollowTriangle"]);
|
|
2195
2962
|
var nodeShapeSchema = zod.z.enum([
|
|
2196
2963
|
"rectangle",
|
|
2197
2964
|
"rounded-rectangle",
|
|
@@ -2219,18 +2986,49 @@ var labelSchema = zod.z.union([
|
|
|
2219
2986
|
maxWidth: finiteNumberSchema.optional()
|
|
2220
2987
|
})
|
|
2221
2988
|
]);
|
|
2989
|
+
var styleSchema = zod.z.object({
|
|
2990
|
+
fill: zod.z.string().optional(),
|
|
2991
|
+
stroke: zod.z.string().optional()
|
|
2992
|
+
});
|
|
2993
|
+
var portSideSchema = zod.z.enum(["top", "right", "bottom", "left"]);
|
|
2994
|
+
var portKindSchema = zod.z.enum(["proxy", "flow"]);
|
|
2995
|
+
var portSchema = zod.z.object({
|
|
2996
|
+
label: labelSchema.optional(),
|
|
2997
|
+
side: portSideSchema,
|
|
2998
|
+
kind: portKindSchema.optional(),
|
|
2999
|
+
order: finiteNumberSchema.optional(),
|
|
3000
|
+
style: styleSchema.optional()
|
|
3001
|
+
});
|
|
3002
|
+
var compartmentsSchema = zod.z.object({
|
|
3003
|
+
stereotype: zod.z.string().optional(),
|
|
3004
|
+
name: zod.z.string().optional(),
|
|
3005
|
+
properties: zod.z.array(zod.z.record(zod.z.string(), zod.z.string()).or(zod.z.string())).optional(),
|
|
3006
|
+
constraints: zod.z.array(zod.z.string()).optional()
|
|
3007
|
+
});
|
|
2222
3008
|
var nodeSchema = zod.z.object({
|
|
2223
3009
|
label: labelSchema.optional(),
|
|
2224
3010
|
shape: nodeShapeSchema.optional(),
|
|
2225
|
-
position: pointSchema.optional()
|
|
3011
|
+
position: pointSchema.optional(),
|
|
3012
|
+
style: styleSchema.optional(),
|
|
3013
|
+
ports: zod.z.record(zod.z.string(), portSchema).optional(),
|
|
3014
|
+
compartments: compartmentsSchema.optional()
|
|
2226
3015
|
});
|
|
3016
|
+
var endpointSchema = zod.z.union([
|
|
3017
|
+
zod.z.string(),
|
|
3018
|
+
zod.z.object({
|
|
3019
|
+
node: zod.z.string(),
|
|
3020
|
+
port: zod.z.string().optional()
|
|
3021
|
+
})
|
|
3022
|
+
]);
|
|
2227
3023
|
var structuredEdgeSchema = zod.z.object({
|
|
2228
3024
|
id: zod.z.string().optional(),
|
|
2229
|
-
source:
|
|
2230
|
-
target:
|
|
3025
|
+
source: endpointSchema.optional(),
|
|
3026
|
+
target: endpointSchema.optional(),
|
|
2231
3027
|
sourceId: zod.z.string().optional(),
|
|
2232
3028
|
targetId: zod.z.string().optional(),
|
|
2233
|
-
label: labelSchema.optional()
|
|
3029
|
+
label: labelSchema.optional(),
|
|
3030
|
+
style: edgeStrokeStyleSchema.optional(),
|
|
3031
|
+
arrowhead: edgeArrowheadSchema.optional()
|
|
2234
3032
|
}).superRefine((edge, context) => {
|
|
2235
3033
|
if (edge.source === void 0 && edge.sourceId === void 0) {
|
|
2236
3034
|
context.addIssue({
|
|
@@ -2254,6 +3052,17 @@ var groupSchema = zod.z.object({
|
|
|
2254
3052
|
groups: zod.z.array(zod.z.string()).optional(),
|
|
2255
3053
|
padding: insetsSchema.optional()
|
|
2256
3054
|
});
|
|
3055
|
+
var swimlaneSchema = zod.z.object({
|
|
3056
|
+
label: labelSchema.optional(),
|
|
3057
|
+
orientation: zod.z.enum(["vertical", "horizontal"]).optional(),
|
|
3058
|
+
lanes: zod.z.record(
|
|
3059
|
+
zod.z.string(),
|
|
3060
|
+
zod.z.object({
|
|
3061
|
+
label: labelSchema.optional(),
|
|
3062
|
+
children: zod.z.array(zod.z.string()).optional()
|
|
3063
|
+
})
|
|
3064
|
+
)
|
|
3065
|
+
});
|
|
2257
3066
|
var exactPositionConstraintSchema = zod.z.object({
|
|
2258
3067
|
kind: zod.z.literal("exact-position"),
|
|
2259
3068
|
target: zod.z.string().optional(),
|
|
@@ -2314,12 +3123,24 @@ var diagramDslSchema = zod.z.object({
|
|
|
2314
3123
|
direction: directionSchema.optional()
|
|
2315
3124
|
}).optional(),
|
|
2316
3125
|
routing: zod.z.object({
|
|
2317
|
-
kind: routeKindSchema.optional()
|
|
3126
|
+
kind: routeKindSchema.optional(),
|
|
3127
|
+
portShifting: zod.z.object({
|
|
3128
|
+
enabled: zod.z.boolean().optional(),
|
|
3129
|
+
spacing: finiteNumberSchema.optional()
|
|
3130
|
+
}).optional()
|
|
2318
3131
|
}).optional(),
|
|
2319
3132
|
nodes: zod.z.record(zod.z.string(), nodeSchema),
|
|
2320
3133
|
edges: zod.z.array(edgeSchema).optional(),
|
|
2321
3134
|
groups: zod.z.record(zod.z.string(), groupSchema).optional(),
|
|
3135
|
+
swimlanes: zod.z.record(zod.z.string(), swimlaneSchema).optional(),
|
|
2322
3136
|
constraints: zod.z.array(constraintSchema).optional(),
|
|
3137
|
+
frame: zod.z.object({
|
|
3138
|
+
kind: zod.z.string(),
|
|
3139
|
+
context: zod.z.string().optional(),
|
|
3140
|
+
name: zod.z.string().optional(),
|
|
3141
|
+
titleTab: zod.z.string(),
|
|
3142
|
+
style: styleSchema.optional()
|
|
3143
|
+
}).optional(),
|
|
2323
3144
|
output: zod.z.object({
|
|
2324
3145
|
format: outputFormatSchema.optional()
|
|
2325
3146
|
}).optional()
|
|
@@ -2516,7 +3337,8 @@ function renderDiagramDsl(source, options = {}) {
|
|
|
2516
3337
|
return { diagnostics };
|
|
2517
3338
|
}
|
|
2518
3339
|
const solved = solveDiagram(normalized.diagram, {
|
|
2519
|
-
routeKind: normalized.diagram.metadata?.routeKind === "straight" ? "straight" : "orthogonal"
|
|
3340
|
+
routeKind: normalized.diagram.metadata?.routeKind === "straight" ? "straight" : "orthogonal",
|
|
3341
|
+
...solvePortShiftingOption(normalized.diagram.metadata?.portShifting)
|
|
2520
3342
|
});
|
|
2521
3343
|
const solveDiagnostics = solved.diagnostics.map(toSolveDiagnostic);
|
|
2522
3344
|
if (hasErrorDiagnostics2(solveDiagnostics)) {
|
|
@@ -2555,6 +3377,22 @@ function renderDiagramDsl(source, options = {}) {
|
|
|
2555
3377
|
function toSolveDiagnostic(diagnostic) {
|
|
2556
3378
|
return { ...diagnostic, layer: "solve" };
|
|
2557
3379
|
}
|
|
3380
|
+
function solvePortShiftingOption(value) {
|
|
3381
|
+
if (!isJsonObject(value)) {
|
|
3382
|
+
return {};
|
|
3383
|
+
}
|
|
3384
|
+
const portShifting = {};
|
|
3385
|
+
if (value.enabled === false) {
|
|
3386
|
+
portShifting.enabled = false;
|
|
3387
|
+
}
|
|
3388
|
+
if (typeof value.spacing === "number") {
|
|
3389
|
+
portShifting.spacing = value.spacing;
|
|
3390
|
+
}
|
|
3391
|
+
return { portShifting };
|
|
3392
|
+
}
|
|
3393
|
+
function isJsonObject(value) {
|
|
3394
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3395
|
+
}
|
|
2558
3396
|
function toExportDiagnostic(diagnostic) {
|
|
2559
3397
|
return { ...diagnostic, layer: "export" };
|
|
2560
3398
|
}
|