@diagrammo/dgmo 0.75.0 → 0.76.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.
Files changed (43) hide show
  1. package/dist/advanced.d.ts +40 -1
  2. package/dist/advanced.js +181 -19
  3. package/dist/block.css +20 -3
  4. package/dist/block.d.ts +10 -2
  5. package/dist/block.js +29 -12
  6. package/dist/chart-meta.js +6 -6
  7. package/dist/{chunk-LYLRNAX2.js → chunk-3EGIU5WY.js} +2 -2
  8. package/dist/{chunk-2NRIGEHZ.js → chunk-46KVXDUJ.js} +10 -3
  9. package/dist/{chunk-M3IVOGZE.js → chunk-4CRLM3IT.js} +26 -20
  10. package/dist/chunk-7IATMZSA.js +72 -0
  11. package/dist/{chunk-6DYZ2JM6.js → chunk-BZQCAZZZ.js} +203 -29
  12. package/dist/{chunk-ZMKCG3FT.js → chunk-C576CU77.js} +2 -2
  13. package/dist/{chunk-DSH7NJ2G.js → chunk-EGXJWRO6.js} +2 -2
  14. package/dist/{chunk-RT7ACF77.js → chunk-EGY3TS62.js} +6 -6
  15. package/dist/{chunk-TDHD3HNO.js → chunk-F4X5NVKY.js} +37 -16
  16. package/dist/{chunk-BFTRW24X.js → chunk-FMZEU7MF.js} +64 -23
  17. package/dist/{chunk-R5JPMW2F.js → chunk-FTTB64OJ.js} +5 -5
  18. package/dist/{chunk-IGQW7TKM.js → chunk-GFXFRKUG.js} +2 -2
  19. package/dist/{chunk-F4CPZRG2.js → chunk-JLJ7SP4X.js} +2 -2
  20. package/dist/{chunk-SUA56ZSB.js → chunk-LTTZX6RD.js} +6 -2
  21. package/dist/{chunk-GE5RO4BS.js → chunk-N6MZSBOL.js} +5 -1
  22. package/dist/{chunk-DU3OIBQE.js → chunk-NWNSXHA5.js} +6 -2
  23. package/dist/{chunk-QUYYL3LP.js → chunk-OBYZU23V.js} +4 -4
  24. package/dist/{chunk-XCAEHWQB.js → chunk-PAW4RMH3.js} +2 -2
  25. package/dist/{chunk-XFLLYY3V.js → chunk-TF76LCZS.js} +33 -49
  26. package/dist/{dgmo-router-KYNLRE7S.js → dgmo-router-A3LIHT6H.js} +7 -7
  27. package/dist/{dimensions-NLQ64ED5.js → dimensions-7NYBSZRJ.js} +3 -3
  28. package/dist/{flowchart-parser-LY5GGQL2.js → flowchart-parser-NVBP3C5D.js} +2 -2
  29. package/dist/{flowchart-renderer-RIJ5FZKO.js → flowchart-renderer-QYGQ64BM.js} +5 -5
  30. package/dist/index.js +8 -8
  31. package/dist/{layout-UJ62RQQ3.js → layout-2OJ25STS.js} +2 -2
  32. package/dist/{layout-DAYQ46PS.js → layout-LAS67TK3.js} +3 -3
  33. package/dist/{parser-LUOINP6H.js → parser-QYAIFXLP.js} +3 -3
  34. package/dist/{parser-L7RXUKYN.js → parser-WVE6SKB7.js} +2 -2
  35. package/dist/{parser-JYIZEKAS.js → parser-ZYAFHXKQ.js} +2 -2
  36. package/dist/{renderer-WDSBFDQ2.js → renderer-E6NHTVN6.js} +3 -3
  37. package/dist/{renderer-A2YWSBPY.js → renderer-F6WSR7UM.js} +3 -3
  38. package/dist/{renderer-UYYBJ7OB.js → renderer-IH45QV6Z.js} +9 -9
  39. package/dist/{renderer-73QHYZ2Q.js → renderer-LE3ZKHNS.js} +3 -3
  40. package/dist/{state-renderer-454ADT7E.js → state-renderer-UIE3AQM6.js} +4 -4
  41. package/docs/language-reference.md +3 -3
  42. package/package.json +2 -2
  43. package/dist/chunk-PDKUANDZ.js +0 -35
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  SKETCH_DIAGNOSTIC_CODES
3
- } from "./chunk-RT7ACF77.js";
3
+ } from "./chunk-EGY3TS62.js";
4
4
  import {
5
5
  parseInArrowLabel
6
6
  } from "./chunk-IHOFUR74.js";
@@ -71,6 +71,7 @@ var BOX_RE = /^\[([^\]]*)\]\s*(.*)$/;
71
71
  var BOX_TAIL_ALIAS_RE = /^as\s+([A-Za-z][A-Za-z0-9_]{0,11})(?=\s|,|$)\s*,?\s*/;
72
72
  var AT_VALUE_RE = /^(-?\d+)\s+(-?\d+)$/;
73
73
  var SKETCH_AT_MAX = 2e3;
74
+ var MAX_BOX_DEPTH = 2;
74
75
  function parseSketch(content, palette) {
75
76
  const options = {
76
77
  noLegend: false,
@@ -262,7 +263,7 @@ function parseSketch(content, palette) {
262
263
  }
263
264
  return { ...alias !== void 0 && { alias }, at, collapsed, meta };
264
265
  };
265
- const openBox = (label, tail, lineNumber) => {
266
+ const openBox = (label, tail, lineNumber, parentBoxId) => {
266
267
  const norm = normalizeName(label);
267
268
  const existing = boxByNorm.get(norm);
268
269
  const { alias, at, collapsed, meta } = parseBoxTail(tail, lineNumber);
@@ -281,9 +282,14 @@ function parseSketch(content, palette) {
281
282
  metadata: meta,
282
283
  collapsed,
283
284
  children: [],
285
+ childBoxes: [],
286
+ parentBoxId,
284
287
  lineNumber
285
288
  };
286
289
  boxes.push(box);
290
+ if (parentBoxId !== null) {
291
+ boxByNorm.get(normalizeName(parentBoxId.slice(1, -1)))?.childBoxes.push(box.id);
292
+ }
287
293
  boxByNorm.set(norm, box);
288
294
  if (alias !== void 0) {
289
295
  if (aliasIndex.has(alias)) {
@@ -353,7 +359,13 @@ function parseSketch(content, palette) {
353
359
  let firstLineConsumed = false;
354
360
  let contentStarted = false;
355
361
  let currentTagGroup = null;
356
- let currentBox = null;
362
+ const boxStack = [];
363
+ const boxAt = (indent) => {
364
+ while (boxStack.length > 0 && indent <= boxStack[boxStack.length - 1].indent) {
365
+ boxStack.pop();
366
+ }
367
+ return boxStack[boxStack.length - 1] ?? null;
368
+ };
357
369
  let currentShape = null;
358
370
  for (let i = 0; i < lines.length; i++) {
359
371
  const raw = lines[i];
@@ -492,8 +504,8 @@ ${descLine}`;
492
504
  if (EDGE_START_RE.test(trimmed)) {
493
505
  if (indent > 0 && currentShape && indent > currentShape.indent) {
494
506
  addEdge(trimmed, lineNumber, currentShape.id);
495
- } else if (indent > 0 && currentBox && indent > currentBox.indent) {
496
- addEdge(trimmed, lineNumber, currentBox.box.id);
507
+ } else if (indent > 0 && boxAt(indent)) {
508
+ addEdge(trimmed, lineNumber, boxAt(indent).box.id);
497
509
  } else {
498
510
  warn(
499
511
  lineNumber,
@@ -509,29 +521,38 @@ ${descLine}`;
509
521
  warn(lineNumber, "Box has no label \u2014 ignored");
510
522
  continue;
511
523
  }
512
- if (indent > 0 && currentBox && indent > currentBox.indent) {
524
+ while (boxStack.length > 0 && indent <= boxStack[boxStack.length - 1].indent) {
525
+ boxStack.pop();
526
+ }
527
+ const depth = boxStack.length + 1;
528
+ if (depth > MAX_BOX_DEPTH) {
513
529
  pushError(
514
530
  lineNumber,
515
- `Box "${label}" is nested inside "${currentBox.box.label}" \u2014 sketch boxes are one level only; its shapes join the outer box`,
516
- SKETCH_DIAGNOSTIC_CODES.NESTED_BOX
531
+ `Box "${label}" is nested ${depth} levels deep \u2014 sketch boxes nest to depth ${MAX_BOX_DEPTH} (decision #58); its shapes join the box above it`,
532
+ SKETCH_DIAGNOSTIC_CODES.BOX_DEPTH
517
533
  );
518
534
  continue;
519
535
  }
520
- currentBox = {
521
- box: openBox(label, boxMatch[2] ?? "", lineNumber),
522
- indent
523
- };
536
+ const parent = boxStack[boxStack.length - 1] ?? null;
537
+ const box = openBox(
538
+ label,
539
+ boxMatch[2] ?? "",
540
+ lineNumber,
541
+ parent ? parent.box.id : null
542
+ );
543
+ boxStack.push({ box, indent });
524
544
  currentShape = null;
525
545
  continue;
526
546
  }
527
547
  if (indent === 0) {
528
- currentBox = null;
548
+ boxStack.length = 0;
529
549
  const node2 = addShape(trimmed, lineNumber, null);
530
550
  currentShape = node2 ? { id: node2.id, indent } : null;
531
551
  continue;
532
552
  }
533
- if (currentBox && indent > currentBox.indent) {
534
- const node2 = addShape(trimmed, lineNumber, currentBox.box);
553
+ const owner = boxAt(indent);
554
+ if (owner) {
555
+ const node2 = addShape(trimmed, lineNumber, owner.box);
535
556
  currentShape = node2 ? { id: node2.id, indent } : currentShape;
536
557
  continue;
537
558
  }
@@ -632,4 +653,4 @@ export {
632
653
  isSketchShapeKind,
633
654
  parseSketch
634
655
  };
635
- //# sourceMappingURL=chunk-TDHD3HNO.js.map
656
+ //# sourceMappingURL=chunk-F4X5NVKY.js.map
@@ -624,17 +624,33 @@ function legLabelPoint(a, b, curved, offset, away) {
624
624
  function buildConnectorLegs(args) {
625
625
  const { resolved, poiScreen, palette, width, height, fillAt, labelOnFill } = args;
626
626
  const legs = [];
627
+ const legDefaultGroups = resolved.tagGroups.filter((g) => {
628
+ if (!g.defaultValue) return false;
629
+ const k = tagAttrKey(g.name);
630
+ return resolved.edges.some((e) => e.tags[k]) || resolved.routes.some((rt) => rt.legs.some((l) => l.tags[k]));
631
+ });
632
+ const entryColor = (group, val) => val ? group.entries.find((e) => e.value.toLowerCase() === val.toLowerCase())?.color : void 0;
627
633
  const lineColor = (tags) => {
628
634
  for (const group of resolved.tagGroups) {
629
- const val = tags[tagAttrKey(group.name)];
630
- if (!val) continue;
631
- const entry = group.entries.find(
632
- (e) => e.value.toLowerCase() === val.toLowerCase()
633
- );
634
- if (entry?.color) return entry.color;
635
+ const hex = entryColor(group, tags[tagAttrKey(group.name)]);
636
+ if (hex) return hex;
637
+ }
638
+ for (const group of legDefaultGroups) {
639
+ if (tags[tagAttrKey(group.name)]) continue;
640
+ const hex = entryColor(group, group.defaultValue);
641
+ if (hex) return hex;
635
642
  }
636
643
  return null;
637
644
  };
645
+ const effectiveTags = (tags) => {
646
+ let out = null;
647
+ for (const group of legDefaultGroups) {
648
+ const key = tagAttrKey(group.name);
649
+ if (tags[key]) continue;
650
+ (out ??= { ...tags })[key] = group.defaultValue;
651
+ }
652
+ return out ?? tags;
653
+ };
638
654
  const placedLegSamples = [];
639
655
  const sampleLeg = (a, b, curved, bow) => {
640
656
  const pts = [];
@@ -754,6 +770,7 @@ function buildConnectorLegs(args) {
754
770
  });
755
771
  const routeLabelStyle = leg.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
756
772
  const routeVal = Number(leg.value);
773
+ const legTags = effectiveTags(leg.tags);
757
774
  legs.push({
758
775
  d: legPath(a, b, bow.curved, bow.offset, bow.center),
759
776
  width: routeWidthFor(routeVal),
@@ -762,7 +779,7 @@ function buildConnectorLegs(args) {
762
779
  fromId: leg.fromId,
763
780
  toId: leg.toId,
764
781
  ...Number.isFinite(routeVal) && routeVal > 0 && { value: routeVal },
765
- ...Object.keys(leg.tags).length > 0 && { tags: leg.tags },
782
+ ...Object.keys(legTags).length > 0 && { tags: legTags },
766
783
  lineNumber: leg.lineNumber,
767
784
  ...leg.label !== void 0 && {
768
785
  label: leg.label,
@@ -815,6 +832,7 @@ function buildConnectorLegs(args) {
815
832
  });
816
833
  const edgeLabelStyle = e.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
817
834
  const edgeVal = Number(e.meta["width"]);
835
+ const edgeTags = effectiveTags(e.tags);
818
836
  legs.push({
819
837
  d: legPath(a, b, bow.curved, bow.offset),
820
838
  width: widthFor(e),
@@ -823,7 +841,7 @@ function buildConnectorLegs(args) {
823
841
  fromId: e.fromId,
824
842
  toId: e.toId,
825
843
  ...Number.isFinite(edgeVal) && edgeVal > 0 && { value: edgeVal },
826
- ...Object.keys(e.tags).length > 0 && { tags: e.tags },
844
+ ...Object.keys(edgeTags).length > 0 && { tags: edgeTags },
827
845
  lineNumber: e.lineNumber,
828
846
  ...e.label !== void 0 && {
829
847
  label: e.label,
@@ -1897,7 +1915,7 @@ function layoutMap(resolvedIn, data, size, opts) {
1897
1915
  };
1898
1916
  const fillGroupNames = /* @__PURE__ */ new Set();
1899
1917
  for (const g of resolved.tagGroups) {
1900
- const k = g.name.toLowerCase();
1918
+ const k = tagAttrKey(g.name);
1901
1919
  if (resolved.regions.some((r) => r.tags[k]) || resolved.pois.some((p) => p.tags[k]))
1902
1920
  fillGroupNames.add(g.name);
1903
1921
  }
@@ -1983,6 +2001,24 @@ function layoutMap(resolvedIn, data, size, opts) {
1983
2001
  const pct = RAMP_FLOOR + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR);
1984
2002
  return mix(rampHue, rampBase, pct);
1985
2003
  };
2004
+ const defaultGroupsFor = (used) => resolved.tagGroups.filter(
2005
+ (g) => g.defaultValue && used(tagAttrKey(g.name))
2006
+ );
2007
+ const poiDefaultGroups = defaultGroupsFor(
2008
+ (k) => resolved.pois.some((p) => p.tags[k])
2009
+ );
2010
+ const regionDefaultGroups = defaultGroupsFor(
2011
+ (k) => resolved.regions.some((r) => r.tags[k])
2012
+ );
2013
+ const effectiveTags = (tags, groups2) => {
2014
+ let out = null;
2015
+ for (const group of groups2) {
2016
+ const key = tagAttrKey(group.name);
2017
+ if (tags[key]) continue;
2018
+ (out ??= { ...tags })[key] = group.defaultValue;
2019
+ }
2020
+ return out ?? tags;
2021
+ };
1986
2022
  const tagFill = (tags, groupName) => {
1987
2023
  if (!groupName) return null;
1988
2024
  const group = resolved.tagGroups.find(
@@ -2366,8 +2402,10 @@ function layoutMap(resolvedIn, data, size, opts) {
2366
2402
  let label;
2367
2403
  let lineNumber = -1;
2368
2404
  let layer = "base";
2405
+ let tags = {};
2369
2406
  if (isThisLayer) {
2370
2407
  fill = regionFill(r);
2408
+ tags = effectiveTags(r.tags, regionDefaultGroups);
2371
2409
  lineNumber = r.lineNumber;
2372
2410
  layer = layerKind;
2373
2411
  label = r.name;
@@ -2384,7 +2422,7 @@ function layoutMap(resolvedIn, data, size, opts) {
2384
2422
  ...label !== void 0 && { label },
2385
2423
  ...hasCentroid && { labelX: geo.cx, labelY: geo.cy },
2386
2424
  ...isThisLayer && r.value !== void 0 && { value: r.value },
2387
- ...isThisLayer && Object.keys(r.tags).length > 0 && { tags: r.tags }
2425
+ ...Object.keys(tags).length > 0 && { tags }
2388
2426
  });
2389
2427
  }
2390
2428
  };
@@ -2522,19 +2560,21 @@ function layoutMap(resolvedIn, data, size, opts) {
2522
2560
  const directHex = p.color ? resolveColor(p.color, palette) : null;
2523
2561
  if (directHex)
2524
2562
  return { fill: directHex, stroke: mix(directHex, palette.text, 18) };
2563
+ const paint = (hex) => ({
2564
+ fill: hex,
2565
+ stroke: mix(hex, palette.text, 18)
2566
+ });
2567
+ const entryColor = (group, val) => val ? group.entries.find((e) => e.value.toLowerCase() === val.toLowerCase())?.color : void 0;
2525
2568
  for (const group of resolved.tagGroups) {
2526
- const val = p.tags[tagAttrKey(group.name)];
2527
- if (!val) continue;
2528
- const entry = group.entries.find(
2529
- (e) => e.value.toLowerCase() === val.toLowerCase()
2530
- );
2531
- const hex = entry?.color;
2532
- if (hex) return { fill: hex, stroke: mix(hex, palette.text, 18) };
2569
+ const hex = entryColor(group, p.tags[tagAttrKey(group.name)]);
2570
+ if (hex) return paint(hex);
2533
2571
  }
2534
- return {
2535
- fill: palette.colors.orange,
2536
- stroke: mix(palette.colors.orange, palette.text, 18)
2537
- };
2572
+ for (const group of poiDefaultGroups) {
2573
+ if (p.tags[tagAttrKey(group.name)]) continue;
2574
+ const hex = entryColor(group, group.defaultValue);
2575
+ if (hex) return paint(hex);
2576
+ }
2577
+ return paint(palette.colors.orange);
2538
2578
  };
2539
2579
  const routeNumberById = /* @__PURE__ */ new Map();
2540
2580
  const originIds = /* @__PURE__ */ new Set();
@@ -2556,6 +2596,7 @@ function layoutMap(resolvedIn, data, size, opts) {
2556
2596
  }
2557
2597
  const placePoi = (e, cx, cy, clusterId) => {
2558
2598
  const { fill, stroke } = poiFill(e.p);
2599
+ const poiTags = effectiveTags(e.p.tags, poiDefaultGroups);
2559
2600
  const r = radiusFor(e.p);
2560
2601
  poiScreen.set(e.p.id, { cx, cy, r });
2561
2602
  const num = routeNumberById.get(e.p.id);
@@ -2571,7 +2612,7 @@ function layoutMap(resolvedIn, data, size, opts) {
2571
2612
  implicit: !!e.p.implicit,
2572
2613
  isOrigin: originIds.has(e.p.id),
2573
2614
  ...num !== void 0 && { routeNumber: num },
2574
- ...Object.keys(e.p.tags).length > 0 && { tags: e.p.tags },
2615
+ ...Object.keys(poiTags).length > 0 && { tags: poiTags },
2575
2616
  ...clusterId !== void 0 && { clusterId }
2576
2617
  });
2577
2618
  };
@@ -3365,4 +3406,4 @@ export {
3365
3406
  albersSkewFallback,
3366
3407
  layoutMap
3367
3408
  };
3368
- //# sourceMappingURL=chunk-BFTRW24X.js.map
3409
+ //# sourceMappingURL=chunk-FMZEU7MF.js.map
@@ -51,7 +51,7 @@ import {
51
51
  } from "./chunk-KRTLS3G6.js";
52
52
  import {
53
53
  parseSketch
54
- } from "./chunk-TDHD3HNO.js";
54
+ } from "./chunk-F4X5NVKY.js";
55
55
  import {
56
56
  parseSwimlane
57
57
  } from "./chunk-W7UBPARG.js";
@@ -89,7 +89,7 @@ import {
89
89
  } from "./chunk-ZM27UI5O.js";
90
90
  import {
91
91
  parseInfra
92
- } from "./chunk-2NRIGEHZ.js";
92
+ } from "./chunk-46KVXDUJ.js";
93
93
  import {
94
94
  parseGantt
95
95
  } from "./chunk-TPN7RJOM.js";
@@ -106,7 +106,7 @@ import {
106
106
  import {
107
107
  looksLikeFlowchart,
108
108
  parseFlowchart
109
- } from "./chunk-DU3OIBQE.js";
109
+ } from "./chunk-NWNSXHA5.js";
110
110
  import {
111
111
  looksLikeState,
112
112
  parseState
@@ -114,7 +114,7 @@ import {
114
114
  import {
115
115
  looksLikeClassDiagram,
116
116
  parseClassDiagram
117
- } from "./chunk-SUA56ZSB.js";
117
+ } from "./chunk-LTTZX6RD.js";
118
118
  import {
119
119
  looksLikeERDiagram,
120
120
  parseERDiagram
@@ -1716,4 +1716,4 @@ export {
1716
1716
  knownChartTypeIds,
1717
1717
  parseDgmo
1718
1718
  };
1719
- //# sourceMappingURL=chunk-R5JPMW2F.js.map
1719
+ //# sourceMappingURL=chunk-FTTB64OJ.js.map
@@ -54,7 +54,7 @@ import {
54
54
  } from "./chunk-MTGGOCND.js";
55
55
  import {
56
56
  parseInfra
57
- } from "./chunk-2NRIGEHZ.js";
57
+ } from "./chunk-46KVXDUJ.js";
58
58
  import {
59
59
  preprocessDescriptionLine
60
60
  } from "./chunk-IYULMRBE.js";
@@ -1613,4 +1613,4 @@ export {
1613
1613
  renderInfra,
1614
1614
  parseAndLayoutInfra
1615
1615
  };
1616
- //# sourceMappingURL=chunk-IGQW7TKM.js.map
1616
+ //# sourceMappingURL=chunk-GFXFRKUG.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  buildMapProjection
3
- } from "./chunk-BFTRW24X.js";
3
+ } from "./chunk-FMZEU7MF.js";
4
4
  import {
5
5
  TITLE_FONT_SIZE,
6
6
  TITLE_Y
@@ -51,4 +51,4 @@ export {
51
51
  mapContentAspect,
52
52
  mapExportDimensions
53
53
  };
54
- //# sourceMappingURL=chunk-F4CPZRG2.js.map
54
+ //# sourceMappingURL=chunk-JLJ7SP4X.js.map
@@ -421,6 +421,7 @@ function looksLikeClassDiagram(content) {
421
421
  }
422
422
  function extractSymbols(docText) {
423
423
  const entities = [];
424
+ const seen = /* @__PURE__ */ new Set();
424
425
  let inMetadata = true;
425
426
  for (const rawLine of docText.split("\n")) {
426
427
  const line = rawLine.trim();
@@ -436,7 +437,10 @@ function extractSymbols(docText) {
436
437
  const m = CLASS_DECL_RE.exec(line);
437
438
  if (m) {
438
439
  const name = (m[2] ?? m[3] ?? "").trim();
439
- if (name && !entities.includes(name)) entities.push(name);
440
+ if (name && !seen.has(name)) {
441
+ seen.add(name);
442
+ entities.push(name);
443
+ }
440
444
  }
441
445
  }
442
446
  return {
@@ -450,4 +454,4 @@ export {
450
454
  looksLikeClassDiagram,
451
455
  extractSymbols
452
456
  };
453
- //# sourceMappingURL=chunk-SUA56ZSB.js.map
457
+ //# sourceMappingURL=chunk-LTTZX6RD.js.map
@@ -283,6 +283,10 @@ function layoutGraph(graph, options) {
283
283
  for (const group of layoutGroups) {
284
284
  extend(group.x, group.y, group.x + group.width, group.y + group.height);
285
285
  }
286
+ for (const edge of layoutEdges) {
287
+ if (edge.source !== edge.target) continue;
288
+ for (const pt of edge.points) extend(pt.x, pt.y, pt.x, pt.y);
289
+ }
286
290
  if (!Number.isFinite(bbMinX)) {
287
291
  bbMinX = 0;
288
292
  bbMinY = 0;
@@ -311,4 +315,4 @@ function layoutGraph(graph, options) {
311
315
  export {
312
316
  layoutGraph
313
317
  };
314
- //# sourceMappingURL=chunk-GE5RO4BS.js.map
318
+ //# sourceMappingURL=chunk-N6MZSBOL.js.map
@@ -452,6 +452,7 @@ function looksLikeFlowchart(content) {
452
452
  var NODE_ID_RE = /^([a-zA-Z_][\w-]*)[\s([</{]/;
453
453
  function extractSymbols(docText) {
454
454
  const entities = [];
455
+ const seen = /* @__PURE__ */ new Set();
455
456
  let inMetadata = true;
456
457
  for (const rawLine of docText.split("\n")) {
457
458
  const line = rawLine.trim();
@@ -460,7 +461,10 @@ function extractSymbols(docText) {
460
461
  inMetadata = false;
461
462
  if (line.length === 0 || /^\s/.test(rawLine)) continue;
462
463
  const m = NODE_ID_RE.exec(line);
463
- if (m && !entities.includes(m[1])) entities.push(m[1]);
464
+ if (m && !seen.has(m[1])) {
465
+ seen.add(m[1]);
466
+ entities.push(m[1]);
467
+ }
464
468
  }
465
469
  return { kind: "flowchart", entities };
466
470
  }
@@ -470,4 +474,4 @@ export {
470
474
  looksLikeFlowchart,
471
475
  extractSymbols
472
476
  };
473
- //# sourceMappingURL=chunk-DU3OIBQE.js.map
477
+ //# sourceMappingURL=chunk-NWNSXHA5.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  edgeSplinePath,
3
3
  fitDiagramToCanvas
4
- } from "./chunk-PDKUANDZ.js";
4
+ } from "./chunk-7IATMZSA.js";
5
5
  import {
6
6
  layoutGraph
7
- } from "./chunk-GE5RO4BS.js";
7
+ } from "./chunk-N6MZSBOL.js";
8
8
  import {
9
9
  appendArrowheadMarkers
10
10
  } from "./chunk-LP7EC4MI.js";
@@ -39,7 +39,7 @@ import {
39
39
  } from "./chunk-MTGGOCND.js";
40
40
  import {
41
41
  parseFlowchart
42
- } from "./chunk-DU3OIBQE.js";
42
+ } from "./chunk-NWNSXHA5.js";
43
43
  import {
44
44
  fillModeFromOptions
45
45
  } from "./chunk-M5OOAP65.js";
@@ -586,4 +586,4 @@ export {
586
586
  renderFlowchart,
587
587
  renderFlowchartForExport
588
588
  };
589
- //# sourceMappingURL=chunk-QUYYL3LP.js.map
589
+ //# sourceMappingURL=chunk-OBYZU23V.js.map
@@ -10,7 +10,7 @@ import {
10
10
  } from "./chunk-U7VO6JAA.js";
11
11
  import {
12
12
  parseDgmoChartType
13
- } from "./chunk-R5JPMW2F.js";
13
+ } from "./chunk-FTTB64OJ.js";
14
14
  import {
15
15
  chartTypes
16
16
  } from "./chunk-M5OOAP65.js";
@@ -204,4 +204,4 @@ export {
204
204
  MONO_FAMILY,
205
205
  renderErrorCard
206
206
  };
207
- //# sourceMappingURL=chunk-XCAEHWQB.js.map
207
+ //# sourceMappingURL=chunk-PAW4RMH3.js.map
@@ -1,10 +1,11 @@
1
1
  import {
2
2
  edgeSplinePath,
3
- fitDiagramToCanvas
4
- } from "./chunk-PDKUANDZ.js";
3
+ fitDiagramToCanvas,
4
+ selfLoopArcPath
5
+ } from "./chunk-7IATMZSA.js";
5
6
  import {
6
7
  layoutGraph
7
- } from "./chunk-GE5RO4BS.js";
8
+ } from "./chunk-N6MZSBOL.js";
8
9
  import {
9
10
  appendArrowheadMarkers
10
11
  } from "./chunk-LP7EC4MI.js";
@@ -88,17 +89,6 @@ function stateFill(palette, isDark, nodeColor, colorOff, fillMode) {
88
89
  function stateStroke(palette, nodeColor, colorOff) {
89
90
  return nodeColor ?? stateDefaultColor(palette, colorOff);
90
91
  }
91
- function selfLoopPath(node) {
92
- const cx = node.x;
93
- const cy = node.y;
94
- const r = node.width / 2;
95
- const startX = cx + r;
96
- const startY = cy - 5;
97
- const endX = cx + r;
98
- const endY = cy + 5;
99
- const loopR = 25;
100
- return `M ${startX} ${startY} C ${startX + loopR * 2} ${startY - loopR * 2}, ${endX + loopR * 2} ${endY + loopR * 2}, ${endX} ${endY}`;
101
- }
102
92
  function renderState(container, graph, layout, palette, isDark, onClickItem, exportDims) {
103
93
  d3Selection.select(container).selectAll(":not([data-d3-tooltip])").remove();
104
94
  const width = exportDims?.width ?? container.clientWidth;
@@ -244,42 +234,46 @@ function renderState(container, graph, layout, palette, isDark, onClickItem, exp
244
234
  groupWrapper.append("rect").attr("x", gx).attr("y", gy).attr("width", gw).attr("height", gh).attr("rx", 6).attr("fill", fillColor).attr("stroke", strokeColor).attr("stroke-width", 1).attr("stroke-opacity", 0.5).attr("class", "st-group");
245
235
  groupWrapper.append("text").attr("x", gx + 8).attr("y", gy + sGroupLabelFontSize + 4).attr("fill", strokeColor).attr("font-size", sGroupLabelFontSize).attr("font-weight", "bold").attr("opacity", 0.7).attr("class", "st-group-label").text(group.label);
246
236
  }
247
- const selfLoopEdges = /* @__PURE__ */ new Set();
248
- for (const edge of layout.edges) {
249
- if (edge.source === edge.target) selfLoopEdges.add(edge.lineNumber);
250
- }
251
- const nodePositionMap = /* @__PURE__ */ new Map();
252
- for (const node of layout.nodes) {
253
- nodePositionMap.set(node.id, node);
254
- }
255
237
  const LABEL_PAD = 8;
256
238
  const LABEL_H = 16;
257
239
  const PERP_OFFSET = 10;
240
+ const nodeCenters = /* @__PURE__ */ new Map();
241
+ for (const node of layout.nodes) nodeCenters.set(node.id, node);
258
242
  const labelPositions = [];
259
243
  for (let ei = 0; ei < layout.edges.length; ei++) {
260
244
  const edge = layout.edges[ei];
261
245
  if (!edge.label) continue;
262
246
  const bgW = measureText(edge.label, sEdgeLabelFontSize) + LABEL_PAD;
263
247
  let lx, ly;
264
- if (edge.source === edge.target) {
265
- const node = nodePositionMap.get(edge.source);
266
- if (!node) continue;
267
- lx = node.x + node.width / 2 + 30;
268
- ly = node.y;
269
- } else if (edge.points.length >= 2) {
248
+ if (edge.points.length >= 2) {
270
249
  const midIdx = Math.floor(edge.points.length / 2);
271
250
  const midPt = edge.points[midIdx];
272
251
  const prev = edge.points[Math.max(0, midIdx - 1)];
273
252
  const next = edge.points[Math.min(edge.points.length - 1, midIdx + 1)];
274
- const dx = next.x - prev.x;
275
- const dy = next.y - prev.y;
276
- const len = Math.sqrt(dx * dx + dy * dy);
277
- if (len > 0) {
278
- lx = midPt.x + -dy / len * PERP_OFFSET;
279
- ly = midPt.y + dx / len * PERP_OFFSET;
253
+ const self = edge.source === edge.target;
254
+ const node = self ? nodeCenters.get(edge.source) : void 0;
255
+ if (self && node) {
256
+ const ox = midPt.x - node.x;
257
+ const oy = midPt.y - node.y;
258
+ const olen = Math.sqrt(ox * ox + oy * oy);
259
+ if (olen > 0) {
260
+ lx = midPt.x + ox / olen * PERP_OFFSET;
261
+ ly = midPt.y + oy / olen * PERP_OFFSET;
262
+ } else {
263
+ lx = midPt.x;
264
+ ly = midPt.y;
265
+ }
280
266
  } else {
281
- lx = midPt.x;
282
- ly = midPt.y;
267
+ const dx = next.x - prev.x;
268
+ const dy = next.y - prev.y;
269
+ const len = Math.sqrt(dx * dx + dy * dy);
270
+ if (len > 0) {
271
+ lx = midPt.x + -dy / len * PERP_OFFSET;
272
+ ly = midPt.y + dx / len * PERP_OFFSET;
273
+ } else {
274
+ lx = midPt.x;
275
+ ly = midPt.y;
276
+ }
283
277
  }
284
278
  } else {
285
279
  continue;
@@ -305,18 +299,8 @@ function renderState(container, graph, layout, palette, isDark, onClickItem, exp
305
299
  const edgeG = contentG.append("g").attr("class", "st-edge-group").attr("data-line-number", String(edge.lineNumber)).attr("data-source", edge.source).attr("data-target", edge.target);
306
300
  const edgeColor = palette.textMuted;
307
301
  const markerId = "st-arrow";
308
- if (edge.source === edge.target) {
309
- const node = nodePositionMap.get(edge.source);
310
- if (node) {
311
- edgeG.append("path").attr("d", selfLoopPath(node)).attr("fill", "none").attr("stroke", edgeColor).attr("stroke-width", sEdgeStrokeWidth).attr("marker-end", `url(#${markerId})`).attr("class", "st-edge");
312
- const lp = labelPosMap.get(ei);
313
- if (edge.label && lp) {
314
- edgeG.append("rect").attr("x", lp.x - lp.w / 2).attr("y", lp.y - lp.h / 2 - 1).attr("width", lp.w).attr("height", lp.h).attr("rx", 3).attr("fill", palette.bg).attr("opacity", 0.85).attr("class", "st-edge-label-bg");
315
- edgeG.append("text").attr("x", lp.x).attr("y", lp.y + 4).attr("text-anchor", "middle").attr("fill", edgeColor).attr("font-size", sEdgeLabelFontSize).attr("class", "st-edge-label").text(edge.label);
316
- }
317
- }
318
- } else if (edge.points.length >= 2) {
319
- const pathD = edgeSplinePath(edge.points);
302
+ if (edge.points.length >= 2) {
303
+ const pathD = edge.source === edge.target ? selfLoopArcPath(edge.points) ?? edgeSplinePath(edge.points) : edgeSplinePath(edge.points);
320
304
  if (pathD) {
321
305
  edgeG.append("path").attr("d", pathD).attr("fill", "none").attr("stroke", edgeColor).attr("stroke-width", sEdgeStrokeWidth).attr("marker-end", `url(#${markerId})`).attr("class", "st-edge");
322
306
  }
@@ -481,4 +465,4 @@ export {
481
465
  renderState,
482
466
  renderStateForExport
483
467
  };
484
- //# sourceMappingURL=chunk-XFLLYY3V.js.map
468
+ //# sourceMappingURL=chunk-TF76LCZS.js.map
@@ -9,7 +9,7 @@ import {
9
9
  looksLikeGantt,
10
10
  parseDgmo,
11
11
  parseDgmoChartType
12
- } from "./chunk-R5JPMW2F.js";
12
+ } from "./chunk-FTTB64OJ.js";
13
13
  import "./chunk-SH4PPRU7.js";
14
14
  import "./chunk-A2RUBBVT.js";
15
15
  import "./chunk-5PFNUDXR.js";
@@ -30,8 +30,8 @@ import "./chunk-Z7KVOVE4.js";
30
30
  import "./chunk-WFA6IULY.js";
31
31
  import "./chunk-BWJLLNUX.js";
32
32
  import "./chunk-KRTLS3G6.js";
33
- import "./chunk-TDHD3HNO.js";
34
- import "./chunk-RT7ACF77.js";
33
+ import "./chunk-F4X5NVKY.js";
34
+ import "./chunk-EGY3TS62.js";
35
35
  import "./chunk-W7UBPARG.js";
36
36
  import "./chunk-S5P5Z5Y5.js";
37
37
  import "./chunk-QQJUTGQH.js";
@@ -45,17 +45,17 @@ import "./chunk-UCZBRGJN.js";
45
45
  import "./chunk-7BMX2M3F.js";
46
46
  import "./chunk-3SP6G4LN.js";
47
47
  import "./chunk-ZM27UI5O.js";
48
- import "./chunk-2NRIGEHZ.js";
48
+ import "./chunk-46KVXDUJ.js";
49
49
  import "./chunk-TPN7RJOM.js";
50
50
  import "./chunk-EQW6HOP4.js";
51
51
  import "./chunk-DAOFNU6J.js";
52
52
  import "./chunk-7NSNE52V.js";
53
53
  import "./chunk-C3Z4DX3V.js";
54
- import "./chunk-DU3OIBQE.js";
54
+ import "./chunk-NWNSXHA5.js";
55
55
  import "./chunk-7TF3QOOD.js";
56
56
  import "./chunk-M5JT2AU7.js";
57
57
  import "./chunk-NXMESY4J.js";
58
- import "./chunk-SUA56ZSB.js";
58
+ import "./chunk-LTTZX6RD.js";
59
59
  import "./chunk-ICVIJLBA.js";
60
60
  import "./chunk-76NHL5UG.js";
61
61
  import "./chunk-E6PNTYRK.js";
@@ -86,4 +86,4 @@ export {
86
86
  parseDgmo,
87
87
  parseDgmoChartType
88
88
  };
89
- //# sourceMappingURL=dgmo-router-KYNLRE7S.js.map
89
+ //# sourceMappingURL=dgmo-router-A3LIHT6H.js.map