@diagrammo/dgmo 0.46.0 → 0.48.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 (534) hide show
  1. package/dist/advanced.d.ts +3 -855
  2. package/dist/advanced.js +541 -70107
  3. package/dist/analyzer-UYKBXAKR.js +15 -0
  4. package/dist/auto.js +1 -1
  5. package/dist/auto.mjs +1 -1
  6. package/dist/block.js +83 -69417
  7. package/dist/calculator-LDYQCDDY.js +11 -0
  8. package/dist/charts-d3-QOZHKTCT.js +25 -0
  9. package/dist/chunk-2DXMZRWJ.js +800 -0
  10. package/dist/chunk-2LACINWN.js +786 -0
  11. package/dist/chunk-33LCUH4H.js +893 -0
  12. package/dist/chunk-3CIOJ5YJ.js +35 -0
  13. package/dist/chunk-3HDBAXF5.js +86 -0
  14. package/dist/chunk-3JLKYGBQ.js +290 -0
  15. package/dist/chunk-3MQQNXPD.js +415 -0
  16. package/dist/chunk-3R5POCTZ.js +967 -0
  17. package/dist/chunk-3SMGIJDD.js +112 -0
  18. package/dist/chunk-44CM72SQ.js +409 -0
  19. package/dist/chunk-4GRI7MEB.js +1604 -0
  20. package/dist/chunk-4OHACBGX.js +606 -0
  21. package/dist/chunk-5DH3KYFH.js +21 -0
  22. package/dist/chunk-5MLYVTYM.js +76 -0
  23. package/dist/chunk-5QXL4NYS.js +553 -0
  24. package/dist/chunk-5WRI5ZAA.js +31 -0
  25. package/dist/chunk-6EK55ART.js +117 -0
  26. package/dist/chunk-6FZYCKXB.js +2065 -0
  27. package/dist/chunk-6HO5ZTXK.js +277 -0
  28. package/dist/chunk-6KFWC4CO.js +7 -0
  29. package/dist/chunk-6MTWIQVO.js +121 -0
  30. package/dist/chunk-6NYWYNBI.js +329 -0
  31. package/dist/chunk-6SM5NJQH.js +620 -0
  32. package/dist/chunk-725LDASD.js +422 -0
  33. package/dist/chunk-76OWZ3BA.js +130 -0
  34. package/{src/block/parser.ts → dist/chunk-7JEGTRLD.js} +100 -189
  35. package/dist/chunk-A44USUV7.js +923 -0
  36. package/dist/chunk-A4GOY3PE.js +25 -0
  37. package/dist/chunk-A4VFQH5G.js +251 -0
  38. package/dist/chunk-AELOBFW5.js +375 -0
  39. package/dist/chunk-AN2MOO5T.js +522 -0
  40. package/dist/chunk-BMR4CIEO.js +41 -0
  41. package/dist/chunk-BS7SV7C3.js +51 -0
  42. package/dist/chunk-BUPDIHML.js +613 -0
  43. package/dist/chunk-BUVJFRPY.js +887 -0
  44. package/dist/chunk-C3Z4DX3V.js +112 -0
  45. package/dist/chunk-CI2G3OEB.js +1818 -0
  46. package/dist/chunk-CKNVO24D.js +54 -0
  47. package/dist/chunk-CUVHQHZ7.js +391 -0
  48. package/dist/chunk-CXK4DZH3.js +114 -0
  49. package/dist/{editor.cjs → chunk-DKEPS5LH.js} +14 -225
  50. package/dist/chunk-DU7W62N5.js +487 -0
  51. package/dist/chunk-DZAQBW35.js +751 -0
  52. package/dist/chunk-EB6FPQUP.js +316 -0
  53. package/dist/chunk-EMS2SK26.js +376 -0
  54. package/dist/chunk-ERLBPDGU.js +510 -0
  55. package/dist/chunk-EVCVDTXE.js +732 -0
  56. package/dist/chunk-FCIIHT24.js +384 -0
  57. package/dist/chunk-FFUN5D66.js +97 -0
  58. package/dist/chunk-FITOLXSX.js +714 -0
  59. package/dist/chunk-FMDSF3OV.js +68 -0
  60. package/dist/chunk-FNB3PNGF.js +410 -0
  61. package/dist/chunk-G2H74XJZ.js +2104 -0
  62. package/dist/chunk-GMR5MFHJ.js +339 -0
  63. package/dist/chunk-H6PI3KJT.js +305 -0
  64. package/dist/chunk-I46X5VUA.js +59 -0
  65. package/dist/chunk-I5IGB56C.js +255 -0
  66. package/dist/chunk-IH6ZMVQ5.js +3950 -0
  67. package/dist/chunk-IJZFN3HM.js +463 -0
  68. package/dist/chunk-IPWPWM6R.js +3079 -0
  69. package/dist/chunk-IYULMRBE.js +23 -0
  70. package/dist/chunk-IZMRON6C.js +167 -0
  71. package/dist/chunk-J5FIXQRT.js +813 -0
  72. package/dist/chunk-JED6ZDEE.js +73 -0
  73. package/dist/chunk-JEUJOX5X.js +136 -0
  74. package/dist/chunk-JM4LEPY3.js +436 -0
  75. package/dist/chunk-L3UHP6TD.js +101 -0
  76. package/dist/chunk-L66GEFB6.js +524 -0
  77. package/dist/chunk-LIOHW36Z.js +469 -0
  78. package/dist/chunk-LP7EC4MI.js +16 -0
  79. package/dist/chunk-MITI6NOL.js +548 -0
  80. package/dist/chunk-MO5YHHMQ.js +168 -0
  81. package/dist/chunk-MZSBFAPJ.js +885 -0
  82. package/dist/chunk-NNAAJVBU.js +9 -0
  83. package/dist/chunk-NOTA6TEI.js +47 -0
  84. package/dist/chunk-NURGB5Z4.js +335 -0
  85. package/dist/chunk-NX4EQS3U.js +1062 -0
  86. package/dist/chunk-NXMESY4J.js +1 -0
  87. package/dist/chunk-OJR3MQYV.js +1458 -0
  88. package/dist/chunk-OURHMODR.js +454 -0
  89. package/dist/chunk-P235SVAH.js +1057 -0
  90. package/dist/chunk-P4RH4OSP.js +1038 -0
  91. package/dist/chunk-P6T66CCZ.js +226 -0
  92. package/dist/chunk-PBAHEPLQ.js +223 -0
  93. package/dist/chunk-PBHE5UG6.js +1530 -0
  94. package/dist/chunk-PDKUANDZ.js +35 -0
  95. package/dist/chunk-PWIHZ6NJ.js +296 -0
  96. package/{src/c4/layout.ts → dist/chunk-QEBUY5NY.js} +384 -1140
  97. package/dist/chunk-QLCCJEJI.js +253 -0
  98. package/dist/chunk-QOOUC2J5.js +52 -0
  99. package/dist/chunk-QYTPPDAO.js +402 -0
  100. package/dist/chunk-R3XI2VC7.js +801 -0
  101. package/dist/chunk-RCERWOJR.js +154 -0
  102. package/dist/chunk-RJE5JTVK.js +362 -0
  103. package/dist/chunk-RTLBSQ3G.js +1155 -0
  104. package/dist/chunk-RUNNI6VE.js +448 -0
  105. package/dist/chunk-RVMRZAPB.js +354 -0
  106. package/dist/chunk-RYEGFMUO.js +955 -0
  107. package/dist/chunk-RZCF2VVM.js +528 -0
  108. package/dist/chunk-SML67VPV.js +1025 -0
  109. package/dist/chunk-SQ7IY53Q.js +44 -0
  110. package/dist/chunk-SQAG3UXH.js +161 -0
  111. package/dist/chunk-SRTU6HMQ.js +1851 -0
  112. package/dist/chunk-T2OE3YQB.js +550 -0
  113. package/dist/chunk-T3UBLACL.js +299 -0
  114. package/dist/chunk-TLVIHFRO.js +296 -0
  115. package/dist/chunk-TYS6CSS5.js +52 -0
  116. package/dist/chunk-U6EQI3U6.js +130 -0
  117. package/dist/chunk-UJ4FJLBF.js +86 -0
  118. package/dist/chunk-ULOEATBZ.js +347 -0
  119. package/dist/chunk-UNCCZ3NU.js +127 -0
  120. package/dist/chunk-USZW2HHU.js +197 -0
  121. package/dist/chunk-UWN33VNX.js +1610 -0
  122. package/dist/chunk-UZ7EZW3B.js +40 -0
  123. package/dist/chunk-VOKGH627.js +37 -0
  124. package/dist/chunk-WBRZJOEC.js +204 -0
  125. package/dist/chunk-WCSOJFU3.js +380 -0
  126. package/dist/chunk-WCT3NYCV.js +160 -0
  127. package/dist/chunk-WVAJFAIA.js +529 -0
  128. package/dist/chunk-X5LCYCL5.js +394 -0
  129. package/dist/chunk-XAKEUMEJ.js +1256 -0
  130. package/dist/chunk-Y2ZE3MSG.js +590 -0
  131. package/dist/chunk-Y3J7VR52.js +646 -0
  132. package/dist/chunk-Y5QGVTVC.js +33 -0
  133. package/dist/chunk-YAA6IID3.js +548 -0
  134. package/dist/chunk-YGJTDXVR.js +692 -0
  135. package/{src/utils/time-ticks.ts → dist/chunk-YRYKTYMQ.js} +45 -112
  136. package/dist/chunk-YYVTBZZC.js +61 -0
  137. package/dist/chunk-Z5CGSFJB.js +647 -0
  138. package/{src/gantt/calculator.ts → dist/chunk-Z72XRXD4.js} +236 -428
  139. package/dist/chunk-ZGR7ULFJ.js +978 -0
  140. package/dist/chunk-ZJEL4H2R.js +851 -0
  141. package/dist/chunk-ZO27FGJS.js +554 -0
  142. package/dist/collapse-CLPJD2RL.js +11 -0
  143. package/dist/collapse-SLINJQW6.js +9 -0
  144. package/dist/collapse-ZWUFFCK2.js +9 -0
  145. package/dist/compute-G55RG53N.js +8 -0
  146. package/dist/dgmo-router-DZCIDUO5.js +73 -0
  147. package/dist/dimensions-J3FHIMJ6.js +22 -0
  148. package/dist/element.js +1 -1
  149. package/dist/element.mjs +1 -1
  150. package/dist/flowchart-parser-ZNSKIBVR.js +21 -0
  151. package/dist/flowchart-renderer-ZAEOL4DX.js +35 -0
  152. package/dist/index.d.ts +3 -469
  153. package/dist/index.js +137 -69685
  154. package/dist/layout-46N4JJYK.js +17 -0
  155. package/dist/layout-5RA6QWR6.js +26 -0
  156. package/dist/layout-5T6RH5M6.js +14 -0
  157. package/dist/layout-7QXCNOVS.js +13 -0
  158. package/dist/layout-EE6GE46Y.js +17 -0
  159. package/dist/layout-G23F7LDH.js +9 -0
  160. package/dist/layout-HRBZPFCN.js +23 -0
  161. package/dist/layout-HWDSRX5E.js +20 -0
  162. package/dist/layout-HYZPWAK5.js +18 -0
  163. package/dist/layout-N76NR4ZO.js +19 -0
  164. package/dist/layout-OB3RI63S.js +14 -0
  165. package/dist/layout-S2QBYSK2.js +15 -0
  166. package/dist/layout-UM5F4DJB.js +15 -0
  167. package/dist/layout-search-OYV77HHS.js +1655 -0
  168. package/dist/load-data-EHDDZ5ZS.js +8 -0
  169. package/dist/palettes-PRJ2RI6D.js +56 -0
  170. package/dist/parser-2MFP2H2E.js +11 -0
  171. package/dist/parser-3STE62GB.js +21 -0
  172. package/dist/parser-4FL2CMDG.js +18 -0
  173. package/dist/parser-4OGOBJJ4.js +13 -0
  174. package/dist/parser-6BTRLKRZ.js +15 -0
  175. package/dist/parser-AQETEVRW.js +21 -0
  176. package/dist/parser-CFZD5IBL.js +12 -0
  177. package/dist/parser-FUSKFGZN.js +16 -0
  178. package/dist/parser-I6KXEYFK.js +13 -0
  179. package/dist/parser-IXSZZQHY.js +18 -0
  180. package/dist/parser-JAL2HD4I.js +13 -0
  181. package/dist/parser-KNSQSKQO.js +20 -0
  182. package/dist/parser-N5O4IHUN.js +13 -0
  183. package/dist/parser-NGU3ETO6.js +16 -0
  184. package/dist/parser-NRAI6O25.js +19 -0
  185. package/dist/parser-O5J4VBII.js +11 -0
  186. package/dist/parser-OV7NOBW6.js +21 -0
  187. package/dist/parser-PQ3POX45.js +23 -0
  188. package/dist/parser-TFZFBVWN.js +11 -0
  189. package/dist/parser-TRTHDFPP.js +18 -0
  190. package/dist/parser-VQP2UJ6W.js +11 -0
  191. package/dist/parser-XDVELHRK.js +13 -0
  192. package/dist/parser-XKRP7QKP.js +11 -0
  193. package/dist/parser-Y6WTBU76.js +14 -0
  194. package/dist/parser-ZSDPZYQP.js +12 -0
  195. package/dist/renderer-2XQQQ6QR.js +28 -0
  196. package/dist/renderer-5NDVNDAZ.js +26 -0
  197. package/dist/renderer-6EEZHMH4.js +26 -0
  198. package/dist/renderer-6W5462RB.js +43 -0
  199. package/dist/renderer-7MVLWWQD.js +22 -0
  200. package/dist/renderer-AWWAF6XD.js +33 -0
  201. package/dist/renderer-BYCNMBF7.js +34 -0
  202. package/dist/renderer-CLJHQPBJ.js +29 -0
  203. package/dist/renderer-GHPZMFU2.js +15 -0
  204. package/dist/renderer-JGBKUCZD.js +16 -0
  205. package/dist/renderer-KQB7UGDS.js +19 -0
  206. package/dist/renderer-PGX2TKVS.js +24 -0
  207. package/dist/renderer-QIWVHWZO.js +15 -0
  208. package/dist/renderer-RPOA5YPZ.js +35 -0
  209. package/dist/renderer-SMIBCRVB.js +24 -0
  210. package/dist/renderer-T7YKC5VP.js +28 -0
  211. package/dist/renderer-TOCOVLHS.js +37 -0
  212. package/dist/renderer-UWA5XS74.js +39 -0
  213. package/dist/renderer-VACVQYML.js +25 -0
  214. package/dist/renderer-W4M6QLIJ.js +37 -0
  215. package/dist/renderer-WZRREQ2P.js +23 -0
  216. package/dist/renderer-YY2OSF6E.js +27 -0
  217. package/dist/renderer-Z7I3W2PP.js +24 -0
  218. package/dist/renderer-ZGNTUWC4.js +22 -0
  219. package/dist/renderer-ZTR3DER3.js +19 -0
  220. package/dist/renderer-radial-C32GPJQ7.js +21 -0
  221. package/dist/resolver-NOAA7ID7.js +13 -0
  222. package/dist/state-collapse-HCGD6IVJ.js +8 -0
  223. package/dist/state-parser-Z2V23ATR.js +18 -0
  224. package/dist/state-renderer-RFYHSP4K.js +34 -0
  225. package/dist/themes-1-CuKpeH.d.ts +908 -0
  226. package/package.json +19 -70
  227. package/dist/advanced.cjs +0 -71648
  228. package/dist/advanced.d.cts +0 -6571
  229. package/dist/auto.cjs +0 -70648
  230. package/dist/auto.d.cts +0 -54
  231. package/dist/block.cjs +0 -70208
  232. package/dist/block.d.cts +0 -115
  233. package/dist/editor.d.cts +0 -26
  234. package/dist/element.cjs +0 -70530
  235. package/dist/element.d.cts +0 -62
  236. package/dist/highlight.cjs +0 -852
  237. package/dist/highlight.d.cts +0 -49
  238. package/dist/index.cjs +0 -70491
  239. package/dist/index.d.cts +0 -626
  240. package/dist/pert.cjs +0 -325
  241. package/dist/pert.d.cts +0 -559
  242. package/src/advanced.ts +0 -873
  243. package/src/arc/parser.ts +0 -15
  244. package/src/arc/renderer.ts +0 -633
  245. package/src/auto/index.ts +0 -621
  246. package/src/auto/shared.ts +0 -370
  247. package/src/auto/styles.ts +0 -73
  248. package/src/block/layout.ts +0 -198
  249. package/src/block/renderer.ts +0 -484
  250. package/src/block/types.ts +0 -67
  251. package/src/boxes-and-lines/collapse.ts +0 -96
  252. package/src/boxes-and-lines/focus.ts +0 -257
  253. package/src/boxes-and-lines/label-placement.ts +0 -339
  254. package/src/boxes-and-lines/layout-grouped.ts +0 -912
  255. package/src/boxes-and-lines/layout-layered.ts +0 -722
  256. package/src/boxes-and-lines/layout-search.ts +0 -1678
  257. package/src/boxes-and-lines/layout.ts +0 -398
  258. package/src/boxes-and-lines/parser.ts +0 -1181
  259. package/src/boxes-and-lines/renderer.ts +0 -1465
  260. package/src/boxes-and-lines/types.ts +0 -66
  261. package/src/c4/parser.ts +0 -1158
  262. package/src/c4/renderer.ts +0 -2008
  263. package/src/c4/types.ts +0 -89
  264. package/src/chart-type-registry.ts +0 -529
  265. package/src/chart-types.ts +0 -225
  266. package/src/chart.ts +0 -685
  267. package/src/charts-d3/bar.ts +0 -338
  268. package/src/charts-d3/chord.ts +0 -140
  269. package/src/charts-d3/function.ts +0 -147
  270. package/src/charts-d3/funnel.ts +0 -104
  271. package/src/charts-d3/heatmap.ts +0 -145
  272. package/src/charts-d3/index.ts +0 -337
  273. package/src/charts-d3/interactions.ts +0 -477
  274. package/src/charts-d3/line.ts +0 -344
  275. package/src/charts-d3/mount.ts +0 -151
  276. package/src/charts-d3/pie.ts +0 -117
  277. package/src/charts-d3/polar.ts +0 -89
  278. package/src/charts-d3/radar.ts +0 -0
  279. package/src/charts-d3/sankey.ts +0 -0
  280. package/src/charts-d3/scatter.ts +0 -185
  281. package/src/charts-d3/shared.ts +0 -208
  282. package/src/class/layout.ts +0 -326
  283. package/src/class/parser.ts +0 -635
  284. package/src/class/renderer.ts +0 -793
  285. package/src/class/types.ts +0 -58
  286. package/src/cli-banner.ts +0 -106
  287. package/src/cli.ts +0 -1080
  288. package/src/colors-diagnostics.ts +0 -35
  289. package/src/colors.ts +0 -379
  290. package/src/completion-types.ts +0 -27
  291. package/src/completion.ts +0 -2668
  292. package/src/cycle/layout.ts +0 -1026
  293. package/src/cycle/parser.ts +0 -387
  294. package/src/cycle/renderer.ts +0 -653
  295. package/src/cycle/types.ts +0 -101
  296. package/src/d3.ts +0 -1434
  297. package/src/data-chart-parser.ts +0 -1007
  298. package/src/dgmo-router.ts +0 -296
  299. package/src/diagnostics-registry.ts +0 -108
  300. package/src/diagnostics.ts +0 -0
  301. package/src/dimensions.ts +0 -20
  302. package/src/directives-registry.ts +0 -396
  303. package/src/editor/dgmo.grammar +0 -76
  304. package/src/editor/dgmo.grammar.d.ts +0 -2
  305. package/src/editor/dgmo.grammar.js +0 -18
  306. package/src/editor/dgmo.grammar.terms.d.ts +0 -5
  307. package/src/editor/dgmo.grammar.terms.js +0 -35
  308. package/src/editor/highlight-api.ts +0 -596
  309. package/src/editor/highlight.ts +0 -36
  310. package/src/editor/index.ts +0 -27
  311. package/src/editor/keywords.ts +0 -128
  312. package/src/editor/tokens.ts +0 -30
  313. package/src/element/index.ts +0 -432
  314. package/src/embed/css.ts +0 -312
  315. package/src/embed/escape.ts +0 -15
  316. package/src/embed/index.ts +0 -280
  317. package/src/er/classify.ts +0 -228
  318. package/src/er/layout.ts +0 -530
  319. package/src/er/parser.ts +0 -750
  320. package/src/er/renderer.ts +0 -725
  321. package/src/er/types.ts +0 -52
  322. package/src/error-card.ts +0 -269
  323. package/src/event-line/diagnostics.ts +0 -117
  324. package/src/event-line/parser.ts +0 -643
  325. package/src/event-line/renderer.ts +0 -1742
  326. package/src/event-line/types.ts +0 -74
  327. package/src/fonts.ts +0 -3
  328. package/src/gantt/parser.ts +0 -1641
  329. package/src/gantt/renderer.ts +0 -3787
  330. package/src/gantt/resolver.ts +0 -172
  331. package/src/gantt/types.ts +0 -206
  332. package/src/graph/diagnostics.ts +0 -64
  333. package/src/graph/edge-spline.ts +0 -29
  334. package/src/graph/flowchart-parser.ts +0 -759
  335. package/src/graph/flowchart-renderer.ts +0 -817
  336. package/src/graph/layout.ts +0 -472
  337. package/src/graph/notes.ts +0 -21
  338. package/src/graph/state-collapse.ts +0 -78
  339. package/src/graph/state-parser.ts +0 -574
  340. package/src/graph/state-renderer.ts +0 -653
  341. package/src/graph/types.ts +0 -65
  342. package/src/index.ts +0 -261
  343. package/src/infra/compute.ts +0 -1385
  344. package/src/infra/layout.ts +0 -888
  345. package/src/infra/parser.ts +0 -1234
  346. package/src/infra/renderer.ts +0 -2534
  347. package/src/infra/roles.ts +0 -75
  348. package/src/infra/types.ts +0 -216
  349. package/src/infra/validation.ts +0 -201
  350. package/src/journey-map/layout.ts +0 -490
  351. package/src/journey-map/parser.ts +0 -557
  352. package/src/journey-map/renderer.ts +0 -1580
  353. package/src/journey-map/types.ts +0 -47
  354. package/src/kanban/mutations.ts +0 -175
  355. package/src/kanban/parser.ts +0 -509
  356. package/src/kanban/renderer.ts +0 -1449
  357. package/src/kanban/types.ts +0 -39
  358. package/src/label-layout.ts +0 -368
  359. package/src/map/colorize.ts +0 -54
  360. package/src/map/completion.ts +0 -316
  361. package/src/map/context-labels.ts +0 -609
  362. package/src/map/data/PROVENANCE.json +0 -1
  363. package/src/map/data/README.md +0 -40
  364. package/src/map/data/airport-collisions.json +0 -1
  365. package/src/map/data/airports.json +0 -1
  366. package/src/map/data/gazetteer.json +0 -1
  367. package/src/map/data/lakes.json +0 -1
  368. package/src/map/data/mountain-ranges.json +0 -1
  369. package/src/map/data/na-lakes.json +0 -1
  370. package/src/map/data/na-land.json +0 -1
  371. package/src/map/data/region-names.json +0 -1
  372. package/src/map/data/rivers.json +0 -1
  373. package/src/map/data/types.ts +0 -121
  374. package/src/map/data/us-states.json +0 -1
  375. package/src/map/data/water-bodies.json +0 -1
  376. package/src/map/data/world-coarse.json +0 -1
  377. package/src/map/data/world-detail.json +0 -1
  378. package/src/map/diagnostics.ts +0 -134
  379. package/src/map/dimensions.ts +0 -150
  380. package/src/map/geo-query.ts +0 -295
  381. package/src/map/geo.ts +0 -438
  382. package/src/map/invert.ts +0 -111
  383. package/src/map/layout.ts +0 -5069
  384. package/src/map/legend-band.ts +0 -127
  385. package/src/map/load-data.ts +0 -186
  386. package/src/map/parser.ts +0 -783
  387. package/src/map/renderer.ts +0 -1445
  388. package/src/map/resolved-types.ts +0 -160
  389. package/src/map/resolver.ts +0 -1146
  390. package/src/map/types.ts +0 -194
  391. package/src/mindmap/collapse.ts +0 -67
  392. package/src/mindmap/layout.ts +0 -649
  393. package/src/mindmap/parser.ts +0 -430
  394. package/src/mindmap/renderer.ts +0 -637
  395. package/src/mindmap/text-wrap.ts +0 -218
  396. package/src/mindmap/types.ts +0 -56
  397. package/src/org/collapse.ts +0 -151
  398. package/src/org/layout.ts +0 -1262
  399. package/src/org/parser.ts +0 -519
  400. package/src/org/renderer.ts +0 -866
  401. package/src/org/resolver.ts +0 -636
  402. package/src/palettes/atlas.ts +0 -77
  403. package/src/palettes/blueprint.ts +0 -73
  404. package/src/palettes/catppuccin.ts +0 -84
  405. package/src/palettes/color-utils.ts +0 -443
  406. package/src/palettes/index.ts +0 -67
  407. package/src/palettes/nord.ts +0 -67
  408. package/src/palettes/registry.ts +0 -114
  409. package/src/palettes/slate.ts +0 -73
  410. package/src/palettes/tidewater.ts +0 -73
  411. package/src/palettes/tokyo-night.ts +0 -86
  412. package/src/palettes/types.ts +0 -88
  413. package/src/pert/analyzer.ts +0 -1183
  414. package/src/pert/diagnostics.ts +0 -110
  415. package/src/pert/index.ts +0 -43
  416. package/src/pert/internal.ts +0 -252
  417. package/src/pert/layout.ts +0 -971
  418. package/src/pert/monte-carlo.ts +0 -446
  419. package/src/pert/parser.ts +0 -1606
  420. package/src/pert/renderer.ts +0 -4009
  421. package/src/pert/share-normalize.ts +0 -62
  422. package/src/pert/types.ts +0 -604
  423. package/src/pyramid/parser.ts +0 -185
  424. package/src/pyramid/renderer.ts +0 -768
  425. package/src/pyramid/types.ts +0 -28
  426. package/src/quadrant/parser.ts +0 -18
  427. package/src/quadrant/renderer.ts +0 -638
  428. package/src/raci/diagnostics.ts +0 -213
  429. package/src/raci/index.ts +0 -23
  430. package/src/raci/mutations.ts +0 -321
  431. package/src/raci/parser.ts +0 -699
  432. package/src/raci/renderer.ts +0 -1627
  433. package/src/raci/types.ts +0 -82
  434. package/src/raci/variants.ts +0 -320
  435. package/src/render.ts +0 -268
  436. package/src/ring/parser.ts +0 -212
  437. package/src/ring/renderer.ts +0 -490
  438. package/src/ring/types.ts +0 -27
  439. package/src/sequence/collapse.ts +0 -174
  440. package/src/sequence/parser.ts +0 -1596
  441. package/src/sequence/participant-inference.ts +0 -152
  442. package/src/sequence/renderer.ts +0 -3168
  443. package/src/sequence/tag-resolution.ts +0 -164
  444. package/src/sharing.ts +0 -211
  445. package/src/sitemap/collapse.ts +0 -100
  446. package/src/sitemap/layout.ts +0 -925
  447. package/src/sitemap/parser.ts +0 -755
  448. package/src/sitemap/renderer.ts +0 -828
  449. package/src/sitemap/types.ts +0 -42
  450. package/src/slope/parser.ts +0 -18
  451. package/src/slope/renderer.ts +0 -378
  452. package/src/swimlane/diagnostics.ts +0 -94
  453. package/src/swimlane/layout.ts +0 -597
  454. package/src/swimlane/parser.ts +0 -613
  455. package/src/swimlane/renderer.ts +0 -681
  456. package/src/swimlane/types.ts +0 -151
  457. package/src/tech-radar/interactive.ts +0 -1129
  458. package/src/tech-radar/layout.ts +0 -197
  459. package/src/tech-radar/parser.ts +0 -436
  460. package/src/tech-radar/renderer.ts +0 -1239
  461. package/src/tech-radar/shared.ts +0 -151
  462. package/src/tech-radar/types.ts +0 -86
  463. package/src/themes.ts +0 -22
  464. package/src/timeline/parser.ts +0 -472
  465. package/src/timeline/renderer.ts +0 -3024
  466. package/src/timeline/types.ts +0 -33
  467. package/src/timeline/viz-parser.ts +0 -21
  468. package/src/treemap/diagnostics.ts +0 -62
  469. package/src/treemap/layout-radial.ts +0 -233
  470. package/src/treemap/layout.ts +0 -189
  471. package/src/treemap/parser.ts +0 -463
  472. package/src/treemap/renderer-radial.ts +0 -438
  473. package/src/treemap/renderer.ts +0 -572
  474. package/src/treemap/treemap-shared.ts +0 -309
  475. package/src/treemap/types.ts +0 -60
  476. package/src/utils/arrow-markers.ts +0 -51
  477. package/src/utils/arrows-diagnostics.ts +0 -62
  478. package/src/utils/arrows.ts +0 -227
  479. package/src/utils/brand.ts +0 -61
  480. package/src/utils/card.ts +0 -183
  481. package/src/utils/collapse-engine/tree-edges.ts +0 -115
  482. package/src/utils/collapse-engine/tree.ts +0 -117
  483. package/src/utils/d3-helpers.ts +0 -219
  484. package/src/utils/d3-types.ts +0 -9
  485. package/src/utils/description-helpers.ts +0 -38
  486. package/src/utils/duration.ts +0 -312
  487. package/src/utils/export-container.ts +0 -41
  488. package/src/utils/expr-eval.ts +0 -27
  489. package/src/utils/fit-canvas.ts +0 -64
  490. package/src/utils/hover-styles.ts +0 -673
  491. package/src/utils/inline-markdown.ts +0 -96
  492. package/src/utils/legend-constants.ts +0 -48
  493. package/src/utils/legend-d3.ts +0 -618
  494. package/src/utils/legend-integration.ts +0 -107
  495. package/src/utils/legend-layout.ts +0 -776
  496. package/src/utils/legend-svg.ts +0 -214
  497. package/src/utils/legend-types.ts +0 -272
  498. package/src/utils/name-normalize.ts +0 -163
  499. package/src/utils/note-box/constants.ts +0 -25
  500. package/src/utils/note-box/index.ts +0 -11
  501. package/src/utils/note-box/metrics.ts +0 -90
  502. package/src/utils/note-box/svg.ts +0 -331
  503. package/src/utils/notes/bounds.ts +0 -30
  504. package/src/utils/notes/build.ts +0 -131
  505. package/src/utils/notes/index.ts +0 -18
  506. package/src/utils/notes/model.ts +0 -19
  507. package/src/utils/notes/parse.ts +0 -131
  508. package/src/utils/notes/place.ts +0 -177
  509. package/src/utils/notes/resolve.ts +0 -88
  510. package/src/utils/number-format.ts +0 -36
  511. package/src/utils/parsing.ts +0 -953
  512. package/src/utils/reserved-key-registry.ts +0 -239
  513. package/src/utils/safe-href.ts +0 -38
  514. package/src/utils/scaling.ts +0 -97
  515. package/src/utils/svg-embed.ts +0 -251
  516. package/src/utils/tag-groups.ts +0 -607
  517. package/src/utils/text-measure.ts +0 -122
  518. package/src/utils/title-constants.ts +0 -24
  519. package/src/utils/visual-conventions.ts +0 -61
  520. package/src/utils/wrapped-desc.ts +0 -87
  521. package/src/venn/parser.ts +0 -18
  522. package/src/venn/renderer.ts +0 -1047
  523. package/src/version-control/diagnostics.ts +0 -67
  524. package/src/version-control/parser.ts +0 -544
  525. package/src/version-control/renderer.ts +0 -724
  526. package/src/version-control/types.ts +0 -100
  527. package/src/visualizations/parse.ts +0 -1560
  528. package/src/visualizations/types.ts +0 -262
  529. package/src/wireframe/layout.ts +0 -479
  530. package/src/wireframe/parser.ts +0 -1114
  531. package/src/wireframe/renderer.ts +0 -1318
  532. package/src/wireframe/types.ts +0 -110
  533. package/src/wordcloud/parser.ts +0 -18
  534. package/src/wordcloud/renderer.ts +0 -357
@@ -1,181 +1,44 @@
1
- // ============================================================
2
- // C4 Context Diagram Layout Engine (dagre)
3
- // ============================================================
4
-
5
- import { tagAttrKey } from '../utils/tag-groups';
6
- import dagre from '@dagrejs/dagre';
7
- import type {
8
- ParsedC4,
9
- C4Element,
10
- C4Relationship,
11
- C4ArrowType,
12
- C4Shape,
13
- C4DeploymentNode,
14
- } from './types';
15
- import type { TagGroup } from '../utils/tag-groups';
16
- import type { Writable } from '../utils/brand';
17
-
18
- /** Mutable edge variant for in-place position shifts during layout. */
19
- type MutableC4LayoutEdge = Writable<C4LayoutEdge> & {
20
- points: { x: number; y: number }[];
21
- };
22
1
  import {
23
- LEGEND_PILL_FONT_SIZE,
24
- LEGEND_ENTRY_FONT_SIZE,
25
- LEGEND_HEIGHT,
26
- LEGEND_PILL_PAD,
2
+ LEGEND_CAPSULE_PAD,
27
3
  LEGEND_DOT_R,
28
4
  LEGEND_ENTRY_DOT_GAP,
5
+ LEGEND_ENTRY_FONT_SIZE,
29
6
  LEGEND_ENTRY_TRAIL,
30
- LEGEND_CAPSULE_PAD,
31
- measureLegendText,
32
- } from '../utils/legend-constants';
33
- import { measureText, wrapTextToWidth } from '../utils/text-measure';
34
-
35
- /** dagre node label shape after layout(). */
36
- interface DagreNodeLabel {
37
- x: number;
38
- y: number;
39
- width: number;
40
- height: number;
41
- [key: string]: unknown;
42
- }
43
-
44
- /** dagre edge label shape after layout(). */
45
- interface DagreEdgeLabel {
46
- points: { x: number; y: number }[];
47
- [key: string]: unknown;
48
- }
49
-
50
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
51
- const gNode = (g: any, name: string): DagreNodeLabel => g.node(name);
52
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
53
- const gEdge = (g: any, v: string, w: string): DagreEdgeLabel | undefined =>
54
- g.edge(v, w);
55
-
56
- // ============================================================
57
- // Types
58
- // ============================================================
59
-
60
- export interface C4LayoutNode {
61
- readonly id: string;
62
- readonly name: string;
63
- readonly type: 'person' | 'system' | 'container' | 'component';
64
- readonly description?: string;
65
- readonly metadata: Readonly<Record<string, string>>;
66
- readonly lineNumber: number;
67
- readonly color?: string;
68
- readonly shape?: C4Shape;
69
- readonly technology?: string;
70
- readonly drillable?: boolean;
71
- readonly importPath?: string;
72
- readonly x: number;
73
- readonly y: number;
74
- readonly width: number;
75
- readonly height: number;
76
- }
77
-
78
- export interface C4LayoutEdge {
79
- readonly source: string;
80
- readonly target: string;
81
- readonly arrowType: C4ArrowType;
82
- readonly label?: string;
83
- readonly technology?: string;
84
- readonly lineNumber: number;
85
- readonly points: ReadonlyArray<{ readonly x: number; readonly y: number }>;
86
- }
87
-
88
- export interface C4LegendEntry {
89
- readonly value: string;
90
- readonly color: string;
91
- }
92
-
93
- export interface C4LegendGroup {
94
- readonly name: string;
95
- readonly entries: readonly C4LegendEntry[];
96
- readonly x: number;
97
- readonly y: number;
98
- readonly width: number;
99
- readonly height: number;
100
- }
101
-
102
- export interface C4LayoutBoundary {
103
- readonly label: string;
104
- readonly typeLabel: string;
105
- readonly lineNumber: number;
106
- readonly x: number;
107
- readonly y: number;
108
- readonly width: number;
109
- readonly height: number;
110
- }
111
-
112
- export interface C4LayoutResult {
113
- readonly nodes: readonly C4LayoutNode[];
114
- readonly edges: readonly C4LayoutEdge[];
115
- readonly legend: readonly C4LegendGroup[];
116
- readonly boundary?: C4LayoutBoundary;
117
- readonly groupBoundaries: readonly C4LayoutBoundary[];
118
- readonly width: number;
119
- readonly height: number;
120
- }
121
-
122
- // ============================================================
123
- // Constants
124
- // ============================================================
125
-
126
- const MIN_NODE_WIDTH = 160;
127
- const MAX_NODE_WIDTH = 260;
128
- const TYPE_LABEL_HEIGHT = 18;
129
- const DIVIDER_GAP = 6;
130
- const NAME_HEIGHT = 20;
131
- const NAME_FONT_SIZE = 14;
132
- const DESC_LINE_HEIGHT = 16;
133
- const DESC_FONT_SIZE = 11;
134
- const CARD_V_PAD = 14;
135
- const CARD_H_PAD = 20;
136
- const META_LINE_HEIGHT = 16;
137
- const META_FONT_SIZE = 11;
138
- const MARGIN = 40;
139
- const BOUNDARY_PAD = 40;
140
- const GROUP_BOUNDARY_PAD = 24;
141
-
142
- // Legend constants (match org)
143
-
144
- // ============================================================
145
- // Post-Layout Crossing Reduction
146
- // ============================================================
147
-
148
- interface NodeGeometry {
149
- y: number;
150
- width: number;
151
- height: number;
152
- }
153
-
154
- // Large penalty per edge-node collision — dominates the distance term so the
155
- // sifter strongly prefers orderings where edges don't pass through other nodes.
156
- const EDGE_NODE_COLLISION_WEIGHT = 5000;
157
-
158
- /**
159
- * Compute penalty for an edge ordering. Uses degree-weighted edge distance:
160
- * long edges to high-degree nodes are penalized more than to low-degree nodes.
161
- * This places shared/important nodes closer to their neighbors, reducing
162
- * visual edge congestion.
163
- *
164
- * When nodeGeometry is provided, also adds a heavy penalty for each case where
165
- * a straight-line edge bounding box overlaps another node — driving the sifter
166
- * to prefer orderings that avoid edge-node collisions.
167
- */
168
- function computeEdgePenalty(
169
- edgeList: { source: string; target: string }[],
170
- nodePositions: Map<string, number>,
171
- degrees: Map<string, number>,
172
- nodeGeometry?: Map<string, NodeGeometry>
173
- ): number {
7
+ LEGEND_HEIGHT,
8
+ LEGEND_PILL_FONT_SIZE,
9
+ LEGEND_PILL_PAD,
10
+ measureLegendText
11
+ } from "./chunk-QOOUC2J5.js";
12
+ import {
13
+ measureText,
14
+ wrapTextToWidth
15
+ } from "./chunk-WCT3NYCV.js";
16
+ import {
17
+ tagAttrKey
18
+ } from "./chunk-QLCCJEJI.js";
19
+
20
+ // src/c4/layout.ts
21
+ import dagre from "@dagrejs/dagre";
22
+ var gNode = (g, name) => g.node(name);
23
+ var gEdge = (g, v, w) => g.edge(v, w);
24
+ var MIN_NODE_WIDTH = 160;
25
+ var MAX_NODE_WIDTH = 260;
26
+ var TYPE_LABEL_HEIGHT = 18;
27
+ var DIVIDER_GAP = 6;
28
+ var NAME_HEIGHT = 20;
29
+ var NAME_FONT_SIZE = 14;
30
+ var DESC_LINE_HEIGHT = 16;
31
+ var DESC_FONT_SIZE = 11;
32
+ var CARD_V_PAD = 14;
33
+ var CARD_H_PAD = 20;
34
+ var META_LINE_HEIGHT = 16;
35
+ var META_FONT_SIZE = 11;
36
+ var MARGIN = 40;
37
+ var BOUNDARY_PAD = 40;
38
+ var GROUP_BOUNDARY_PAD = 24;
39
+ var EDGE_NODE_COLLISION_WEIGHT = 5e3;
40
+ function computeEdgePenalty(edgeList, nodePositions, degrees, nodeGeometry) {
174
41
  let penalty = 0;
175
-
176
- // Degree-weighted edge distance: longer edges to higher-degree nodes
177
- // are penalized more, pulling "important" (shared) nodes closer to
178
- // their neighbors.
179
42
  for (const edge of edgeList) {
180
43
  const sx = nodePositions.get(edge.source);
181
44
  const tx = nodePositions.get(edge.target);
@@ -187,116 +50,74 @@ function computeEdgePenalty(
187
50
  );
188
51
  penalty += dist * weight;
189
52
  }
190
-
191
- // Edge-node collision penalty: for each edge A→B, check if any other node C
192
- // has its bounding box inside the straight-line bounding box of the edge.
193
- // Uses x from nodePositions (updated per permutation) and y/size from nodeGeometry.
194
53
  if (nodeGeometry) {
195
54
  for (const edge of edgeList) {
196
55
  const geomA = nodeGeometry.get(edge.source);
197
56
  const geomB = nodeGeometry.get(edge.target);
198
57
  if (!geomA || !geomB) continue;
199
-
200
58
  const ax = nodePositions.get(edge.source) ?? 0;
201
59
  const bx = nodePositions.get(edge.target) ?? 0;
202
60
  const ay = geomA.y;
203
61
  const by = geomB.y;
204
-
205
- // Skip edges within the same rank — they have no vertical span to check
206
62
  if (ay === by) continue;
207
-
208
63
  const edgeMinX = Math.min(ax, bx);
209
64
  const edgeMaxX = Math.max(ax, bx);
210
65
  const edgeMinY = Math.min(ay, by);
211
66
  const edgeMaxY = Math.max(ay, by);
212
-
213
67
  for (const [name, geomC] of nodeGeometry) {
214
68
  if (name === edge.source || name === edge.target) continue;
215
69
  const cx = nodePositions.get(name) ?? 0;
216
70
  const cy = geomC.y;
217
71
  const hw = geomC.width / 2;
218
72
  const hh = geomC.height / 2;
219
-
220
- // AABB overlap: node C's box intersects the edge's straight-line bounding box
221
- if (
222
- cx + hw > edgeMinX &&
223
- cx - hw < edgeMaxX &&
224
- cy + hh > edgeMinY &&
225
- cy - hh < edgeMaxY
226
- ) {
73
+ if (cx + hw > edgeMinX && cx - hw < edgeMaxX && cy + hh > edgeMinY && cy - hh < edgeMaxY) {
227
74
  penalty += EDGE_NODE_COLLISION_WEIGHT;
228
75
  }
229
76
  }
230
77
  }
231
78
  }
232
-
233
79
  return penalty;
234
80
  }
235
-
236
- /**
237
- * Post-dagre crossing reduction via permutation search.
238
- *
239
- * For each rank, tries all permutations (up to rank size 8) to find the
240
- * node ordering that minimizes degree-weighted edge distance. Nodes with
241
- * more connections (like a database shared by multiple services) get placed
242
- * closer to their neighbors, producing cleaner visual layouts.
243
- */
244
- function reduceCrossings(
245
- g: InstanceType<typeof dagre.graphlib.Graph>,
246
- edgeList: { source: string; target: string }[],
247
- nodeGroupMap?: Map<string, string>
248
- ): void {
81
+ function reduceCrossings(g, edgeList, nodeGroupMap) {
249
82
  if (edgeList.length < 2) return;
250
-
251
- // Compute degree (number of edges) for each node
252
- const degrees = new Map<string, number>();
83
+ const degrees = /* @__PURE__ */ new Map();
253
84
  for (const edge of edgeList) {
254
85
  degrees.set(edge.source, (degrees.get(edge.source) ?? 0) + 1);
255
86
  degrees.set(edge.target, (degrees.get(edge.target) ?? 0) + 1);
256
87
  }
257
-
258
- // Build geometry map for edge-node collision scoring
259
- const nodeGeometry = new Map<string, NodeGeometry>();
88
+ const nodeGeometry = /* @__PURE__ */ new Map();
260
89
  for (const name of g.nodes()) {
261
90
  const pos = gNode(g, name);
262
91
  if (pos)
263
92
  nodeGeometry.set(name, {
264
93
  y: pos.y,
265
94
  width: pos.width,
266
- height: pos.height,
95
+ height: pos.height
267
96
  });
268
97
  }
269
-
270
- // Group nodes by rank
271
- const rankMap = new Map<number, string[]>();
98
+ const rankMap = /* @__PURE__ */ new Map();
272
99
  for (const name of g.nodes()) {
273
100
  const pos = gNode(g, name);
274
101
  if (!pos) continue;
275
102
  const rankY = Math.round(pos.y);
276
103
  if (!rankMap.has(rankY)) rankMap.set(rankY, []);
277
- rankMap.get(rankY)!.push(name);
104
+ rankMap.get(rankY).push(name);
278
105
  }
279
-
280
- // Sort each rank by current x position
281
106
  for (const [, rankNodes] of rankMap) {
282
107
  rankNodes.sort((a, b) => gNode(g, a).x - gNode(g, b).x);
283
108
  }
284
-
285
109
  let anyMoved = false;
286
-
287
110
  for (const [, rankNodes] of rankMap) {
288
111
  if (rankNodes.length < 2) continue;
289
-
290
- // When groups exist, partition rank nodes by group and only permute within groups
291
- const partitions: string[][] = [];
112
+ const partitions = [];
292
113
  if (nodeGroupMap && nodeGroupMap.size > 0) {
293
- const groupBuckets = new Map<string, string[]>();
294
- const ungrouped: string[] = [];
114
+ const groupBuckets = /* @__PURE__ */ new Map();
115
+ const ungrouped = [];
295
116
  for (const name of rankNodes) {
296
117
  const grp = nodeGroupMap.get(name);
297
118
  if (grp) {
298
119
  if (!groupBuckets.has(grp)) groupBuckets.set(grp, []);
299
- groupBuckets.get(grp)!.push(name);
120
+ groupBuckets.get(grp).push(name);
300
121
  } else {
301
122
  ungrouped.push(name);
302
123
  }
@@ -308,40 +129,28 @@ function reduceCrossings(
308
129
  } else {
309
130
  partitions.push(rankNodes);
310
131
  }
311
-
312
132
  for (const partition of partitions) {
313
133
  if (partition.length < 2) continue;
314
-
315
- // Collect the x-slots for this partition (sorted)
316
- const xSlots = partition
317
- .map((name) => gNode(g, name).x)
318
- .sort((a, b) => a - b);
319
-
320
- // Build position map snapshot
321
- const basePositions = new Map<string, number>();
134
+ const xSlots = partition.map((name) => gNode(g, name).x).sort((a, b) => a - b);
135
+ const basePositions = /* @__PURE__ */ new Map();
322
136
  for (const name of g.nodes()) {
323
137
  const pos = gNode(g, name);
324
138
  if (pos) basePositions.set(name, pos.x);
325
139
  }
326
-
327
- // Current penalty
328
140
  const currentPenalty = computeEdgePenalty(
329
141
  edgeList,
330
142
  basePositions,
331
143
  degrees,
332
144
  nodeGeometry
333
145
  );
334
-
335
- // Try permutations (feasible for partition sizes ≤ 8)
336
146
  let bestPerm = [...partition];
337
147
  let bestPenalty = currentPenalty;
338
-
339
148
  if (partition.length <= 8) {
340
149
  const perms = permutations(partition);
341
150
  for (const perm of perms) {
342
151
  const testPositions = new Map(basePositions);
343
152
  for (let i = 0; i < perm.length; i++) {
344
- testPositions.set(perm[i]!, xSlots[i]!);
153
+ testPositions.set(perm[i], xSlots[i]);
345
154
  }
346
155
  const penalty = computeEdgePenalty(
347
156
  edgeList,
@@ -355,7 +164,6 @@ function reduceCrossings(
355
164
  }
356
165
  }
357
166
  } else {
358
- // For large partitions, use adjacent swap
359
167
  const workingOrder = [...partition];
360
168
  let improved = true;
361
169
  let passes = 0;
@@ -365,7 +173,7 @@ function reduceCrossings(
365
173
  for (let i = 0; i < workingOrder.length - 1; i++) {
366
174
  const testPositions = new Map(basePositions);
367
175
  for (let k = 0; k < workingOrder.length; k++) {
368
- testPositions.set(workingOrder[k]!, xSlots[k]!);
176
+ testPositions.set(workingOrder[k], xSlots[k]);
369
177
  }
370
178
  const before = computeEdgePenalty(
371
179
  edgeList,
@@ -373,14 +181,13 @@ function reduceCrossings(
373
181
  degrees,
374
182
  nodeGeometry
375
183
  );
376
-
377
184
  [workingOrder[i], workingOrder[i + 1]] = [
378
- workingOrder[i + 1]!,
379
- workingOrder[i]!,
185
+ workingOrder[i + 1],
186
+ workingOrder[i]
380
187
  ];
381
188
  const testPositions2 = new Map(basePositions);
382
189
  for (let k = 0; k < workingOrder.length; k++) {
383
- testPositions2.set(workingOrder[k]!, xSlots[k]!);
190
+ testPositions2.set(workingOrder[k], xSlots[k]);
384
191
  }
385
192
  const after = computeEdgePenalty(
386
193
  edgeList,
@@ -388,7 +195,6 @@ function reduceCrossings(
388
195
  degrees,
389
196
  nodeGeometry
390
197
  );
391
-
392
198
  if (after < before) {
393
199
  improved = true;
394
200
  if (after < bestPenalty) {
@@ -397,28 +203,23 @@ function reduceCrossings(
397
203
  }
398
204
  } else {
399
205
  [workingOrder[i], workingOrder[i + 1]] = [
400
- workingOrder[i + 1]!,
401
- workingOrder[i]!,
206
+ workingOrder[i + 1],
207
+ workingOrder[i]
402
208
  ];
403
209
  }
404
210
  }
405
211
  }
406
212
  }
407
-
408
- // Apply best permutation if it differs from current
409
213
  if (bestPerm.some((name, i) => name !== partition[i])) {
410
214
  for (let i = 0; i < bestPerm.length; i++) {
411
- gNode(g, bestPerm[i]!).x = xSlots[i]!;
412
- // Update in the original rankNodes too
413
- const rankIdx = rankNodes.indexOf(partition[i]!);
414
- if (rankIdx >= 0) rankNodes[rankIdx] = bestPerm[i]!;
215
+ gNode(g, bestPerm[i]).x = xSlots[i];
216
+ const rankIdx = rankNodes.indexOf(partition[i]);
217
+ if (rankIdx >= 0) rankNodes[rankIdx] = bestPerm[i];
415
218
  }
416
219
  anyMoved = true;
417
220
  }
418
221
  }
419
222
  }
420
-
421
- // Recompute edge waypoints if any positions changed
422
223
  if (anyMoved) {
423
224
  for (const edge of edgeList) {
424
225
  const edgeData = gEdge(g, edge.source, edge.target);
@@ -426,73 +227,45 @@ function reduceCrossings(
426
227
  const srcPos = gNode(g, edge.source);
427
228
  const tgtPos = gNode(g, edge.target);
428
229
  if (!srcPos || !tgtPos) continue;
429
-
430
230
  const srcBottom = { x: srcPos.x, y: srcPos.y + srcPos.height / 2 };
431
231
  const tgtTop = { x: tgtPos.x, y: tgtPos.y - tgtPos.height / 2 };
432
232
  const midY = (srcBottom.y + tgtTop.y) / 2;
433
-
434
233
  edgeData.points = [
435
234
  srcBottom,
436
235
  { x: srcBottom.x, y: midY },
437
236
  { x: tgtTop.x, y: midY },
438
- tgtTop,
237
+ tgtTop
439
238
  ];
440
239
  }
441
240
  }
442
241
  }
443
-
444
- /** Generate all permutations of an array (Heap's algorithm). */
445
- function permutations<T>(arr: T[]): T[][] {
446
- const result: T[][] = [];
242
+ function permutations(arr) {
243
+ const result = [];
447
244
  const a = [...arr];
448
245
  const n = a.length;
449
- const c = new Array(n).fill(0) as number[];
450
-
246
+ const c = new Array(n).fill(0);
451
247
  result.push([...a]);
452
-
453
248
  let i = 0;
454
249
  while (i < n) {
455
- if (c[i]! < i) {
250
+ if (c[i] < i) {
456
251
  if (i % 2 === 0) {
457
- [a[0], a[i]] = [a[i]!, a[0]!];
252
+ [a[0], a[i]] = [a[i], a[0]];
458
253
  } else {
459
- [a[c[i]!], a[i]] = [a[i]!, a[c[i]!]!];
254
+ [a[c[i]], a[i]] = [a[i], a[c[i]]];
460
255
  }
461
256
  result.push([...a]);
462
- c[i]!++;
257
+ c[i]++;
463
258
  i = 0;
464
259
  } else {
465
260
  c[i] = 0;
466
261
  i++;
467
262
  }
468
263
  }
469
-
470
264
  return result;
471
265
  }
472
-
473
- // ============================================================
474
- // Roll-Up Logic
475
- // ============================================================
476
-
477
- export interface ContextRelationship {
478
- sourceName: string;
479
- targetName: string;
480
- label?: string;
481
- technology?: string;
482
- arrowType: C4ArrowType;
483
- lineNumber: number;
484
- }
485
-
486
- /**
487
- * Build a map from element name → top-level ancestor name.
488
- * Top-level elements map to themselves.
489
- */
490
- function buildOwnershipMap(
491
- elements: readonly C4Element[]
492
- ): Map<string, string> {
493
- const map = new Map<string, string>();
494
-
495
- function walk(el: C4Element, ancestor: string): void {
266
+ function buildOwnershipMap(elements) {
267
+ const map = /* @__PURE__ */ new Map();
268
+ function walk(el, ancestor) {
496
269
  map.set(el.name, ancestor);
497
270
  for (const child of el.children) {
498
271
  walk(child, ancestor);
@@ -503,24 +276,14 @@ function buildOwnershipMap(
503
276
  }
504
277
  }
505
278
  }
506
-
507
279
  for (const el of elements) {
508
280
  walk(el, el.name);
509
281
  }
510
-
511
282
  return map;
512
283
  }
513
-
514
- /**
515
- * Collect all relationships from the entire element tree.
516
- */
517
- function collectAllRelationships(
518
- elements: readonly C4Element[],
519
- _ownerMap: Map<string, string>
520
- ): { sourceName: string; rel: C4Relationship }[] {
521
- const result: { sourceName: string; rel: C4Relationship }[] = [];
522
-
523
- function walk(el: C4Element): void {
284
+ function collectAllRelationships(elements, _ownerMap) {
285
+ const result = [];
286
+ function walk(el) {
524
287
  for (const rel of el.relationships) {
525
288
  result.push({ sourceName: el.name, rel });
526
289
  }
@@ -533,96 +296,59 @@ function collectAllRelationships(
533
296
  }
534
297
  }
535
298
  }
536
-
537
299
  for (const el of elements) {
538
300
  walk(el);
539
301
  }
540
-
541
302
  return result;
542
303
  }
543
-
544
- /**
545
- * Roll up container/component-level relationships to system-to-system edges.
546
- * - Skips internal relationships (same top-level ancestor).
547
- * - Deduplicates: same source→target pair keeps only one (first seen).
548
- * - Explicit system-level relationships override rolled-up ones.
549
- */
550
- export function rollUpContextRelationships(
551
- parsed: ParsedC4
552
- ): ContextRelationship[] {
304
+ function rollUpContextRelationships(parsed) {
553
305
  const ownerMap = buildOwnershipMap(parsed.elements);
554
306
  const allRels = collectAllRelationships(parsed.elements, ownerMap);
555
-
556
- // Also include orphan relationships
557
- // Separate system-level (explicit) from nested (rolled-up)
558
307
  const topLevelNames = new Set(parsed.elements.map((e) => e.name));
559
- const explicitKeys = new Set<string>();
560
- const explicit: ContextRelationship[] = [];
561
- const nested: ContextRelationship[] = [];
562
-
308
+ const explicitKeys = /* @__PURE__ */ new Set();
309
+ const explicit = [];
310
+ const nested = [];
563
311
  for (const { sourceName, rel } of allRels) {
564
312
  const sourceAncestor = ownerMap.get(sourceName) ?? sourceName;
565
313
  const targetAncestor = ownerMap.get(rel.target) ?? rel.target;
566
-
567
- // Skip internal relationships (both in same system)
568
314
  if (sourceAncestor === targetAncestor) continue;
569
-
570
- const entry: ContextRelationship = {
315
+ const entry = {
571
316
  sourceName: sourceAncestor,
572
317
  targetName: targetAncestor,
573
- ...(rel.label !== undefined && { label: rel.label }),
574
- ...(rel.technology !== undefined && { technology: rel.technology }),
318
+ ...rel.label !== void 0 && { label: rel.label },
319
+ ...rel.technology !== void 0 && { technology: rel.technology },
575
320
  arrowType: rel.arrowType,
576
- lineNumber: rel.lineNumber,
321
+ lineNumber: rel.lineNumber
577
322
  };
578
-
579
- // Check if source is a top-level element (explicit system-level rel)
580
323
  if (topLevelNames.has(sourceName) && sourceName === sourceAncestor) {
581
- const key = `${sourceAncestor}→${targetAncestor}`;
324
+ const key = `${sourceAncestor}\u2192${targetAncestor}`;
582
325
  explicitKeys.add(key);
583
326
  explicit.push(entry);
584
327
  } else {
585
328
  nested.push(entry);
586
329
  }
587
330
  }
588
-
589
- // Deduplicate: explicit overrides rolled-up
590
331
  const result = [...explicit];
591
332
  const seenKeys = new Set(explicitKeys);
592
-
593
333
  for (const rel of nested) {
594
- const key = `${rel.sourceName}→${rel.targetName}`;
334
+ const key = `${rel.sourceName}\u2192${rel.targetName}`;
595
335
  if (!seenKeys.has(key)) {
596
336
  seenKeys.add(key);
597
337
  result.push(rel);
598
338
  }
599
339
  }
600
-
601
340
  return result;
602
341
  }
603
-
604
- // ============================================================
605
- // Tag Group Color Resolution
606
- // ============================================================
607
-
608
- function resolveNodeColor(
609
- el: C4Element,
610
- tagGroups: readonly TagGroup[],
611
- activeGroupName: string | null,
612
- ancestors?: readonly C4Element[]
613
- ): string | undefined {
614
- // Check metadata for explicit color
615
- const colorMeta = el.metadata['color'];
342
+ function resolveNodeColor(el, tagGroups, activeGroupName, ancestors) {
343
+ const colorMeta = el.metadata["color"];
616
344
  if (colorMeta) return colorMeta;
617
- if (!activeGroupName) return undefined;
618
-
345
+ if (!activeGroupName) return void 0;
619
346
  const group = tagGroups.find(
620
347
  (g) => g.name.toLowerCase() === activeGroupName.toLowerCase()
621
348
  );
622
- if (!group) return undefined;
349
+ if (!group) return void 0;
623
350
  const key = tagAttrKey(group.name);
624
- // Walk inheritance chain: element → ancestors (container → system)
625
- let metaValue: string | undefined = el.metadata[key];
351
+ let metaValue = el.metadata[key];
626
352
  if (!metaValue && ancestors) {
627
353
  for (const ancestor of ancestors) {
628
354
  metaValue = ancestor.metadata[key];
@@ -630,185 +356,105 @@ function resolveNodeColor(
630
356
  }
631
357
  }
632
358
  const resolvedValue = metaValue ?? group.defaultValue;
633
- if (!resolvedValue) return '#999999';
634
- return (
635
- group.entries.find(
636
- (e) => e.value.toLowerCase() === resolvedValue.toLowerCase()
637
- )?.color ?? '#999999'
638
- );
359
+ if (!resolvedValue) return "#999999";
360
+ return group.entries.find(
361
+ (e) => e.value.toLowerCase() === resolvedValue.toLowerCase()
362
+ )?.color ?? "#999999";
639
363
  }
640
-
641
- // ============================================================
642
- // Node Sizing
643
- // ============================================================
644
-
645
- /** Keys to exclude from the below-divider metadata display. */
646
- const META_EXCLUDE_KEYS = new Set([
647
- 'description',
648
- 'tech',
649
- 'technology',
650
- 'is a',
364
+ var META_EXCLUDE_KEYS = /* @__PURE__ */ new Set([
365
+ "description",
366
+ "tech",
367
+ "technology",
368
+ "is a"
651
369
  ]);
652
-
653
- /** Collect displayable metadata entries for a container card. */
654
- export function collectCardMetadata(
655
- metadata: Record<string, string>
656
- ): { key: string; value: string }[] {
657
- const entries: { key: string; value: string }[] = [];
658
- // Technology first
659
- const tech = metadata['tech'] ?? metadata['technology'];
660
- if (tech) entries.push({ key: 'Technology', value: tech });
661
- // Then other metadata (tag groups, etc.)
370
+ function collectCardMetadata(metadata) {
371
+ const entries = [];
372
+ const tech = metadata["tech"] ?? metadata["technology"];
373
+ if (tech) entries.push({ key: "Technology", value: tech });
662
374
  for (const [k, v] of Object.entries(metadata)) {
663
375
  if (META_EXCLUDE_KEYS.has(k.toLowerCase())) continue;
664
- // Capitalize key for display
665
376
  const displayKey = k.charAt(0).toUpperCase() + k.slice(1);
666
377
  entries.push({ key: displayKey, value: v });
667
378
  }
668
379
  return entries;
669
380
  }
670
-
671
- export function computeC4NodeDimensions(
672
- el: C4Element,
673
- options?: { showTechnology?: boolean }
674
- ): { width: number; height: number } {
675
- // Width: based on name length, clamped
381
+ function computeC4NodeDimensions(el, options) {
676
382
  const nameWidth = measureText(el.name, NAME_FONT_SIZE) + CARD_H_PAD * 2;
677
383
  let width = Math.max(MIN_NODE_WIDTH, Math.min(MAX_NODE_WIDTH, nameWidth));
678
-
679
384
  if (options?.showTechnology) {
680
- // Container card layout: name + description | divider | metadata rows
681
- // (no type label — containers are the default in container view)
682
- let height = CARD_V_PAD + NAME_HEIGHT;
683
-
684
- const desc = el.description?.join('\n');
685
- if (desc) {
385
+ let height2 = CARD_V_PAD + NAME_HEIGHT;
386
+ const desc2 = el.description?.join("\n");
387
+ if (desc2) {
686
388
  const contentWidth = width - CARD_H_PAD * 2;
687
- const lines = wrapTextToWidth(desc, DESC_FONT_SIZE, contentWidth);
688
- height += lines.length * DESC_LINE_HEIGHT;
389
+ const lines = wrapTextToWidth(desc2, DESC_FONT_SIZE, contentWidth);
390
+ height2 += lines.length * DESC_LINE_HEIGHT;
689
391
  }
690
-
691
- // Metadata rows below divider
692
392
  const metaEntries = collectCardMetadata(el.metadata);
693
393
  if (metaEntries.length > 0) {
694
- height += DIVIDER_GAP; // divider
695
- height += metaEntries.length * META_LINE_HEIGHT;
696
- // Widen card if metadata rows need more space
394
+ height2 += DIVIDER_GAP;
395
+ height2 += metaEntries.length * META_LINE_HEIGHT;
697
396
  const maxMetaWidth = Math.max(
698
397
  ...metaEntries.map(
699
- (e) =>
700
- measureText(`${e.key}: ${e.value}`, META_FONT_SIZE) + CARD_H_PAD * 2
398
+ (e) => measureText(`${e.key}: ${e.value}`, META_FONT_SIZE) + CARD_H_PAD * 2
701
399
  )
702
400
  );
703
401
  if (maxMetaWidth > width) width = Math.min(MAX_NODE_WIDTH, maxMetaWidth);
704
402
  }
705
-
706
- height += CARD_V_PAD;
707
- return { width, height };
403
+ height2 += CARD_V_PAD;
404
+ return { width, height: height2 };
708
405
  }
709
-
710
- // Context card layout: type + name | divider | description
711
406
  let height = CARD_V_PAD + TYPE_LABEL_HEIGHT + DIVIDER_GAP + NAME_HEIGHT;
712
-
713
- const desc = el.description?.join('\n');
407
+ const desc = el.description?.join("\n");
714
408
  if (desc) {
715
409
  const contentWidth = width - CARD_H_PAD * 2;
716
410
  const lines = wrapTextToWidth(desc, DESC_FONT_SIZE, contentWidth);
717
411
  height += lines.length * DESC_LINE_HEIGHT;
718
412
  }
719
-
720
413
  height += CARD_V_PAD;
721
-
722
414
  return { width, height };
723
415
  }
724
-
725
- // ============================================================
726
- // Legend Helpers
727
- // ============================================================
728
-
729
- function computeLegendGroups(
730
- tagGroups: readonly TagGroup[]
731
- ): Writable<C4LegendGroup>[] {
732
- const result: Writable<C4LegendGroup>[] = [];
733
-
416
+ function computeLegendGroups(tagGroups) {
417
+ const result = [];
734
418
  for (const group of tagGroups) {
735
- const entries: C4LegendEntry[] = [];
419
+ const entries = [];
736
420
  for (const entry of group.entries) {
737
421
  entries.push({ value: entry.value, color: entry.color });
738
422
  }
739
423
  if (entries.length === 0) continue;
740
-
741
- // Compute pill width: group name + entries
742
- const nameW =
743
- measureLegendText(group.name, LEGEND_PILL_FONT_SIZE) +
744
- LEGEND_PILL_PAD * 2;
424
+ const nameW = measureLegendText(group.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD * 2;
745
425
  let capsuleW = LEGEND_CAPSULE_PAD;
746
426
  for (const e of entries) {
747
- capsuleW +=
748
- LEGEND_DOT_R * 2 +
749
- LEGEND_ENTRY_DOT_GAP +
750
- measureLegendText(e.value, LEGEND_ENTRY_FONT_SIZE) +
751
- LEGEND_ENTRY_TRAIL;
427
+ capsuleW += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
752
428
  }
753
429
  capsuleW += LEGEND_CAPSULE_PAD;
754
-
755
430
  result.push({
756
431
  name: group.name,
757
432
  entries,
758
433
  x: 0,
759
434
  y: 0,
760
435
  width: nameW + capsuleW,
761
- height: LEGEND_HEIGHT,
436
+ height: LEGEND_HEIGHT
762
437
  });
763
438
  }
764
-
765
439
  return result;
766
440
  }
767
-
768
- // ============================================================
769
- // Adaptive Spacing
770
- // ============================================================
771
-
772
- /**
773
- * Compute dagre graph spacing based on edge density.
774
- * Nodes with high fan-out (many labeled edges) need more inter-rank
775
- * space so labels don't overlap. Returns ranksep and edgesep.
776
- */
777
- function computeAdaptiveSpacing(
778
- edges: { sourceName: string; label?: string; technology?: string }[]
779
- ): { nodesep: number; ranksep: number; edgesep: number } {
780
- // Count max labeled out-degree for any single source node
781
- const outDegree = new Map<string, number>();
441
+ function computeAdaptiveSpacing(edges) {
442
+ const outDegree = /* @__PURE__ */ new Map();
782
443
  for (const edge of edges) {
783
444
  if (edge.label || edge.technology) {
784
445
  outDegree.set(edge.sourceName, (outDegree.get(edge.sourceName) ?? 0) + 1);
785
446
  }
786
447
  }
787
448
  const maxFanOut = Math.max(0, ...outDegree.values());
788
-
789
- // Scale spacing: each additional fan-out edge needs more room for its label.
790
- // nodesep: wider horizontal gaps give fan-out edges distinct angles,
791
- // making it clear which label belongs to which line.
792
449
  const nodesep = Math.max(80, 60 + maxFanOut * 20);
793
450
  const ranksep = Math.max(140, 100 + maxFanOut * 35);
794
451
  const edgesep = Math.max(30, 20 + maxFanOut * 8);
795
-
796
452
  return { nodesep, ranksep, edgesep };
797
453
  }
798
-
799
- // ============================================================
800
- // Main Layout
801
- // ============================================================
802
-
803
- export function layoutC4Context(
804
- parsed: ParsedC4,
805
- activeTagGroup?: string | null
806
- ): C4LayoutResult {
807
- // Filter to person + system elements only
454
+ function layoutC4Context(parsed, activeTagGroup) {
808
455
  const contextElements = parsed.elements.filter(
809
- (el) => el.type === 'person' || el.type === 'system'
456
+ (el) => el.type === "person" || el.type === "system"
810
457
  );
811
-
812
458
  if (contextElements.length === 0) {
813
459
  return {
814
460
  nodes: [],
@@ -816,108 +462,80 @@ export function layoutC4Context(
816
462
  legend: [],
817
463
  groupBoundaries: [],
818
464
  width: 0,
819
- height: 0,
465
+ height: 0
820
466
  };
821
467
  }
822
-
823
- // Roll up relationships
824
468
  const contextRels = rollUpContextRelationships(parsed);
825
-
826
- // Compute adaptive spacing based on edge density
827
469
  const spacing = computeAdaptiveSpacing(contextRels);
828
-
829
- // Create dagre graph
830
470
  const g = new dagre.graphlib.Graph();
831
471
  g.setGraph({
832
- rankdir: 'TB',
472
+ rankdir: "TB",
833
473
  nodesep: spacing.nodesep,
834
474
  ranksep: spacing.ranksep,
835
- edgesep: spacing.edgesep,
475
+ edgesep: spacing.edgesep
836
476
  });
837
477
  g.setDefaultEdgeLabel(() => ({}));
838
-
839
- // Add nodes
840
- const nameToElement = new Map<string, C4Element>();
478
+ const nameToElement = /* @__PURE__ */ new Map();
841
479
  for (const el of contextElements) {
842
480
  nameToElement.set(el.name, el);
843
481
  const dims = computeC4NodeDimensions(el);
844
482
  g.setNode(el.name, { width: dims.width, height: dims.height });
845
483
  }
846
-
847
- // Add edges — only between known nodes
848
- const validRels: ContextRelationship[] = [];
484
+ const validRels = [];
849
485
  for (const rel of contextRels) {
850
- if (
851
- nameToElement.has(rel.sourceName) &&
852
- nameToElement.has(rel.targetName)
853
- ) {
486
+ if (nameToElement.has(rel.sourceName) && nameToElement.has(rel.targetName)) {
854
487
  validRels.push(rel);
855
- g.setEdge(rel.sourceName, rel.targetName, { label: rel.label ?? '' });
488
+ g.setEdge(rel.sourceName, rel.targetName, { label: rel.label ?? "" });
856
489
  }
857
490
  }
858
-
859
- // Run layout
860
491
  dagre.layout(g);
861
-
862
- // Post-dagre crossing reduction
863
492
  reduceCrossings(
864
493
  g,
865
494
  validRels.map((r) => ({ source: r.sourceName, target: r.targetName }))
866
495
  );
867
-
868
- // Extract positioned nodes
869
- const nodes: Writable<C4LayoutNode>[] = contextElements.map(
870
- (el): Writable<C4LayoutNode> => {
496
+ const nodes = contextElements.map(
497
+ (el) => {
871
498
  const pos = g.node(el.name);
872
499
  const color = resolveNodeColor(
873
500
  el,
874
501
  parsed.tagGroups,
875
502
  activeTagGroup ?? null
876
503
  );
877
- const hasContainers =
878
- el.children.some((c) => c.type === 'container') ||
879
- el.groups.some((g) => g.children.some((c) => c.type === 'container'));
880
- const description = el.description?.join('\n');
881
- const drillable = hasContainers || el.importPath ? true : undefined;
504
+ const hasContainers = el.children.some((c) => c.type === "container") || el.groups.some((g2) => g2.children.some((c) => c.type === "container"));
505
+ const description = el.description?.join("\n");
506
+ const drillable = hasContainers || el.importPath ? true : void 0;
882
507
  return {
883
508
  id: el.name,
884
509
  name: el.name,
885
- type: el.type as 'person' | 'system',
886
- ...(description !== undefined && { description }),
510
+ type: el.type,
511
+ ...description !== void 0 && { description },
887
512
  metadata: el.metadata,
888
513
  lineNumber: el.lineNumber,
889
- ...(color !== undefined && { color }),
890
- ...(drillable !== undefined && { drillable }),
891
- ...(el.importPath !== undefined && { importPath: el.importPath }),
514
+ ...color !== void 0 && { color },
515
+ ...drillable !== void 0 && { drillable },
516
+ ...el.importPath !== void 0 && { importPath: el.importPath },
892
517
  x: pos.x,
893
518
  y: pos.y,
894
519
  width: pos.width,
895
- height: pos.height,
520
+ height: pos.height
896
521
  };
897
522
  }
898
523
  );
899
-
900
- // Extract edges with waypoints
901
- const edges: MutableC4LayoutEdge[] = validRels.map(
902
- (rel): MutableC4LayoutEdge => {
524
+ const edges = validRels.map(
525
+ (rel) => {
903
526
  const edgeData = g.edge(rel.sourceName, rel.targetName);
904
527
  return {
905
528
  source: rel.sourceName,
906
529
  target: rel.targetName,
907
530
  arrowType: rel.arrowType,
908
- ...(rel.label !== undefined && { label: rel.label }),
909
- ...(rel.technology !== undefined && { technology: rel.technology }),
531
+ ...rel.label !== void 0 && { label: rel.label },
532
+ ...rel.technology !== void 0 && { technology: rel.technology },
910
533
  lineNumber: rel.lineNumber,
911
- points: edgeData?.points ?? [],
534
+ points: edgeData?.points ?? []
912
535
  };
913
536
  }
914
537
  );
915
-
916
- // Compute bounding box of all content (nodes + edge points)
917
- let minX = Infinity,
918
- minY = Infinity,
919
- maxX = -Infinity,
920
- maxY = -Infinity;
538
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
921
539
  for (const node of nodes) {
922
540
  const left = node.x - node.width / 2;
923
541
  const top = node.y - node.height / 2;
@@ -936,8 +554,6 @@ export function layoutC4Context(
936
554
  if (pt.y > maxY) maxY = pt.y;
937
555
  }
938
556
  }
939
-
940
- // Shift everything so content starts at (MARGIN, MARGIN)
941
557
  if (nodes.length > 0) {
942
558
  const shiftX = MARGIN - minX;
943
559
  const shiftY = MARGIN - minY;
@@ -952,15 +568,9 @@ export function layoutC4Context(
952
568
  }
953
569
  }
954
570
  }
955
-
956
571
  let totalWidth = nodes.length > 0 ? maxX - minX + MARGIN * 2 : 0;
957
572
  let totalHeight = nodes.length > 0 ? maxY - minY + MARGIN * 2 : 0;
958
-
959
- // Legend: show all defined tag groups and entries so users see the full
960
- // tag vocabulary regardless of which elements are visible at this view level.
961
573
  const legendGroups = computeLegendGroups(parsed.tagGroups);
962
-
963
- // Position legend below diagram
964
574
  if (legendGroups.length > 0) {
965
575
  const legendY = totalHeight + MARGIN;
966
576
  let legendX = MARGIN;
@@ -974,31 +584,16 @@ export function layoutC4Context(
974
584
  if (legendRight > totalWidth) totalWidth = legendRight;
975
585
  if (legendBottom > totalHeight) totalHeight = legendBottom;
976
586
  }
977
-
978
587
  return {
979
588
  nodes,
980
589
  edges,
981
590
  legend: legendGroups,
982
591
  groupBoundaries: [],
983
592
  width: totalWidth,
984
- height: totalHeight,
593
+ height: totalHeight
985
594
  };
986
595
  }
987
-
988
- // ============================================================
989
- // Container-Level Layout
990
- // ============================================================
991
-
992
- /**
993
- * Layout containers within a specific system, plus external elements
994
- * that have relationships with those containers.
995
- */
996
- export function layoutC4Containers(
997
- parsed: ParsedC4,
998
- systemName: string,
999
- activeTagGroup?: string | null
1000
- ): C4LayoutResult {
1001
- // Find the system element by name
596
+ function layoutC4Containers(parsed, systemName, activeTagGroup) {
1002
597
  const system = parsed.elements.find(
1003
598
  (el) => el.name.toLowerCase() === systemName.toLowerCase()
1004
599
  );
@@ -1009,21 +604,18 @@ export function layoutC4Containers(
1009
604
  legend: [],
1010
605
  groupBoundaries: [],
1011
606
  width: 0,
1012
- height: 0,
607
+ height: 0
1013
608
  };
1014
609
  }
1015
-
1016
- // Collect all containers: direct children + group children
1017
- const containers: C4Element[] = [];
610
+ const containers = [];
1018
611
  for (const child of system.children) {
1019
- if (child.type === 'container') containers.push(child);
612
+ if (child.type === "container") containers.push(child);
1020
613
  }
1021
614
  for (const group of system.groups) {
1022
615
  for (const child of group.children) {
1023
- if (child.type === 'container') containers.push(child);
616
+ if (child.type === "container") containers.push(child);
1024
617
  }
1025
618
  }
1026
-
1027
619
  if (containers.length === 0) {
1028
620
  return {
1029
621
  nodes: [],
@@ -1031,23 +623,15 @@ export function layoutC4Containers(
1031
623
  legend: [],
1032
624
  groupBoundaries: [],
1033
625
  width: 0,
1034
- height: 0,
626
+ height: 0
1035
627
  };
1036
628
  }
1037
-
1038
629
  const containerNames = new Set(containers.map((c) => c.name.toLowerCase()));
1039
-
1040
- // Build name → element map for all top-level elements
1041
- const topElementsByName = new Map<string, C4Element>();
630
+ const topElementsByName = /* @__PURE__ */ new Map();
1042
631
  for (const el of parsed.elements) {
1043
632
  topElementsByName.set(el.name.toLowerCase(), el);
1044
633
  }
1045
-
1046
- // Identify external elements: targets of container relationships that aren't
1047
- // in this system, OR top-level elements that target containers in this system
1048
- const externalNames = new Set<string>();
1049
-
1050
- // Forward: container → target outside this system
634
+ const externalNames = /* @__PURE__ */ new Set();
1051
635
  for (const container of containers) {
1052
636
  for (const rel of container.relationships) {
1053
637
  const targetLower = rel.target.toLowerCase();
@@ -1056,175 +640,120 @@ export function layoutC4Containers(
1056
640
  }
1057
641
  }
1058
642
  }
1059
-
1060
- // Reverse: top-level elements (and their children) that target containers in this system
1061
643
  const ownerMap = buildOwnershipMap(parsed.elements);
1062
644
  const allRels = collectAllRelationships(parsed.elements, ownerMap);
1063
645
  for (const { sourceName, rel } of allRels) {
1064
646
  const sourceAncestor = ownerMap.get(sourceName) ?? sourceName;
1065
- // Skip relationships from within this system
1066
647
  if (sourceAncestor.toLowerCase() === system.name.toLowerCase()) continue;
1067
- // Check if target is a container in this system
1068
648
  if (containerNames.has(rel.target.toLowerCase())) {
1069
649
  externalNames.add(sourceAncestor.toLowerCase());
1070
650
  }
1071
651
  }
1072
-
1073
- // Resolve external elements
1074
- const externals: C4Element[] = [];
652
+ const externals = [];
1075
653
  for (const name of externalNames) {
1076
654
  const el = topElementsByName.get(name);
1077
655
  if (el) externals.push(el);
1078
656
  }
1079
-
1080
- // Build element-to-group mapping for compound graph
1081
- const elementToGroup = new Map<
1082
- string,
1083
- { name: string; lineNumber: number }
1084
- >();
657
+ const elementToGroup = /* @__PURE__ */ new Map();
1085
658
  for (const group of system.groups) {
1086
659
  for (const child of group.children) {
1087
- if (child.type === 'container') {
660
+ if (child.type === "container") {
1088
661
  elementToGroup.set(child.name, {
1089
662
  name: group.name,
1090
- lineNumber: group.lineNumber,
663
+ lineNumber: group.lineNumber
1091
664
  });
1092
665
  }
1093
666
  }
1094
667
  }
1095
668
  const hasGroups = elementToGroup.size > 0;
1096
-
1097
- // Create dagre graph — use compound when groups exist
1098
- const g = hasGroups
1099
- ? new dagre.graphlib.Graph({ compound: true })
1100
- : new dagre.graphlib.Graph();
669
+ const g = hasGroups ? new dagre.graphlib.Graph({ compound: true }) : new dagre.graphlib.Graph();
1101
670
  g.setDefaultEdgeLabel(() => ({}));
1102
-
1103
- // Add virtual group parent nodes
1104
671
  if (hasGroups) {
1105
- const seenGroups = new Set<string>();
672
+ const seenGroups = /* @__PURE__ */ new Set();
1106
673
  for (const { name } of elementToGroup.values()) {
1107
674
  if (!seenGroups.has(name)) {
1108
675
  seenGroups.add(name);
1109
- g.setNode('__group_' + name, {});
676
+ g.setNode("__group_" + name, {});
1110
677
  }
1111
678
  }
1112
679
  }
1113
-
1114
- // Add container nodes
1115
- const nameToElement = new Map<string, C4Element>();
680
+ const nameToElement = /* @__PURE__ */ new Map();
1116
681
  for (const el of containers) {
1117
682
  nameToElement.set(el.name, el);
1118
683
  const dims = computeC4NodeDimensions(el, { showTechnology: true });
1119
684
  g.setNode(el.name, { width: dims.width, height: dims.height });
1120
- // Set group parent
1121
685
  const grp = elementToGroup.get(el.name);
1122
686
  if (grp) {
1123
- g.setParent(el.name, '__group_' + grp.name);
687
+ g.setParent(el.name, "__group_" + grp.name);
1124
688
  }
1125
689
  }
1126
-
1127
- // Add external nodes
1128
690
  for (const el of externals) {
1129
691
  nameToElement.set(el.name, el);
1130
692
  const dims = computeC4NodeDimensions(el);
1131
693
  g.setNode(el.name, { width: dims.width, height: dims.height });
1132
694
  }
1133
-
1134
- // Collect container-level relationships (not rolled up)
1135
- interface ContainerRel {
1136
- sourceName: string;
1137
- targetName: string;
1138
- label?: string;
1139
- technology?: string;
1140
- arrowType: C4ArrowType;
1141
- lineNumber: number;
1142
- }
1143
-
1144
- const containerRels: ContainerRel[] = [];
1145
- const seenEdgeKeys = new Set<string>();
1146
-
1147
- // Forward: container → target
695
+ const containerRels = [];
696
+ const seenEdgeKeys = /* @__PURE__ */ new Set();
1148
697
  for (const container of containers) {
1149
698
  for (const rel of container.relationships) {
1150
699
  const targetEl = nameToElement.get(rel.target);
1151
700
  if (!targetEl) continue;
1152
- const key = `${container.name}→${rel.target}`;
701
+ const key = `${container.name}\u2192${rel.target}`;
1153
702
  if (!seenEdgeKeys.has(key)) {
1154
703
  seenEdgeKeys.add(key);
1155
704
  containerRels.push({
1156
705
  sourceName: container.name,
1157
706
  targetName: rel.target,
1158
- ...(rel.label !== undefined && { label: rel.label }),
1159
- ...(rel.technology !== undefined && { technology: rel.technology }),
707
+ ...rel.label !== void 0 && { label: rel.label },
708
+ ...rel.technology !== void 0 && { technology: rel.technology },
1160
709
  arrowType: rel.arrowType,
1161
- lineNumber: rel.lineNumber,
710
+ lineNumber: rel.lineNumber
1162
711
  });
1163
712
  }
1164
713
  }
1165
714
  }
1166
-
1167
- // Reverse: external → container (find specific container-level relationships)
1168
715
  for (const { sourceName, rel } of allRels) {
1169
716
  const sourceAncestor = ownerMap.get(sourceName) ?? sourceName;
1170
717
  if (sourceAncestor.toLowerCase() === system.name.toLowerCase()) continue;
1171
718
  if (containerNames.has(rel.target.toLowerCase())) {
1172
719
  const externalEl = nameToElement.get(sourceAncestor);
1173
720
  if (!externalEl) continue;
1174
- const key = `${sourceAncestor}→${rel.target}`;
721
+ const key = `${sourceAncestor}\u2192${rel.target}`;
1175
722
  if (!seenEdgeKeys.has(key)) {
1176
723
  seenEdgeKeys.add(key);
1177
724
  containerRels.push({
1178
725
  sourceName: sourceAncestor,
1179
726
  targetName: rel.target,
1180
- ...(rel.label !== undefined && { label: rel.label }),
1181
- ...(rel.technology !== undefined && { technology: rel.technology }),
727
+ ...rel.label !== void 0 && { label: rel.label },
728
+ ...rel.technology !== void 0 && { technology: rel.technology },
1182
729
  arrowType: rel.arrowType,
1183
- lineNumber: rel.lineNumber,
730
+ lineNumber: rel.lineNumber
1184
731
  });
1185
732
  }
1186
733
  }
1187
734
  }
1188
-
1189
- // Compute adaptive spacing based on edge fan-out
1190
735
  const spacing = computeAdaptiveSpacing(containerRels);
1191
736
  g.setGraph({
1192
- rankdir: 'TB',
737
+ rankdir: "TB",
1193
738
  nodesep: spacing.nodesep,
1194
739
  ranksep: spacing.ranksep,
1195
- edgesep: spacing.edgesep,
740
+ edgesep: spacing.edgesep
1196
741
  });
1197
-
1198
- // Add edges to dagre
1199
742
  for (const rel of containerRels) {
1200
- if (
1201
- nameToElement.has(rel.sourceName) &&
1202
- nameToElement.has(rel.targetName)
1203
- ) {
1204
- g.setEdge(rel.sourceName, rel.targetName, { label: rel.label ?? '' });
743
+ if (nameToElement.has(rel.sourceName) && nameToElement.has(rel.targetName)) {
744
+ g.setEdge(rel.sourceName, rel.targetName, { label: rel.label ?? "" });
1205
745
  }
1206
746
  }
1207
-
1208
- // Run layout
1209
747
  dagre.layout(g);
1210
-
1211
- // Post-dagre crossing reduction (with group-aware partitioning)
1212
- const nodeGroupMap = hasGroups
1213
- ? new Map([...elementToGroup.entries()].map(([k, v]) => [k, v.name]))
1214
- : undefined;
748
+ const nodeGroupMap = hasGroups ? new Map([...elementToGroup.entries()].map(([k, v]) => [k, v.name])) : void 0;
1215
749
  reduceCrossings(
1216
750
  g,
1217
- containerRels
1218
- .filter(
1219
- (r) =>
1220
- nameToElement.has(r.sourceName) && nameToElement.has(r.targetName)
1221
- )
1222
- .map((r) => ({ source: r.sourceName, target: r.targetName })),
751
+ containerRels.filter(
752
+ (r) => nameToElement.has(r.sourceName) && nameToElement.has(r.targetName)
753
+ ).map((r) => ({ source: r.sourceName, target: r.targetName })),
1223
754
  nodeGroupMap
1224
755
  );
1225
-
1226
- // Extract positioned nodes
1227
- const nodes: Writable<C4LayoutNode>[] = [];
756
+ const nodes = [];
1228
757
  for (const el of containers) {
1229
758
  const pos = g.node(el.name);
1230
759
  const color = resolveNodeColor(
@@ -1232,31 +761,28 @@ export function layoutC4Containers(
1232
761
  parsed.tagGroups,
1233
762
  activeTagGroup ?? null
1234
763
  );
1235
- const tech = el.metadata['tech'] ?? el.metadata['technology'];
1236
- const hasComponents =
1237
- el.children.some((c) => c.type === 'component') ||
1238
- el.groups.some((grp) => grp.children.some((c) => c.type === 'component'));
1239
- const description = el.description?.join('\n');
1240
- const drillable = hasComponents || el.importPath ? true : undefined;
764
+ const tech = el.metadata["tech"] ?? el.metadata["technology"];
765
+ const hasComponents = el.children.some((c) => c.type === "component") || el.groups.some((grp) => grp.children.some((c) => c.type === "component"));
766
+ const description = el.description?.join("\n");
767
+ const drillable = hasComponents || el.importPath ? true : void 0;
1241
768
  nodes.push({
1242
769
  id: el.name,
1243
770
  name: el.name,
1244
- type: 'container',
1245
- ...(description !== undefined && { description }),
771
+ type: "container",
772
+ ...description !== void 0 && { description },
1246
773
  metadata: el.metadata,
1247
774
  lineNumber: el.lineNumber,
1248
- ...(color !== undefined && { color }),
775
+ ...color !== void 0 && { color },
1249
776
  shape: el.shape,
1250
- ...(tech !== undefined && { technology: tech }),
1251
- ...(drillable !== undefined && { drillable }),
1252
- ...(el.importPath !== undefined && { importPath: el.importPath }),
777
+ ...tech !== void 0 && { technology: tech },
778
+ ...drillable !== void 0 && { drillable },
779
+ ...el.importPath !== void 0 && { importPath: el.importPath },
1253
780
  x: pos.x,
1254
781
  y: pos.y,
1255
782
  width: pos.width,
1256
- height: pos.height,
783
+ height: pos.height
1257
784
  });
1258
785
  }
1259
-
1260
786
  for (const el of externals) {
1261
787
  const pos = g.node(el.name);
1262
788
  const color = resolveNodeColor(
@@ -1264,47 +790,37 @@ export function layoutC4Containers(
1264
790
  parsed.tagGroups,
1265
791
  activeTagGroup ?? null
1266
792
  );
1267
- const description = el.description?.join('\n');
793
+ const description = el.description?.join("\n");
1268
794
  nodes.push({
1269
795
  id: el.name,
1270
796
  name: el.name,
1271
- type: el.type as 'person' | 'system',
1272
- ...(description !== undefined && { description }),
797
+ type: el.type,
798
+ ...description !== void 0 && { description },
1273
799
  metadata: el.metadata,
1274
800
  lineNumber: el.lineNumber,
1275
- ...(color !== undefined && { color }),
801
+ ...color !== void 0 && { color },
1276
802
  x: pos.x,
1277
803
  y: pos.y,
1278
804
  width: pos.width,
1279
- height: pos.height,
805
+ height: pos.height
1280
806
  });
1281
807
  }
1282
-
1283
- // Extract edges
1284
- const edges: MutableC4LayoutEdge[] = containerRels
1285
- .filter(
1286
- (rel) =>
1287
- nameToElement.has(rel.sourceName) && nameToElement.has(rel.targetName)
1288
- )
1289
- .map((rel): MutableC4LayoutEdge => {
1290
- const edgeData = g.edge(rel.sourceName, rel.targetName);
1291
- return {
1292
- source: rel.sourceName,
1293
- target: rel.targetName,
1294
- arrowType: rel.arrowType,
1295
- ...(rel.label !== undefined && { label: rel.label }),
1296
- ...(rel.technology !== undefined && { technology: rel.technology }),
1297
- lineNumber: rel.lineNumber,
1298
- points: edgeData?.points ?? [],
1299
- };
1300
- });
1301
-
1302
- // Compute boundary box from container nodes only
1303
- const containerNodes = nodes.filter((n) => n.type === 'container');
1304
- let bMinX = Infinity,
1305
- bMinY = Infinity,
1306
- bMaxX = -Infinity,
1307
- bMaxY = -Infinity;
808
+ const edges = containerRels.filter(
809
+ (rel) => nameToElement.has(rel.sourceName) && nameToElement.has(rel.targetName)
810
+ ).map((rel) => {
811
+ const edgeData = g.edge(rel.sourceName, rel.targetName);
812
+ return {
813
+ source: rel.sourceName,
814
+ target: rel.targetName,
815
+ arrowType: rel.arrowType,
816
+ ...rel.label !== void 0 && { label: rel.label },
817
+ ...rel.technology !== void 0 && { technology: rel.technology },
818
+ lineNumber: rel.lineNumber,
819
+ points: edgeData?.points ?? []
820
+ };
821
+ });
822
+ const containerNodes = nodes.filter((n) => n.type === "container");
823
+ let bMinX = Infinity, bMinY = Infinity, bMaxX = -Infinity, bMaxY = -Infinity;
1308
824
  for (const n of containerNodes) {
1309
825
  const left = n.x - n.width / 2;
1310
826
  const top = n.y - n.height / 2;
@@ -1315,39 +831,30 @@ export function layoutC4Containers(
1315
831
  if (right > bMaxX) bMaxX = right;
1316
832
  if (bottom > bMaxY) bMaxY = bottom;
1317
833
  }
1318
-
1319
- const boundary: Writable<C4LayoutBoundary> = {
834
+ const boundary = {
1320
835
  label: system.name,
1321
- typeLabel: 'system',
836
+ typeLabel: "system",
1322
837
  lineNumber: system.lineNumber,
1323
838
  x: bMinX - BOUNDARY_PAD,
1324
839
  y: bMinY - BOUNDARY_PAD,
1325
840
  width: bMaxX - bMinX + BOUNDARY_PAD * 2,
1326
- height: bMaxY - bMinY + BOUNDARY_PAD * 2,
841
+ height: bMaxY - bMinY + BOUNDARY_PAD * 2
1327
842
  };
1328
-
1329
- // Compute group boundaries from member node positions
1330
- const groupBoundaries: Writable<C4LayoutBoundary>[] = [];
843
+ const groupBoundaries = [];
1331
844
  if (hasGroups) {
1332
845
  const nodeMap = new Map(containerNodes.map((n) => [n.name, n]));
1333
- const seenGroups = new Map<
1334
- string,
1335
- { lineNumber: number; members: Writable<C4LayoutNode>[] }
1336
- >();
846
+ const seenGroups = /* @__PURE__ */ new Map();
1337
847
  for (const [elName, grp] of elementToGroup) {
1338
848
  const node = nodeMap.get(elName);
1339
849
  if (!node) continue;
1340
850
  if (!seenGroups.has(grp.name)) {
1341
851
  seenGroups.set(grp.name, { lineNumber: grp.lineNumber, members: [] });
1342
852
  }
1343
- seenGroups.get(grp.name)!.members.push(node);
853
+ seenGroups.get(grp.name).members.push(node);
1344
854
  }
1345
855
  for (const [groupName, { lineNumber, members }] of seenGroups) {
1346
856
  if (members.length === 0) continue;
1347
- let gMinX = Infinity,
1348
- gMinY = Infinity,
1349
- gMaxX = -Infinity,
1350
- gMaxY = -Infinity;
857
+ let gMinX = Infinity, gMinY = Infinity, gMaxX = -Infinity, gMaxY = -Infinity;
1351
858
  for (const m of members) {
1352
859
  const left = m.x - m.width / 2;
1353
860
  const top = m.y - m.height / 2;
@@ -1360,21 +867,16 @@ export function layoutC4Containers(
1360
867
  }
1361
868
  groupBoundaries.push({
1362
869
  label: groupName,
1363
- typeLabel: 'group',
870
+ typeLabel: "group",
1364
871
  lineNumber,
1365
872
  x: gMinX - GROUP_BOUNDARY_PAD,
1366
873
  y: gMinY - GROUP_BOUNDARY_PAD,
1367
874
  width: gMaxX - gMinX + GROUP_BOUNDARY_PAD * 2,
1368
- height: gMaxY - gMinY + GROUP_BOUNDARY_PAD * 2,
875
+ height: gMaxY - gMinY + GROUP_BOUNDARY_PAD * 2
1369
876
  });
1370
877
  }
1371
878
  }
1372
-
1373
- // Compute bounding box of all content (nodes + boundary + group boundaries + edge points)
1374
- let minX = Infinity,
1375
- minY = Infinity,
1376
- maxX = -Infinity,
1377
- maxY = -Infinity;
879
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
1378
880
  for (const node of nodes) {
1379
881
  const left = node.x - node.width / 2;
1380
882
  const top = node.y - node.height / 2;
@@ -1403,8 +905,6 @@ export function layoutC4Containers(
1403
905
  if (pt.y > maxY) maxY = pt.y;
1404
906
  }
1405
907
  }
1406
-
1407
- // Shift everything so content starts at (MARGIN, MARGIN)
1408
908
  const shiftX = MARGIN - minX;
1409
909
  const shiftY = MARGIN - minY;
1410
910
  for (const node of nodes) {
@@ -1423,13 +923,9 @@ export function layoutC4Containers(
1423
923
  pt.y += shiftY;
1424
924
  }
1425
925
  }
1426
-
1427
926
  let totalWidth = maxX - minX + MARGIN * 2;
1428
927
  let totalHeight = maxY - minY + MARGIN * 2;
1429
-
1430
928
  const legendGroups = computeLegendGroups(parsed.tagGroups);
1431
-
1432
- // Position legend below diagram
1433
929
  if (legendGroups.length > 0) {
1434
930
  const legendY = totalHeight + MARGIN;
1435
931
  let legendX = MARGIN;
@@ -1443,7 +939,6 @@ export function layoutC4Containers(
1443
939
  if (legendRight > totalWidth) totalWidth = legendRight;
1444
940
  if (legendBottom > totalHeight) totalHeight = legendBottom;
1445
941
  }
1446
-
1447
942
  return {
1448
943
  nodes,
1449
944
  edges,
@@ -1451,25 +946,10 @@ export function layoutC4Containers(
1451
946
  boundary,
1452
947
  groupBoundaries,
1453
948
  width: totalWidth,
1454
- height: totalHeight,
949
+ height: totalHeight
1455
950
  };
1456
951
  }
1457
-
1458
- // ============================================================
1459
- // Component-Level Layout
1460
- // ============================================================
1461
-
1462
- /**
1463
- * Layout components within a specific container, plus external elements
1464
- * that have relationships with those components.
1465
- */
1466
- export function layoutC4Components(
1467
- parsed: ParsedC4,
1468
- systemName: string,
1469
- containerName: string,
1470
- activeTagGroup?: string | null
1471
- ): C4LayoutResult {
1472
- // Find the system element by name
952
+ function layoutC4Components(parsed, systemName, containerName, activeTagGroup) {
1473
953
  const system = parsed.elements.find(
1474
954
  (el) => el.name.toLowerCase() === systemName.toLowerCase()
1475
955
  );
@@ -1480,17 +960,12 @@ export function layoutC4Components(
1480
960
  legend: [],
1481
961
  groupBoundaries: [],
1482
962
  width: 0,
1483
- height: 0,
963
+ height: 0
1484
964
  };
1485
965
  }
1486
-
1487
- // Find the container within the system (direct children + group children)
1488
- let targetContainer: C4Element | undefined;
966
+ let targetContainer;
1489
967
  for (const child of system.children) {
1490
- if (
1491
- child.type === 'container' &&
1492
- child.name.toLowerCase() === containerName.toLowerCase()
1493
- ) {
968
+ if (child.type === "container" && child.name.toLowerCase() === containerName.toLowerCase()) {
1494
969
  targetContainer = child;
1495
970
  break;
1496
971
  }
@@ -1498,10 +973,7 @@ export function layoutC4Components(
1498
973
  if (!targetContainer) {
1499
974
  for (const group of system.groups) {
1500
975
  for (const child of group.children) {
1501
- if (
1502
- child.type === 'container' &&
1503
- child.name.toLowerCase() === containerName.toLowerCase()
1504
- ) {
976
+ if (child.type === "container" && child.name.toLowerCase() === containerName.toLowerCase()) {
1505
977
  targetContainer = child;
1506
978
  break;
1507
979
  }
@@ -1516,21 +988,18 @@ export function layoutC4Components(
1516
988
  legend: [],
1517
989
  groupBoundaries: [],
1518
990
  width: 0,
1519
- height: 0,
991
+ height: 0
1520
992
  };
1521
993
  }
1522
-
1523
- // Collect all components: direct children + group children
1524
- const components: C4Element[] = [];
994
+ const components = [];
1525
995
  for (const child of targetContainer.children) {
1526
- if (child.type === 'component') components.push(child);
996
+ if (child.type === "component") components.push(child);
1527
997
  }
1528
998
  for (const group of targetContainer.groups) {
1529
999
  for (const child of group.children) {
1530
- if (child.type === 'component') components.push(child);
1000
+ if (child.type === "component") components.push(child);
1531
1001
  }
1532
1002
  }
1533
-
1534
1003
  if (components.length === 0) {
1535
1004
  return {
1536
1005
  nodes: [],
@@ -1538,36 +1007,27 @@ export function layoutC4Components(
1538
1007
  legend: [],
1539
1008
  groupBoundaries: [],
1540
1009
  width: 0,
1541
- height: 0,
1010
+ height: 0
1542
1011
  };
1543
1012
  }
1544
-
1545
1013
  const componentNames = new Set(components.map((c) => c.name.toLowerCase()));
1546
-
1547
- // Build name → element map for all top-level elements and containers in this system
1548
- const topElementsByName = new Map<string, C4Element>();
1014
+ const topElementsByName = /* @__PURE__ */ new Map();
1549
1015
  for (const el of parsed.elements) {
1550
1016
  topElementsByName.set(el.name.toLowerCase(), el);
1551
- // Also index containers in every system for external container resolution
1552
1017
  for (const child of el.children) {
1553
- if (child.type === 'container') {
1018
+ if (child.type === "container") {
1554
1019
  topElementsByName.set(child.name.toLowerCase(), child);
1555
1020
  }
1556
1021
  }
1557
1022
  for (const group of el.groups) {
1558
1023
  for (const child of group.children) {
1559
- if (child.type === 'container') {
1024
+ if (child.type === "container") {
1560
1025
  topElementsByName.set(child.name.toLowerCase(), child);
1561
1026
  }
1562
1027
  }
1563
1028
  }
1564
1029
  }
1565
-
1566
- // Identify external elements: targets of component relationships not in this container,
1567
- // or elements whose relationships target components in this container
1568
- const externalNames = new Set<string>();
1569
-
1570
- // Forward: component → target outside this container
1030
+ const externalNames = /* @__PURE__ */ new Set();
1571
1031
  for (const component of components) {
1572
1032
  for (const rel of component.relationships) {
1573
1033
  const targetLower = rel.target.toLowerCase();
@@ -1576,23 +1036,15 @@ export function layoutC4Components(
1576
1036
  }
1577
1037
  }
1578
1038
  }
1579
-
1580
- // Reverse: any element that targets a component in this container
1581
1039
  const ownerMap = buildOwnershipMap(parsed.elements);
1582
1040
  const allRels = collectAllRelationships(parsed.elements, ownerMap);
1583
1041
  for (const { sourceName, rel } of allRels) {
1584
- // Skip relationships from within this container
1585
1042
  if (componentNames.has(sourceName.toLowerCase())) continue;
1586
- // Check if target is a component in this container
1587
1043
  if (componentNames.has(rel.target.toLowerCase())) {
1588
- // Resolve to the most specific known element: if source is a container, use it;
1589
- // otherwise roll up to system ancestor
1590
1044
  const sourceAncestor = ownerMap.get(sourceName) ?? sourceName;
1591
- // If source is inside the same container, skip
1592
1045
  if (sourceAncestor.toLowerCase() === targetContainer.name.toLowerCase())
1593
1046
  continue;
1594
1047
  if (sourceAncestor.toLowerCase() === system.name.toLowerCase()) {
1595
- // Source is in same system — try to resolve to container level
1596
1048
  const sourceLower = sourceName.toLowerCase();
1597
1049
  if (topElementsByName.has(sourceLower)) {
1598
1050
  externalNames.add(sourceLower);
@@ -1604,175 +1056,118 @@ export function layoutC4Components(
1604
1056
  }
1605
1057
  }
1606
1058
  }
1607
-
1608
- // Resolve external elements
1609
- const externals: C4Element[] = [];
1059
+ const externals = [];
1610
1060
  for (const name of externalNames) {
1611
1061
  const el = topElementsByName.get(name);
1612
1062
  if (el) externals.push(el);
1613
1063
  }
1614
-
1615
- // Build element-to-group mapping for compound graph
1616
- const elementToGroup = new Map<
1617
- string,
1618
- { name: string; lineNumber: number }
1619
- >();
1064
+ const elementToGroup = /* @__PURE__ */ new Map();
1620
1065
  for (const group of targetContainer.groups) {
1621
1066
  for (const child of group.children) {
1622
- if (child.type === 'component') {
1067
+ if (child.type === "component") {
1623
1068
  elementToGroup.set(child.name, {
1624
1069
  name: group.name,
1625
- lineNumber: group.lineNumber,
1070
+ lineNumber: group.lineNumber
1626
1071
  });
1627
1072
  }
1628
1073
  }
1629
1074
  }
1630
1075
  const hasGroups = elementToGroup.size > 0;
1631
-
1632
- // Create dagre graph — use compound when groups exist
1633
- const g = hasGroups
1634
- ? new dagre.graphlib.Graph({ compound: true })
1635
- : new dagre.graphlib.Graph();
1076
+ const g = hasGroups ? new dagre.graphlib.Graph({ compound: true }) : new dagre.graphlib.Graph();
1636
1077
  g.setDefaultEdgeLabel(() => ({}));
1637
-
1638
- // Add virtual group parent nodes
1639
1078
  if (hasGroups) {
1640
- const seenGroups = new Set<string>();
1079
+ const seenGroups = /* @__PURE__ */ new Set();
1641
1080
  for (const { name } of elementToGroup.values()) {
1642
1081
  if (!seenGroups.has(name)) {
1643
1082
  seenGroups.add(name);
1644
- g.setNode('__group_' + name, {});
1083
+ g.setNode("__group_" + name, {});
1645
1084
  }
1646
1085
  }
1647
1086
  }
1648
-
1649
- // Add component nodes
1650
- const nameToElement = new Map<string, C4Element>();
1087
+ const nameToElement = /* @__PURE__ */ new Map();
1651
1088
  for (const el of components) {
1652
1089
  nameToElement.set(el.name, el);
1653
1090
  const dims = computeC4NodeDimensions(el, { showTechnology: true });
1654
1091
  g.setNode(el.name, { width: dims.width, height: dims.height });
1655
- // Set group parent
1656
1092
  const grp = elementToGroup.get(el.name);
1657
1093
  if (grp) {
1658
- g.setParent(el.name, '__group_' + grp.name);
1094
+ g.setParent(el.name, "__group_" + grp.name);
1659
1095
  }
1660
1096
  }
1661
-
1662
- // Add external nodes
1663
1097
  for (const el of externals) {
1664
1098
  nameToElement.set(el.name, el);
1665
1099
  const dims = computeC4NodeDimensions(el);
1666
1100
  g.setNode(el.name, { width: dims.width, height: dims.height });
1667
1101
  }
1668
-
1669
- // Collect component-level relationships
1670
- interface ComponentRel {
1671
- sourceName: string;
1672
- targetName: string;
1673
- label?: string;
1674
- technology?: string;
1675
- arrowType: C4ArrowType;
1676
- lineNumber: number;
1677
- }
1678
-
1679
- const componentRels: ComponentRel[] = [];
1680
- const seenEdgeKeys = new Set<string>();
1681
-
1682
- // Forward: component → target
1102
+ const componentRels = [];
1103
+ const seenEdgeKeys = /* @__PURE__ */ new Set();
1683
1104
  for (const component of components) {
1684
1105
  for (const rel of component.relationships) {
1685
1106
  const targetEl = nameToElement.get(rel.target);
1686
1107
  if (!targetEl) continue;
1687
- const key = `${component.name}→${rel.target}`;
1108
+ const key = `${component.name}\u2192${rel.target}`;
1688
1109
  if (!seenEdgeKeys.has(key)) {
1689
1110
  seenEdgeKeys.add(key);
1690
1111
  componentRels.push({
1691
1112
  sourceName: component.name,
1692
1113
  targetName: rel.target,
1693
- ...(rel.label !== undefined && { label: rel.label }),
1694
- ...(rel.technology !== undefined && { technology: rel.technology }),
1114
+ ...rel.label !== void 0 && { label: rel.label },
1115
+ ...rel.technology !== void 0 && { technology: rel.technology },
1695
1116
  arrowType: rel.arrowType,
1696
- lineNumber: rel.lineNumber,
1117
+ lineNumber: rel.lineNumber
1697
1118
  });
1698
1119
  }
1699
1120
  }
1700
1121
  }
1701
-
1702
- // Reverse: external → component
1703
1122
  for (const { sourceName, rel } of allRels) {
1704
1123
  if (componentNames.has(sourceName.toLowerCase())) continue;
1705
1124
  if (!componentNames.has(rel.target.toLowerCase())) continue;
1706
-
1707
1125
  const sourceAncestor = ownerMap.get(sourceName) ?? sourceName;
1708
1126
  if (sourceAncestor.toLowerCase() === targetContainer.name.toLowerCase())
1709
1127
  continue;
1710
-
1711
- // Resolve source to the external element we added
1712
- let resolvedSource: string | undefined;
1128
+ let resolvedSource;
1713
1129
  if (nameToElement.has(sourceName)) {
1714
1130
  resolvedSource = sourceName;
1715
1131
  } else if (nameToElement.has(sourceAncestor)) {
1716
1132
  resolvedSource = sourceAncestor;
1717
1133
  }
1718
1134
  if (!resolvedSource) continue;
1719
-
1720
- const key = `${resolvedSource}→${rel.target}`;
1135
+ const key = `${resolvedSource}\u2192${rel.target}`;
1721
1136
  if (!seenEdgeKeys.has(key)) {
1722
1137
  seenEdgeKeys.add(key);
1723
1138
  componentRels.push({
1724
1139
  sourceName: resolvedSource,
1725
1140
  targetName: rel.target,
1726
- ...(rel.label !== undefined && { label: rel.label }),
1727
- ...(rel.technology !== undefined && { technology: rel.technology }),
1141
+ ...rel.label !== void 0 && { label: rel.label },
1142
+ ...rel.technology !== void 0 && { technology: rel.technology },
1728
1143
  arrowType: rel.arrowType,
1729
- lineNumber: rel.lineNumber,
1144
+ lineNumber: rel.lineNumber
1730
1145
  });
1731
1146
  }
1732
1147
  }
1733
-
1734
- // Compute adaptive spacing based on edge fan-out
1735
1148
  const spacing = computeAdaptiveSpacing(componentRels);
1736
1149
  g.setGraph({
1737
- rankdir: 'TB',
1150
+ rankdir: "TB",
1738
1151
  nodesep: spacing.nodesep,
1739
1152
  ranksep: spacing.ranksep,
1740
- edgesep: spacing.edgesep,
1153
+ edgesep: spacing.edgesep
1741
1154
  });
1742
-
1743
- // Add edges to dagre
1744
1155
  for (const rel of componentRels) {
1745
- if (
1746
- nameToElement.has(rel.sourceName) &&
1747
- nameToElement.has(rel.targetName)
1748
- ) {
1749
- g.setEdge(rel.sourceName, rel.targetName, { label: rel.label ?? '' });
1156
+ if (nameToElement.has(rel.sourceName) && nameToElement.has(rel.targetName)) {
1157
+ g.setEdge(rel.sourceName, rel.targetName, { label: rel.label ?? "" });
1750
1158
  }
1751
1159
  }
1752
-
1753
- // Run layout
1754
1160
  dagre.layout(g);
1755
-
1756
- // Post-dagre crossing reduction (with group-aware partitioning)
1757
- const nodeGroupMap = hasGroups
1758
- ? new Map([...elementToGroup.entries()].map(([k, v]) => [k, v.name]))
1759
- : undefined;
1161
+ const nodeGroupMap = hasGroups ? new Map([...elementToGroup.entries()].map(([k, v]) => [k, v.name])) : void 0;
1760
1162
  reduceCrossings(
1761
1163
  g,
1762
- componentRels
1763
- .filter(
1764
- (r) =>
1765
- nameToElement.has(r.sourceName) && nameToElement.has(r.targetName)
1766
- )
1767
- .map((r) => ({ source: r.sourceName, target: r.targetName })),
1164
+ componentRels.filter(
1165
+ (r) => nameToElement.has(r.sourceName) && nameToElement.has(r.targetName)
1166
+ ).map((r) => ({ source: r.sourceName, target: r.targetName })),
1768
1167
  nodeGroupMap
1769
1168
  );
1770
-
1771
- // Tag inheritance ancestors: container → system
1772
1169
  const ancestors = [targetContainer, system];
1773
-
1774
- // Extract positioned nodes
1775
- const nodes: Writable<C4LayoutNode>[] = [];
1170
+ const nodes = [];
1776
1171
  for (const el of components) {
1777
1172
  const pos = g.node(el.name);
1778
1173
  const color = resolveNodeColor(
@@ -1781,31 +1176,28 @@ export function layoutC4Components(
1781
1176
  activeTagGroup ?? null,
1782
1177
  ancestors
1783
1178
  );
1784
- const tech = el.metadata['tech'] ?? el.metadata['technology'];
1785
- const hasComponents =
1786
- el.children.some((c) => c.type === 'component') ||
1787
- el.groups.some((grp) => grp.children.some((c) => c.type === 'component'));
1788
- const description = el.description?.join('\n');
1789
- const drillable = hasComponents || el.importPath ? true : undefined;
1179
+ const tech = el.metadata["tech"] ?? el.metadata["technology"];
1180
+ const hasComponents = el.children.some((c) => c.type === "component") || el.groups.some((grp) => grp.children.some((c) => c.type === "component"));
1181
+ const description = el.description?.join("\n");
1182
+ const drillable = hasComponents || el.importPath ? true : void 0;
1790
1183
  nodes.push({
1791
1184
  id: el.name,
1792
1185
  name: el.name,
1793
- type: 'component',
1794
- ...(description !== undefined && { description }),
1186
+ type: "component",
1187
+ ...description !== void 0 && { description },
1795
1188
  metadata: el.metadata,
1796
1189
  lineNumber: el.lineNumber,
1797
- ...(color !== undefined && { color }),
1190
+ ...color !== void 0 && { color },
1798
1191
  shape: el.shape,
1799
- ...(tech !== undefined && { technology: tech }),
1800
- ...(drillable !== undefined && { drillable }),
1801
- ...(el.importPath !== undefined && { importPath: el.importPath }),
1192
+ ...tech !== void 0 && { technology: tech },
1193
+ ...drillable !== void 0 && { drillable },
1194
+ ...el.importPath !== void 0 && { importPath: el.importPath },
1802
1195
  x: pos.x,
1803
1196
  y: pos.y,
1804
1197
  width: pos.width,
1805
- height: pos.height,
1198
+ height: pos.height
1806
1199
  });
1807
1200
  }
1808
-
1809
1201
  for (const el of externals) {
1810
1202
  const pos = g.node(el.name);
1811
1203
  const color = resolveNodeColor(
@@ -1813,47 +1205,37 @@ export function layoutC4Components(
1813
1205
  parsed.tagGroups,
1814
1206
  activeTagGroup ?? null
1815
1207
  );
1816
- const description = el.description?.join('\n');
1208
+ const description = el.description?.join("\n");
1817
1209
  nodes.push({
1818
1210
  id: el.name,
1819
1211
  name: el.name,
1820
- type: el.type as 'person' | 'system' | 'container',
1821
- ...(description !== undefined && { description }),
1212
+ type: el.type,
1213
+ ...description !== void 0 && { description },
1822
1214
  metadata: el.metadata,
1823
1215
  lineNumber: el.lineNumber,
1824
- ...(color !== undefined && { color }),
1216
+ ...color !== void 0 && { color },
1825
1217
  x: pos.x,
1826
1218
  y: pos.y,
1827
1219
  width: pos.width,
1828
- height: pos.height,
1220
+ height: pos.height
1829
1221
  });
1830
1222
  }
1831
-
1832
- // Extract edges
1833
- const edges: MutableC4LayoutEdge[] = componentRels
1834
- .filter(
1835
- (rel) =>
1836
- nameToElement.has(rel.sourceName) && nameToElement.has(rel.targetName)
1837
- )
1838
- .map((rel): MutableC4LayoutEdge => {
1839
- const edgeData = g.edge(rel.sourceName, rel.targetName);
1840
- return {
1841
- source: rel.sourceName,
1842
- target: rel.targetName,
1843
- arrowType: rel.arrowType,
1844
- ...(rel.label !== undefined && { label: rel.label }),
1845
- ...(rel.technology !== undefined && { technology: rel.technology }),
1846
- lineNumber: rel.lineNumber,
1847
- points: edgeData?.points ?? [],
1848
- };
1849
- });
1850
-
1851
- // Compute boundary box from component nodes only
1852
- const componentNodes = nodes.filter((n) => n.type === 'component');
1853
- let bMinX = Infinity,
1854
- bMinY = Infinity,
1855
- bMaxX = -Infinity,
1856
- bMaxY = -Infinity;
1223
+ const edges = componentRels.filter(
1224
+ (rel) => nameToElement.has(rel.sourceName) && nameToElement.has(rel.targetName)
1225
+ ).map((rel) => {
1226
+ const edgeData = g.edge(rel.sourceName, rel.targetName);
1227
+ return {
1228
+ source: rel.sourceName,
1229
+ target: rel.targetName,
1230
+ arrowType: rel.arrowType,
1231
+ ...rel.label !== void 0 && { label: rel.label },
1232
+ ...rel.technology !== void 0 && { technology: rel.technology },
1233
+ lineNumber: rel.lineNumber,
1234
+ points: edgeData?.points ?? []
1235
+ };
1236
+ });
1237
+ const componentNodes = nodes.filter((n) => n.type === "component");
1238
+ let bMinX = Infinity, bMinY = Infinity, bMaxX = -Infinity, bMaxY = -Infinity;
1857
1239
  for (const n of componentNodes) {
1858
1240
  const left = n.x - n.width / 2;
1859
1241
  const top = n.y - n.height / 2;
@@ -1864,39 +1246,30 @@ export function layoutC4Components(
1864
1246
  if (right > bMaxX) bMaxX = right;
1865
1247
  if (bottom > bMaxY) bMaxY = bottom;
1866
1248
  }
1867
-
1868
- const boundary: Writable<C4LayoutBoundary> = {
1249
+ const boundary = {
1869
1250
  label: targetContainer.name,
1870
- typeLabel: 'container',
1251
+ typeLabel: "container",
1871
1252
  lineNumber: targetContainer.lineNumber,
1872
1253
  x: bMinX - BOUNDARY_PAD,
1873
1254
  y: bMinY - BOUNDARY_PAD,
1874
1255
  width: bMaxX - bMinX + BOUNDARY_PAD * 2,
1875
- height: bMaxY - bMinY + BOUNDARY_PAD * 2,
1256
+ height: bMaxY - bMinY + BOUNDARY_PAD * 2
1876
1257
  };
1877
-
1878
- // Compute group boundaries from member node positions
1879
- const groupBoundaries: Writable<C4LayoutBoundary>[] = [];
1258
+ const groupBoundaries = [];
1880
1259
  if (hasGroups) {
1881
1260
  const nodeMap = new Map(componentNodes.map((n) => [n.name, n]));
1882
- const seenGroups = new Map<
1883
- string,
1884
- { lineNumber: number; members: Writable<C4LayoutNode>[] }
1885
- >();
1261
+ const seenGroups = /* @__PURE__ */ new Map();
1886
1262
  for (const [elName, grp] of elementToGroup) {
1887
1263
  const node = nodeMap.get(elName);
1888
1264
  if (!node) continue;
1889
1265
  if (!seenGroups.has(grp.name)) {
1890
1266
  seenGroups.set(grp.name, { lineNumber: grp.lineNumber, members: [] });
1891
1267
  }
1892
- seenGroups.get(grp.name)!.members.push(node);
1268
+ seenGroups.get(grp.name).members.push(node);
1893
1269
  }
1894
1270
  for (const [groupName, { lineNumber, members }] of seenGroups) {
1895
1271
  if (members.length === 0) continue;
1896
- let gMinX = Infinity,
1897
- gMinY = Infinity,
1898
- gMaxX = -Infinity,
1899
- gMaxY = -Infinity;
1272
+ let gMinX = Infinity, gMinY = Infinity, gMaxX = -Infinity, gMaxY = -Infinity;
1900
1273
  for (const m of members) {
1901
1274
  const left = m.x - m.width / 2;
1902
1275
  const top = m.y - m.height / 2;
@@ -1909,21 +1282,16 @@ export function layoutC4Components(
1909
1282
  }
1910
1283
  groupBoundaries.push({
1911
1284
  label: groupName,
1912
- typeLabel: 'group',
1285
+ typeLabel: "group",
1913
1286
  lineNumber,
1914
1287
  x: gMinX - GROUP_BOUNDARY_PAD,
1915
1288
  y: gMinY - GROUP_BOUNDARY_PAD,
1916
1289
  width: gMaxX - gMinX + GROUP_BOUNDARY_PAD * 2,
1917
- height: gMaxY - gMinY + GROUP_BOUNDARY_PAD * 2,
1290
+ height: gMaxY - gMinY + GROUP_BOUNDARY_PAD * 2
1918
1291
  });
1919
1292
  }
1920
1293
  }
1921
-
1922
- // Compute bounding box of all content (nodes + boundary + group boundaries + edge points)
1923
- let minX = Infinity,
1924
- minY = Infinity,
1925
- maxX = -Infinity,
1926
- maxY = -Infinity;
1294
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
1927
1295
  for (const node of nodes) {
1928
1296
  const left = node.x - node.width / 2;
1929
1297
  const top = node.y - node.height / 2;
@@ -1952,8 +1320,6 @@ export function layoutC4Components(
1952
1320
  if (pt.y > maxY) maxY = pt.y;
1953
1321
  }
1954
1322
  }
1955
-
1956
- // Shift everything so content starts at (MARGIN, MARGIN)
1957
1323
  const shiftX = MARGIN - minX;
1958
1324
  const shiftY = MARGIN - minY;
1959
1325
  for (const node of nodes) {
@@ -1972,13 +1338,9 @@ export function layoutC4Components(
1972
1338
  pt.y += shiftY;
1973
1339
  }
1974
1340
  }
1975
-
1976
1341
  let totalWidth = maxX - minX + MARGIN * 2;
1977
1342
  let totalHeight = maxY - minY + MARGIN * 2;
1978
-
1979
1343
  const legendGroups = computeLegendGroups(parsed.tagGroups);
1980
-
1981
- // Position legend below diagram
1982
1344
  if (legendGroups.length > 0) {
1983
1345
  const legendY = totalHeight + MARGIN;
1984
1346
  let legendX = MARGIN;
@@ -1992,7 +1354,6 @@ export function layoutC4Components(
1992
1354
  if (legendRight > totalWidth) totalWidth = legendRight;
1993
1355
  if (legendBottom > totalHeight) totalHeight = legendBottom;
1994
1356
  }
1995
-
1996
1357
  return {
1997
1358
  nodes,
1998
1359
  edges,
@@ -2000,63 +1361,30 @@ export function layoutC4Components(
2000
1361
  boundary,
2001
1362
  groupBoundaries,
2002
1363
  width: totalWidth,
2003
- height: totalHeight,
1364
+ height: totalHeight
2004
1365
  };
2005
1366
  }
2006
-
2007
- // ============================================================
2008
- // Deployment Diagram Layout
2009
- // ============================================================
2010
-
2011
- /**
2012
- * Resolve a container reference name to its C4Element by walking the parsed
2013
- * element tree. Matches container names case-insensitively.
2014
- */
2015
- function resolveContainerRef(
2016
- parsed: ParsedC4,
2017
- refName: string
2018
- ): C4Element | undefined {
1367
+ function resolveContainerRef(parsed, refName) {
2019
1368
  const lower = refName.toLowerCase();
2020
1369
  for (const el of parsed.elements) {
2021
1370
  for (const child of el.children) {
2022
- if (child.type === 'container' && child.name.toLowerCase() === lower)
1371
+ if (child.type === "container" && child.name.toLowerCase() === lower)
2023
1372
  return child;
2024
1373
  }
2025
1374
  for (const group of el.groups) {
2026
1375
  for (const child of group.children) {
2027
- if (child.type === 'container' && child.name.toLowerCase() === lower)
1376
+ if (child.type === "container" && child.name.toLowerCase() === lower)
2028
1377
  return child;
2029
1378
  }
2030
1379
  }
2031
1380
  }
2032
- return undefined;
1381
+ return void 0;
2033
1382
  }
2034
-
2035
- /**
2036
- * Collect all container ref nodes from the deployment tree, flattened with
2037
- * their parent infra node ID for compound graph assignment.
2038
- */
2039
- interface DeploymentRefEntry {
2040
- refName: string;
2041
- element: C4Element;
2042
- infraId: string;
2043
- /** Line number of the infra node containing this ref. */
2044
- deployLineNumber: number;
2045
- }
2046
-
2047
- function collectDeploymentRefs(
2048
- nodes: readonly C4DeploymentNode[],
2049
- parsed: ParsedC4,
2050
- parentId: string | null,
2051
- refs: DeploymentRefEntry[],
2052
- infraIds: Map<string, C4DeploymentNode>,
2053
- infraParents: Map<string, string | null>
2054
- ): void {
1383
+ function collectDeploymentRefs(nodes, parsed, parentId, refs, infraIds, infraParents) {
2055
1384
  for (const node of nodes) {
2056
1385
  const infraId = `__infra_${node.name}`;
2057
1386
  infraIds.set(infraId, node);
2058
1387
  infraParents.set(infraId, parentId);
2059
-
2060
1388
  for (const ref of node.containerRefs) {
2061
1389
  const el = resolveContainerRef(parsed, ref);
2062
1390
  if (el) {
@@ -2064,11 +1392,10 @@ function collectDeploymentRefs(
2064
1392
  refName: ref,
2065
1393
  element: el,
2066
1394
  infraId,
2067
- deployLineNumber: node.lineNumber,
1395
+ deployLineNumber: node.lineNumber
2068
1396
  });
2069
1397
  }
2070
1398
  }
2071
-
2072
1399
  collectDeploymentRefs(
2073
1400
  node.children,
2074
1401
  parsed,
@@ -2079,18 +1406,7 @@ function collectDeploymentRefs(
2079
1406
  );
2080
1407
  }
2081
1408
  }
2082
-
2083
- /**
2084
- * Layout a C4 deployment diagram.
2085
- *
2086
- * Infrastructure nodes become boundary boxes (nested).
2087
- * Container refs inside them become cards.
2088
- * Edges are drawn between referenced containers that have relationships.
2089
- */
2090
- export function layoutC4Deployment(
2091
- parsed: ParsedC4,
2092
- activeTagGroup?: string | null
2093
- ): C4LayoutResult {
1409
+ function layoutC4Deployment(parsed, activeTagGroup) {
2094
1410
  if (parsed.deployment.length === 0) {
2095
1411
  return {
2096
1412
  nodes: [],
@@ -2098,14 +1414,12 @@ export function layoutC4Deployment(
2098
1414
  legend: [],
2099
1415
  groupBoundaries: [],
2100
1416
  width: 0,
2101
- height: 0,
1417
+ height: 0
2102
1418
  };
2103
1419
  }
2104
-
2105
- // Collect all refs and infra node info
2106
- const refs: DeploymentRefEntry[] = [];
2107
- const infraIds = new Map<string, C4DeploymentNode>();
2108
- const infraParents = new Map<string, string | null>();
1420
+ const refs = [];
1421
+ const infraIds = /* @__PURE__ */ new Map();
1422
+ const infraParents = /* @__PURE__ */ new Map();
2109
1423
  collectDeploymentRefs(
2110
1424
  parsed.deployment,
2111
1425
  parsed,
@@ -2114,7 +1428,6 @@ export function layoutC4Deployment(
2114
1428
  infraIds,
2115
1429
  infraParents
2116
1430
  );
2117
-
2118
1431
  if (refs.length === 0) {
2119
1432
  return {
2120
1433
  nodes: [],
@@ -2122,56 +1435,34 @@ export function layoutC4Deployment(
2122
1435
  legend: [],
2123
1436
  groupBoundaries: [],
2124
1437
  width: 0,
2125
- height: 0,
1438
+ height: 0
2126
1439
  };
2127
1440
  }
2128
-
2129
- // Deduplicate refs by element name (a container can appear in multiple infra
2130
- // nodes — keep first occurrence). Track which container names are in scope.
2131
- const seenRefs = new Map<string, DeploymentRefEntry>();
1441
+ const seenRefs = /* @__PURE__ */ new Map();
2132
1442
  for (const ref of refs) {
2133
1443
  const key = ref.element.name.toLowerCase();
2134
1444
  if (!seenRefs.has(key)) seenRefs.set(key, ref);
2135
1445
  }
2136
1446
  const refEntries = [...seenRefs.values()];
2137
1447
  const refNames = new Set(refEntries.map((r) => r.element.name.toLowerCase()));
2138
-
2139
- // Build a name→element map for resolved containers
2140
- const nameToElement = new Map<string, C4Element>();
1448
+ const nameToElement = /* @__PURE__ */ new Map();
2141
1449
  for (const r of refEntries) {
2142
1450
  nameToElement.set(r.element.name, r.element);
2143
1451
  }
2144
-
2145
- // Build compound dagre graph: infra nodes as parents, container refs as leaf nodes
2146
1452
  const g = new dagre.graphlib.Graph({ compound: true });
2147
1453
  g.setDefaultEdgeLabel(() => ({}));
2148
-
2149
- // Add virtual parent nodes for each infra node
2150
1454
  for (const [infraId] of infraIds) {
2151
1455
  g.setNode(infraId, {});
2152
1456
  const parentId = infraParents.get(infraId);
2153
1457
  if (parentId) g.setParent(infraId, parentId);
2154
1458
  }
2155
-
2156
- // Add container ref nodes
2157
1459
  for (const r of refEntries) {
2158
1460
  const dims = computeC4NodeDimensions(r.element, { showTechnology: true });
2159
1461
  g.setNode(r.element.name, { width: dims.width, height: dims.height });
2160
1462
  g.setParent(r.element.name, r.infraId);
2161
1463
  }
2162
-
2163
- // Collect relationships between referenced containers
2164
- interface DeployRel {
2165
- sourceName: string;
2166
- targetName: string;
2167
- label?: string;
2168
- technology?: string;
2169
- arrowType: C4ArrowType;
2170
- lineNumber: number;
2171
- }
2172
- const deployRels: DeployRel[] = [];
2173
- const seenEdgeKeys = new Set<string>();
2174
-
1464
+ const deployRels = [];
1465
+ const seenEdgeKeys = /* @__PURE__ */ new Set();
2175
1466
  for (const r of refEntries) {
2176
1467
  for (const rel of r.element.relationships) {
2177
1468
  if (refNames.has(rel.target.toLowerCase())) {
@@ -2181,54 +1472,38 @@ export function layoutC4Deployment(
2181
1472
  deployRels.push({
2182
1473
  sourceName: r.element.name,
2183
1474
  targetName: rel.target,
2184
- ...(rel.label !== undefined && { label: rel.label }),
2185
- ...(rel.technology !== undefined && { technology: rel.technology }),
1475
+ ...rel.label !== void 0 && { label: rel.label },
1476
+ ...rel.technology !== void 0 && { technology: rel.technology },
2186
1477
  arrowType: rel.arrowType,
2187
- lineNumber: rel.lineNumber,
1478
+ lineNumber: rel.lineNumber
2188
1479
  });
2189
1480
  }
2190
1481
  }
2191
1482
  }
2192
1483
  }
2193
-
2194
- // Adaptive spacing and graph config
2195
1484
  const spacing = computeAdaptiveSpacing(deployRels);
2196
1485
  g.setGraph({
2197
- rankdir: 'TB',
1486
+ rankdir: "TB",
2198
1487
  nodesep: spacing.nodesep,
2199
1488
  ranksep: spacing.ranksep,
2200
- edgesep: spacing.edgesep,
1489
+ edgesep: spacing.edgesep
2201
1490
  });
2202
-
2203
- // Add edges to dagre
2204
1491
  for (const rel of deployRels) {
2205
- if (
2206
- nameToElement.has(rel.sourceName) &&
2207
- nameToElement.has(rel.targetName)
2208
- ) {
2209
- g.setEdge(rel.sourceName, rel.targetName, { label: rel.label ?? '' });
1492
+ if (nameToElement.has(rel.sourceName) && nameToElement.has(rel.targetName)) {
1493
+ g.setEdge(rel.sourceName, rel.targetName, { label: rel.label ?? "" });
2210
1494
  }
2211
1495
  }
2212
-
2213
- // Run layout
2214
1496
  dagre.layout(g);
2215
-
2216
- // Post-dagre crossing reduction
2217
- const nodeInfraMap = new Map<string, string>();
1497
+ const nodeInfraMap = /* @__PURE__ */ new Map();
2218
1498
  for (const r of refEntries) nodeInfraMap.set(r.element.name, r.infraId);
2219
1499
  reduceCrossings(
2220
1500
  g,
2221
- deployRels
2222
- .filter(
2223
- (r) =>
2224
- nameToElement.has(r.sourceName) && nameToElement.has(r.targetName)
2225
- )
2226
- .map((r) => ({ source: r.sourceName, target: r.targetName })),
1501
+ deployRels.filter(
1502
+ (r) => nameToElement.has(r.sourceName) && nameToElement.has(r.targetName)
1503
+ ).map((r) => ({ source: r.sourceName, target: r.targetName })),
2227
1504
  nodeInfraMap
2228
1505
  );
2229
-
2230
- // Extract positioned nodes
2231
- const nodes: Writable<C4LayoutNode>[] = [];
1506
+ const nodes = [];
2232
1507
  for (const r of refEntries) {
2233
1508
  const pos = g.node(r.element.name);
2234
1509
  const color = resolveNodeColor(
@@ -2236,75 +1511,52 @@ export function layoutC4Deployment(
2236
1511
  parsed.tagGroups,
2237
1512
  activeTagGroup ?? null
2238
1513
  );
2239
- const tech = r.element.metadata['tech'] ?? r.element.metadata['technology'];
2240
- const description = r.element.description?.join('\n');
1514
+ const tech = r.element.metadata["tech"] ?? r.element.metadata["technology"];
1515
+ const description = r.element.description?.join("\n");
2241
1516
  nodes.push({
2242
1517
  id: r.element.name,
2243
1518
  name: r.element.name,
2244
- type: 'container',
2245
- ...(description !== undefined && { description }),
1519
+ type: "container",
1520
+ ...description !== void 0 && { description },
2246
1521
  metadata: r.element.metadata,
2247
1522
  lineNumber: r.element.lineNumber,
2248
- ...(color !== undefined && { color }),
1523
+ ...color !== void 0 && { color },
2249
1524
  shape: r.element.shape,
2250
- ...(tech !== undefined && { technology: tech }),
1525
+ ...tech !== void 0 && { technology: tech },
2251
1526
  x: pos.x,
2252
1527
  y: pos.y,
2253
1528
  width: pos.width,
2254
- height: pos.height,
1529
+ height: pos.height
2255
1530
  });
2256
1531
  }
2257
-
2258
- // Extract edges
2259
- const edges: MutableC4LayoutEdge[] = deployRels
2260
- .filter(
2261
- (rel) =>
2262
- nameToElement.has(rel.sourceName) && nameToElement.has(rel.targetName)
2263
- )
2264
- .map((rel): MutableC4LayoutEdge => {
2265
- const edgeData = g.edge(rel.sourceName, rel.targetName);
2266
- return {
2267
- source: rel.sourceName,
2268
- target: rel.targetName,
2269
- arrowType: rel.arrowType,
2270
- ...(rel.label !== undefined && { label: rel.label }),
2271
- ...(rel.technology !== undefined && { technology: rel.technology }),
2272
- lineNumber: rel.lineNumber,
2273
- points: edgeData?.points ?? [],
2274
- };
2275
- });
2276
-
2277
- // Compute infrastructure boundary boxes from member node positions
2278
- const groupBoundaries: Writable<C4LayoutBoundary>[] = [];
1532
+ const edges = deployRels.filter(
1533
+ (rel) => nameToElement.has(rel.sourceName) && nameToElement.has(rel.targetName)
1534
+ ).map((rel) => {
1535
+ const edgeData = g.edge(rel.sourceName, rel.targetName);
1536
+ return {
1537
+ source: rel.sourceName,
1538
+ target: rel.targetName,
1539
+ arrowType: rel.arrowType,
1540
+ ...rel.label !== void 0 && { label: rel.label },
1541
+ ...rel.technology !== void 0 && { technology: rel.technology },
1542
+ lineNumber: rel.lineNumber,
1543
+ points: edgeData?.points ?? []
1544
+ };
1545
+ });
1546
+ const groupBoundaries = [];
2279
1547
  const nodeMap = new Map(nodes.map((n) => [n.name, n]));
2280
-
2281
- // Collect members for each infra node (containers directly inside it)
2282
- const infraMembers = new Map<string, Writable<C4LayoutNode>[]>();
1548
+ const infraMembers = /* @__PURE__ */ new Map();
2283
1549
  for (const r of refEntries) {
2284
1550
  const members = infraMembers.get(r.infraId) ?? [];
2285
1551
  const node = nodeMap.get(r.element.name);
2286
1552
  if (node) members.push(node);
2287
1553
  infraMembers.set(r.infraId, members);
2288
1554
  }
2289
-
2290
- // Compute boundaries bottom-up: leaf infra nodes first, then parents.
2291
- const infraBounds = new Map<
2292
- string,
2293
- { x: number; y: number; width: number; height: number }
2294
- >();
2295
-
2296
- function computeInfraBounds(
2297
- infraId: string
2298
- ): { x: number; y: number; width: number; height: number } | null {
2299
- if (infraBounds.has(infraId)) return infraBounds.get(infraId)!;
2300
-
2301
- let bMinX = Infinity,
2302
- bMinY = Infinity,
2303
- bMaxX = -Infinity,
2304
- bMaxY = -Infinity;
1555
+ const infraBounds = /* @__PURE__ */ new Map();
1556
+ function computeInfraBounds(infraId) {
1557
+ if (infraBounds.has(infraId)) return infraBounds.get(infraId);
1558
+ let bMinX = Infinity, bMinY = Infinity, bMaxX = -Infinity, bMaxY = -Infinity;
2305
1559
  let hasContent = false;
2306
-
2307
- // Direct container ref members
2308
1560
  const members = infraMembers.get(infraId) ?? [];
2309
1561
  for (const m of members) {
2310
1562
  hasContent = true;
@@ -2317,8 +1569,6 @@ export function layoutC4Deployment(
2317
1569
  if (right > bMaxX) bMaxX = right;
2318
1570
  if (bottom > bMaxY) bMaxY = bottom;
2319
1571
  }
2320
-
2321
- // Child infra node boundaries
2322
1572
  for (const [childId, parentId] of infraParents) {
2323
1573
  if (parentId === infraId) {
2324
1574
  const childBounds = computeInfraBounds(childId);
@@ -2333,41 +1583,30 @@ export function layoutC4Deployment(
2333
1583
  }
2334
1584
  }
2335
1585
  }
2336
-
2337
1586
  if (!hasContent) return null;
2338
-
2339
1587
  const bounds = {
2340
1588
  x: bMinX - BOUNDARY_PAD,
2341
1589
  y: bMinY - BOUNDARY_PAD,
2342
1590
  width: bMaxX - bMinX + BOUNDARY_PAD * 2,
2343
- height: bMaxY - bMinY + BOUNDARY_PAD * 2,
1591
+ height: bMaxY - bMinY + BOUNDARY_PAD * 2
2344
1592
  };
2345
1593
  infraBounds.set(infraId, bounds);
2346
1594
  return bounds;
2347
1595
  }
2348
-
2349
- // Process all infra nodes (recursion handles ordering)
2350
1596
  for (const [infraId, node] of infraIds) {
2351
1597
  const bounds = computeInfraBounds(infraId);
2352
1598
  if (bounds) {
2353
- const shapeLabel = node.shape !== 'default' ? node.shape : 'node';
1599
+ const shapeLabel = node.shape !== "default" ? node.shape : "node";
2354
1600
  groupBoundaries.push({
2355
1601
  label: node.name,
2356
1602
  typeLabel: shapeLabel,
2357
1603
  lineNumber: node.lineNumber,
2358
- ...bounds,
1604
+ ...bounds
2359
1605
  });
2360
1606
  }
2361
1607
  }
2362
-
2363
- // Sort boundaries so outermost (largest area) are first — rendered bottom to top
2364
1608
  groupBoundaries.sort((a, b) => b.width * b.height - a.width * a.height);
2365
-
2366
- // Compute total bounding box
2367
- let minX = Infinity,
2368
- minY = Infinity,
2369
- maxX = -Infinity,
2370
- maxY = -Infinity;
1609
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
2371
1610
  for (const node of nodes) {
2372
1611
  const left = node.x - node.width / 2;
2373
1612
  const top = node.y - node.height / 2;
@@ -2392,8 +1631,6 @@ export function layoutC4Deployment(
2392
1631
  if (pt.y > maxY) maxY = pt.y;
2393
1632
  }
2394
1633
  }
2395
-
2396
- // Shift everything so content starts at (MARGIN, MARGIN)
2397
1634
  const shiftX = MARGIN - minX;
2398
1635
  const shiftY = MARGIN - minY;
2399
1636
  for (const node of nodes) {
@@ -2410,12 +1647,9 @@ export function layoutC4Deployment(
2410
1647
  pt.y += shiftY;
2411
1648
  }
2412
1649
  }
2413
-
2414
1650
  let totalWidth = maxX - minX + MARGIN * 2;
2415
1651
  let totalHeight = maxY - minY + MARGIN * 2;
2416
-
2417
1652
  const legendGroups = computeLegendGroups(parsed.tagGroups);
2418
-
2419
1653
  if (legendGroups.length > 0) {
2420
1654
  const legendY = totalHeight + MARGIN;
2421
1655
  let legendX = MARGIN;
@@ -2429,13 +1663,23 @@ export function layoutC4Deployment(
2429
1663
  if (legendRight > totalWidth) totalWidth = legendRight;
2430
1664
  if (legendBottom > totalHeight) totalHeight = legendBottom;
2431
1665
  }
2432
-
2433
1666
  return {
2434
1667
  nodes,
2435
1668
  edges,
2436
1669
  legend: legendGroups,
2437
1670
  groupBoundaries,
2438
1671
  width: totalWidth,
2439
- height: totalHeight,
1672
+ height: totalHeight
2440
1673
  };
2441
1674
  }
1675
+
1676
+ export {
1677
+ rollUpContextRelationships,
1678
+ collectCardMetadata,
1679
+ computeC4NodeDimensions,
1680
+ layoutC4Context,
1681
+ layoutC4Containers,
1682
+ layoutC4Components,
1683
+ layoutC4Deployment
1684
+ };
1685
+ //# sourceMappingURL=chunk-QEBUY5NY.js.map