@diagrammo/dgmo 0.49.0 → 0.50.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 (192) hide show
  1. package/.cursorrules +6 -2
  2. package/.github/copilot-instructions.md +6 -2
  3. package/.windsurfrules +6 -2
  4. package/SKILL.md +6 -2
  5. package/dist/advanced.d.ts +419 -12
  6. package/dist/advanced.js +557 -195
  7. package/dist/auto.js +129 -119
  8. package/dist/auto.mjs +11543 -4815
  9. package/dist/block.js +145 -48
  10. package/dist/{charts-d3-EW3YQTEA.js → charts-d3-DKUD7MQE.js} +5 -5
  11. package/dist/{chunk-5FGDJIJX.js → chunk-2C56LEML.js} +3 -3
  12. package/dist/{chunk-35BBZDFE.js → chunk-2JJ2KNPI.js} +4 -4
  13. package/dist/{chunk-ZTLWVRNS.js → chunk-2QYTMIRR.js} +2 -2
  14. package/dist/{chunk-VC3TR4NL.js → chunk-3G6TMNVF.js} +3 -3
  15. package/dist/{chunk-ZDUQGL3N.js → chunk-3LKM6FMW.js} +2 -2
  16. package/dist/{chunk-4BD7EVPK.js → chunk-3P2DKJCG.js} +2 -2
  17. package/dist/{chunk-6CLKNXVP.js → chunk-3TDRHT4J.js} +457 -78
  18. package/dist/chunk-3XPUDB7B.js +420 -0
  19. package/dist/{chunk-DDTJ5N7Q.js → chunk-3ZPC476N.js} +6 -6
  20. package/dist/{chunk-BPIJLRYE.js → chunk-4BMJQFNK.js} +3 -3
  21. package/dist/{chunk-N4J5KGWG.js → chunk-4S723I74.js} +8 -8
  22. package/dist/{chunk-4YNP6O47.js → chunk-5JSWBPZZ.js} +3 -3
  23. package/dist/{chunk-KUBBJ2CD.js → chunk-5Z736BSU.js} +6 -6
  24. package/dist/{chunk-MJCG5K2O.js → chunk-6BFZKBGD.js} +2 -2
  25. package/dist/{chunk-XCC2RENT.js → chunk-6IAA2QQ2.js} +2 -2
  26. package/dist/{chunk-FUCAB3KQ.js → chunk-6M5PJFQG.js} +3 -3
  27. package/dist/{chunk-T7IKPCMI.js → chunk-6X4AKWLF.js} +3 -3
  28. package/dist/{chunk-JFPY3UJ7.js → chunk-6ZT4U37Q.js} +8 -8
  29. package/dist/{chunk-CLR4A2N2.js → chunk-7G2ER4CY.js} +4 -4
  30. package/dist/chunk-7PQYTZMA.js +681 -0
  31. package/dist/{chunk-LG4TWW4U.js → chunk-7RB5Q6MB.js} +8 -8
  32. package/dist/{chunk-7OVSJI2V.js → chunk-A3WQVFBS.js} +3 -3
  33. package/dist/{chunk-X2CH42BN.js → chunk-ASS5YYIZ.js} +7 -7
  34. package/dist/{chunk-3NFJWFNP.js → chunk-BDXC7MDK.js} +1045 -124
  35. package/dist/chunk-BTUTZMPT.js +482 -0
  36. package/dist/{chunk-UVCXZEGU.js → chunk-CVV36CWI.js} +2 -2
  37. package/dist/{chunk-TC3YWBFO.js → chunk-DMJJ3CEQ.js} +29 -8
  38. package/dist/{chunk-NVT6C2VE.js → chunk-EJTKV7CY.js} +4 -4
  39. package/dist/{chunk-4NQ3IKUM.js → chunk-ER5SCQWQ.js} +5 -5
  40. package/dist/{chunk-7VLUGEMJ.js → chunk-F5UDBSJY.js} +4 -4
  41. package/dist/{chunk-IHLSHCPZ.js → chunk-FAL7NOK3.js} +5 -5
  42. package/dist/{chunk-YRVLP7UU.js → chunk-FB2WHOEQ.js} +4 -4
  43. package/dist/chunk-FL4IOQ37.js +379 -0
  44. package/dist/{chunk-6VE3VLWM.js → chunk-GBE54KY6.js} +6 -5
  45. package/dist/{chunk-ZXL6MB4R.js → chunk-GL5UZ6NY.js} +3 -3
  46. package/dist/{chunk-3BIAFYD2.js → chunk-GPWHQ5FJ.js} +2 -2
  47. package/dist/chunk-GROQGHCT.js +960 -0
  48. package/dist/{chunk-GB3YZTAM.js → chunk-H73FP42Q.js} +5 -5
  49. package/dist/{chunk-O5MQPK7E.js → chunk-I4IFRCUB.js} +3 -3
  50. package/dist/{chunk-IUK7AGD4.js → chunk-I7F2A35O.js} +2 -2
  51. package/dist/{chunk-YTN572Q2.js → chunk-IA3FJYWR.js} +2 -2
  52. package/dist/{chunk-RI4NIMFP.js → chunk-JFYIP7XU.js} +75 -35
  53. package/dist/{chunk-UWDO3O52.js → chunk-JZNMXEIV.js} +2 -2
  54. package/dist/chunk-KJXIHOVL.js +940 -0
  55. package/dist/{chunk-26RVGM44.js → chunk-L2ZTFHAY.js} +2 -2
  56. package/dist/{chunk-PU3AUQPA.js → chunk-M5RXSRO2.js} +2 -2
  57. package/dist/{chunk-XKTN7CZF.js → chunk-NFFIKVNO.js} +4 -4
  58. package/dist/{chunk-SVDWQGX2.js → chunk-NISQC5KW.js} +139 -78
  59. package/dist/{chunk-4HVNZ7WF.js → chunk-O4VUFXIH.js} +3 -3
  60. package/dist/{chunk-F743CM2N.js → chunk-O76UD6VJ.js} +3 -3
  61. package/dist/{chunk-TLKMTQYL.js → chunk-OHQEMBLI.js} +3 -3
  62. package/dist/{chunk-BGJV5ATD.js → chunk-ONA5KPV3.js} +2 -2
  63. package/dist/{chunk-ZNQX6QWH.js → chunk-OTAL43EH.js} +6 -2
  64. package/dist/{chunk-FMKTYMP4.js → chunk-OTP5KVLO.js} +3 -3
  65. package/dist/{chunk-5ZZLLBFK.js → chunk-PGEGPSCZ.js} +2 -2
  66. package/dist/{chunk-XJ7J6WOO.js → chunk-PJUGRJHJ.js} +4 -4
  67. package/dist/{chunk-6SA7FJE4.js → chunk-PLZI6KPM.js} +10 -10
  68. package/dist/{chunk-AJ2PEY7J.js → chunk-PMN3Q7RJ.js} +2 -2
  69. package/dist/chunk-Q4V4XQWV.js +158 -0
  70. package/dist/{chunk-5XCM7UUW.js → chunk-QDFNCATJ.js} +99 -35
  71. package/dist/{chunk-CEHZOPGM.js → chunk-QFQ35BTO.js} +2 -2
  72. package/dist/{chunk-4UDKKGHH.js → chunk-QUJGFNFN.js} +2 -2
  73. package/dist/{chunk-IBC35BTK.js → chunk-R56LASIN.js} +2 -2
  74. package/dist/{chunk-SJEGO2QL.js → chunk-RV26LTUU.js} +4 -4
  75. package/dist/chunk-RV6A2B5S.js +354 -0
  76. package/dist/{chunk-65RTDUZH.js → chunk-S5GRONXL.js} +3 -3
  77. package/dist/{chunk-K6HNAY5V.js → chunk-SCHXJTZL.js} +2 -2
  78. package/dist/{chunk-ALRHIR6I.js → chunk-SGFZZAUO.js} +4 -4
  79. package/dist/{chunk-KV6Y2HE6.js → chunk-SU2VBK4L.js} +4 -4
  80. package/dist/{chunk-D5AVQCDN.js → chunk-T4BRO3Z6.js} +3 -3
  81. package/dist/{chunk-IFK3GIUW.js → chunk-TSA237IM.js} +2 -2
  82. package/dist/{chunk-SQDFK5ZQ.js → chunk-TWCLK2GA.js} +3 -3
  83. package/dist/{chunk-DKEPS5LH.js → chunk-U2HGPLZS.js} +36 -2
  84. package/dist/{chunk-EYN7VFKL.js → chunk-URSQLCTR.js} +3 -3
  85. package/dist/{chunk-BCT5G2VN.js → chunk-UUS2GIJZ.js} +5 -5
  86. package/dist/{chunk-LVHPTBO3.js → chunk-UXOSVCLJ.js} +4 -4
  87. package/dist/{chunk-HBVD67XG.js → chunk-WCUHAQKB.js} +2 -2
  88. package/dist/{chunk-YYX3SU6H.js → chunk-WWN566I7.js} +257 -101
  89. package/dist/{chunk-YM2BSPYW.js → chunk-X2NMFTG3.js} +2 -2
  90. package/dist/{chunk-ZREZOIGS.js → chunk-XCLHOZAM.js} +6 -6
  91. package/dist/{chunk-KQAEKMIX.js → chunk-XDXNDSKO.js} +2 -2
  92. package/dist/{chunk-RTERS6S5.js → chunk-XMVQ5F4M.js} +4 -4
  93. package/dist/{chunk-4FIV4K4Z.js → chunk-YA7D2N2O.js} +7 -7
  94. package/dist/{chunk-B57V3DWN.js → chunk-YB3FW24O.js} +3 -3
  95. package/dist/chunk-YNRDWYZP.js +295 -0
  96. package/dist/{chunk-2WMBWZY2.js → chunk-YZLMKW4T.js} +3 -3
  97. package/dist/{chunk-SGHSY3LU.js → chunk-Z6XJQ6KO.js} +81 -6
  98. package/dist/cli.cjs +153 -144
  99. package/dist/clock.d.ts +10 -0
  100. package/dist/clock.js +235 -0
  101. package/dist/countdown.d.ts +12 -0
  102. package/dist/countdown.js +450 -0
  103. package/dist/dgmo-router-QOMFCOOV.js +84 -0
  104. package/dist/{dimensions-WSIJXT5Q.js → dimensions-P5FSX2QN.js} +5 -5
  105. package/dist/editor.js +39 -1
  106. package/dist/element.js +131 -121
  107. package/dist/element.mjs +11543 -4815
  108. package/dist/{flowchart-parser-IVZN7CQN.js → flowchart-parser-OE4WHLTF.js} +4 -4
  109. package/dist/{flowchart-renderer-GMI2U3DD.js → flowchart-renderer-GPCSMTOR.js} +6 -6
  110. package/dist/highlight.d.ts +17 -1
  111. package/dist/highlight.js +156 -5
  112. package/dist/index.js +50 -45
  113. package/dist/{layout-HQMBPJVS.js → layout-46366KBT.js} +2 -2
  114. package/dist/{layout-D42XE4RE.js → layout-5BG6DFCU.js} +3 -3
  115. package/dist/{layout-K2ZN3Q42.js → layout-T3OZU5QW.js} +4 -4
  116. package/dist/{layout-S3EK4IYO.js → layout-TJIWF7EM.js} +4 -4
  117. package/dist/{layout-GZ2CWONU.js → layout-VYELEAW7.js} +4 -4
  118. package/dist/{layout-4Z5JM7PT.js → layout-WZHNDT2O.js} +4 -4
  119. package/dist/{parser-OBQG655V.js → parser-45DENHFZ.js} +4 -4
  120. package/dist/{parser-MCJWF5G3.js → parser-4AI5ZN5F.js} +3 -3
  121. package/dist/{parser-SMBJO3XN.js → parser-4P36TUVD.js} +4 -4
  122. package/dist/{parser-ZYC3XGNS.js → parser-5AURY4A6.js} +4 -4
  123. package/dist/{parser-WISPH7LW.js → parser-A2BEFMGK.js} +4 -4
  124. package/dist/parser-B5FVS7O6.js +11 -0
  125. package/dist/{parser-KPMN5KKE.js → parser-C2HF2C2E.js} +4 -4
  126. package/dist/parser-CSFUN3CT.js +14 -0
  127. package/dist/{parser-TITK4YW6.js → parser-D3QT6GWN.js} +5 -5
  128. package/dist/{parser-ZKF5K2H2.js → parser-D5637H5H.js} +4 -4
  129. package/dist/{parser-IKZFTLOJ.js → parser-DFFEDKHH.js} +3 -3
  130. package/dist/parser-DOKMZXVZ.js +13 -0
  131. package/dist/parser-FMPCVFRK.js +15 -0
  132. package/dist/{parser-UBGPTIZD.js → parser-HYRTF3DO.js} +3 -3
  133. package/dist/{parser-TNYX5S7E.js → parser-I2UIJKVQ.js} +4 -4
  134. package/dist/{parser-K647FRI4.js → parser-IBWNAPY4.js} +3 -3
  135. package/dist/{parser-JD7OQ2E6.js → parser-KUQWRPIT.js} +4 -4
  136. package/dist/{parser-HVJFTOXL.js → parser-LWKKBNSA.js} +3 -3
  137. package/dist/{parser-4ROBKVUR.js → parser-O4QFCUW7.js} +5 -5
  138. package/dist/{parser-BL7Z72EY.js → parser-PGMQDD4G.js} +4 -4
  139. package/dist/{parser-QJYS7KQQ.js → parser-Q4QKCIWQ.js} +4 -4
  140. package/dist/{parser-UGA23PYK.js → parser-QTOB4KFL.js} +4 -4
  141. package/dist/{parser-DERPY5KC.js → parser-QYYM4QVW.js} +4 -4
  142. package/dist/{parser-GFSOPDB7.js → parser-RZMQP7MM.js} +4 -4
  143. package/dist/parser-RZPVAQVX.js +11 -0
  144. package/dist/parser-SOUJOEYI.js +13 -0
  145. package/dist/{parser-MBJSBTL5.js → parser-UQE5OWZI.js} +5 -5
  146. package/dist/{parser-MRBPXXIV.js → parser-WAV5JRPT.js} +4 -4
  147. package/dist/{parser-4BKIFG2C.js → parser-YLKYBRIT.js} +5 -5
  148. package/dist/{parser-D6ONJQFR.js → parser-YS7TOS2K.js} +3 -3
  149. package/dist/{parser-CLMFZWCC.js → parser-ZSOWUBML.js} +5 -5
  150. package/dist/{parser-XWUDFJ7P.js → parser-ZTBATMLX.js} +4 -4
  151. package/dist/{renderer-LWGJFT3D.js → renderer-35HSIDMZ.js} +5 -5
  152. package/dist/{renderer-BB5PREMY.js → renderer-4ITCHBT7.js} +4 -4
  153. package/dist/{renderer-YHXPN3GF.js → renderer-67NPCBIS.js} +7 -7
  154. package/dist/{renderer-TPIBXNOS.js → renderer-6GHYK7DX.js} +6 -6
  155. package/dist/{renderer-VICQ4WNY.js → renderer-6RNGHC5Z.js} +5 -5
  156. package/dist/renderer-72LGR2YF.js +14 -0
  157. package/dist/{renderer-W5RMOURB.js → renderer-7SWMIFMM.js} +6 -6
  158. package/dist/{renderer-6L3NBEY5.js → renderer-BBCEFILK.js} +6 -6
  159. package/dist/{renderer-VFUVRNLK.js → renderer-BSW7SRIZ.js} +4 -4
  160. package/dist/{renderer-CGW7QPNA.js → renderer-BY533UWU.js} +7 -7
  161. package/dist/{renderer-V3JEMWMM.js → renderer-BZSBPTZJ.js} +6 -6
  162. package/dist/{renderer-DKESNMU5.js → renderer-CXUC4KAD.js} +6 -6
  163. package/dist/{renderer-XEKIRPI6.js → renderer-FZUKFUNZ.js} +5 -5
  164. package/dist/renderer-G2NLGNKF.js +17 -0
  165. package/dist/{renderer-THD6V5TL.js → renderer-GO3FE3RA.js} +9 -7
  166. package/dist/{renderer-ROV756WT.js → renderer-HPGR6USK.js} +5 -5
  167. package/dist/renderer-ICJN2SA2.js +24 -0
  168. package/dist/{renderer-4IUPINAE.js → renderer-INEXO7B6.js} +7 -7
  169. package/dist/{renderer-SQ3JUAI7.js → renderer-KDYCFRBX.js} +6 -6
  170. package/dist/renderer-KY4KQBTF.js +19 -0
  171. package/dist/{renderer-MJDDU27W.js → renderer-LBN65V45.js} +10 -10
  172. package/dist/{renderer-UZF3JROD.js → renderer-MGBWOCXG.js} +8 -8
  173. package/dist/{renderer-MFJ7HY2H.js → renderer-O4JKUGKO.js} +5 -5
  174. package/dist/{renderer-QL5KO6SK.js → renderer-OOGFODWP.js} +7 -7
  175. package/dist/{renderer-A5VFZQQK.js → renderer-Q6ZKPLS6.js} +6 -6
  176. package/dist/{renderer-TYXRHMRI.js → renderer-SZQ326M5.js} +9 -9
  177. package/dist/{renderer-6T3KK4S3.js → renderer-TKG6LS4U.js} +7 -7
  178. package/dist/{renderer-QNHUXCRL.js → renderer-TQMZGDAX.js} +9 -9
  179. package/dist/{renderer-radial-MHO2VDXN.js → renderer-radial-JELMHQ24.js} +6 -6
  180. package/dist/{state-parser-RX3GXOIB.js → state-parser-3REXRK3R.js} +4 -4
  181. package/dist/{state-renderer-AJUKGNWU.js → state-renderer-XYLNRWXR.js} +6 -6
  182. package/docs/ai-integration.md +6 -2
  183. package/docs/language-reference.md +253 -22
  184. package/gallery/fixtures/body.dgmo +17 -0
  185. package/gallery/fixtures/bracket.dgmo +30 -0
  186. package/gallery/fixtures/clock.dgmo +8 -0
  187. package/gallery/fixtures/countdown.dgmo +3 -0
  188. package/gallery/fixtures/goal.dgmo +4 -0
  189. package/package.json +12 -4
  190. package/dist/dgmo-router-ODKPEJ3P.js +0 -79
  191. package/dist/parser-667RGSUW.js +0 -13
  192. package/dist/parser-J3P2D6IP.js +0 -13
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  GANTT_BOOLEAN_SET,
3
3
  GANTT_OPTION_SET
4
- } from "./chunk-DKEPS5LH.js";
4
+ } from "./chunk-U2HGPLZS.js";
5
5
  import {
6
6
  parseDuration,
7
7
  parseOffset,
@@ -15,7 +15,7 @@ import {
15
15
  stripDefaultModifier,
16
16
  tagAttrKey,
17
17
  validateTagGroupNames
18
- } from "./chunk-HBVD67XG.js";
18
+ } from "./chunk-WCUHAQKB.js";
19
19
  import {
20
20
  normalizeName
21
21
  } from "./chunk-NOTA6TEI.js";
@@ -28,7 +28,7 @@ import {
28
28
  splitNameAndMeta,
29
29
  warnUnknownMetaKeys,
30
30
  withTagAliases
31
- } from "./chunk-ZNQX6QWH.js";
31
+ } from "./chunk-OTAL43EH.js";
32
32
  import {
33
33
  formatDgmoError,
34
34
  makeDgmoError
@@ -1253,4 +1253,4 @@ export {
1253
1253
  GANTT_KNOWN_OPTIONS,
1254
1254
  GANTT_KNOWN_BOOLEANS
1255
1255
  };
1256
- //# sourceMappingURL=chunk-LVHPTBO3.js.map
1256
+ //# sourceMappingURL=chunk-UXOSVCLJ.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  stripQuotes,
3
3
  tokenizeQuoteAware
4
- } from "./chunk-ZNQX6QWH.js";
4
+ } from "./chunk-OTAL43EH.js";
5
5
  import {
6
6
  CATEGORICAL_COLOR_ORDER,
7
7
  RECOGNIZED_COLOR_NAMES,
@@ -250,4 +250,4 @@ export {
250
250
  resolveActiveTagGroup,
251
251
  matchTagBlockHeading
252
252
  };
253
- //# sourceMappingURL=chunk-HBVD67XG.js.map
253
+ //# sourceMappingURL=chunk-WCUHAQKB.js.map
@@ -4,12 +4,12 @@ import {
4
4
  matchTagBlockHeading,
5
5
  stripDefaultModifier,
6
6
  tagAttrKey
7
- } from "./chunk-HBVD67XG.js";
7
+ } from "./chunk-WCUHAQKB.js";
8
8
  import {
9
9
  extractColor,
10
10
  measureIndent,
11
11
  parseFirstLine
12
- } from "./chunk-ZNQX6QWH.js";
12
+ } from "./chunk-OTAL43EH.js";
13
13
  import {
14
14
  emit
15
15
  } from "./chunk-CXK4DZH3.js";
@@ -22,10 +22,9 @@ var SWIMLANE_DX = {
22
22
  chartType: "swimlane",
23
23
  title: "Duplicate node",
24
24
  message: (p) => `Duplicate node name '${p.name ?? "Foo"}'`,
25
- hint: "Every node name must be unique across the diagram \u2014 rename or remove the second declaration.",
25
+ hint: "Within a lane a node name must be unique \u2014 rename or remove the second declaration (different lanes may reuse a name).",
26
26
  example: `swimlane T
27
27
  lane L
28
- L
29
28
  Foo
30
29
  Foo`
31
30
  },
@@ -35,12 +34,23 @@ L
35
34
  chartType: "swimlane",
36
35
  title: "Unknown node in edge",
37
36
  message: (p) => `Edge references unknown node '${p.node ?? "Bar"}'`,
38
- hint: "Declare the node under a lane before referencing it in a flow arrow.",
37
+ hint: "A bare-task target must be declared as a line-head in some lane; delimited endpoints ((\u2026)/<\u2026>/[[\u2026]]) auto-create. Check for a typo, or qualify a cross-lane name as Lane.Node.",
39
38
  example: `swimlane T
40
39
  lane L
41
- L
42
- Foo
43
- Foo -> Bar`
40
+ Foo -> Bar`
41
+ },
42
+ AMBIGUOUS_NODE: {
43
+ code: "E_SWIMLANE_AMBIGUOUS_NODE",
44
+ severity: "warning",
45
+ chartType: "swimlane",
46
+ title: "Ambiguous node reference",
47
+ message: (p) => `Node '${p.node ?? "Review"}' is declared in more than one lane${p.lanes ? ` (${p.lanes})` : ""} \u2014 qualify it as Lane.${p.node ?? "Review"}`,
48
+ hint: "Two lanes hold a node with this name. Prefix the reference with its lane (`Customs.Inspect`) to pick one; resolved to the first match otherwise.",
49
+ example: `swimlane T
50
+ lane Customs
51
+ Customs.Inspect -> Harbor.Inspect
52
+ lane Harbor
53
+ Harbor.Inspect`
44
54
  },
45
55
  UNKNOWN_LANE: {
46
56
  code: "E_SWIMLANE_UNKNOWN_LANE",
@@ -205,7 +215,6 @@ function parseSwimlane(content, palette) {
205
215
  const tagGroups = [];
206
216
  const laneByKey = /* @__PURE__ */ new Map();
207
217
  const phaseByKey = /* @__PURE__ */ new Map();
208
- const nodeByKey = /* @__PURE__ */ new Map();
209
218
  const metaAliasMap = /* @__PURE__ */ new Map();
210
219
  const options = {};
211
220
  let direction = "LR";
@@ -299,7 +308,7 @@ function parseSwimlane(content, palette) {
299
308
  }
300
309
  continue;
301
310
  }
302
- if (indent === 0 && /^lane\s+/i.test(trimmed)) {
311
+ if (/^lane\s+/i.test(trimmed)) {
303
312
  const rest = trimmed.replace(/^lane\s+/i, "").trim();
304
313
  const { label, color } = extractColor(
305
314
  rest,
@@ -321,39 +330,22 @@ function parseSwimlane(content, palette) {
321
330
  }
322
331
  if (indent === 0 && !trimmed.startsWith("tag ")) sawContent = true;
323
332
  }
324
- let currentPhase = null;
325
- let currentLane = null;
326
- let laneIndent = -1;
327
- let currentFlowSource = null;
328
- const declareNode = (token, meta, lineNum) => {
329
- const parsed = parseNodeToken(token);
330
- if (parsed.unsupported) {
331
- diagnostics.push(
332
- emit(SWIMLANE_DX.UNSUPPORTED, lineNum, { reason: parsed.unsupported })
333
- );
334
- return;
335
- }
336
- if (!parsed.label) return;
337
- if (!currentLane) {
338
- diagnostics.push(
339
- emit(SWIMLANE_DX.UNKNOWN_LANE, lineNum, { node: parsed.label })
340
- );
341
- return;
333
+ const drafts = [];
334
+ const draftByKey = /* @__PURE__ */ new Map();
335
+ const draftsByLabel = /* @__PURE__ */ new Map();
336
+ const rawEdges = [];
337
+ const laneKey = (laneId, label) => `${normKey(laneId)}\0${normKey(label)}`;
338
+ const splitQualifier = (token) => {
339
+ const t = token.trim();
340
+ if (/^[<([]/.test(t)) return { rest: t };
341
+ const dot = t.indexOf(".");
342
+ if (dot > 0) {
343
+ const lane = laneByKey.get(normKey(t.slice(0, dot)));
344
+ if (lane) return { laneId: lane.id, rest: t.slice(dot + 1).trim() };
342
345
  }
343
- const { label: cleanLabel, color } = extractColor(
344
- parsed.label,
345
- palette,
346
- diagnostics,
347
- lineNum
348
- );
349
- const key = normKey(cleanLabel);
350
- if (nodeByKey.has(key)) {
351
- diagnostics.push(
352
- emit(SWIMLANE_DX.DUPLICATE_NODE, lineNum, { name: cleanLabel })
353
- );
354
- return;
355
- }
356
- const tags = {};
346
+ return { rest: t };
347
+ };
348
+ const applyMeta = (draft, meta, lineNum) => {
357
349
  for (const [k, v] of Object.entries(meta)) {
358
350
  if (k === "note") {
359
351
  diagnostics.push(
@@ -380,75 +372,147 @@ function parseSwimlane(content, palette) {
380
372
  continue;
381
373
  }
382
374
  const canonical = metaAliasMap.get(k) ?? k;
383
- tags[canonical] = v;
375
+ draft.tags[canonical] = v;
384
376
  }
385
- const node = {
377
+ };
378
+ const registerDraft = (draft) => {
379
+ draftByKey.set(laneKey(draft.laneId, draft.label), draft);
380
+ const nk = normKey(draft.label);
381
+ (draftsByLabel.get(nk) ?? draftsByLabel.set(nk, []).get(nk)).push(draft);
382
+ drafts.push(draft);
383
+ };
384
+ const mergeDraft = (draft, parsed, color) => {
385
+ if (draft.shape === "task" && parsed.shape !== "task")
386
+ draft.shape = parsed.shape;
387
+ if (draft.event === "none" && parsed.event !== "none")
388
+ draft.event = parsed.event;
389
+ if (draft.color === void 0 && color !== void 0) draft.color = color;
390
+ };
391
+ const declareInLane = (rawText, laneId, phaseId, bare, lineNum) => {
392
+ const { token, meta } = splitNodeMeta(rawText);
393
+ const { rest } = splitQualifier(token);
394
+ const parsed = parseNodeToken(rest);
395
+ if (parsed.unsupported) {
396
+ diagnostics.push(
397
+ emit(SWIMLANE_DX.UNSUPPORTED, lineNum, { reason: parsed.unsupported })
398
+ );
399
+ return null;
400
+ }
401
+ if (!parsed.label) return null;
402
+ const { label: cleanLabel, color } = extractColor(
403
+ parsed.label,
404
+ palette,
405
+ diagnostics,
406
+ lineNum
407
+ );
408
+ const key = laneKey(laneId, cleanLabel);
409
+ const existing = draftByKey.get(key);
410
+ if (existing) {
411
+ if (bare && existing.hasBareDecl) {
412
+ diagnostics.push(
413
+ emit(SWIMLANE_DX.DUPLICATE_NODE, lineNum, { name: cleanLabel })
414
+ );
415
+ return existing;
416
+ }
417
+ mergeDraft(existing, parsed, color);
418
+ if (bare) existing.hasBareDecl = true;
419
+ if (existing.phaseId === void 0 && phaseId !== void 0)
420
+ existing.phaseId = phaseId;
421
+ applyMeta(existing, meta, lineNum);
422
+ return existing;
423
+ }
424
+ const draft = {
386
425
  id: cleanLabel,
387
426
  label: cleanLabel,
427
+ laneId,
428
+ ...phaseId !== void 0 && { phaseId },
388
429
  shape: parsed.shape,
389
430
  event: parsed.event,
390
- lane: currentLane.id,
391
- ...currentPhase && { phase: currentPhase.id },
392
431
  ...color !== void 0 && { color },
393
- tags,
394
- lineNumber: lineNum
432
+ tags: {},
433
+ lineNumber: lineNum,
434
+ hasBareDecl: bare
395
435
  };
396
- nodes.push(node);
397
- nodeByKey.set(key, node);
436
+ applyMeta(draft, meta, lineNum);
437
+ registerDraft(draft);
438
+ return draft;
398
439
  };
399
- const resolveRef = (token, lineNum) => {
400
- const parsed = parseNodeToken(token);
440
+ const resolveEndpoint = (rawText, laneId, phaseId, lineNum) => {
441
+ const { token, meta } = splitNodeMeta(rawText);
442
+ const { laneId: qLane, rest } = splitQualifier(token);
443
+ const parsed = parseNodeToken(rest);
401
444
  if (parsed.unsupported) {
402
445
  diagnostics.push(
403
446
  emit(SWIMLANE_DX.UNSUPPORTED, lineNum, { reason: parsed.unsupported })
404
447
  );
405
448
  return null;
406
449
  }
407
- const { label } = extractColor(parsed.label, palette);
408
- const key = normKey(label);
409
- const node = nodeByKey.get(key);
410
- if (!node) {
450
+ const { label: cleanLabel } = extractColor(parsed.label, palette);
451
+ const nk = normKey(cleanLabel);
452
+ const delimited = parsed.shape !== "task";
453
+ const finish = (d) => {
454
+ applyMeta(d, meta, lineNum);
455
+ return d;
456
+ };
457
+ const implicit = (owner) => {
458
+ const draft = {
459
+ id: cleanLabel,
460
+ label: cleanLabel,
461
+ laneId: owner,
462
+ ...phaseId !== void 0 && { phaseId },
463
+ shape: parsed.shape,
464
+ event: parsed.event,
465
+ tags: {},
466
+ lineNumber: lineNum,
467
+ hasBareDecl: false
468
+ };
469
+ applyMeta(draft, meta, lineNum);
470
+ registerDraft(draft);
471
+ return draft;
472
+ };
473
+ if (qLane) {
474
+ const hit = draftByKey.get(laneKey(qLane, cleanLabel));
475
+ if (hit) return finish(hit);
476
+ if (delimited) return implicit(qLane);
411
477
  diagnostics.push(
412
- emit(SWIMLANE_DX.UNKNOWN_NODE, lineNum, { node: parsed.label })
478
+ emit(SWIMLANE_DX.UNKNOWN_NODE, lineNum, {
479
+ node: `${qLane}.${cleanLabel}`
480
+ })
413
481
  );
414
482
  return null;
415
483
  }
416
- return node.id;
417
- };
418
- const addChain = (line, lineNum) => {
419
- if (line.includes("~>")) {
484
+ if (laneId) {
485
+ const own = draftByKey.get(laneKey(laneId, cleanLabel));
486
+ if (own) return finish(own);
487
+ }
488
+ const cands = draftsByLabel.get(nk) ?? [];
489
+ if (cands.length === 1) return finish(cands[0]);
490
+ if (cands.length > 1) {
420
491
  diagnostics.push(
421
- emit(SWIMLANE_DX.UNSUPPORTED, lineNum, {
422
- reason: "message flow (~>) is fast-follow"
492
+ emit(SWIMLANE_DX.AMBIGUOUS_NODE, lineNum, {
493
+ node: cleanLabel,
494
+ lanes: cands.map((c) => c.laneId).join(", ")
423
495
  })
424
496
  );
425
- return;
426
- }
427
- const parts = splitChain(line);
428
- if (parts.length < 2) return;
429
- const resolved = [];
430
- for (let p = 0; p < parts.length; p++) {
431
- const text = parts[p].text;
432
- if (p === 0 && text === "") {
433
- resolved.push(currentFlowSource);
434
- continue;
435
- }
436
- resolved.push(resolveRef(text, lineNum));
437
- }
438
- for (let p = 0; p < parts.length - 1; p++) {
439
- const src = resolved[p];
440
- const tgt = resolved[p + 1];
441
- const label = parts[p].labelAfter;
442
- if (!src || !tgt) continue;
443
- edges.push({
444
- source: src,
445
- target: tgt,
446
- ...label !== void 0 && { label },
447
- lineNumber: lineNum
448
- });
497
+ return finish(cands[0]);
449
498
  }
499
+ if (delimited && laneId) return implicit(laneId);
500
+ diagnostics.push(
501
+ emit(SWIMLANE_DX.UNKNOWN_NODE, lineNum, { node: parsed.label })
502
+ );
503
+ return null;
450
504
  };
505
+ let currentPhase = null;
506
+ let currentLane = null;
507
+ let laneIndent = -1;
508
+ let flowSource = null;
451
509
  let inTagBlock = false;
510
+ const openLane = (lane, indent, phased) => {
511
+ currentLane = lane;
512
+ laneIndent = indent;
513
+ if (!phased) currentPhase = null;
514
+ flowSource = null;
515
+ };
452
516
  for (let i = startIdx; i < rawLines.length; i++) {
453
517
  const raw = rawLines[i];
454
518
  const lineNum = i + 1;
@@ -458,10 +522,7 @@ function parseSwimlane(content, palette) {
458
522
  if (cIdx > 0) trimmed = trimmed.slice(0, cIdx).trim();
459
523
  if (!trimmed) continue;
460
524
  const indent = measureIndent(raw);
461
- if (indent === 0 && /^(lane|direction|tag)\s+/i.test(trimmed)) {
462
- inTagBlock = /^tag\s+/i.test(trimmed);
463
- continue;
464
- }
525
+ if (indent === 0 && /^direction\s+/i.test(trimmed)) continue;
465
526
  if (indent === 0 && /^solid-fill\s*$/i.test(trimmed)) continue;
466
527
  if (matchTagBlockHeading(trimmed) && indent === 0) {
467
528
  inTagBlock = true;
@@ -469,6 +530,13 @@ function parseSwimlane(content, palette) {
469
530
  }
470
531
  if (indent === 0) inTagBlock = false;
471
532
  if (inTagBlock && indent > 0) continue;
533
+ if (/^lane\s+/i.test(trimmed)) {
534
+ const rest = trimmed.replace(/^lane\s+/i, "").trim();
535
+ const { label } = extractColor(rest, palette);
536
+ const lane = laneByKey.get(normKey(label));
537
+ if (lane) openLane(lane, indent, indent > 0);
538
+ continue;
539
+ }
472
540
  if (indent === 0 && trimmed.startsWith("[") && trimmed.endsWith("]") && !trimmed.startsWith("[[")) {
473
541
  const label = trimmed.slice(1, -1).trim();
474
542
  if (lanes.length === 0) {
@@ -484,27 +552,115 @@ function parseSwimlane(content, palette) {
484
552
  currentPhase = phase;
485
553
  currentLane = null;
486
554
  laneIndent = -1;
487
- currentFlowSource = null;
555
+ flowSource = null;
488
556
  continue;
489
557
  }
558
+ const cl = currentLane;
559
+ const cp = currentPhase;
560
+ const laneCtx = cl?.id ?? null;
561
+ const phaseCtx = cp?.id;
562
+ const inLane = cl !== null && indent > laneIndent;
490
563
  if (trimmed.includes("->") || trimmed.includes("~>")) {
491
- addChain(trimmed, lineNum);
564
+ if (trimmed.includes("~>")) {
565
+ diagnostics.push(
566
+ emit(SWIMLANE_DX.UNSUPPORTED, lineNum, {
567
+ reason: "message flow (~>) is fast-follow"
568
+ })
569
+ );
570
+ continue;
571
+ }
572
+ const parts = splitChain(trimmed);
573
+ if (parts.length < 2) continue;
574
+ let headText;
575
+ if (parts[0].text === "") {
576
+ headText = flowSource;
577
+ } else {
578
+ headText = parts[0].text;
579
+ if (inLane) declareInLane(headText, laneCtx, phaseCtx, false, lineNum);
580
+ }
581
+ for (let p = 0; p < parts.length - 1; p++) {
582
+ const srcText = p === 0 ? headText : parts[p].text;
583
+ rawEdges.push({
584
+ srcText,
585
+ tgtText: parts[p + 1].text,
586
+ ...parts[p].labelAfter !== void 0 && {
587
+ label: parts[p].labelAfter
588
+ },
589
+ laneId: laneCtx,
590
+ ...phaseCtx !== void 0 && { phaseId: phaseCtx },
591
+ inLane,
592
+ lineNumber: lineNum
593
+ });
594
+ }
492
595
  continue;
493
596
  }
494
597
  const laneRef = laneByKey.get(normKey(trimmed));
495
598
  if (laneRef && (laneIndent < 0 || indent <= laneIndent)) {
496
- currentLane = laneRef;
497
- laneIndent = indent;
498
- currentFlowSource = null;
599
+ openLane(laneRef, indent, currentPhase !== null && indent > 0);
600
+ continue;
601
+ }
602
+ if (inLane) {
603
+ declareInLane(trimmed, laneCtx, phaseCtx, true, lineNum);
604
+ flowSource = trimmed;
499
605
  continue;
500
606
  }
501
607
  if (indent === 0) {
502
- const ref = resolveRef(trimmed, lineNum);
503
- if (ref) currentFlowSource = ref;
608
+ flowSource = trimmed;
504
609
  continue;
505
610
  }
506
- const { token, meta } = splitNodeMeta(trimmed);
507
- declareNode(token, meta, lineNum);
611
+ const { token } = splitNodeMeta(trimmed);
612
+ const nodeLabel = parseNodeToken(splitQualifier(token).rest).label;
613
+ diagnostics.push(
614
+ emit(SWIMLANE_DX.UNKNOWN_LANE, lineNum, { node: nodeLabel })
615
+ );
616
+ }
617
+ const resolvedPairs = [];
618
+ for (const e of rawEdges) {
619
+ if (e.srcText === null) continue;
620
+ const s = resolveEndpoint(e.srcText, e.laneId, e.phaseId, e.lineNumber);
621
+ const t = resolveEndpoint(e.tgtText, e.laneId, e.phaseId, e.lineNumber);
622
+ if (!s || !t) continue;
623
+ resolvedPairs.push({
624
+ s,
625
+ t,
626
+ ...e.label !== void 0 && { label: e.label },
627
+ lineNumber: e.lineNumber
628
+ });
629
+ }
630
+ const labelCounts = /* @__PURE__ */ new Map();
631
+ for (const d of drafts)
632
+ labelCounts.set(
633
+ normKey(d.label),
634
+ (labelCounts.get(normKey(d.label)) ?? 0) + 1
635
+ );
636
+ const usedIds = /* @__PURE__ */ new Set();
637
+ for (const d of drafts) {
638
+ let id = d.label;
639
+ if ((labelCounts.get(normKey(d.label)) ?? 0) > 1)
640
+ id = `${d.label}\u241F${d.laneId}`;
641
+ while (usedIds.has(id)) id = `${id}\u241F`;
642
+ usedIds.add(id);
643
+ d.id = id;
644
+ nodes.push({
645
+ id,
646
+ label: d.label,
647
+ shape: d.shape,
648
+ event: d.event,
649
+ lane: d.laneId,
650
+ ...d.phaseId !== void 0 && { phase: d.phaseId },
651
+ ...d.color !== void 0 && { color: d.color },
652
+ tags: d.tags,
653
+ lineNumber: d.lineNumber
654
+ });
655
+ }
656
+ for (const p of resolvedPairs) {
657
+ if (p.s.id === p.t.id) continue;
658
+ edges.push({
659
+ source: p.s.id,
660
+ target: p.t.id,
661
+ ...p.label !== void 0 && { label: p.label },
662
+ lineNumber: p.lineNumber
663
+ });
508
664
  }
509
665
  finalizeAutoTagColors(tagGroups, palette);
510
666
  return {
@@ -526,4 +682,4 @@ export {
526
682
  SWIMLANE_DIAGNOSTICS,
527
683
  parseSwimlane
528
684
  };
529
- //# sourceMappingURL=chunk-YYX3SU6H.js.map
685
+ //# sourceMappingURL=chunk-WWN566I7.js.map
@@ -29,7 +29,7 @@ import {
29
29
  } from "./chunk-P6T66CCZ.js";
30
30
  import {
31
31
  tagAttrKey
32
- } from "./chunk-HBVD67XG.js";
32
+ } from "./chunk-WCUHAQKB.js";
33
33
  import {
34
34
  resolveColor
35
35
  } from "./chunk-TLVIHFRO.js";
@@ -3177,4 +3177,4 @@ export {
3177
3177
  albersSkewFallback,
3178
3178
  layoutMap
3179
3179
  };
3180
- //# sourceMappingURL=chunk-YM2BSPYW.js.map
3180
+ //# sourceMappingURL=chunk-X2NMFTG3.js.map
@@ -5,15 +5,15 @@ import {
5
5
  import {
6
6
  ScaleContext
7
7
  } from "./chunk-YYVTBZZC.js";
8
+ import {
9
+ renderIntegratedLegend
10
+ } from "./chunk-QUJGFNFN.js";
8
11
  import {
9
12
  createTooltip,
10
13
  hideTooltip,
11
14
  renderChartTitle,
12
15
  showTooltip
13
16
  } from "./chunk-U6EQI3U6.js";
14
- import {
15
- renderIntegratedLegend
16
- } from "./chunk-4UDKKGHH.js";
17
17
  import {
18
18
  FONT_FAMILY
19
19
  } from "./chunk-6KFWC4CO.js";
@@ -31,7 +31,7 @@ import {
31
31
  } from "./chunk-HQCHYB5F.js";
32
32
  import {
33
33
  parseTimelineDate
34
- } from "./chunk-IUK7AGD4.js";
34
+ } from "./chunk-I7F2A35O.js";
35
35
  import {
36
36
  getSeriesColors,
37
37
  mix,
@@ -41,7 +41,7 @@ import {
41
41
  import {
42
42
  resolveTagColor,
43
43
  tagAttrKey
44
- } from "./chunk-HBVD67XG.js";
44
+ } from "./chunk-WCUHAQKB.js";
45
45
 
46
46
  // src/timeline/renderer.ts
47
47
  import * as d3Scale from "d3-scale";
@@ -1607,4 +1607,4 @@ export {
1607
1607
  formatDateLabel,
1608
1608
  renderTimeline
1609
1609
  };
1610
- //# sourceMappingURL=chunk-ZREZOIGS.js.map
1610
+ //# sourceMappingURL=chunk-XCLHOZAM.js.map
@@ -5,7 +5,7 @@ import {
5
5
  normalizeNumericToken,
6
6
  parseFirstLine,
7
7
  parseSeriesNames
8
- } from "./chunk-ZNQX6QWH.js";
8
+ } from "./chunk-OTAL43EH.js";
9
9
  import {
10
10
  RECOGNIZED_COLOR_NAMES,
11
11
  resolveColorWithDiagnostic
@@ -1054,4 +1054,4 @@ export {
1054
1054
  getSimpleChartLegendGroups,
1055
1055
  getExtendedChartLegendGroups
1056
1056
  };
1057
- //# sourceMappingURL=chunk-KQAEKMIX.js.map
1057
+ //# sourceMappingURL=chunk-XDXNDSKO.js.map
@@ -2,7 +2,7 @@ import {
2
2
  INFRA_BEHAVIOR_KEY_SET,
3
3
  INFRA_EDGE_ONLY_KEY_SET,
4
4
  INFRA_TOP_LEVEL_OPTION_SET
5
- } from "./chunk-DKEPS5LH.js";
5
+ } from "./chunk-U2HGPLZS.js";
6
6
  import {
7
7
  tryStripDescriptionKeyword
8
8
  } from "./chunk-IYULMRBE.js";
@@ -11,7 +11,7 @@ import {
11
11
  stripDefaultModifier,
12
12
  tagAttrKey,
13
13
  validateTagGroupNames
14
- } from "./chunk-HBVD67XG.js";
14
+ } from "./chunk-WCUHAQKB.js";
15
15
  import {
16
16
  GRAPH_DX
17
17
  } from "./chunk-I46X5VUA.js";
@@ -30,7 +30,7 @@ import {
30
30
  tryParseSharedOption,
31
31
  warnUnknownMetaKeys,
32
32
  withTagAliases
33
- } from "./chunk-ZNQX6QWH.js";
33
+ } from "./chunk-OTAL43EH.js";
34
34
  import {
35
35
  isRecognizedColorName
36
36
  } from "./chunk-TLVIHFRO.js";
@@ -890,4 +890,4 @@ export {
890
890
  parseInfra,
891
891
  extractSymbols
892
892
  };
893
- //# sourceMappingURL=chunk-RTERS6S5.js.map
893
+ //# sourceMappingURL=chunk-XMVQ5F4M.js.map
@@ -1,6 +1,3 @@
1
- import {
2
- layoutERDiagram
3
- } from "./chunk-4XK3FLFB.js";
4
1
  import {
5
2
  NOTE_BADGE_RADIUS,
6
3
  noteConnectorPoints,
@@ -8,6 +5,9 @@ import {
8
5
  renderNoteBox,
9
6
  renderNoteConnector
10
7
  } from "./chunk-JEUJOX5X.js";
8
+ import {
9
+ layoutERDiagram
10
+ } from "./chunk-4XK3FLFB.js";
11
11
  import {
12
12
  EDGE_STROKE_WIDTH,
13
13
  NODE_STROKE_WIDTH
@@ -17,7 +17,7 @@ import {
17
17
  } from "./chunk-YYVTBZZC.js";
18
18
  import {
19
19
  renderIntegratedLegend
20
- } from "./chunk-4UDKKGHH.js";
20
+ } from "./chunk-QUJGFNFN.js";
21
21
  import {
22
22
  TITLE_FONT_SIZE,
23
23
  TITLE_FONT_WEIGHT,
@@ -34,7 +34,7 @@ import {
34
34
  } from "./chunk-5LWQH6QV.js";
35
35
  import {
36
36
  parseERDiagram
37
- } from "./chunk-35BBZDFE.js";
37
+ } from "./chunk-2JJ2KNPI.js";
38
38
  import {
39
39
  contrastText,
40
40
  getSeriesColors,
@@ -43,7 +43,7 @@ import {
43
43
  import {
44
44
  resolveTagColor,
45
45
  tagAttrKey
46
- } from "./chunk-HBVD67XG.js";
46
+ } from "./chunk-WCUHAQKB.js";
47
47
 
48
48
  // src/er/renderer.ts
49
49
  import * as d3Selection from "d3-selection";
@@ -545,4 +545,4 @@ export {
545
545
  renderERDiagram,
546
546
  renderERDiagramForExport
547
547
  };
548
- //# sourceMappingURL=chunk-4FIV4K4Z.js.map
548
+ //# sourceMappingURL=chunk-YA7D2N2O.js.map