@diagrammo/dgmo 0.55.0 → 0.57.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 (292) hide show
  1. package/dist/advanced.d.ts +62 -2
  2. package/dist/advanced.js +190 -188
  3. package/dist/{analyzer-TDN5KJFP.js → analyzer-HQUXKZ5J.js} +3 -3
  4. package/dist/auto.css +24 -0
  5. package/dist/auto.js +155 -129
  6. package/dist/auto.mjs +1354 -729
  7. package/dist/block.css +24 -0
  8. package/dist/block.d.ts +12 -0
  9. package/dist/block.js +93 -63
  10. package/dist/{calculator-VBIT6GQF.js → calculator-BBKAAQGD.js} +3 -3
  11. package/dist/chart-meta.js +55 -55
  12. package/dist/charts-d3-Z6FOKUAL.js +29 -0
  13. package/dist/{chunk-IALX52TR.js → chunk-3D6LDLIH.js} +10 -10
  14. package/dist/{chunk-VVIRAGID.js → chunk-3G7BCZ4J.js} +20 -17
  15. package/dist/{chunk-A2ARDILY.js → chunk-3KOPPSUQ.js} +3 -3
  16. package/dist/{chunk-IWG2ECAO.js → chunk-3M6MKHIQ.js} +11 -9
  17. package/dist/{chunk-M53MDBIW.js → chunk-3NSOKT7C.js} +5 -5
  18. package/dist/{chunk-INTAQV2Y.js → chunk-3ZONSZOX.js} +5 -5
  19. package/dist/{chunk-JYDMBWRP.js → chunk-42IT4BG2.js} +2 -2
  20. package/dist/{chunk-ASPS5O6F.js → chunk-44GBBTMU.js} +7 -7
  21. package/dist/{chunk-COVYNAKJ.js → chunk-46NVO5UA.js} +3 -3
  22. package/dist/{chunk-JQLSFZZP.js → chunk-4MB4UOT5.js} +3 -3
  23. package/dist/{chunk-ITXL2KU5.js → chunk-4MJOBVY7.js} +3 -3
  24. package/dist/{chunk-LW7STMYZ.js → chunk-57RE4N22.js} +7 -7
  25. package/dist/{chunk-WITOJZGL.js → chunk-5J2RQGFG.js} +4 -4
  26. package/dist/{chunk-ZGIBV36U.js → chunk-5LBCOFA5.js} +8 -8
  27. package/dist/{chunk-FBP33UM6.js → chunk-5VLUAAAE.js} +4 -4
  28. package/dist/{chunk-P5XXIVEU.js → chunk-5XMDSXZT.js} +3 -3
  29. package/dist/{chunk-QZYGRDMM.js → chunk-6DR2GMDM.js} +100 -100
  30. package/dist/{chunk-6NJWBMJV.js → chunk-6HSRT6WI.js} +10 -10
  31. package/dist/{chunk-MEQYZZFR.js → chunk-6IVXRTXH.js} +96 -23
  32. package/dist/{chunk-FGAMFJNJ.js → chunk-6PRLPGJB.js} +14 -14
  33. package/dist/{chunk-US3P2DQO.js → chunk-6VJCURWU.js} +2 -2
  34. package/dist/{chunk-QZAW5SFH.js → chunk-7NK42OIB.js} +2 -2
  35. package/dist/{chunk-RKBCKCSF.js → chunk-7Q35X3AL.js} +2 -2
  36. package/dist/{chunk-NN5TF4OV.js → chunk-7SXTD7L6.js} +3 -3
  37. package/dist/{chunk-LCRPGGGS.js → chunk-7YPSFQFA.js} +20 -17
  38. package/dist/{chunk-JGCEFKZP.js → chunk-A6XELFU6.js} +15 -15
  39. package/dist/{chunk-RYNCWA5X.js → chunk-ADKDIWCW.js} +7 -7
  40. package/dist/{chunk-MEH4TJEX.js → chunk-APD52YJV.js} +8 -8
  41. package/dist/{chunk-PIXZTCKH.js → chunk-BIWMOFSE.js} +9 -9
  42. package/dist/{chunk-ZXNHHO6D.js → chunk-BQLJAYVB.js} +9 -9
  43. package/dist/{chunk-HO3RCNF6.js → chunk-CGLBK5Q4.js} +2 -2
  44. package/dist/{chunk-ADYKAKE3.js → chunk-CQ7Y3O67.js} +7 -4
  45. package/dist/{chunk-2R6HG6D5.js → chunk-CQJ5SE5T.js} +9 -9
  46. package/dist/{chunk-A2PTRSAO.js → chunk-CXI6X54X.js} +3 -3
  47. package/dist/{chunk-PCVXXPYU.js → chunk-CY5KE2P5.js} +57 -7
  48. package/dist/{chunk-JR7Q6GHE.js → chunk-D5FANMSG.js} +3 -3
  49. package/dist/{chunk-MSWIBF6J.js → chunk-D64FRGKU.js} +3 -3
  50. package/dist/{chunk-W4TSD3IP.js → chunk-D76B4DMV.js} +5 -5
  51. package/dist/{chunk-5K5XBEXT.js → chunk-DIKIHU52.js} +4 -4
  52. package/dist/{chunk-EMSOFHEN.js → chunk-DNSEG6P2.js} +2 -2
  53. package/dist/{chunk-UJRTPOHH.js → chunk-DUI5SMFX.js} +2 -2
  54. package/dist/{chunk-O4CZDTQA.js → chunk-EEKGMS63.js} +4 -4
  55. package/dist/{chunk-2HX6ZGY7.js → chunk-ES3MUYRX.js} +5 -5
  56. package/dist/{chunk-GRXPFBYC.js → chunk-ES66QH6J.js} +2 -2
  57. package/dist/{chunk-ZKPPI6BF.js → chunk-EXNKNJ65.js} +2 -2
  58. package/dist/{chunk-VMWSZCAK.js → chunk-FERE46TP.js} +5 -5
  59. package/dist/{chunk-GTO5VCYG.js → chunk-FMPYKUKI.js} +8 -8
  60. package/dist/{chunk-B4XS2AF2.js → chunk-FWVKPEG3.js} +3 -3
  61. package/dist/{chunk-KK3L5NVK.js → chunk-FZECLCCU.js} +4 -4
  62. package/dist/{chunk-ETTDF3S2.js → chunk-G3L4GWLA.js} +90 -59
  63. package/dist/{chunk-3IUHKMJI.js → chunk-H52HJ26L.js} +3 -3
  64. package/dist/{chunk-5H5GWWA4.js → chunk-HBRGNLF5.js} +19 -19
  65. package/dist/{chunk-BEOAKGNA.js → chunk-I55PVEIX.js} +2 -2
  66. package/dist/{chunk-EFUQENO5.js → chunk-IMXG673Y.js} +3 -3
  67. package/dist/{chunk-Y4BBGFKY.js → chunk-INU6ANOH.js} +2 -2
  68. package/dist/{chunk-32HUNA33.js → chunk-J6V3SMR3.js} +18 -15
  69. package/dist/{chunk-VXTUWXFB.js → chunk-K2GDF2ZR.js} +10 -10
  70. package/dist/{chunk-HX7QNHC6.js → chunk-KF575IXC.js} +4 -4
  71. package/dist/{chunk-5D5VHDJM.js → chunk-KH74OWHU.js} +13 -13
  72. package/dist/{chunk-ZP265ICS.js → chunk-KRKU6WRS.js} +10 -10
  73. package/dist/{chunk-JTSMEYIZ.js → chunk-L43KTQTW.js} +5 -2
  74. package/dist/{chunk-5HWPEYWB.js → chunk-LDVUPGWC.js} +2 -2
  75. package/dist/{chunk-3B2GXZCX.js → chunk-LSFZDBAP.js} +3 -3
  76. package/dist/{chunk-ZWVKTWK6.js → chunk-LV5BFA24.js} +6 -6
  77. package/dist/{chunk-IG6J7JWH.js → chunk-LZX3RLRP.js} +24 -21
  78. package/dist/{chunk-L2DIXZUT.js → chunk-M3IYDSI7.js} +24 -21
  79. package/dist/{chunk-KC3WBBI7.js → chunk-M65UOFJA.js} +12 -12
  80. package/dist/{chunk-HES4K6DV.js → chunk-MD2KWAXJ.js} +4 -4
  81. package/dist/{chunk-ETYF5QZR.js → chunk-MGLJA5TK.js} +3 -3
  82. package/dist/{chunk-RZWIPDZ2.js → chunk-MXDT446P.js} +8 -8
  83. package/dist/chunk-NCT22MOD.js +93 -0
  84. package/dist/{chunk-3BZJ5KD5.js → chunk-NFAHDPCG.js} +4 -4
  85. package/dist/{chunk-S52F62GW.js → chunk-NHZAYL2X.js} +7 -7
  86. package/dist/{chunk-YXKNXIWA.js → chunk-NIUE5VWY.js} +8 -8
  87. package/dist/chunk-NZ5QVASG.js +20 -0
  88. package/dist/{chunk-QQXFYTLC.js → chunk-OFEUXZPI.js} +38 -21
  89. package/dist/{chunk-PC4YLEKA.js → chunk-OHBIN74X.js} +4 -4
  90. package/dist/{chunk-4W2PE66Q.js → chunk-OLMWTJVU.js} +11 -1
  91. package/dist/{chunk-SCOHNGPG.js → chunk-ORZQVUGW.js} +33 -20
  92. package/dist/{chunk-4MZCJV4M.js → chunk-OYCIVSL3.js} +22 -19
  93. package/dist/{chunk-MNS2ENXF.js → chunk-PFG3EVRD.js} +4 -4
  94. package/dist/{chunk-UBQU2BY6.js → chunk-PKFW6GJD.js} +10 -10
  95. package/dist/{chunk-UXXLE6AH.js → chunk-PRKPFRC2.js} +6 -6
  96. package/dist/{chunk-AKE6C2D7.js → chunk-PUGUOFM6.js} +8 -8
  97. package/dist/{chunk-UES4P7FN.js → chunk-Q772PVKH.js} +11 -19
  98. package/dist/{chunk-F5ZNUMSY.js → chunk-QMOX5I3G.js} +22 -19
  99. package/dist/{chunk-HLGOG44K.js → chunk-QWUYFUNO.js} +3 -3
  100. package/dist/{chunk-WVGNXDEE.js → chunk-RB4HOOKP.js} +6 -6
  101. package/dist/{chunk-HUTP35XT.js → chunk-RQGNELB3.js} +5 -5
  102. package/dist/{chunk-WF64MW5G.js → chunk-RRX4Z4TH.js} +2 -2
  103. package/dist/{chunk-PSIDVCBA.js → chunk-RV2N7COG.js} +4 -4
  104. package/dist/{chunk-X3X4LZDC.js → chunk-S6QDCFEU.js} +2 -2
  105. package/dist/{chunk-NPPUZ4SK.js → chunk-SADYIA5Q.js} +9 -9
  106. package/dist/{chunk-Q5IHQ4NW.js → chunk-SCJ7CAJF.js} +2 -2
  107. package/dist/{chunk-LKGQ46P4.js → chunk-SFVG4AIG.js} +9 -9
  108. package/dist/{chunk-2ZJXKJSI.js → chunk-SQWWYGPT.js} +21 -21
  109. package/dist/{chunk-4R5KIPNX.js → chunk-ST3ZNEUQ.js} +3 -3
  110. package/dist/{chunk-SSHS42QG.js → chunk-SZCZOA2L.js} +3 -3
  111. package/dist/{chunk-HGKOVKAX.js → chunk-T2VMOWAM.js} +12 -9
  112. package/dist/{chunk-DS4MDEQ7.js → chunk-TZ72UBOA.js} +5 -5
  113. package/dist/{chunk-Q5CMQVWF.js → chunk-U3DGAE7L.js} +9 -9
  114. package/dist/{chunk-PV7ND5WL.js → chunk-U4FSWAOJ.js} +16 -16
  115. package/dist/{chunk-A4UJP4IS.js → chunk-UG4MWUXE.js} +18 -18
  116. package/dist/{chunk-NL7FUIVD.js → chunk-ULR3BVNH.js} +8 -8
  117. package/dist/{chunk-YP2T5YUP.js → chunk-USFZQPJ2.js} +5 -5
  118. package/dist/{chunk-UU6LUYUH.js → chunk-VJARCVMH.js} +2 -2
  119. package/dist/{chunk-PKUWYPI5.js → chunk-VS7DGDT3.js} +17 -25
  120. package/dist/{chunk-NYOOPQFD.js → chunk-VSFAJUEF.js} +4 -4
  121. package/dist/{chunk-XKKH2DPG.js → chunk-VYCV5WKH.js} +71 -52
  122. package/dist/{chunk-IIUYKQ5J.js → chunk-VYEQPPS6.js} +7 -7
  123. package/dist/{chunk-WB3NA3JJ.js → chunk-W4EKQ2P6.js} +2 -2
  124. package/dist/{chunk-3HDBAXF5.js → chunk-WGC42WJU.js} +8 -1
  125. package/dist/{chunk-IF4KYSJZ.js → chunk-WOMXS5R7.js} +20 -5
  126. package/dist/chunk-WTTIODDV.js +10 -0
  127. package/dist/{chunk-RSBH2C7O.js → chunk-X32RDWT5.js} +5 -5
  128. package/dist/{chunk-3FUTFYSP.js → chunk-X3ON4M5S.js} +15 -15
  129. package/dist/{chunk-3BFXELBL.js → chunk-XBTJJLAU.js} +10 -5
  130. package/dist/{chunk-AU75JHSR.js → chunk-YNAHUNMA.js} +3 -3
  131. package/dist/cli.cjs +153 -150
  132. package/dist/cloud-reference.d.ts +69 -0
  133. package/dist/cloud-reference.js +49 -0
  134. package/dist/completion-registry.js +6 -6
  135. package/dist/dgmo-router-PMEKTIJ7.js +88 -0
  136. package/dist/dimensions-XRWIPAFO.js +22 -0
  137. package/dist/element.js +156 -130
  138. package/dist/element.mjs +1354 -729
  139. package/dist/flowchart-parser-DA3V2SLH.js +21 -0
  140. package/dist/flowchart-renderer-JGLZB5P5.js +36 -0
  141. package/dist/index.js +70 -65
  142. package/dist/layout-5CX27X7I.js +21 -0
  143. package/dist/layout-AO3TPZUS.js +15 -0
  144. package/dist/layout-AQXLQVAJ.js +15 -0
  145. package/dist/layout-EQTOVNEE.js +15 -0
  146. package/dist/layout-NU5LQ4UP.js +21 -0
  147. package/dist/{layout-CB3XWCOI.js → layout-NX37NSRY.js} +3 -3
  148. package/dist/layout-OHAIIXBC.js +10 -0
  149. package/dist/layout-RIS5VTGL.js +18 -0
  150. package/dist/layout-TCWNJ2OZ.js +18 -0
  151. package/dist/{layout-CRLTSFYQ.js → layout-TZKPVXKJ.js} +6 -6
  152. package/dist/{layout-LGXOKUCD.js → layout-WHOOLGPO.js} +8 -8
  153. package/dist/{layout-search-U2H4ORFJ.js → layout-search-6CVR2MTZ.js} +320 -37
  154. package/dist/{legend-constants-B77VKB3R.js → legend-constants-QQU3QYBF.js} +5 -5
  155. package/dist/{palettes-FGTNFARW.js → palettes-WO3VA6NU.js} +4 -4
  156. package/dist/parser-4TX6U4ZU.js +11 -0
  157. package/dist/{parser-DYYTPLBL.js → parser-4ZIJDGPG.js} +6 -6
  158. package/dist/parser-5UZWYSIV.js +16 -0
  159. package/dist/{parser-PVBUAVRR.js → parser-5WMH55UA.js} +8 -8
  160. package/dist/parser-6CM27UPA.js +14 -0
  161. package/dist/parser-73YUU35J.js +11 -0
  162. package/dist/parser-A6M25MLK.js +11 -0
  163. package/dist/parser-AYZTKZC3.js +11 -0
  164. package/dist/parser-CCAUZLYI.js +15 -0
  165. package/dist/parser-D7YZX3CH.js +12 -0
  166. package/dist/parser-DQ2DGDYO.js +11 -0
  167. package/dist/parser-DTXM5ROT.js +14 -0
  168. package/dist/parser-HMQZPPOK.js +19 -0
  169. package/dist/parser-IPBEW2DG.js +13 -0
  170. package/dist/parser-IQLLBMBQ.js +15 -0
  171. package/dist/parser-KTVDCWHG.js +13 -0
  172. package/dist/parser-LMNFVTIV.js +16 -0
  173. package/dist/{parser-2LF33IS2.js → parser-MH62NYKM.js} +6 -6
  174. package/dist/parser-O5XCVGZG.js +11 -0
  175. package/dist/parser-OPOGIKFR.js +17 -0
  176. package/dist/parser-PEBXIOPX.js +12 -0
  177. package/dist/parser-PQXN6SBB.js +18 -0
  178. package/dist/parser-Q3KNFXQR.js +12 -0
  179. package/dist/parser-Q62VR2UJ.js +20 -0
  180. package/dist/parser-QEWSTNEJ.js +15 -0
  181. package/dist/{parser-SUV52NQW.js → parser-QL2LBPFE.js} +7 -7
  182. package/dist/{parser-BMOTF72G.js → parser-QN3GJJ3J.js} +5 -5
  183. package/dist/parser-RBNOWHGM.js +15 -0
  184. package/dist/parser-SJ7ECFAP.js +13 -0
  185. package/dist/parser-WT3DSNPQ.js +13 -0
  186. package/dist/{parser-TO7IENWL.js → parser-XQNM7BGD.js} +7 -7
  187. package/dist/parser-XWNSCDY6.js +13 -0
  188. package/dist/renderer-2TEGR3RX.js +26 -0
  189. package/dist/renderer-3WYLLPQL.js +27 -0
  190. package/dist/renderer-5BFS4NBL.js +24 -0
  191. package/dist/renderer-6OFPEBHG.js +25 -0
  192. package/dist/renderer-AK2X3VRY.js +30 -0
  193. package/dist/renderer-B6XOO6EE.js +20 -0
  194. package/dist/{renderer-TKTM2SL4.js → renderer-BNEO5W3E.js} +15 -15
  195. package/dist/renderer-BZZKS7KQ.js +38 -0
  196. package/dist/renderer-EJ3FETD2.js +28 -0
  197. package/dist/renderer-FQLFE3TQ.js +26 -0
  198. package/dist/renderer-HDLM6OY6.js +39 -0
  199. package/dist/renderer-HGWKAXS6.js +16 -0
  200. package/dist/renderer-I2P5FTZ2.js +39 -0
  201. package/dist/renderer-IAJMS5U5.js +30 -0
  202. package/dist/{renderer-CENXCMWG.js → renderer-JHYUK5TN.js} +8 -8
  203. package/dist/{renderer-RDBUXW7P.js → renderer-KXMKAXPQ.js} +9 -9
  204. package/dist/renderer-LMLSA457.js +25 -0
  205. package/dist/renderer-LNOBG226.js +29 -0
  206. package/dist/renderer-LRQ3OPNJ.js +27 -0
  207. package/dist/renderer-LU4R3BP2.js +16 -0
  208. package/dist/{renderer-IO4KCFVL.js → renderer-N4V7XVC3.js} +17 -16
  209. package/dist/{renderer-5EMHIQL5.js → renderer-ND7YIUHD.js} +6 -6
  210. package/dist/renderer-NKVIQA3C.js +17 -0
  211. package/dist/{renderer-TXTTV4HA.js → renderer-PLRNQ6T3.js} +15 -14
  212. package/dist/renderer-Q6TJ52B4.js +21 -0
  213. package/dist/{renderer-QZESC66H.js → renderer-RJT3MOUU.js} +5 -5
  214. package/dist/renderer-TIIHLRMM.js +19 -0
  215. package/dist/{renderer-DW6TEBLA.js → renderer-VWBNIZV3.js} +16 -16
  216. package/dist/renderer-W3JK5YVD.js +22 -0
  217. package/dist/renderer-W5GF5USI.js +25 -0
  218. package/dist/renderer-XKMG3SYD.js +23 -0
  219. package/dist/renderer-XSZ5MUIF.js +28 -0
  220. package/dist/renderer-radial-LZAPQVM5.js +21 -0
  221. package/dist/{resolver-ZSFQQRTH.js → resolver-W3WKLWDP.js} +3 -3
  222. package/dist/state-parser-NQGVYSM3.js +19 -0
  223. package/dist/state-renderer-KSAKMFQ2.js +40 -0
  224. package/docs/language-reference.md +9 -1
  225. package/package.json +6 -2
  226. package/dist/charts-d3-KZ6V4OP2.js +0 -28
  227. package/dist/chunk-BMR4CIEO.js +0 -41
  228. package/dist/dgmo-router-T4HGLIGA.js +0 -88
  229. package/dist/dimensions-3JINHSYK.js +0 -22
  230. package/dist/flowchart-parser-M7KKTLX7.js +0 -21
  231. package/dist/flowchart-renderer-FFEQFQEU.js +0 -35
  232. package/dist/layout-3ZZBKUQC.js +0 -20
  233. package/dist/layout-AUKTWGYL.js +0 -15
  234. package/dist/layout-FNZDJGKF.js +0 -19
  235. package/dist/layout-GHWRJKZQ.js +0 -15
  236. package/dist/layout-NF4EWFLT.js +0 -17
  237. package/dist/layout-SP7HJWKA.js +0 -17
  238. package/dist/layout-UR7CYAHL.js +0 -23
  239. package/dist/layout-UTMEVFHN.js +0 -15
  240. package/dist/parser-2AXPSKWB.js +0 -14
  241. package/dist/parser-2AZ2KQTO.js +0 -12
  242. package/dist/parser-3QJ2Z4H4.js +0 -11
  243. package/dist/parser-5GCQFSTQ.js +0 -13
  244. package/dist/parser-62OHBRU5.js +0 -11
  245. package/dist/parser-7LYJFZCP.js +0 -14
  246. package/dist/parser-CIFLYZYP.js +0 -15
  247. package/dist/parser-D2UL2G5U.js +0 -11
  248. package/dist/parser-DM2APTKB.js +0 -11
  249. package/dist/parser-GOUGUTPU.js +0 -12
  250. package/dist/parser-HGVUVD6J.js +0 -11
  251. package/dist/parser-IEJD3CZB.js +0 -11
  252. package/dist/parser-JBEWNLAV.js +0 -20
  253. package/dist/parser-JMXPHNZD.js +0 -12
  254. package/dist/parser-JMXSQY3K.js +0 -13
  255. package/dist/parser-LUXS7J32.js +0 -16
  256. package/dist/parser-M5BUHULF.js +0 -15
  257. package/dist/parser-MESRHUS4.js +0 -17
  258. package/dist/parser-OOYNI2UT.js +0 -15
  259. package/dist/parser-QKRBSQLJ.js +0 -18
  260. package/dist/parser-S6NWSIJO.js +0 -16
  261. package/dist/parser-SFEK6Q7Z.js +0 -19
  262. package/dist/parser-SZHGLOOZ.js +0 -13
  263. package/dist/parser-TVAMC7CQ.js +0 -13
  264. package/dist/parser-VAW46R57.js +0 -13
  265. package/dist/parser-XDSPOXSE.js +0 -15
  266. package/dist/renderer-3PWLOJPD.js +0 -29
  267. package/dist/renderer-5PODNLYP.js +0 -16
  268. package/dist/renderer-AQJIQ2XU.js +0 -25
  269. package/dist/renderer-BEW3AYFT.js +0 -28
  270. package/dist/renderer-C3UYAXA6.js +0 -26
  271. package/dist/renderer-CXM3ARYN.js +0 -23
  272. package/dist/renderer-FE5M6SEZ.js +0 -25
  273. package/dist/renderer-FXK6ZL3P.js +0 -20
  274. package/dist/renderer-G5ESLCJB.js +0 -29
  275. package/dist/renderer-HTDS4FED.js +0 -37
  276. package/dist/renderer-IRAFJNTK.js +0 -27
  277. package/dist/renderer-K7XLVPH5.js +0 -17
  278. package/dist/renderer-MFTTFW32.js +0 -38
  279. package/dist/renderer-MPXI4FVL.js +0 -24
  280. package/dist/renderer-NVBEMQ6L.js +0 -19
  281. package/dist/renderer-OOGDCR6K.js +0 -16
  282. package/dist/renderer-Q5P72O4A.js +0 -26
  283. package/dist/renderer-S4XB3JR2.js +0 -27
  284. package/dist/renderer-SIWEEWJ5.js +0 -26
  285. package/dist/renderer-UZIU4AHK.js +0 -28
  286. package/dist/renderer-V72VJIGG.js +0 -38
  287. package/dist/renderer-VEGOEZOI.js +0 -25
  288. package/dist/renderer-W6I6T2TA.js +0 -21
  289. package/dist/renderer-WSHJRR2T.js +0 -22
  290. package/dist/renderer-radial-AG75PBYD.js +0 -21
  291. package/dist/state-parser-KIPZGIB4.js +0 -19
  292. package/dist/state-renderer-U6OSJG52.js +0 -39
package/dist/element.mjs CHANGED
@@ -104,7 +104,7 @@ function nameMergedMessage(args) {
104
104
  function emptyMetadataValueMessage(key) {
105
105
  return `Metadata key '${key}:' has no value \u2014 the pair is dropped. Provide a value or remove the key.`;
106
106
  }
107
- var NAME_DIAGNOSTIC_CODES, METADATA_DIAGNOSTIC_CODES, TITLE_DIRECTIVE_DX;
107
+ var NAME_DIAGNOSTIC_CODES, METADATA_DIAGNOSTIC_CODES, NEGATIVE_VALUE_DX, TITLE_DIRECTIVE_DX;
108
108
  var init_diagnostics = __esm({
109
109
  "src/diagnostics.ts"() {
110
110
  "use strict";
@@ -135,6 +135,15 @@ var init_diagnostics = __esm({
135
135
  */
136
136
  EMPTY_METADATA_VALUE: "W_EMPTY_METADATA_VALUE"
137
137
  };
138
+ NEGATIVE_VALUE_DX = {
139
+ code: "E_VALUE_NEGATIVE",
140
+ severity: "error",
141
+ chartType: null,
142
+ title: "Negative value on a magnitude channel",
143
+ message: (p) => `Negative value ${p.value ?? -300} on "${p.label ?? "Refunds"}" \u2014 ${p.channel ?? "this chart's values"} encode magnitude and can't be negative.`,
144
+ hint: 'Restate the data as positive magnitudes (e.g. "decline %"). If direction matters, use a bar chart \u2014 bars support negative values.',
145
+ example: "pie Budget\nRent 1200\nRefunds -300"
146
+ };
138
147
  TITLE_DIRECTIVE_DX = {
139
148
  code: "E_TITLE_DIRECTIVE",
140
149
  severity: "error",
@@ -2708,6 +2717,16 @@ function parseVisualizationFull(content, palette) {
2708
2717
  palette
2709
2718
  ) ?? null : null;
2710
2719
  const arcValue = linkMatch[4] ? parseFloat(normalizeNumericToken(linkMatch[4]) ?? linkMatch[4]) : 1;
2720
+ if (arcValue < 0) {
2721
+ result.diagnostics.push(
2722
+ emit(NEGATIVE_VALUE_DX, lineNumber, {
2723
+ value: arcValue,
2724
+ label: `${source} -> ${target}`,
2725
+ channel: "arc link weights"
2726
+ })
2727
+ );
2728
+ continue;
2729
+ }
2711
2730
  result.links.push({
2712
2731
  source,
2713
2732
  target,
@@ -3327,6 +3346,14 @@ function parseVisualizationFull(content, palette) {
3327
3346
  weight: maybeWeight,
3328
3347
  lineNumber
3329
3348
  });
3349
+ } else if (lastSpace >= 0 && !isNaN(maybeWeight) && maybeWeight < 0) {
3350
+ result.diagnostics.push(
3351
+ emit(NEGATIVE_VALUE_DX, lineNumber, {
3352
+ value: maybeWeight,
3353
+ label: line11.substring(0, lastSpace).trim(),
3354
+ channel: "wordcloud weights"
3355
+ })
3356
+ );
3330
3357
  } else {
3331
3358
  freeformLines.push(line11);
3332
3359
  }
@@ -3639,6 +3666,27 @@ var init_parse = __esm({
3639
3666
  }
3640
3667
  });
3641
3668
 
3669
+ // src/utils/svg-serialize.ts
3670
+ function escapeAttributeAngleBrackets(svg) {
3671
+ return svg.replace(
3672
+ // ` name="value"` / ` xlink:href="value"` — attribute names in SVG may carry
3673
+ // a namespace prefix, a dot, or a dash.
3674
+ /(\s[\w:.-]+=")([^"]*)"/g,
3675
+ (match, prefix, value) => {
3676
+ if (!value.includes("<") && !value.includes(">")) return match;
3677
+ return `${prefix}${value.replace(/</g, "&lt;").replace(/>/g, "&gt;")}"`;
3678
+ }
3679
+ );
3680
+ }
3681
+ function serializeSvg(svgEl) {
3682
+ return escapeAttributeAngleBrackets(svgEl.outerHTML);
3683
+ }
3684
+ var init_svg_serialize = __esm({
3685
+ "src/utils/svg-serialize.ts"() {
3686
+ "use strict";
3687
+ }
3688
+ });
3689
+
3642
3690
  // src/fonts.ts
3643
3691
  var FONT_FAMILY;
3644
3692
  var init_fonts = __esm({
@@ -4842,15 +4890,15 @@ function showTooltip(tooltip, html, event) {
4842
4890
  tooltip.style.display = "block";
4843
4891
  const container = tooltip.parentElement;
4844
4892
  const rect2 = container.getBoundingClientRect();
4845
- let left = event.clientX - rect2.left + 12;
4846
- let top = event.clientY - rect2.top - 28;
4893
+ let left2 = event.clientX - rect2.left + 12;
4894
+ let top2 = event.clientY - rect2.top - 28;
4847
4895
  const tipW = tooltip.offsetWidth;
4848
4896
  const tipH = tooltip.offsetHeight;
4849
- if (left + tipW > rect2.width) left = rect2.width - tipW - 4;
4850
- if (top < 0) top = event.clientY - rect2.top + 16;
4851
- if (top + tipH > rect2.height) top = rect2.height - tipH - 4;
4852
- tooltip.style.left = `${left}px`;
4853
- tooltip.style.top = `${top}px`;
4897
+ if (left2 + tipW > rect2.width) left2 = rect2.width - tipW - 4;
4898
+ if (top2 < 0) top2 = event.clientY - rect2.top + 16;
4899
+ if (top2 + tipH > rect2.height) top2 = rect2.height - tipH - 4;
4900
+ tooltip.style.left = `${left2}px`;
4901
+ tooltip.style.top = `${top2}px`;
4854
4902
  }
4855
4903
  function hideTooltip(tooltip) {
4856
4904
  tooltip.style.display = "none";
@@ -4880,7 +4928,7 @@ function finalizeSvgExport(container, theme, palette) {
4880
4928
  svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
4881
4929
  svgEl.style.fontFamily = FONT_FAMILY;
4882
4930
  svgEl.querySelectorAll("[data-export-ignore]").forEach((el) => el.remove());
4883
- const svgHtml = svgEl.outerHTML;
4931
+ const svgHtml = serializeSvg(svgEl);
4884
4932
  document.body.removeChild(container);
4885
4933
  return svgHtml;
4886
4934
  }
@@ -4888,6 +4936,7 @@ var EXPORT_WIDTH, EXPORT_HEIGHT;
4888
4936
  var init_d3_helpers = __esm({
4889
4937
  "src/utils/d3-helpers.ts"() {
4890
4938
  "use strict";
4939
+ init_svg_serialize();
4891
4940
  init_fonts();
4892
4941
  init_palettes();
4893
4942
  init_title_constants();
@@ -5932,13 +5981,13 @@ function getMaxLegendReservedHeight(config, containerWidth) {
5932
5981
  }
5933
5982
  function getLegendExtent(config, state, containerWidth) {
5934
5983
  const layout = computeLegendLayout(config, state, containerWidth);
5935
- let left = Infinity;
5936
- let right = 0;
5937
- let bottom = 0;
5984
+ let left2 = Infinity;
5985
+ let right2 = 0;
5986
+ let bottom2 = 0;
5938
5987
  const track = (x, y, w, h) => {
5939
- left = Math.min(left, x);
5940
- right = Math.max(right, x + w);
5941
- bottom = Math.max(bottom, y + h);
5988
+ left2 = Math.min(left2, x);
5989
+ right2 = Math.max(right2, x + w);
5990
+ bottom2 = Math.max(bottom2, y + h);
5942
5991
  };
5943
5992
  if (layout.activeCapsule) {
5944
5993
  const c = layout.activeCapsule;
@@ -5946,8 +5995,8 @@ function getLegendExtent(config, state, containerWidth) {
5946
5995
  }
5947
5996
  for (const pill of layout.pills) track(pill.x, pill.y, pill.width, pill.height);
5948
5997
  return {
5949
- width: right - (left === Infinity ? 0 : left),
5950
- height: bottom || LEGEND_HEIGHT
5998
+ width: right2 - (left2 === Infinity ? 0 : left2),
5999
+ height: bottom2 || LEGEND_HEIGHT
5951
6000
  };
5952
6001
  }
5953
6002
  var CONTROL_PILL_PAD, CONTROL_FONT_SIZE, CONTROL_ICON_GAP, CONTROL_GAP, RAMP_LEGEND_W, RAMP_LEGEND_H, RAMP_LABEL_GAP;
@@ -8658,9 +8707,9 @@ function parseSequenceDgmo(content, palette) {
8658
8707
  const blockStack = [];
8659
8708
  const currentContainer = () => {
8660
8709
  if (blockStack.length === 0) return result.elements;
8661
- const top = blockStack[blockStack.length - 1];
8662
- if (top.activeElseIfBranch) return top.activeElseIfBranch.children;
8663
- return top.inElse ? top.block.elseChildren : top.block.children;
8710
+ const top2 = blockStack[blockStack.length - 1];
8711
+ if (top2.activeElseIfBranch) return top2.activeElseIfBranch.children;
8712
+ return top2.inElse ? top2.block.elseChildren : top2.block.children;
8664
8713
  };
8665
8714
  let lastMsgFrom = null;
8666
8715
  for (let i = 0; i < lines.length; i++) {
@@ -8798,8 +8847,8 @@ function parseSequenceDgmo(content, palette) {
8798
8847
  if (sectionMatch) {
8799
8848
  const sectionIndent = measureIndent(raw);
8800
8849
  while (blockStack.length > 0) {
8801
- const top = blockStack[blockStack.length - 1];
8802
- if (sectionIndent > top.indent) break;
8850
+ const top2 = blockStack[blockStack.length - 1];
8851
+ if (sectionIndent > top2.indent) break;
8803
8852
  blockStack.pop();
8804
8853
  }
8805
8854
  const labelRaw = sectionMatch[1].trim();
@@ -8999,9 +9048,9 @@ function parseSequenceDgmo(content, palette) {
8999
9048
  }
9000
9049
  const indent = measureIndent(raw);
9001
9050
  while (blockStack.length > 0) {
9002
- const top = blockStack[blockStack.length - 1];
9003
- if (indent > top.indent) break;
9004
- if (indent === top.indent && (top.block.type === "if" || top.block.type === "parallel")) {
9051
+ const top2 = blockStack[blockStack.length - 1];
9052
+ if (indent > top2.indent) break;
9053
+ if (indent === top2.indent && (top2.block.type === "if" || top2.block.type === "parallel")) {
9005
9054
  const lower = trimmed.toLowerCase();
9006
9055
  if (lower === "else" || lower.startsWith("else if ")) break;
9007
9056
  }
@@ -9158,26 +9207,26 @@ function parseSequenceDgmo(content, palette) {
9158
9207
  if (elseIfMatch) {
9159
9208
  if (blockStack.length > 0 && // In-bounds by the length check above.
9160
9209
  blockStack[blockStack.length - 1].indent === indent) {
9161
- const top = blockStack[blockStack.length - 1];
9162
- if (top.block.type === "parallel") {
9210
+ const top2 = blockStack[blockStack.length - 1];
9211
+ if (top2.block.type === "parallel") {
9163
9212
  pushError(
9164
9213
  lineNumber,
9165
9214
  "parallel blocks don't support else if \u2014 list all concurrent messages directly inside the block"
9166
9215
  );
9167
9216
  continue;
9168
9217
  }
9169
- if (top.block.type === "if") {
9218
+ if (top2.block.type === "if") {
9170
9219
  const branch = {
9171
9220
  // Capture group 1 guaranteed present after successful match.
9172
9221
  label: elseIfMatch[1].trim(),
9173
9222
  children: [],
9174
9223
  lineNumber
9175
9224
  };
9176
- if (!top.block.elseIfBranches) top.block.elseIfBranches = [];
9177
- const branches = top.block.elseIfBranches;
9225
+ if (!top2.block.elseIfBranches) top2.block.elseIfBranches = [];
9226
+ const branches = top2.block.elseIfBranches;
9178
9227
  branches.push(branch);
9179
- top.activeElseIfBranch = branch;
9180
- top.inElse = false;
9228
+ top2.activeElseIfBranch = branch;
9229
+ top2.inElse = false;
9181
9230
  }
9182
9231
  }
9183
9232
  continue;
@@ -9185,18 +9234,18 @@ function parseSequenceDgmo(content, palette) {
9185
9234
  if (trimmed.toLowerCase() === "else") {
9186
9235
  if (blockStack.length > 0 && // In-bounds by the length check above.
9187
9236
  blockStack[blockStack.length - 1].indent === indent) {
9188
- const top = blockStack[blockStack.length - 1];
9189
- if (top.block.type === "parallel") {
9237
+ const top2 = blockStack[blockStack.length - 1];
9238
+ if (top2.block.type === "parallel") {
9190
9239
  pushError(
9191
9240
  lineNumber,
9192
9241
  "parallel blocks don't support else \u2014 list all concurrent messages directly inside the block"
9193
9242
  );
9194
9243
  continue;
9195
9244
  }
9196
- if (top.block.type === "if") {
9197
- top.inElse = true;
9198
- delete top.activeElseIfBranch;
9199
- top.block.elseLineNumber = lineNumber;
9245
+ if (top2.block.type === "if") {
9246
+ top2.inElse = true;
9247
+ delete top2.activeElseIfBranch;
9248
+ top2.block.elseLineNumber = lineNumber;
9200
9249
  }
9201
9250
  }
9202
9251
  continue;
@@ -9628,88 +9677,6 @@ var init_constants = __esm({
9628
9677
  }
9629
9678
  });
9630
9679
 
9631
- // src/utils/wrapped-desc.ts
9632
- function wrapDescriptionLines(lines, charsPerLine, lengthFn = (s) => s.length) {
9633
- const result = [];
9634
- for (const line11 of lines) {
9635
- if (!line11.startsWith(BULLET_PREFIX)) {
9636
- const wrapped2 = wrapPlainLine(line11, charsPerLine, lengthFn);
9637
- for (const w of wrapped2) result.push({ text: w, kind: "plain" });
9638
- continue;
9639
- }
9640
- const body = line11.slice(BULLET_PREFIX.length);
9641
- const bodyLimit = Math.max(8, charsPerLine - BULLET_INDENT_CHARS);
9642
- const wrapped = wrapPlainLine(body, bodyLimit, lengthFn);
9643
- wrapped.forEach((w, i) => {
9644
- result.push({ text: w, kind: i === 0 ? "bullet-first" : "bullet-cont" });
9645
- });
9646
- }
9647
- return result;
9648
- }
9649
- function wrapPlainLine(line11, charsPerLine, lengthFn) {
9650
- const words = line11.split(/\s+/);
9651
- const result = [];
9652
- let current = "";
9653
- for (const word of words) {
9654
- const test = current ? `${current} ${word}` : word;
9655
- if (lengthFn(test) > charsPerLine && current) {
9656
- result.push(current);
9657
- current = word;
9658
- } else {
9659
- current = test;
9660
- }
9661
- }
9662
- if (current) result.push(current);
9663
- return result;
9664
- }
9665
- var BULLET_PREFIX, BULLET_INDENT_CHARS;
9666
- var init_wrapped_desc = __esm({
9667
- "src/utils/wrapped-desc.ts"() {
9668
- "use strict";
9669
- BULLET_PREFIX = "\u2022 ";
9670
- BULLET_INDENT_CHARS = 2;
9671
- }
9672
- });
9673
-
9674
- // src/utils/note-box/metrics.ts
9675
- function normalizeBulletLine(line11) {
9676
- return line11.replace(/^\s*[-*]\s+/, "\u2022 ");
9677
- }
9678
- function wrapNoteBody(body, textMaxWidth, fontSize = NOTE_FONT_SIZE) {
9679
- const sourceLines = body.split("\n").map(normalizeBulletLine);
9680
- return wrapDescriptionLines(
9681
- sourceLines,
9682
- textMaxWidth,
9683
- (s) => measureText(s, fontSize)
9684
- );
9685
- }
9686
- function noteBoxSize(body, opts = {}) {
9687
- const fontSize = opts.fontSize ?? NOTE_FONT_SIZE;
9688
- const maxW = opts.maxW ?? NOTE_MAX_W;
9689
- const textMaxWidth = maxW - NOTE_PAD_H * 2;
9690
- const lines = wrapNoteBody(body, textMaxWidth, fontSize);
9691
- let maxLineW = 0;
9692
- for (const line11 of lines) {
9693
- const indent = line11.kind === "plain" ? 0 : NOTE_BULLET_INDENT;
9694
- const w = measureText(line11.text, fontSize) + indent;
9695
- if (w > maxLineW) maxLineW = w;
9696
- }
9697
- const width = Math.min(
9698
- maxW,
9699
- Math.max(80, maxLineW + NOTE_PAD_H * 2 + NOTE_FOLD)
9700
- );
9701
- const height = Math.max(1, lines.length) * NOTE_LINE_H + NOTE_PAD_V * 2;
9702
- return { width, height, lines };
9703
- }
9704
- var init_metrics = __esm({
9705
- "src/utils/note-box/metrics.ts"() {
9706
- "use strict";
9707
- init_wrapped_desc();
9708
- init_text_measure();
9709
- init_constants();
9710
- }
9711
- });
9712
-
9713
9680
  // src/utils/safe-href.ts
9714
9681
  function safeHref(url) {
9715
9682
  if (typeof url !== "string") return null;
@@ -9769,6 +9736,12 @@ function truncateBareUrl(url) {
9769
9736
  if (stripped.length <= BARE_URL_MAX_DISPLAY) return stripped;
9770
9737
  return stripped.slice(0, BARE_URL_MAX_DISPLAY - 1) + "\u2026";
9771
9738
  }
9739
+ function stripInlineMarkdown(text) {
9740
+ return text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1").replace(
9741
+ /https?:\/\/[^\s)>\]]+|www\.[^\s)>\]]+/g,
9742
+ (u) => truncateBareUrl(u)
9743
+ ).replace(/\*\*|__|[*_`]/g, "");
9744
+ }
9772
9745
  function renderInlineText(textEl, text, palette, fontSize) {
9773
9746
  const spans = parseInlineMarkdown(text);
9774
9747
  for (const span of spans) {
@@ -9802,6 +9775,137 @@ var init_inline_markdown = __esm({
9802
9775
  }
9803
9776
  });
9804
9777
 
9778
+ // src/utils/wrapped-desc.ts
9779
+ function reflowDescriptionLines(lines) {
9780
+ const blocks = [];
9781
+ let open = null;
9782
+ let gapPending = false;
9783
+ let breakPending = false;
9784
+ const openBlock = (kind, text) => {
9785
+ const block = {
9786
+ kind,
9787
+ segments: [text],
9788
+ gapBefore: gapPending && blocks.length > 0
9789
+ };
9790
+ blocks.push(block);
9791
+ gapPending = false;
9792
+ return block;
9793
+ };
9794
+ for (const raw of lines) {
9795
+ const line11 = raw.trimEnd();
9796
+ if (!line11) {
9797
+ open = null;
9798
+ breakPending = false;
9799
+ gapPending = blocks.length > 0;
9800
+ continue;
9801
+ }
9802
+ const hard = line11.endsWith(HARD_BREAK);
9803
+ const text = hard ? line11.slice(0, -1).trimEnd() : line11;
9804
+ if (!text) {
9805
+ breakPending = hard;
9806
+ continue;
9807
+ }
9808
+ if (text.startsWith(BULLET_PREFIX)) {
9809
+ open = openBlock("bullet", text.slice(BULLET_PREFIX.length));
9810
+ } else if (open) {
9811
+ if (breakPending) open.segments.push(text);
9812
+ else open.segments[open.segments.length - 1] += ` ${text}`;
9813
+ } else {
9814
+ open = openBlock("plain", text);
9815
+ }
9816
+ breakPending = hard;
9817
+ }
9818
+ return blocks;
9819
+ }
9820
+ function wrapDescriptionLines(lines, charsPerLine, lengthFn = (s) => s.length) {
9821
+ const measure = (s) => lengthFn(stripInlineMarkdown(s));
9822
+ const result = [];
9823
+ for (const block of reflowDescriptionLines(lines)) {
9824
+ if (block.gapBefore && result.length > 0)
9825
+ result.push({ text: "", kind: "plain" });
9826
+ if (block.kind === "plain") {
9827
+ for (const segment of block.segments)
9828
+ for (const w of wrapPlainLine(segment, charsPerLine, measure))
9829
+ result.push({ text: w, kind: "plain" });
9830
+ continue;
9831
+ }
9832
+ const bodyLimit = Math.max(8, charsPerLine - BULLET_INDENT_CHARS);
9833
+ let first = true;
9834
+ for (const segment of block.segments) {
9835
+ for (const w of wrapPlainLine(segment, bodyLimit, measure)) {
9836
+ result.push({ text: w, kind: first ? "bullet-first" : "bullet-cont" });
9837
+ first = false;
9838
+ }
9839
+ }
9840
+ }
9841
+ return result;
9842
+ }
9843
+ function wrapPlainLine(line11, charsPerLine, lengthFn) {
9844
+ const words = line11.split(/\s+/);
9845
+ const result = [];
9846
+ let current = "";
9847
+ for (const word of words) {
9848
+ const test = current ? `${current} ${word}` : word;
9849
+ if (lengthFn(test) > charsPerLine && current) {
9850
+ result.push(current);
9851
+ current = word;
9852
+ } else {
9853
+ current = test;
9854
+ }
9855
+ }
9856
+ if (current) result.push(current);
9857
+ return result;
9858
+ }
9859
+ var BULLET_PREFIX, BULLET_INDENT_CHARS, HARD_BREAK;
9860
+ var init_wrapped_desc = __esm({
9861
+ "src/utils/wrapped-desc.ts"() {
9862
+ "use strict";
9863
+ init_inline_markdown();
9864
+ BULLET_PREFIX = "\u2022 ";
9865
+ BULLET_INDENT_CHARS = 2;
9866
+ HARD_BREAK = "\\";
9867
+ }
9868
+ });
9869
+
9870
+ // src/utils/note-box/metrics.ts
9871
+ function normalizeBulletLine(line11) {
9872
+ return line11.replace(/^\s*[-*]\s+/, "\u2022 ");
9873
+ }
9874
+ function wrapNoteBody(body, textMaxWidth, fontSize = NOTE_FONT_SIZE) {
9875
+ const sourceLines = body.split("\n").map(normalizeBulletLine);
9876
+ return wrapDescriptionLines(
9877
+ sourceLines,
9878
+ textMaxWidth,
9879
+ (s) => measureText(s, fontSize)
9880
+ );
9881
+ }
9882
+ function noteBoxSize(body, opts = {}) {
9883
+ const fontSize = opts.fontSize ?? NOTE_FONT_SIZE;
9884
+ const maxW = opts.maxW ?? NOTE_MAX_W;
9885
+ const textMaxWidth = maxW - NOTE_PAD_H * 2;
9886
+ const lines = wrapNoteBody(body, textMaxWidth, fontSize);
9887
+ let maxLineW = 0;
9888
+ for (const line11 of lines) {
9889
+ const indent = line11.kind === "plain" ? 0 : NOTE_BULLET_INDENT;
9890
+ const w = measureText(line11.text, fontSize) + indent;
9891
+ if (w > maxLineW) maxLineW = w;
9892
+ }
9893
+ const width = Math.min(
9894
+ maxW,
9895
+ Math.max(80, maxLineW + NOTE_PAD_H * 2 + NOTE_FOLD)
9896
+ );
9897
+ const height = Math.max(1, lines.length) * NOTE_LINE_H + NOTE_PAD_V * 2;
9898
+ return { width, height, lines };
9899
+ }
9900
+ var init_metrics = __esm({
9901
+ "src/utils/note-box/metrics.ts"() {
9902
+ "use strict";
9903
+ init_wrapped_desc();
9904
+ init_text_measure();
9905
+ init_constants();
9906
+ }
9907
+ });
9908
+
9805
9909
  // src/utils/note-box/svg.ts
9806
9910
  function renderNoteConnector(parent, x1, y1, x2, y2, palette) {
9807
9911
  parent.append("line").attr("x1", x1).attr("y1", y1).attr("x2", x2).attr("y2", y2).attr("stroke", palette.textMuted).attr("stroke-width", NOTE_STROKE_WIDTH).attr("stroke-opacity", NOTE_STROKE_OPACITY).attr("class", "note-connector").style("pointer-events", "none");
@@ -9964,25 +10068,25 @@ function placeNotes(obstacles, requests, direction) {
9964
10068
  const rectFor = (side) => {
9965
10069
  switch (side) {
9966
10070
  case "right": {
9967
- const left = nodeRight + NOTE_GAP;
9968
- const top = cy - noteH / 2;
9969
- return { left, top, right: left + noteW, bottom: top + noteH };
10071
+ const left2 = nodeRight + NOTE_GAP;
10072
+ const top2 = cy - noteH / 2;
10073
+ return { left: left2, top: top2, right: left2 + noteW, bottom: top2 + noteH };
9970
10074
  }
9971
10075
  case "left": {
9972
- const right = nodeLeft - NOTE_GAP;
9973
- const top = cy - noteH / 2;
9974
- return { left: right - noteW, top, right, bottom: top + noteH };
10076
+ const right2 = nodeLeft - NOTE_GAP;
10077
+ const top2 = cy - noteH / 2;
10078
+ return { left: right2 - noteW, top: top2, right: right2, bottom: top2 + noteH };
9975
10079
  }
9976
10080
  case "below": {
9977
- const left = cx - noteW / 2;
9978
- const top = nodeBottom + NOTE_GAP;
9979
- return { left, top, right: left + noteW, bottom: top + noteH };
10081
+ const left2 = cx - noteW / 2;
10082
+ const top2 = nodeBottom + NOTE_GAP;
10083
+ return { left: left2, top: top2, right: left2 + noteW, bottom: top2 + noteH };
9980
10084
  }
9981
10085
  case "above":
9982
10086
  default: {
9983
- const left = cx - noteW / 2;
9984
- const bottom = nodeTop - NOTE_GAP;
9985
- return { left, top: bottom - noteH, right: left + noteW, bottom };
10087
+ const left2 = cx - noteW / 2;
10088
+ const bottom2 = nodeTop - NOTE_GAP;
10089
+ return { left: left2, top: bottom2 - noteH, right: left2 + noteW, bottom: bottom2 };
9986
10090
  }
9987
10091
  }
9988
10092
  };
@@ -10006,17 +10110,17 @@ function placeNotes(obstacles, requests, direction) {
10006
10110
  );
10007
10111
  if (blockers.length === 0) break;
10008
10112
  if (axisIsY && outward > 0) {
10009
- const top = Math.max(...blockers.map((b) => b.bottom)) + NOTE_CLEAR;
10010
- rect2 = { ...rect2, top, bottom: top + noteH };
10113
+ const top2 = Math.max(...blockers.map((b) => b.bottom)) + NOTE_CLEAR;
10114
+ rect2 = { ...rect2, top: top2, bottom: top2 + noteH };
10011
10115
  } else if (axisIsY) {
10012
- const bottom = Math.min(...blockers.map((b) => b.top)) - NOTE_CLEAR;
10013
- rect2 = { ...rect2, bottom, top: bottom - noteH };
10116
+ const bottom2 = Math.min(...blockers.map((b) => b.top)) - NOTE_CLEAR;
10117
+ rect2 = { ...rect2, bottom: bottom2, top: bottom2 - noteH };
10014
10118
  } else if (outward > 0) {
10015
- const left = Math.max(...blockers.map((b) => b.right)) + NOTE_CLEAR;
10016
- rect2 = { ...rect2, left, right: left + noteW };
10119
+ const left2 = Math.max(...blockers.map((b) => b.right)) + NOTE_CLEAR;
10120
+ rect2 = { ...rect2, left: left2, right: left2 + noteW };
10017
10121
  } else {
10018
- const right = Math.min(...blockers.map((b) => b.left)) - NOTE_CLEAR;
10019
- rect2 = { ...rect2, right, left: right - noteW };
10122
+ const right2 = Math.min(...blockers.map((b) => b.left)) - NOTE_CLEAR;
10123
+ rect2 = { ...rect2, right: right2, left: right2 - noteW };
10020
10124
  }
10021
10125
  }
10022
10126
  chosen = { rect: rect2, side };
@@ -10356,8 +10460,8 @@ function parseFlowchart(content, palette) {
10356
10460
  function processContentLine(trimmed, lineNumber, indent) {
10357
10461
  contentStarted = true;
10358
10462
  while (indentStack.length > 0) {
10359
- const top = indentStack[indentStack.length - 1];
10360
- if (top.indent >= indent) {
10463
+ const top2 = indentStack[indentStack.length - 1];
10464
+ if (top2.indent >= indent) {
10361
10465
  indentStack.pop();
10362
10466
  } else {
10363
10467
  break;
@@ -10943,8 +11047,8 @@ function parseState(content, palette) {
10943
11047
  groupIndent = -1;
10944
11048
  }
10945
11049
  while (indentStack.length > 0) {
10946
- const top = indentStack[indentStack.length - 1];
10947
- if (top.indent >= indent) {
11050
+ const top2 = indentStack[indentStack.length - 1];
11051
+ if (top2.indent >= indent) {
10948
11052
  indentStack.pop();
10949
11053
  } else {
10950
11054
  break;
@@ -12325,8 +12429,8 @@ function parseNodeLabel(trimmed, _indent, lineNumber, _palette, counter, metaAli
12325
12429
  }
12326
12430
  function attachNode(node, indent, indentStack, result) {
12327
12431
  while (indentStack.length > 0) {
12328
- const top = indentStack[indentStack.length - 1];
12329
- if (top.indent < indent) break;
12432
+ const top2 = indentStack[indentStack.length - 1];
12433
+ if (top2.indent < indent) break;
12330
12434
  indentStack.pop();
12331
12435
  }
12332
12436
  if (indentStack.length > 0) {
@@ -12849,8 +12953,8 @@ function parseSitemapMetaTail(tail, metaAliasMap) {
12849
12953
  }
12850
12954
  function attachNode2(node, indent, indentStack, result) {
12851
12955
  while (indentStack.length > 0) {
12852
- const top = indentStack[indentStack.length - 1];
12853
- if (top.indent < indent) break;
12956
+ const top2 = indentStack[indentStack.length - 1];
12957
+ if (top2.indent < indent) break;
12854
12958
  indentStack.pop();
12855
12959
  }
12856
12960
  if (indentStack.length > 0) {
@@ -13530,8 +13634,8 @@ function parsePert(content, parseOpts = {}) {
13530
13634
  if (trimmed.startsWith("#") || trimmed.startsWith("//")) continue;
13531
13635
  const indent = measureIndent(rawLine);
13532
13636
  while (groupStack.length > 0) {
13533
- const top = groupStack[groupStack.length - 1];
13534
- if (indent <= top.indent) groupStack.pop();
13637
+ const top2 = groupStack[groupStack.length - 1];
13638
+ if (indent <= top2.indent) groupStack.pop();
13535
13639
  else break;
13536
13640
  }
13537
13641
  if (currentSourceIndent >= 0 && indent <= currentSourceIndent && !trimmed.startsWith("-")) {
@@ -14944,6 +15048,19 @@ function parseChart(content, palette) {
14944
15048
  lineNumber
14945
15049
  );
14946
15050
  const [first, ...rest] = dataValues.values;
15051
+ if (result.type === "pie" || result.type === "polar-area" || result.type === "radar") {
15052
+ const neg = dataValues.values.find((v) => v < 0);
15053
+ if (neg !== void 0) {
15054
+ result.diagnostics.push(
15055
+ emit(NEGATIVE_VALUE_DX, lineNumber, {
15056
+ value: neg,
15057
+ label: rawLabel,
15058
+ channel: CHANNEL_NAME[result.type]
15059
+ })
15060
+ );
15061
+ continue;
15062
+ }
15063
+ }
14947
15064
  result.data.push({
14948
15065
  label: rawLabel,
14949
15066
  // parseDataRowValues guarantees values.length >= 1.
@@ -15095,13 +15212,18 @@ function trailingNumerics(tokens, minIndex) {
15095
15212
  }
15096
15213
  return values;
15097
15214
  }
15098
- var VALID_TYPES, KNOWN_OPTIONS3, DEFAULT_HOLE, KNOWN_BOOLEANS2, KNOWN_FIRST_TOKENS;
15215
+ var CHANNEL_NAME, VALID_TYPES, KNOWN_OPTIONS3, DEFAULT_HOLE, KNOWN_BOOLEANS2, KNOWN_FIRST_TOKENS;
15099
15216
  var init_chart = __esm({
15100
15217
  "src/chart.ts"() {
15101
15218
  "use strict";
15102
15219
  init_colors();
15103
15220
  init_diagnostics();
15104
15221
  init_parsing();
15222
+ CHANNEL_NAME = {
15223
+ pie: "pie slices",
15224
+ "polar-area": "polar-area wedges",
15225
+ radar: "radar axis values"
15226
+ };
15105
15227
  VALID_TYPES = /* @__PURE__ */ new Set([
15106
15228
  "bar",
15107
15229
  "line",
@@ -15382,11 +15504,22 @@ function parseExtendedChartFull(content, palette) {
15382
15504
  result.diagnostics,
15383
15505
  palette
15384
15506
  ) : void 0;
15507
+ const linkValue = parseFloat(val);
15508
+ if (linkValue < 0) {
15509
+ result.diagnostics.push(
15510
+ emit(NEGATIVE_VALUE_DX, lineNumber, {
15511
+ value: linkValue,
15512
+ label: `${source} -> ${target}`,
15513
+ channel: "flow widths"
15514
+ })
15515
+ );
15516
+ continue;
15517
+ }
15385
15518
  if (!result.links) result.links = [];
15386
15519
  result.links.push({
15387
15520
  source,
15388
15521
  target,
15389
- value: parseFloat(val),
15522
+ value: linkValue,
15390
15523
  ...linkColor && { color: linkColor },
15391
15524
  directed: arrow === "->",
15392
15525
  lineNumber
@@ -15424,12 +15557,22 @@ function parseExtendedChartFull(content, palette) {
15424
15557
  if (!result.nodeColors) result.nodeColors = {};
15425
15558
  result.nodeColors[target] = targetColor;
15426
15559
  }
15560
+ const childValue = dataRow2.values[0];
15561
+ if (childValue < 0) {
15562
+ result.diagnostics.push(
15563
+ emit(NEGATIVE_VALUE_DX, lineNumber, {
15564
+ value: childValue,
15565
+ label: `${source} -> ${target}`,
15566
+ channel: "flow widths"
15567
+ })
15568
+ );
15569
+ continue;
15570
+ }
15427
15571
  if (!result.links) result.links = [];
15428
15572
  result.links.push({
15429
15573
  source,
15430
15574
  target,
15431
- // In-bounds by values.length === 1 guard above.
15432
- value: dataRow2.values[0],
15575
+ value: childValue,
15433
15576
  ...linkColor && { color: linkColor },
15434
15577
  lineNumber
15435
15578
  });
@@ -15677,6 +15820,16 @@ function parseExtendedChartFull(content, palette) {
15677
15820
  result.diagnostics,
15678
15821
  lineNumber
15679
15822
  );
15823
+ if (result.type === "funnel" && dataRow.values[0] < 0) {
15824
+ result.diagnostics.push(
15825
+ emit(NEGATIVE_VALUE_DX, lineNumber, {
15826
+ value: dataRow.values[0],
15827
+ label: rawLabel,
15828
+ channel: "funnel stage sizes"
15829
+ })
15830
+ );
15831
+ continue;
15832
+ }
15680
15833
  result.data.push({
15681
15834
  label: rawLabel,
15682
15835
  // In-bounds by values.length === 1 guard above.
@@ -16016,6 +16169,7 @@ function parseEventLine(content, palette) {
16016
16169
  let currentEra = null;
16017
16170
  let eraIndent = -1;
16018
16171
  let currentEventIndent = 0;
16172
+ let pendingDescBreak = false;
16019
16173
  const aliasMap = /* @__PURE__ */ new Map();
16020
16174
  for (let i = 0; i < lines.length; i++) {
16021
16175
  const line11 = lines[i];
@@ -16023,6 +16177,7 @@ function parseEventLine(content, palette) {
16023
16177
  const trimmed = line11.trim();
16024
16178
  if (!trimmed) {
16025
16179
  currentTagGroup = null;
16180
+ pendingDescBreak = true;
16026
16181
  continue;
16027
16182
  }
16028
16183
  if (trimmed.startsWith("//")) continue;
@@ -16090,6 +16245,9 @@ function parseEventLine(content, palette) {
16090
16245
  continue;
16091
16246
  }
16092
16247
  if (currentEvent && indent > currentEventIndent) {
16248
+ if (pendingDescBreak && currentEvent.description.length > 0)
16249
+ currentEvent.description.push("");
16250
+ pendingDescBreak = false;
16093
16251
  const descLine = trimmed.startsWith("- ") ? `\u2022 ${trimmed.substring(2)}` : trimmed;
16094
16252
  currentEvent.description.push(descLine);
16095
16253
  continue;
@@ -16312,10 +16470,10 @@ function resolveFutureEvents(events) {
16312
16470
  e.futureSpan = [lo, hi];
16313
16471
  });
16314
16472
  } else if (lo === null && hi !== null) {
16315
- const left = hi - pad3;
16473
+ const left2 = hi - pad3;
16316
16474
  group.forEach((e, k) => {
16317
- e.dateValue = left + (hi - left) * (k + 1) / (g + 1);
16318
- e.futureSpan = [left, hi];
16475
+ e.dateValue = left2 + (hi - left2) * (k + 1) / (g + 1);
16476
+ e.futureSpan = [left2, hi];
16319
16477
  });
16320
16478
  } else {
16321
16479
  group.forEach((e, k) => {
@@ -17579,8 +17737,8 @@ function parseC4(content, palette) {
17579
17737
  const indent = measureIndent(line11);
17580
17738
  if (inDeployment) {
17581
17739
  while (deployStack.length > 0) {
17582
- const top = deployStack[deployStack.length - 1];
17583
- if (top.indent < indent) break;
17740
+ const top2 = deployStack[deployStack.length - 1];
17741
+ if (top2.indent < indent) break;
17584
17742
  deployStack.pop();
17585
17743
  }
17586
17744
  if (indent === 0 && (C4_IS_A_RE.test(trimmed) || ELEMENT_RE.test(trimmed))) {
@@ -17658,8 +17816,8 @@ function parseC4(content, palette) {
17658
17816
  continue;
17659
17817
  }
17660
17818
  while (stack.length > 0) {
17661
- const top = stack[stack.length - 1];
17662
- if (top.indent < indent) break;
17819
+ const top2 = stack[stack.length - 1];
17820
+ if (top2.indent < indent) break;
17663
17821
  stack.pop();
17664
17822
  }
17665
17823
  const containerMatch = trimmed.match(CONTAINER_RE3);
@@ -19435,11 +19593,11 @@ function parseGantt(content, palette) {
19435
19593
  let hadDeeperPop = false;
19436
19594
  let lastPoppedTaskRef = null;
19437
19595
  while (blockStack.length > 0) {
19438
- const top = blockStack[blockStack.length - 1];
19439
- if (indent <= top.indent) {
19440
- if (top.indent > indent) hadDeeperPop = true;
19441
- if (top.containerType === "task" && top.taskRef) {
19442
- lastPoppedTaskRef = top.taskRef;
19596
+ const top2 = blockStack[blockStack.length - 1];
19597
+ if (indent <= top2.indent) {
19598
+ if (top2.indent > indent) hadDeeperPop = true;
19599
+ if (top2.containerType === "task" && top2.taskRef) {
19600
+ lastPoppedTaskRef = top2.taskRef;
19443
19601
  }
19444
19602
  blockStack.pop();
19445
19603
  } else {
@@ -20612,6 +20770,19 @@ function parseMap(content, palette) {
20612
20770
  delete meta[k];
20613
20771
  }
20614
20772
  }
20773
+ if (own !== "heat" && meta[own] !== void 0) {
20774
+ const n = Number(meta[own]);
20775
+ if (Number.isFinite(n) && n < 0) {
20776
+ diagnostics.push(
20777
+ emit(NEGATIVE_VALUE_DX, line11, {
20778
+ value: n,
20779
+ label: `${own}: ${meta[own]}`,
20780
+ channel: own === "size" ? "marker sizes" : "edge widths"
20781
+ })
20782
+ );
20783
+ delete meta[own];
20784
+ }
20785
+ }
20615
20786
  }
20616
20787
  function handleDirective2(key, value, line11) {
20617
20788
  const d = result.directives;
@@ -23389,17 +23560,17 @@ function hasCycle(n, edges) {
23389
23560
  stack.push({ v: s, i: 0 });
23390
23561
  color[s] = 1;
23391
23562
  while (stack.length) {
23392
- const top = stack[stack.length - 1];
23393
- const nbrs = adj.get(top.v) ?? [];
23394
- if (top.i < nbrs.length) {
23395
- const w = nbrs[top.i++];
23563
+ const top2 = stack[stack.length - 1];
23564
+ const nbrs = adj.get(top2.v) ?? [];
23565
+ if (top2.i < nbrs.length) {
23566
+ const w = nbrs[top2.i++];
23396
23567
  if (color[w] === 1) return true;
23397
23568
  if (color[w] === 0) {
23398
23569
  color[w] = 1;
23399
23570
  stack.push({ v: w, i: 0 });
23400
23571
  }
23401
23572
  } else {
23402
- color[top.v] = 2;
23573
+ color[top2.v] = 2;
23403
23574
  stack.pop();
23404
23575
  }
23405
23576
  }
@@ -24191,8 +24362,8 @@ function parseNodeLine2(trimmed, lineNumber, _palette, counter, aliasMap, diagno
24191
24362
  }
24192
24363
  function attachNode3(node, indent, indentStack, result, nodesWithChildren) {
24193
24364
  while (indentStack.length > 0) {
24194
- const top = indentStack[indentStack.length - 1];
24195
- if (top.indent < indent) break;
24365
+ const top2 = indentStack[indentStack.length - 1];
24366
+ if (top2.indent < indent) break;
24196
24367
  indentStack.pop();
24197
24368
  }
24198
24369
  if (indentStack.length > 0) {
@@ -26638,8 +26809,8 @@ function parseNodeLine3(trimmed, lineNumber, counter, aliasMap, diagnostics, bad
26638
26809
  }
26639
26810
  function attachNode4(node, indent, indentStack, result) {
26640
26811
  while (indentStack.length > 0) {
26641
- const top = indentStack[indentStack.length - 1];
26642
- if (top.indent < indent) break;
26812
+ const top2 = indentStack[indentStack.length - 1];
26813
+ if (top2.indent < indent) break;
26643
26814
  indentStack.pop();
26644
26815
  }
26645
26816
  if (indentStack.length > 0) {
@@ -33639,13 +33810,13 @@ function renderLegendSvg(groups, options) {
33639
33810
  }
33640
33811
  const { groupBg, pillBorder } = legendChromeColors(palette, isDark);
33641
33812
  const parts = [];
33642
- let bottom = 0;
33643
- let left = Infinity;
33644
- let right = 0;
33813
+ let bottom2 = 0;
33814
+ let left2 = Infinity;
33815
+ let right2 = 0;
33645
33816
  const track = (x, y, w, h) => {
33646
- left = Math.min(left, x);
33647
- right = Math.max(right, x + w);
33648
- bottom = Math.max(bottom, y + h);
33817
+ left2 = Math.min(left2, x);
33818
+ right2 = Math.max(right2, x + w);
33819
+ bottom2 = Math.max(bottom2, y + h);
33649
33820
  };
33650
33821
  if (layout.activeCapsule) {
33651
33822
  const c = layout.activeCapsule;
@@ -33661,8 +33832,8 @@ function renderLegendSvg(groups, options) {
33661
33832
  const svg = `<g${classAttr}${activeAttr}>${parts.join("")}</g>`;
33662
33833
  return {
33663
33834
  svg,
33664
- height: bottom,
33665
- width: right - (left === Infinity ? 0 : left)
33835
+ height: bottom2,
33836
+ width: right2 - (left2 === Infinity ? 0 : left2)
33666
33837
  };
33667
33838
  }
33668
33839
  var init_legend_svg = __esm({
@@ -33901,7 +34072,7 @@ var init_shared = __esm({
33901
34072
 
33902
34073
  // src/charts-d3/bar.ts
33903
34074
  import { scaleBand, scaleLinear as scaleLinear5 } from "d3-scale";
33904
- import { max as d3max } from "d3-array";
34075
+ import { max as d3max, min as d3min } from "d3-array";
33905
34076
  function seriesValues(pt, seriesCount) {
33906
34077
  const out = [pt.value];
33907
34078
  for (let s = 1; s < seriesCount; s++) out.push(pt.extraValues?.[s - 1] ?? 0);
@@ -33925,7 +34096,7 @@ function renderBar(svg, chart, width, height, colors, palette, isDark, textColor
33925
34096
  return multiSeries ? chart.seriesNameColors?.[seriesIdx] ?? colors[seriesIdx % colors.length] : colors[catIdx % colors.length];
33926
34097
  };
33927
34098
  const fillOf = (c) => shapeFill(palette, c, isDark, { mode: fillMode });
33928
- const top = reserveHeader(
34099
+ const top2 = reserveHeader(
33929
34100
  svg,
33930
34101
  chart,
33931
34102
  colors,
@@ -33936,11 +34107,20 @@ function renderBar(svg, chart, width, height, colors, palette, isDark, textColor
33936
34107
  inlineTitle
33937
34108
  );
33938
34109
  const perCat = data.map((d) => seriesValues(d, seriesCount));
33939
- const maxVal = stacked ? d3max(perCat, (vals) => vals.reduce((a, b) => a + b, 0)) ?? 0 : d3max(perCat, (vals) => d3max(vals) ?? 0) ?? 0;
33940
- const niceMax = maxVal === 0 ? 1 : maxVal;
33941
- const leftLabels = horizontal ? data.map((d) => d.label) : [fmtNum(niceMax), fmtNum(niceMax / 2)];
34110
+ const maxVal = stacked ? d3max(
34111
+ perCat,
34112
+ (vals) => vals.filter((v) => v > 0).reduce((a, b) => a + b, 0)
34113
+ ) ?? 0 : d3max(perCat, (vals) => d3max(vals) ?? 0) ?? 0;
34114
+ const minVal = stacked ? d3min(
34115
+ perCat,
34116
+ (vals) => vals.filter((v) => v < 0).reduce((a, b) => a + b, 0)
34117
+ ) ?? 0 : d3min(perCat, (vals) => d3min(vals) ?? 0) ?? 0;
34118
+ const hiVal = Math.max(0, maxVal);
34119
+ const loVal = Math.min(0, minVal);
34120
+ const niceMax = hiVal === 0 && loVal === 0 ? 1 : hiVal;
34121
+ const leftLabels = horizontal ? data.map((d) => d.label) : [fmtNum(niceMax), fmtNum(niceMax / 2), fmtNum(loVal), fmtNum(loVal / 2)];
33942
34122
  const m = {
33943
- top: top + 8,
34123
+ top: top2 + 8,
33944
34124
  right: 32,
33945
34125
  bottom: 64,
33946
34126
  left: computeLeftMargin(chart.ylabel, leftLabels)
@@ -33951,7 +34131,7 @@ function renderBar(svg, chart, width, height, colors, palette, isDark, textColor
33951
34131
  const catRange = horiz ? [m.top, m.top + plotH] : [m.left, m.left + plotW];
33952
34132
  const cat = scaleBand().domain(data.map((d) => d.label)).range(catRange).padding(0.3);
33953
34133
  const valRange = horiz ? [m.left, m.left + plotW] : [m.top + plotH, m.top];
33954
- const val = scaleLinear5().domain([0, niceMax]).nice().range(valRange);
34134
+ const val = scaleLinear5().domain([loVal, niceMax]).nice().range(valRange);
33955
34135
  for (const t of val.ticks(6)) {
33956
34136
  if (horiz) {
33957
34137
  const x = val(t);
@@ -33976,7 +34156,8 @@ function renderBar(svg, chart, width, height, colors, palette, isDark, textColor
33976
34156
  data.forEach((d, ci) => {
33977
34157
  const base = cat(d.label) ?? 0;
33978
34158
  const vals = seriesValues(d, seriesCount);
33979
- let acc = 0;
34159
+ let accPos = 0;
34160
+ let accNeg = 0;
33980
34161
  vals.forEach((v, s) => {
33981
34162
  const stroke2 = colorFor(s, ci, seriesCount === 1 ? d.color : void 0);
33982
34163
  const fill2 = fillOf(stroke2);
@@ -33990,6 +34171,7 @@ function renderBar(svg, chart, width, height, colors, palette, isDark, textColor
33990
34171
  seriesName: multiSeries ? sName : void 0
33991
34172
  };
33992
34173
  if (stacked) {
34174
+ const acc = v < 0 ? accNeg : accPos;
33993
34175
  if (horiz) {
33994
34176
  const x0 = val(acc);
33995
34177
  const x1 = val(acc + v);
@@ -34033,7 +34215,8 @@ function renderBar(svg, chart, width, height, colors, palette, isDark, textColor
34033
34215
  textColor
34034
34216
  );
34035
34217
  }
34036
- acc += v;
34218
+ if (v < 0) accNeg += v;
34219
+ else accPos += v;
34037
34220
  } else {
34038
34221
  const off = inner(s) ?? 0;
34039
34222
  const bw = inner.bandwidth();
@@ -34049,13 +34232,16 @@ function renderBar(svg, chart, width, height, colors, palette, isDark, textColor
34049
34232
  stroke2,
34050
34233
  tag
34051
34234
  );
34235
+ const txt = fmtNum(v);
34236
+ const approxW = txt.length * 7 + 6;
34237
+ const inside = v < 0 ? x1 - approxW < m.left : x1 + approxW > m.left + plotW;
34052
34238
  drawValueLabel(
34053
34239
  svg,
34054
- fmtNum(v),
34055
- x1 + 6,
34240
+ txt,
34241
+ v < 0 ? inside ? x1 + 6 : x1 - 6 : inside ? x1 - 6 : x1 + 6,
34056
34242
  base + off + bw / 2 + 4,
34057
34243
  textColor,
34058
- "start"
34244
+ v < 0 !== inside ? "end" : "start"
34059
34245
  );
34060
34246
  } else {
34061
34247
  const y1 = val(v);
@@ -34069,11 +34255,13 @@ function renderBar(svg, chart, width, height, colors, palette, isDark, textColor
34069
34255
  stroke2,
34070
34256
  tag
34071
34257
  );
34258
+ const yOut = v < 0 ? y1 + 14 : y1 - 6;
34259
+ const yInside = v < 0 ? yOut > m.top + plotH - 2 : yOut < m.top + 2;
34072
34260
  drawValueLabel(
34073
34261
  svg,
34074
34262
  fmtNum(v),
34075
34263
  base + off + bw / 2,
34076
- y1 - 6,
34264
+ yInside ? v < 0 ? y1 - 6 : y1 + 14 : yOut,
34077
34265
  textColor
34078
34266
  );
34079
34267
  }
@@ -34127,7 +34315,7 @@ function renderLine(svg, chart, width, height, colors, palette, isDark, textColo
34127
34315
  if (axisOf(s) === side) owners.push(s);
34128
34316
  return owners.length === 1 ? seriesColor(owners[0]) : void 0;
34129
34317
  };
34130
- const top = reserveHeader(
34318
+ const top2 = reserveHeader(
34131
34319
  svg,
34132
34320
  chart,
34133
34321
  colors,
@@ -34162,7 +34350,7 @@ function renderLine(svg, chart, width, height, colors, palette, isDark, textColo
34162
34350
  const [loL, hiL] = extentFor("left");
34163
34351
  const [loR, hiR] = dual ? extentFor("right") : [0, 1];
34164
34352
  const m = {
34165
- top: top + 8,
34353
+ top: top2 + 8,
34166
34354
  right: dual ? computeLeftMargin(chart.yrlabel, [fmtNum(hiR), fmtNum(loR)]) : 32,
34167
34355
  bottom: 64,
34168
34356
  left: computeLeftMargin(chart.ylabel, [fmtNum(hiL), fmtNum(loL)])
@@ -34278,9 +34466,9 @@ function renderPie(svg, chart, width, height, palette, isDark, textColor, topIns
34278
34466
  const fillMode = chart.fillMode;
34279
34467
  const total = data.reduce((a, d) => a + d.value, 0);
34280
34468
  const cx = width / 2;
34281
- const top = topInset + 12;
34282
- const availH = height - top;
34283
- const cy = top + availH / 2;
34469
+ const top2 = topInset + 12;
34470
+ const availH = height - top2;
34471
+ const cy = top2 + availH / 2;
34284
34472
  const labels = data.map((d) => {
34285
34473
  const pct = Math.round(d.value / total * 100);
34286
34474
  const nm = chart.noName ? "" : d.label;
@@ -34291,8 +34479,8 @@ function renderPie(svg, chart, width, height, palette, isDark, textColor, topIns
34291
34479
  return [nm, tail].filter(Boolean).join(" \u2014 ");
34292
34480
  });
34293
34481
  const maxLabelLen = labels.reduce((m, s) => Math.max(m, s.length), 0);
34294
- const MARGIN11 = 6;
34295
- const halfW = width / 2 - MARGIN11;
34482
+ const MARGIN12 = 6;
34483
+ const halfW = width / 2 - MARGIN12;
34296
34484
  const rH = availH / 2 - availH * 0.06;
34297
34485
  const labelExtent = 1.27 + 0.06 * maxLabelLen;
34298
34486
  const rLabeled = Math.min(rH, halfW / labelExtent);
@@ -34419,9 +34607,9 @@ function renderRadar(svg, chart, width, height, colors, palette, isDark, textCol
34419
34607
  for (let s = 0; s < seriesCount; s++) allValues.push(seriesValue2(d, s));
34420
34608
  const maxValue = Math.max(...allValues) * 1.15 || 1;
34421
34609
  const cx = width / 2;
34422
- const top = topInset + 8;
34423
- const cy = top + (height - top) / 2;
34424
- const radius = Math.min(width / 2 - 130, (height - top) / 2 - 50);
34610
+ const top2 = topInset + 8;
34611
+ const cy = top2 + (height - top2) / 2;
34612
+ const radius = Math.min(width / 2 - 130, (height - top2) / 2 - 50);
34425
34613
  const angle = (i) => -Math.PI / 2 + i * 2 * Math.PI / n;
34426
34614
  const pt = (i, r) => [
34427
34615
  cx + Math.cos(angle(i)) * r,
@@ -34497,9 +34685,9 @@ function renderPolarArea(svg, chart, width, height, palette, isDark, textColor,
34497
34685
  const total = data.reduce((a, d) => a + d.value, 0);
34498
34686
  const maxValue = Math.max(...data.map((d) => d.value)) || 1;
34499
34687
  const cx = width / 2;
34500
- const top = topInset + 8;
34501
- const cy = top + (height - top) / 2;
34502
- const outerR = Math.min(width / 2 - 200, (height - top) / 2 - 40);
34688
+ const top2 = topInset + 8;
34689
+ const cy = top2 + (height - top2) / 2;
34690
+ const outerR = Math.min(width / 2 - 200, (height - top2) / 2 - 40);
34503
34691
  const innerR = outerR * 0.14;
34504
34692
  const segColors = getSegmentColors(palette, n);
34505
34693
  const g = svg.append("g").attr("transform", `translate(${cx},${cy})`);
@@ -34549,9 +34737,9 @@ function renderFunnel(svg, chart, width, height, colors, palette, isDark, topIns
34549
34737
  const n = sorted.length;
34550
34738
  if (n === 0) return;
34551
34739
  const fillMode = chart.fillMode;
34552
- const top = topInset + 8;
34553
- const bottom = height - 30;
34554
- const H2 = bottom - top;
34740
+ const top2 = topInset + 8;
34741
+ const bottom2 = height - 30;
34742
+ const H2 = bottom2 - top2;
34555
34743
  const bandH = H2 / n;
34556
34744
  const maxValue = sorted[0].value || 1;
34557
34745
  const sideFont = Math.max(11, Math.min(21, width / 52));
@@ -34608,7 +34796,7 @@ function renderFunnel(svg, chart, width, height, colors, palette, isDark, topIns
34608
34796
  const stroke2 = d.color ?? colors[chart.data.indexOf(d) % colors.length];
34609
34797
  const fill2 = shapeFill(palette, stroke2, isDark, { mode: fillMode });
34610
34798
  const { topW, botW } = bandWidthsAt(plotW, i);
34611
- const y0 = top + i * bandH;
34799
+ const y0 = top2 + i * bandH;
34612
34800
  const y1 = y0 + bandH;
34613
34801
  const seg = svg.append("polygon").attr(
34614
34802
  "points",
@@ -34697,12 +34885,12 @@ function renderHeatmap(svg, chart, width, height, palette, isDark, textColor, bg
34697
34885
  return hslToHex(h, targetS, targetL);
34698
34886
  };
34699
34887
  const rowLabelW = Math.max(0, ...rows.map((r) => measureText(r.label, 13))) + 16;
34700
- const left = 20 + rowLabelW;
34701
- const top = topInset + 28;
34702
- const right = 24;
34703
- const bottom = 24;
34704
- const plotW = width - left - right;
34705
- const plotH = height - top - bottom;
34888
+ const left2 = 20 + rowLabelW;
34889
+ const top2 = topInset + 28;
34890
+ const right2 = 24;
34891
+ const bottom2 = 24;
34892
+ const plotW = width - left2 - right2;
34893
+ const plotH = height - top2 - bottom2;
34706
34894
  const cw = plotW / ncols;
34707
34895
  const ch = plotH / nrows;
34708
34896
  const REF2 = 100;
@@ -34716,26 +34904,26 @@ function renderHeatmap(svg, chart, width, height, palette, isDark, textColor, bg
34716
34904
  );
34717
34905
  const rotate = cols.some((c) => measureText(c, 12) > cw * 0.85);
34718
34906
  cols.forEach((c, ci) => {
34719
- const x = left + ci * cw + cw / 2;
34907
+ const x = left2 + ci * cw + cw / 2;
34720
34908
  const t = svg.append("text").attr("class", "dgmo-axis-label").attr("data-filter-attr", "data-col-key").attr("data-filter-value", c).attr("fill", textColor).attr("font-size", 12).attr("font-family", FONT_FAMILY).text(c);
34721
34909
  if (rotate) {
34722
- t.attr("transform", `translate(${x},${top - 8}) rotate(-40)`).attr(
34910
+ t.attr("transform", `translate(${x},${top2 - 8}) rotate(-40)`).attr(
34723
34911
  "text-anchor",
34724
34912
  "start"
34725
34913
  );
34726
34914
  } else {
34727
- t.attr("x", x).attr("y", top - 8).attr("text-anchor", "middle");
34915
+ t.attr("x", x).attr("y", top2 - 8).attr("text-anchor", "middle");
34728
34916
  }
34729
34917
  });
34730
34918
  rows.forEach((row, ri) => {
34731
- svg.append("text").attr("class", "dgmo-axis-label").attr("data-filter-attr", "data-row-key").attr("data-filter-value", row.label).attr("x", left - 10).attr("y", top + ri * ch + ch / 2 + 4).attr("text-anchor", "end").attr("fill", textColor).attr("font-size", 13).attr("font-family", FONT_FAMILY).text(row.label);
34919
+ svg.append("text").attr("class", "dgmo-axis-label").attr("data-filter-attr", "data-row-key").attr("data-filter-value", row.label).attr("x", left2 - 10).attr("y", top2 + ri * ch + ch / 2 + 4).attr("text-anchor", "end").attr("fill", textColor).attr("font-size", 13).attr("font-family", FONT_FAMILY).text(row.label);
34732
34920
  row.values.forEach((v, ci) => {
34733
34921
  const t = maxValue === minValue ? 0.5 : (v - minValue) / (maxValue - minValue);
34734
34922
  const ramp = gradientAt(t);
34735
34923
  const cell = outline ? baseBg : ramp;
34736
34924
  const colLabel = cols[ci] ?? `Col ${ci + 1}`;
34737
34925
  const cellKey = `${row.label} \xB7 ${colLabel}`;
34738
- const r = svg.append("rect").attr("x", left + ci * cw).attr("y", top + ri * ch).attr("width", cw).attr("height", ch).attr("fill", cell).attr("stroke", outline ? ramp : bgColor).attr("stroke-width", outline ? 1.5 : 2).attr("data-row-key", row.label).attr("data-col-key", colLabel);
34926
+ const r = svg.append("rect").attr("x", left2 + ci * cw).attr("y", top2 + ri * ch).attr("width", cw).attr("height", ch).attr("fill", cell).attr("stroke", outline ? ramp : bgColor).attr("stroke-width", outline ? 1.5 : 2).attr("data-row-key", row.label).attr("data-col-key", colLabel);
34739
34927
  tagDatum(r, {
34740
34928
  line: row.lineNumber,
34741
34929
  key: cellKey,
@@ -34744,7 +34932,7 @@ function renderHeatmap(svg, chart, width, height, palette, isDark, textColor, bg
34744
34932
  color: ramp
34745
34933
  });
34746
34934
  if (!chart.noValue) {
34747
- const label = svg.append("text").attr("x", left + ci * cw + cw / 2).attr("y", top + ri * ch + ch / 2 + cellFont / 3).attr("text-anchor", "middle").attr("fill", labelTint(ramp)).attr("font-size", cellFont).attr("font-weight", 600).attr("font-family", FONT_FAMILY).text(fmtNum(v));
34935
+ const label = svg.append("text").attr("x", left2 + ci * cw + cw / 2).attr("y", top2 + ri * ch + ch / 2 + cellFont / 3).attr("text-anchor", "middle").attr("fill", labelTint(ramp)).attr("font-size", cellFont).attr("font-weight", 600).attr("font-family", FONT_FAMILY).text(fmtNum(v));
34748
34936
  tagDatum(label, {
34749
34937
  line: row.lineNumber,
34750
34938
  key: cellKey,
@@ -35029,9 +35217,9 @@ function renderSankey(svg, chart, width, height, colors, bgColor, textColor, top
35029
35217
  const layers = Array.from({ length: maxRank + 1 }, () => []);
35030
35218
  for (const n of node.values()) layers[n.rank].push(n);
35031
35219
  const plotLeft = 16;
35032
- const top = topInset + 8;
35220
+ const top2 = topInset + 8;
35033
35221
  const plotW = width - plotLeft - 16 - measureText("M", 14);
35034
- const plotH = height - top - 24;
35222
+ const plotH = height - top2 - 24;
35035
35223
  let valueScale = Infinity;
35036
35224
  for (const layer of layers) {
35037
35225
  const tot = layer.reduce((a, n) => a + n.value, 0);
@@ -35043,7 +35231,7 @@ function renderSankey(svg, chart, width, height, colors, bgColor, textColor, top
35043
35231
  const placeLayer = (layer) => {
35044
35232
  layer.sort((a, b) => a.order - b.order);
35045
35233
  const totH = layer.reduce((a, n) => a + n.value * valueScale, 0) + (layer.length - 1) * NODE_GAP;
35046
- let y = top + (plotH - totH) / 2;
35234
+ let y = top2 + (plotH - totH) / 2;
35047
35235
  for (const n of layer) {
35048
35236
  n.h = n.value * valueScale;
35049
35237
  n.x = layerX(n.rank);
@@ -35149,11 +35337,11 @@ function renderChord(svg, chart, width, height, colors, palette, isDark, textCol
35149
35337
  const n = names.length;
35150
35338
  const idx = new Map(names.map((nm, i) => [nm, i]));
35151
35339
  const colorOf2 = (i) => colors[i % colors.length];
35152
- const top = topInset + 8;
35340
+ const top2 = topInset + 8;
35153
35341
  const cx = width / 2;
35154
- const cy = top + (height - top) / 2;
35342
+ const cy = top2 + (height - top2) / 2;
35155
35343
  const maxLabel = Math.max(0, ...names.map((nm) => measureText(nm, 14)));
35156
- const radius = Math.min(width / 2 - maxLabel - 60, (height - top) / 2 - 50);
35344
+ const radius = Math.min(width / 2 - maxLabel - 60, (height - top2) / 2 - 50);
35157
35345
  const angle = (i) => -Math.PI / 2 + i * 2 * Math.PI / n;
35158
35346
  const pos = (i) => [
35159
35347
  cx + Math.cos(angle(i)) * radius,
@@ -35598,7 +35786,7 @@ function renderInto(s, content, palette, isDark, width, height, textColor, muted
35598
35786
  return true;
35599
35787
  case "radar": {
35600
35788
  const groups = std.noLegend ? [] : getSimpleChartLegendGroups(std, colors);
35601
- const top = injectLegendGroups(
35789
+ const top2 = injectLegendGroups(
35602
35790
  s,
35603
35791
  groups,
35604
35792
  palette,
@@ -35617,7 +35805,7 @@ function renderInto(s, content, palette, isDark, width, height, textColor, muted
35617
35805
  isDark,
35618
35806
  textColor,
35619
35807
  mutedColor,
35620
- top
35808
+ top2
35621
35809
  );
35622
35810
  return true;
35623
35811
  }
@@ -35670,7 +35858,7 @@ function renderInto(s, content, palette, isDark, width, height, textColor, muted
35670
35858
  return true;
35671
35859
  case "scatter": {
35672
35860
  const groups = ext.noLegend ? [] : getExtendedChartLegendGroups(ext, seriesColors2);
35673
- const top = injectLegendGroups(
35861
+ const top2 = injectLegendGroups(
35674
35862
  s,
35675
35863
  groups,
35676
35864
  palette,
@@ -35689,7 +35877,7 @@ function renderInto(s, content, palette, isDark, width, height, textColor, muted
35689
35877
  isDark,
35690
35878
  textColor,
35691
35879
  mutedColor,
35692
- top
35880
+ top2
35693
35881
  );
35694
35882
  return true;
35695
35883
  }
@@ -35720,7 +35908,7 @@ function renderInto(s, content, palette, isDark, width, height, textColor, muted
35720
35908
  return true;
35721
35909
  case "function": {
35722
35910
  const groups = ext.noLegend ? [] : getExtendedChartLegendGroups(ext, seriesColors2);
35723
- const top = injectLegendGroups(
35911
+ const top2 = injectLegendGroups(
35724
35912
  s,
35725
35913
  groups,
35726
35914
  palette,
@@ -35737,7 +35925,7 @@ function renderInto(s, content, palette, isDark, width, height, textColor, muted
35737
35925
  seriesColors2,
35738
35926
  textColor,
35739
35927
  mutedColor,
35740
- top,
35928
+ top2,
35741
35929
  palette,
35742
35930
  isDark
35743
35931
  );
@@ -36160,17 +36348,17 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
36160
36348
  const maxLeft = p.x - CARD_INSET;
36161
36349
  const minLeft = p.x - CARD_W + CARD_INSET;
36162
36350
  let lane = laneRight.length;
36163
- let left = Math.max(preferred, minLeft);
36351
+ let left2 = Math.max(preferred, minLeft);
36164
36352
  for (let l = 0; l < laneRight.length; l++) {
36165
36353
  const want = Math.max(preferred, laneRight[l] + FAN_GAP, minLeft);
36166
36354
  if (want <= maxLeft) {
36167
36355
  lane = l;
36168
- left = want;
36356
+ left2 = want;
36169
36357
  break;
36170
36358
  }
36171
36359
  }
36172
36360
  p.lane = lane;
36173
- p.left = Math.max(6, left);
36361
+ p.left = Math.max(6, left2);
36174
36362
  laneRight[lane] = p.left + CARD_W;
36175
36363
  }
36176
36364
  }
@@ -36302,8 +36490,8 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
36302
36490
  }
36303
36491
  const geo = placed.map((p) => {
36304
36492
  const near = p.side === "above" ? spineY - laneNear(p) : spineY + laneNear(p);
36305
- const top = p.side === "above" ? near - p.cardH : near;
36306
- return { p, near, top };
36493
+ const top2 = p.side === "above" ? near - p.cardH : near;
36494
+ return { p, near, top: top2 };
36307
36495
  });
36308
36496
  const leaderCrossesBox = (owner, near) => {
36309
36497
  const lo = Math.min(spineY, near);
@@ -36322,9 +36510,9 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
36322
36510
  applyHoverHooks(leader, p);
36323
36511
  }
36324
36512
  let shelfClipSeq = 0;
36325
- for (const { p, top } of geo) {
36326
- const left = p.left;
36327
- const cardG = svg.append("g").attr("class", "dgmo-event-card").attr("transform", `translate(${left}, ${top})`).attr("data-line-number", p.lineNumber);
36513
+ for (const { p, top: top2 } of geo) {
36514
+ const left2 = p.left;
36515
+ const cardG = svg.append("g").attr("class", "dgmo-event-card").attr("transform", `translate(${left2}, ${top2})`).attr("data-line-number", p.lineNumber);
36328
36516
  applyHoverHooks(cardG, p);
36329
36517
  if (p.kind === "era") {
36330
36518
  cardG.attr("data-era", p.era.name).attr("data-era-collapsed", "true");
@@ -36882,15 +37070,7 @@ function axisBreakPaths(cx, cy) {
36882
37070
  return [wave(cx - BREAK_GAP / 2), wave(cx + BREAK_GAP / 2)];
36883
37071
  }
36884
37072
  function wrapDescription(lines, charsPerLine) {
36885
- const out = [];
36886
- for (const line11 of lines) {
36887
- if (line11 === "") {
36888
- out.push({ text: "", kind: "plain" });
36889
- continue;
36890
- }
36891
- out.push(...wrapDescriptionLines([line11], charsPerLine));
36892
- }
36893
- return out;
37073
+ return wrapDescriptionLines([...lines], charsPerLine);
36894
37074
  }
36895
37075
  function renderBody(cardG, lines, bodyColor, palette, startBaseline = CARD_BODY_TOP + DESC_FONT, bulletColors = [], bulletMeta = []) {
36896
37076
  let y = startBaseline;
@@ -37014,27 +37194,27 @@ function renderFigureBody(fig, view, parts, partColor, emphKey, form, palette, i
37014
37194
  const muscleFill = mix(palette.bg, palette.border, 0.7);
37015
37195
  const seam = palette.bg;
37016
37196
  const outlineStroke = palette.textMuted;
37017
- const gid = `body-skin-${vx}-${vy}`;
37197
+ const gid2 = `body-skin-${vx}-${vy}`;
37018
37198
  defs.push(
37019
- `<linearGradient id="${gid}" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="${mix(palette.surface, palette.bg, 0.4)}"/><stop offset="1" stop-color="${mix(palette.border, palette.bg, 0.3)}"/></linearGradient>`
37199
+ `<linearGradient id="${gid2}" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="${mix(palette.surface, palette.bg, 0.4)}"/><stop offset="1" stop-color="${mix(palette.border, palette.bg, 0.3)}"/></linearGradient>`
37020
37200
  );
37021
37201
  let out = "";
37022
37202
  if (form === "skin") {
37023
- out += `<path d="${fig.outline}" fill="url(#${gid})"/>`;
37203
+ out += `<path d="${fig.outline}" fill="url(#${gid2})"/>`;
37024
37204
  for (const d of fig.headPaths) {
37025
- out += `<path d="${d}" fill="url(#${gid})" stroke="${outlineStroke}" stroke-width="2.5"/>`;
37205
+ out += `<path d="${d}" fill="url(#${gid2})" stroke="${outlineStroke}" stroke-width="2.5"/>`;
37026
37206
  }
37027
37207
  const hairFill = mix(palette.text, palette.bg, 0.6);
37028
37208
  for (const d of fig.hairPaths) {
37029
37209
  out += `<path d="${d}" fill="${hairFill}" stroke="${outlineStroke}" stroke-width="1.5"/>`;
37030
37210
  }
37031
37211
  } else {
37032
- out += `<path d="${fig.outline}" fill="url(#${gid})"/>`;
37212
+ out += `<path d="${fig.outline}" fill="url(#${gid2})"/>`;
37033
37213
  for (const d of fig.base) {
37034
37214
  out += `<path d="${d}" fill="${muscleFill}" fill-opacity="0.55" stroke="${seam}" stroke-width="1"/>`;
37035
37215
  }
37036
37216
  for (const d of fig.headPaths) {
37037
- out += `<path d="${d}" fill="url(#${gid})" stroke="${outlineStroke}" stroke-width="2.5"/>`;
37217
+ out += `<path d="${d}" fill="url(#${gid2})" stroke="${outlineStroke}" stroke-width="2.5"/>`;
37038
37218
  }
37039
37219
  for (const d of fig.hairPaths) {
37040
37220
  out += `<path d="${d}" fill="none" stroke="${outlineStroke}" stroke-width="2.5"/>`;
@@ -37107,10 +37287,10 @@ function gutterLabels(r, palette) {
37107
37287
  const cx = vx + vw / 2;
37108
37288
  const list = [...r.anchors.values()];
37109
37289
  const band = vw * 0.1;
37110
- const left = list.filter((a) => a.x < cx - band);
37111
- const right = list.filter((a) => a.x > cx + band);
37290
+ const left2 = list.filter((a) => a.x < cx - band);
37291
+ const right2 = list.filter((a) => a.x > cx + band);
37112
37292
  const mid = list.filter((a) => a.x >= cx - band && a.x <= cx + band).sort((a, b) => a.y - b.y);
37113
- for (const a of mid) (left.length <= right.length ? left : right).push(a);
37293
+ for (const a of mid) (left2.length <= right2.length ? left2 : right2).push(a);
37114
37294
  let labels = "";
37115
37295
  const place = (arr, side) => {
37116
37296
  const gx = side === "L" ? vx - 14 : vx + vw + 14;
@@ -37130,8 +37310,8 @@ function gutterLabels(r, palette) {
37130
37310
  }
37131
37311
  }
37132
37312
  };
37133
- place(left, "L");
37134
- place(right, "R");
37313
+ place(left2, "L");
37314
+ place(right2, "R");
37135
37315
  return labels;
37136
37316
  }
37137
37317
  function renderBody2(container, parsed, palette, _isDark, _onClickItem, exportDims, tagOverride) {
@@ -37202,17 +37382,17 @@ function renderBody2(container, parsed, palette, _isDark, _onClickItem, exportDi
37202
37382
  const aR = fR.anchors.get(nm);
37203
37383
  if (!aL && !aR) continue;
37204
37384
  seen.add(nm);
37205
- const left = aL ? mapL(nearestCenter(aL, fL.vx + fL.vw)) : void 0;
37206
- const right = aR ? mapR(nearestCenter(aR, fR.vx)) : void 0;
37207
- const ys = [left?.y, right?.y].filter((v) => v != null);
37385
+ const left2 = aL ? mapL(nearestCenter(aL, fL.vx + fL.vw)) : void 0;
37386
+ const right2 = aR ? mapR(nearestCenter(aR, fR.vx)) : void 0;
37387
+ const ys = [left2?.y, right2?.y].filter((v) => v != null);
37208
37388
  items.push({
37209
37389
  name: partLabel(part),
37210
37390
  note: part.notes.length ? part.notes[0] : "",
37211
37391
  color: (aL ?? aR).color,
37212
37392
  emph: (aL ?? aR).emph,
37213
37393
  line: part.lineNumber,
37214
- ...left && { left },
37215
- ...right && { right },
37394
+ ...left2 && { left: left2 },
37395
+ ...right2 && { right: right2 },
37216
37396
  y: ys.reduce((s, v) => s + v, 0) / ys.length
37217
37397
  });
37218
37398
  }
@@ -37408,25 +37588,25 @@ function renderVersionControl(container, parsed, palette, isDark, onClickItem, e
37408
37588
  for (const n of sorted) {
37409
37589
  const p = pos.get(n.key);
37410
37590
  const w = label.get(n.key).lw + SHELF_PAD * 2;
37411
- const left = p.x - w / 2;
37591
+ const left2 = p.x - w / 2;
37412
37592
  let row = rowRight.length;
37413
37593
  for (let l = 0; l < rowRight.length; l++)
37414
- if (rowRight[l] + shelfGap <= left) {
37594
+ if (rowRight[l] + shelfGap <= left2) {
37415
37595
  row = l;
37416
37596
  break;
37417
37597
  }
37418
- const top = bandTop + row * (SHELF_H + ROW_GAP);
37419
- rowRight[row] = left + w;
37598
+ const top2 = bandTop + row * (SHELF_H + ROW_GAP);
37599
+ rowRight[row] = left2 + w;
37420
37600
  placements.push({
37421
37601
  node: n,
37422
37602
  kind: "msg",
37423
37603
  x: p.x,
37424
- y: top,
37604
+ y: top2,
37425
37605
  anchor: "start",
37426
- shelfLeft: Math.max(4, left),
37427
- shelfTop: top,
37606
+ shelfLeft: Math.max(4, left2),
37607
+ shelfTop: top2,
37428
37608
  shelfW: w,
37429
- leader: { x1: p.x, y1: p.y + DOT, x2: p.x, y2: top }
37609
+ leader: { x1: p.x, y1: p.y + DOT, x2: p.x, y2: top2 }
37430
37610
  });
37431
37611
  const stack = above.get(n.key) ?? [];
37432
37612
  stack.forEach(
@@ -37689,15 +37869,15 @@ function drawGraph(g, parsed, palette, TB, pos, placements, label, colorOf2, byK
37689
37869
  let ty = pl.y + 4;
37690
37870
  let anchor = pl.anchor;
37691
37871
  if (pl.shelfW != null) {
37692
- const left = pl.shelfLeft;
37693
- const top = pl.shelfTop;
37872
+ const left2 = pl.shelfLeft;
37873
+ const top2 = pl.shelfTop;
37694
37874
  const w = pl.shelfW;
37695
37875
  const clipId = `dgmo-vc-shelf-${shelfSeq++}`;
37696
- g.append("clipPath").attr("id", clipId).append("rect").attr("x", left).attr("y", top).attr("width", w).attr("height", SHELF_H).attr("rx", SHELF_EDGE2);
37697
- g.append("rect").attr("x", left).attr("y", top).attr("width", w).attr("height", SHELF_H).attr("rx", SHELF_EDGE2).attr("fill", gh ? palette.bg : mix(c, palette.bg, SHELF_TINT2)).attr("data-branch", n.branch).attr("opacity", gh ? 0.5 : 1);
37698
- g.append("rect").attr("x", left).attr("y", top).attr("width", w).attr("height", SHELF_LIP2).attr("clip-path", `url(#${clipId})`).attr("fill", c).attr("data-branch", n.branch).attr("opacity", gh ? 0.4 : 1);
37699
- tx = left + SHELF_PAD;
37700
- ty = top + SHELF_H / 2 + 4;
37876
+ g.append("clipPath").attr("id", clipId).append("rect").attr("x", left2).attr("y", top2).attr("width", w).attr("height", SHELF_H).attr("rx", SHELF_EDGE2);
37877
+ g.append("rect").attr("x", left2).attr("y", top2).attr("width", w).attr("height", SHELF_H).attr("rx", SHELF_EDGE2).attr("fill", gh ? palette.bg : mix(c, palette.bg, SHELF_TINT2)).attr("data-branch", n.branch).attr("opacity", gh ? 0.5 : 1);
37878
+ g.append("rect").attr("x", left2).attr("y", top2).attr("width", w).attr("height", SHELF_LIP2).attr("clip-path", `url(#${clipId})`).attr("fill", c).attr("data-branch", n.branch).attr("opacity", gh ? 0.4 : 1);
37879
+ tx = left2 + SHELF_PAD;
37880
+ ty = top2 + SHELF_H / 2 + 4;
37701
37881
  anchor = "start";
37702
37882
  }
37703
37883
  const t = g.append("text").attr("x", tx).attr("y", ty).attr("text-anchor", anchor).attr("font-size", 12).attr("data-branch", n.branch).attr("opacity", gh ? 0.6 : 1);
@@ -37836,18 +38016,18 @@ function centerHeavyChildren(node) {
37836
38016
  const weighted = node.children.map((child) => ({ child, weight: countDescendants(child) })).sort((a, b) => b.weight - a.weight);
37837
38017
  const result = new Array(weighted.length);
37838
38018
  const mid = Math.floor((weighted.length - 1) / 2);
37839
- let left = mid;
37840
- let right = mid;
38019
+ let left2 = mid;
38020
+ let right2 = mid;
37841
38021
  for (let i = 0; i < weighted.length; i++) {
37842
38022
  const w = weighted[i];
37843
38023
  if (i === 0) {
37844
38024
  result[mid] = w.child;
37845
38025
  } else if (i % 2 === 1) {
37846
- right++;
37847
- result[right] = w.child;
38026
+ right2++;
38027
+ result[right2] = w.child;
37848
38028
  } else {
37849
- left--;
37850
- result[left] = w.child;
38029
+ left2--;
38030
+ result[left2] = w.child;
37851
38031
  }
37852
38032
  }
37853
38033
  node.children = result;
@@ -38182,8 +38362,8 @@ function layoutOrg(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, expan
38182
38362
  }
38183
38363
  }
38184
38364
  const screenRect = (ax, ay, w, h2) => {
38185
- const { left, top } = screenTopLeft(ax, ay, w, h2);
38186
- return { left, top, right: left + w, bottom: top + h2 };
38365
+ const { left: left2, top: top2 } = screenTopLeft(ax, ay, w, h2);
38366
+ return { left: left2, top: top2, right: left2 + w, bottom: top2 + h2 };
38187
38367
  };
38188
38368
  const growBBox = (r) => {
38189
38369
  if (r.left < minX) minX = r.left;
@@ -38397,11 +38577,11 @@ function layoutOrg(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, expan
38397
38577
  let descMaxX = -Infinity;
38398
38578
  let descMinY = Infinity;
38399
38579
  let descMaxY = -Infinity;
38400
- const growDesc = (left, top, right, bottom) => {
38401
- if (left < descMinX) descMinX = left;
38402
- if (right > descMaxX) descMaxX = right;
38403
- if (top < descMinY) descMinY = top;
38404
- if (bottom > descMaxY) descMaxY = bottom;
38580
+ const growDesc = (left2, top2, right2, bottom2) => {
38581
+ if (left2 < descMinX) descMinX = left2;
38582
+ if (right2 > descMaxX) descMaxX = right2;
38583
+ if (top2 < descMinY) descMinY = top2;
38584
+ if (bottom2 > descMaxY) descMaxY = bottom2;
38405
38585
  };
38406
38586
  for (const desc of allDesc) {
38407
38587
  const innerBounds = containerBoundsMap.get(desc.data.orgNode.id);
@@ -38773,11 +38953,12 @@ function extractExportSvg(container, theme, palette) {
38773
38953
  svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
38774
38954
  svgEl.style.fontFamily = FONT_FAMILY;
38775
38955
  svgEl.querySelectorAll("[data-export-ignore]").forEach((el) => el.remove());
38776
- return svgEl.outerHTML;
38956
+ return serializeSvg(svgEl);
38777
38957
  }
38778
38958
  var init_export_container = __esm({
38779
38959
  "src/utils/export-container.ts"() {
38780
38960
  "use strict";
38961
+ init_svg_serialize();
38781
38962
  init_fonts();
38782
38963
  }
38783
38964
  });
@@ -39739,16 +39920,16 @@ function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, e
39739
39920
  let totalWidth = 0;
39740
39921
  let totalHeight = 0;
39741
39922
  for (const node of layoutNodes) {
39742
- const right = node.x + node.width / 2;
39743
- const bottom = node.y + node.height;
39744
- if (right > totalWidth) totalWidth = right;
39745
- if (bottom > totalHeight) totalHeight = bottom;
39923
+ const right2 = node.x + node.width / 2;
39924
+ const bottom2 = node.y + node.height;
39925
+ if (right2 > totalWidth) totalWidth = right2;
39926
+ if (bottom2 > totalHeight) totalHeight = bottom2;
39746
39927
  }
39747
39928
  for (const c of layoutContainers) {
39748
- const right = c.x + c.width;
39749
- const bottom = c.y + c.height;
39750
- if (right > totalWidth) totalWidth = right;
39751
- if (bottom > totalHeight) totalHeight = bottom;
39929
+ const right2 = c.x + c.width;
39930
+ const bottom2 = c.y + c.height;
39931
+ if (right2 > totalWidth) totalWidth = right2;
39932
+ if (bottom2 > totalHeight) totalHeight = bottom2;
39752
39933
  }
39753
39934
  for (const edge of layoutEdges) {
39754
39935
  for (const p of edge.points) {
@@ -40378,7 +40559,7 @@ async function renderSitemapForExport(content, theme, palette) {
40378
40559
  }
40379
40560
  svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
40380
40561
  svgEl.style.fontFamily = FONT_FAMILY;
40381
- const svgHtml = svgEl.outerHTML;
40562
+ const svgHtml = serializeSvg(svgEl);
40382
40563
  document.body.removeChild(container);
40383
40564
  return svgHtml;
40384
40565
  }
@@ -40386,6 +40567,7 @@ var DIAGRAM_PADDING2, MAX_SCALE2, TITLE_HEIGHT2, ARROWHEAD_W, ARROWHEAD_H, EDGE_
40386
40567
  var init_renderer6 = __esm({
40387
40568
  "src/sitemap/renderer.ts"() {
40388
40569
  "use strict";
40570
+ init_svg_serialize();
40389
40571
  init_tag_groups();
40390
40572
  init_parsing();
40391
40573
  init_inline_header();
@@ -40819,7 +41001,7 @@ function renderKanbanForExport(content, theme, palette) {
40819
41001
  exportMode: true
40820
41002
  });
40821
41003
  const svgEl = container.querySelector("svg");
40822
- return svgEl?.outerHTML ?? "";
41004
+ return svgEl ? serializeSvg(svgEl) : "";
40823
41005
  }
40824
41006
  function drawSwimlaneIcon(parent, x, y, isActive, palette) {
40825
41007
  const iconG = parent.append("g").attr("class", "kanban-swimlane-icon").attr("transform", `translate(${x}, ${y})`);
@@ -41154,6 +41336,7 @@ var DIAGRAM_PADDING3, COLUMN_GAP, COLUMN_HEADER_HEIGHT, COLUMN_PADDING, COLUMN_M
41154
41336
  var init_renderer7 = __esm({
41155
41337
  "src/kanban/renderer.ts"() {
41156
41338
  "use strict";
41339
+ init_svg_serialize();
41157
41340
  init_tag_groups();
41158
41341
  init_parsing();
41159
41342
  init_fonts();
@@ -42667,7 +42850,7 @@ function renderERDiagramForExport(content, theme, palette) {
42667
42850
  }
42668
42851
  svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
42669
42852
  svgEl.style.fontFamily = FONT_FAMILY;
42670
- return svgEl.outerHTML;
42853
+ return serializeSvg(svgEl);
42671
42854
  } finally {
42672
42855
  document.body.removeChild(container);
42673
42856
  }
@@ -42676,6 +42859,7 @@ var DIAGRAM_PADDING5, MAX_SCALE4, TABLE_FONT_SIZE2, COLUMN_FONT_SIZE2, EDGE_LABE
42676
42859
  var init_renderer9 = __esm({
42677
42860
  "src/er/renderer.ts"() {
42678
42861
  "use strict";
42862
+ init_svg_serialize();
42679
42863
  init_tag_groups();
42680
42864
  init_parsing();
42681
42865
  init_fonts();
@@ -42785,6 +42969,16 @@ var layout_exports5 = {};
42785
42969
  __export(layout_exports5, {
42786
42970
  layoutSketch: () => layoutSketch
42787
42971
  });
42972
+ function resolveAutoFlags(f = {}) {
42973
+ return {
42974
+ normalizeOrigin: f.normalizeOrigin ?? true,
42975
+ sortRootsBySource: f.sortRootsBySource ?? true,
42976
+ resolveOverlap: f.resolveOverlap ?? true,
42977
+ groupCollisionAsRect: f.groupCollisionAsRect ?? true,
42978
+ flowPlaceUnpositioned: f.flowPlaceUnpositioned ?? true,
42979
+ avoidEdges: f.avoidEdges ?? true
42980
+ };
42981
+ }
42788
42982
  function unitRect(c, r) {
42789
42983
  return { c, r, w: SKETCH_SEP, h: SKETCH_SEP };
42790
42984
  }
@@ -42817,7 +43011,7 @@ function nearestFree(base, occupied) {
42817
43011
  }
42818
43012
  return { c: base.c, r: base.r };
42819
43013
  }
42820
- function layoutChildren(box, nodesById, warn) {
43014
+ function layoutChildren(box, nodesById, warn, flags) {
42821
43015
  const occupied = [];
42822
43016
  const children = [];
42823
43017
  const pending = [];
@@ -42829,13 +43023,17 @@ function layoutChildren(box, nodesById, warn) {
42829
43023
  continue;
42830
43024
  }
42831
43025
  const target = unitRect(node.at.c, node.at.r);
42832
- const spot = nearestFree(target, occupied);
43026
+ const spot = flags.resolveOverlap ? nearestFree(target, occupied) : { c: node.at.c, r: node.at.r };
42833
43027
  if (spot.c !== node.at.c || spot.r !== node.at.r) {
42834
43028
  warn(node.lineNumber, node.label);
42835
43029
  }
42836
43030
  occupied.push(unitRect(spot.c, spot.r));
42837
43031
  children.push({ node, c: spot.c, r: spot.r });
42838
43032
  }
43033
+ if (!flags.flowPlaceUnpositioned) {
43034
+ for (const node of pending) children.push({ node, c: 0, r: 0 });
43035
+ pending.length = 0;
43036
+ }
42839
43037
  let flowRow = occupied.length > 0 ? Math.max(...occupied.map((o) => o.r)) + SKETCH_SEP : 0;
42840
43038
  let flowCol = 0;
42841
43039
  const wrapAt = Math.max(
@@ -42882,6 +43080,7 @@ function layoutSketch(parsed, options = {}) {
42882
43080
  )
42883
43081
  );
42884
43082
  };
43083
+ const flags = resolveAutoFlags(options.autoLayout);
42885
43084
  const collapsed = collapseSketch(parsed, options.collapsedBoxes);
42886
43085
  const nodesById = new Map(collapsed.nodes.map((n) => [n.id, n]));
42887
43086
  const padHsX = SKETCH_GEOMETRY.boxPadPx / SKETCH_HALF_SLOT_X;
@@ -42890,10 +43089,39 @@ function layoutSketch(parsed, options = {}) {
42890
43089
  const boxLocal = /* @__PURE__ */ new Map();
42891
43090
  const inExpandedBox = /* @__PURE__ */ new Set();
42892
43091
  for (const box of collapsed.boxes) {
42893
- const local = layoutChildren(box, nodesById, overlapWarn);
43092
+ const local = layoutChildren(box, nodesById, overlapWarn, flags);
42894
43093
  boxLocal.set(box.id, local);
42895
43094
  for (const child of local.children) inExpandedBox.add(child.node.id);
42896
43095
  }
43096
+ const allNodesById = new Map(parsed.nodes.map((n) => [n.id, n]));
43097
+ const noWarn = () => {
43098
+ };
43099
+ const virtualLocal = /* @__PURE__ */ new Map();
43100
+ for (const box of collapsed.virtualBoxes) {
43101
+ virtualLocal.set(box.id, layoutChildren(box, allNodesById, noWarn, flags));
43102
+ }
43103
+ const footWs = SKETCH_FOOT_W / SKETCH_HALF_SLOT_X;
43104
+ const footHs = SKETCH_FOOT_H / SKETCH_HALF_SLOT_Y;
43105
+ const virtualCardSpot = (boxId, spot) => {
43106
+ const local = virtualLocal.get(boxId);
43107
+ if (local.children.length === 0) return { c: spot.c, r: spot.r };
43108
+ let minC = Infinity;
43109
+ let minR = Infinity;
43110
+ let maxC = -Infinity;
43111
+ let maxR = -Infinity;
43112
+ for (const ch of local.children) {
43113
+ minC = Math.min(minC, ch.c);
43114
+ minR = Math.min(minR, ch.r);
43115
+ maxC = Math.max(maxC, ch.c + footWs);
43116
+ maxR = Math.max(maxR, ch.r + footHs);
43117
+ }
43118
+ const cx = spot.c + (minC + maxC) / 2;
43119
+ const cy = spot.r + (minR + maxR) / 2 + (padHsY - bandHs) / 2;
43120
+ return {
43121
+ c: Math.round(cx - footWs / 2),
43122
+ r: Math.round(cy - footHs / 2)
43123
+ };
43124
+ };
42897
43125
  const rootUnits = [];
42898
43126
  for (const node of collapsed.nodes) {
42899
43127
  if (!inExpandedBox.has(node.id)) rootUnits.push({ kind: "shape", node });
@@ -42904,14 +43132,27 @@ function layoutSketch(parsed, options = {}) {
42904
43132
  for (const box of collapsed.boxes) {
42905
43133
  rootUnits.push({ kind: "box", box });
42906
43134
  }
42907
- rootUnits.sort((a, b) => {
42908
- const la = a.kind === "shape" ? a.node.lineNumber : a.box.lineNumber;
42909
- const lb = b.kind === "shape" ? b.node.lineNumber : b.box.lineNumber;
42910
- return la - lb;
42911
- });
43135
+ const lineOf = (u) => u.kind === "shape" ? u.node.lineNumber : u.box.lineNumber;
43136
+ const atOf = (u) => u.kind === "shape" ? u.node.at : u.box.at;
43137
+ if (flags.sortRootsBySource) {
43138
+ rootUnits.sort((a, b) => lineOf(a) - lineOf(b));
43139
+ } else {
43140
+ rootUnits.sort((a, b) => {
43141
+ const aa = atOf(a);
43142
+ const ba = atOf(b);
43143
+ if (aa && ba) {
43144
+ return aa.r - ba.r || aa.c - ba.c || lineOf(a) - lineOf(b);
43145
+ }
43146
+ if (aa) return -1;
43147
+ if (ba) return 1;
43148
+ return lineOf(a) - lineOf(b);
43149
+ });
43150
+ }
42912
43151
  const rectFor = (unit, c, r) => {
42913
- if (unit.kind === "box") {
42914
- const local = boxLocal.get(unit.box.id);
43152
+ if (unit.kind !== "shape" && flags.groupCollisionAsRect) {
43153
+ const local = (unit.kind === "box" ? boxLocal : virtualLocal).get(
43154
+ unit.box.id
43155
+ );
42915
43156
  return {
42916
43157
  c: c + local.extent.c - padHsX,
42917
43158
  r: r + local.extent.r - bandHs,
@@ -42925,26 +43166,31 @@ function layoutSketch(parsed, options = {}) {
42925
43166
  const placedAt = /* @__PURE__ */ new Map();
42926
43167
  const pending = [];
42927
43168
  for (const unit of rootUnits) {
42928
- const at = unit.kind === "shape" ? unit.node.at : unit.box.at;
43169
+ const at = atOf(unit);
42929
43170
  if (at === null) {
42930
43171
  pending.push(unit);
42931
43172
  continue;
42932
43173
  }
42933
43174
  const base = rectFor(unit, at.c, at.r);
42934
43175
  let spot = { c: at.c, r: at.r };
42935
- if (collidesAny(base, occupied)) {
43176
+ if (flags.resolveOverlap && unit.kind === "shape" && collidesAny(base, occupied)) {
42936
43177
  const freed = nearestFree(base, occupied);
42937
43178
  spot = {
42938
43179
  c: at.c + (freed.c - base.c),
42939
43180
  r: at.r + (freed.r - base.r)
42940
43181
  };
42941
- const line11 = unit.kind === "shape" ? unit.node.lineNumber : unit.box.lineNumber;
42942
- const label = unit.kind === "shape" ? unit.node.label : unit.box.label;
42943
- overlapWarn(line11, label);
43182
+ overlapWarn(unit.node.lineNumber, unit.node.label);
42944
43183
  }
42945
43184
  occupied.push(rectFor(unit, spot.c, spot.r));
42946
43185
  placedAt.set(unit, spot);
42947
43186
  }
43187
+ if (!flags.flowPlaceUnpositioned) {
43188
+ for (const unit of pending) {
43189
+ occupied.push(rectFor(unit, 0, 0));
43190
+ placedAt.set(unit, { c: 0, r: 0 });
43191
+ }
43192
+ pending.length = 0;
43193
+ }
42948
43194
  let flowRow = occupied.length > 0 ? Math.ceil(Math.max(...occupied.map((o) => o.r + o.h))) : 0;
42949
43195
  let flowCol = 0;
42950
43196
  const wrapAt = Math.max(
@@ -42971,8 +43217,10 @@ function layoutSketch(parsed, options = {}) {
42971
43217
  const spot = placedAt.get(u);
42972
43218
  return rectFor(u, spot.c, spot.r);
42973
43219
  });
42974
- const cMin = allRects.length > 0 ? Math.min(...allRects.map((r) => r.c)) : 0;
42975
- const rMin = allRects.length > 0 ? Math.min(...allRects.map((r) => r.r)) : 0;
43220
+ const liveCMin = allRects.length > 0 ? Math.min(...allRects.map((r) => r.c)) : 0;
43221
+ const liveRMin = allRects.length > 0 ? Math.min(...allRects.map((r) => r.r)) : 0;
43222
+ const cMin = flags.normalizeOrigin ? liveCMin : Math.min(options.frozenOrigin?.c ?? liveCMin, liveCMin);
43223
+ const rMin = flags.normalizeOrigin ? liveRMin : Math.min(options.frozenOrigin?.r ?? liveRMin, liveRMin);
42976
43224
  const toPx = (c, r) => ({
42977
43225
  x: (c - cMin) * SKETCH_HALF_SLOT_X,
42978
43226
  y: (r - rMin) * SKETCH_HALF_SLOT_Y
@@ -42997,14 +43245,15 @@ function layoutSketch(parsed, options = {}) {
42997
43245
  h: SKETCH_FOOT_H
42998
43246
  });
42999
43247
  } else if (unit.kind === "virtual") {
43000
- const { x, y } = toPx(spot.c, spot.r);
43248
+ const cardSpot = virtualCardSpot(unit.box.id, spot);
43249
+ const { x, y } = toPx(cardSpot.c, cardSpot.r);
43001
43250
  nodes.push({
43002
43251
  id: unit.box.id,
43003
43252
  label: unit.box.label,
43004
43253
  shape: "rectangle",
43005
43254
  metadata: unit.box.metadata,
43006
43255
  lineNumber: unit.box.lineNumber,
43007
- slot: spot,
43256
+ slot: cardSpot,
43008
43257
  x,
43009
43258
  y,
43010
43259
  w: SKETCH_FOOT_W,
@@ -43061,7 +43310,13 @@ function layoutSketch(parsed, options = {}) {
43061
43310
  });
43062
43311
  }
43063
43312
  }
43064
- {
43313
+ if (flags.avoidEdges) {
43314
+ const authored = /* @__PURE__ */ new Set();
43315
+ for (const unit of rootUnits) {
43316
+ if (atOf(unit) !== null) {
43317
+ authored.add(unit.kind === "shape" ? unit.node.id : unit.box.id);
43318
+ }
43319
+ }
43065
43320
  const centerOf = (id) => {
43066
43321
  const n = nodes.find((nd) => nd.id === id);
43067
43322
  if (n) return { x: n.x + n.w / 2, y: n.y + n.h / 2 };
@@ -43095,6 +43350,7 @@ function layoutSketch(parsed, options = {}) {
43095
43350
  let moved = false;
43096
43351
  for (const n of nodes) {
43097
43352
  if (n.boxLabel) continue;
43353
+ if (authored.has(n.id)) continue;
43098
43354
  for (const e of collapsed.edges) {
43099
43355
  if (e.sourceId === n.id || e.targetId === n.id) continue;
43100
43356
  const a = centerOf(e.sourceId);
@@ -43145,7 +43401,8 @@ function layoutSketch(parsed, options = {}) {
43145
43401
  edges: collapsed.edges,
43146
43402
  width,
43147
43403
  height,
43148
- diagnostics
43404
+ diagnostics,
43405
+ origin: { c: cMin, r: rMin }
43149
43406
  };
43150
43407
  }
43151
43408
  var init_layout5 = __esm({
@@ -43328,7 +43585,7 @@ function drawMarkdownBlock(container, text, opts) {
43328
43585
  const textEl = container.append("text").attr("x", line11.x).attr("y", y).attr("font-size", fontSize);
43329
43586
  let cursorX = line11.x;
43330
43587
  const segs = line11.segments.slice();
43331
- if (clamped && isLast) {
43588
+ if (clamped && isLast && !opts.noEllipsis) {
43332
43589
  segs.push({ text: ELLIPSIS, bold: false });
43333
43590
  }
43334
43591
  for (const seg of segs) {
@@ -43342,7 +43599,11 @@ function drawMarkdownBlock(container, text, opts) {
43342
43599
  cursorX += w;
43343
43600
  }
43344
43601
  }
43345
- return shown.length * lineHeight;
43602
+ return {
43603
+ height: shown.length * lineHeight,
43604
+ shown: shown.length,
43605
+ total: visualLines.length
43606
+ };
43346
43607
  }
43347
43608
  var BOLD_WIDTH_FACTOR2, INDENT_PX, BULLET_HANG_PX, ELLIPSIS, BULLET;
43348
43609
  var init_markdown_card = __esm({
@@ -43395,14 +43656,6 @@ function drawTypeBadge(g, kind, color, bx, by) {
43395
43656
  return;
43396
43657
  }
43397
43658
  }
43398
- function metaRows(metadata, tagGroups) {
43399
- const rows = [];
43400
- for (const grp of tagGroups) {
43401
- const v = metadata[tagAttrKey(grp.name)];
43402
- if (v !== void 0) rows.push([grp.name, v]);
43403
- }
43404
- return rows;
43405
- }
43406
43659
  function fitWrapped(label, maxWidth, maxFont = CARD_LABEL_MAX, minFont = CARD_LABEL_MIN, maxLines = 2) {
43407
43660
  for (let fs = maxFont; fs >= minFont; fs--) {
43408
43661
  const lines2 = wrapTextToWidth(label, fs, maxWidth, { hardBreak: true });
@@ -43421,7 +43674,8 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
43421
43674
  const {
43422
43675
  activeTagGroup,
43423
43676
  exportMode = false,
43424
- hideDescriptions = false
43677
+ hideDescriptions = false,
43678
+ splitCardIds
43425
43679
  } = options;
43426
43680
  const hideDesc = hideDescriptions || parsed.options.noDescriptions;
43427
43681
  const neutralFill = parsed.options.fillMode === "outline" ? themeBaseBg(palette, isDark) : mix(palette.textMuted, palette.bg, 12);
@@ -43686,7 +43940,7 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
43686
43940
  colorsFor(node.metadata),
43687
43941
  palette,
43688
43942
  isDark,
43689
- hideDesc ? [] : tagGroups
43943
+ !hideDesc && (splitCardIds?.includes(node.id) ?? false)
43690
43944
  );
43691
43945
  }
43692
43946
  const labelLayer = root.append("g").attr("class", "sk-edge-labels");
@@ -43713,7 +43967,7 @@ function drawBoxFrame(layer, box, colors, palette) {
43713
43967
  g.append("text").attr("x", box.x + box.w / 2).attr("y", startY + li * lineH).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", fit.fontSize).attr("font-weight", 800).attr("fill", palette.text).attr("opacity", BAND_LABEL_OPACITY).text(fit.lines[li]);
43714
43968
  }
43715
43969
  }
43716
- function drawNode(layer, node, colors, palette, isDark, tagGroups) {
43970
+ function drawNode(layer, node, colors, palette, isDark, splitCard) {
43717
43971
  void isDark;
43718
43972
  const g = layer.append("g").attr("class", node.isCollapsedBox ? "sk-node sk-box-collapsed" : "sk-node").attr("transform", `translate(${node.x},${node.y})`).attr("data-node-id", node.id).attr("data-line-number", node.lineNumber);
43719
43973
  for (const [k, v] of Object.entries(node.metadata)) {
@@ -43730,12 +43984,11 @@ function drawNode(layer, node, colors, palette, isDark, tagGroups) {
43730
43984
  g.append("text").attr("x", 10).attr("y", 20 + i * lineHeight).attr("font-size", NOTE_FONT_SIZE2).attr("fill", colors.text).text(line11);
43731
43985
  });
43732
43986
  } else {
43733
- const rows = node.isCollapsedBox ? [] : metaRows(node.metadata, tagGroups);
43734
43987
  const badge = node.shape !== "rectangle";
43735
43988
  const labelInset = badge ? 22 : 0;
43736
43989
  const solidLike = colors.stroke === colors.fill;
43737
43990
  const ruleColor = solidLike ? colors.text : colors.stroke;
43738
- if (node.description && !node.isCollapsedBox) {
43991
+ if (!node.isCollapsedBox && (node.description || splitCard)) {
43739
43992
  const fitH = fitWrapped(
43740
43993
  node.label,
43741
43994
  node.w - 24 - labelInset,
@@ -43756,33 +44009,37 @@ function drawNode(layer, node, colors, palette, isDark, tagGroups) {
43756
44009
  headerHeight: CARD_HEADER_H
43757
44010
  });
43758
44011
  g.append("line").attr("x1", 0).attr("y1", CARD_HEADER_H).attr("x2", node.w).attr("y2", CARD_HEADER_H).attr("stroke", ruleColor).attr("stroke-opacity", 0.3).attr("stroke-width", 1);
43759
- const inset = 12;
43760
- const bodyGap = 8;
43761
- const lh = CARD_META_FONT + 4;
43762
- const avail = node.h - CARD_HEADER_H - bodyGap - 8;
43763
- const body = g.append("g").attr("class", "sk-desc").attr("transform", `translate(${inset} ${CARD_HEADER_H + bodyGap})`);
43764
- drawMarkdownBlock(body, node.description, {
43765
- width: node.w - inset * 2,
43766
- fontSize: CARD_META_FONT,
43767
- lineHeight: lh,
43768
- color: colors.text,
43769
- // match the header label (contrast-aware in solid)
43770
- linkColor: colors.text,
43771
- maxLines: Math.max(1, Math.floor(avail / lh))
43772
- });
44012
+ if (node.description) {
44013
+ const inset = 12;
44014
+ const bodyGap = 8;
44015
+ const lh = CARD_META_FONT + 4;
44016
+ const avail = node.h - CARD_HEADER_H - bodyGap - 8;
44017
+ const body = g.append("g").attr("class", "sk-desc").attr("transform", `translate(${inset} ${CARD_HEADER_H + bodyGap})`);
44018
+ const block = drawMarkdownBlock(body, node.description, {
44019
+ width: node.w - inset * 2,
44020
+ fontSize: CARD_META_FONT,
44021
+ lineHeight: lh,
44022
+ color: colors.text,
44023
+ // match the header label (contrast-aware in solid)
44024
+ linkColor: colors.text,
44025
+ maxLines: Math.max(1, Math.floor(avail / lh)),
44026
+ noEllipsis: true
44027
+ });
44028
+ if (block.total > block.shown) {
44029
+ g.append("text").attr("class", "sk-desc-more").attr("x", node.w - 8).attr("y", node.h - 5).attr("text-anchor", "end").attr("font-size", 9).attr("fill", palette.textMuted).attr("data-line-number", node.lineNumber).style("cursor", "pointer").text(`+${block.total - block.shown} more in source`);
44030
+ }
44031
+ }
43773
44032
  if (badge) {
43774
44033
  drawTypeBadge(g, node.shape, colors.text, 10, (CARD_HEADER_H - 16) / 2);
43775
44034
  }
43776
44035
  return;
43777
44036
  }
43778
- const headerH = rows.length ? CARD_HEADER_H : node.h;
43779
- const fillTitle = rows.length === 0;
43780
44037
  const fit = fitWrapped(
43781
44038
  node.label,
43782
44039
  node.w - 24 - labelInset,
43783
- fillTitle ? CARD_TITLE_MAX : CARD_LABEL_MAX,
44040
+ CARD_TITLE_MAX,
43784
44041
  CARD_LABEL_MIN,
43785
- fillTitle ? 3 : 2
44042
+ 3
43786
44043
  );
43787
44044
  renderNodeCard(g, {
43788
44045
  width: node.w,
@@ -43795,18 +44052,7 @@ function drawNode(layer, node, colors, palette, isDark, tagGroups) {
43795
44052
  labelLines: fit.lines,
43796
44053
  labelColor: colors.text,
43797
44054
  labelFontSize: fit.fontSize,
43798
- headerHeight: headerH,
43799
- ...rows.length ? {
43800
- meta: {
43801
- rows,
43802
- fontSize: CARD_META_FONT,
43803
- lineHeight: CARD_META_FONT + 5,
43804
- separatorGap: 8,
43805
- separatorColor: ruleColor,
43806
- textColor: solidLike ? colors.text : palette.text,
43807
- keyX: 12
43808
- }
43809
- } : {}
44055
+ headerHeight: node.h
43810
44056
  });
43811
44057
  if (badge) {
43812
44058
  drawTypeBadge(g, node.shape, colors.text, 10, (CARD_HEADER_H - 16) / 2);
@@ -43842,8 +44088,8 @@ function assignEdgeSides(edges, rectById) {
43842
44088
  return { s: below ? "B" : "T", t: below ? "T" : "B" };
43843
44089
  }
43844
44090
  if (yOverlap >= 0 && yOverlap >= xOverlap) {
43845
- const right = dx >= 0;
43846
- return { s: right ? "R" : "L", t: right ? "L" : "R" };
44091
+ const right2 = dx >= 0;
44092
+ return { s: right2 ? "R" : "L", t: right2 ? "L" : "R" };
43847
44093
  }
43848
44094
  return { s: facing(dx, dy), t: facing(-dx, -dy) };
43849
44095
  });
@@ -44059,6 +44305,8 @@ function sketchEdgeGeometry(layout, offsets) {
44059
44305
  const n = normalOf(side);
44060
44306
  return 1 - (n.x * dx + n.y * dy) / len;
44061
44307
  };
44308
+ const W_BACK = 2.6;
44309
+ const backFacingCost = (from, to, side) => W_BACK * Math.max(0, facingCost(from, to, side) - 1);
44062
44310
  const ctx = layout.edges.map((edge) => {
44063
44311
  const source = rectById.get(edge.sourceId);
44064
44312
  const target = rectById.get(edge.targetId);
@@ -44093,6 +44341,7 @@ function sketchEdgeGeometry(layout, offsets) {
44093
44341
  const W_NODE = 100;
44094
44342
  const W_EDGE = 8;
44095
44343
  const W_PORT = 1.5;
44344
+ const W_PORT_SAME = 0.6;
44096
44345
  const isBox = (id) => portsById.has(id);
44097
44346
  const portClashCount = (self, s, t) => {
44098
44347
  const e = layout.edges[self];
@@ -44110,6 +44359,44 @@ function sketchEdgeGeometry(layout, offsets) {
44110
44359
  }
44111
44360
  return n;
44112
44361
  };
44362
+ const portStackCount = (self, _s, t) => {
44363
+ const e = layout.edges[self];
44364
+ if (isBox(e.targetId)) return 0;
44365
+ let n = 0;
44366
+ for (let j = 0; j < layout.edges.length; j++) {
44367
+ if (j === self) continue;
44368
+ const ej = layout.edges[j];
44369
+ if (ej.targetId === e.targetId && ej.sourceId !== e.sourceId && // not reciprocal
44370
+ chosen[j].t === t)
44371
+ n++;
44372
+ }
44373
+ return n;
44374
+ };
44375
+ const W_TURN = 0.55;
44376
+ const W_SCURVE = 1.8;
44377
+ const CURVE_STRAIGHT = 0.35;
44378
+ const curveCostPoly = (pts) => {
44379
+ let totalTurn = 0;
44380
+ let inflections = 0;
44381
+ let prevSign = 0;
44382
+ for (let i = 1; i < pts.length - 1; i++) {
44383
+ const ax = pts[i].x - pts[i - 1].x;
44384
+ const ay = pts[i].y - pts[i - 1].y;
44385
+ const bx = pts[i + 1].x - pts[i].x;
44386
+ const by = pts[i + 1].y - pts[i].y;
44387
+ const cross = ax * by - ay * bx;
44388
+ const dot = ax * bx + ay * by;
44389
+ if (ax === 0 && ay === 0) continue;
44390
+ if (bx === 0 && by === 0) continue;
44391
+ totalTurn += Math.abs(Math.atan2(cross, dot));
44392
+ const sign = cross > 1e-6 ? 1 : cross < -1e-6 ? -1 : 0;
44393
+ if (sign !== 0) {
44394
+ if (prevSign !== 0 && sign !== prevSign) inflections++;
44395
+ prevSign = sign;
44396
+ }
44397
+ }
44398
+ return totalTurn * W_TURN + inflections * W_SCURVE;
44399
+ };
44113
44400
  const scoreOf = (c, g, poly, self, polys2, s, t) => {
44114
44401
  let edgeCross = 0;
44115
44402
  for (let j = 0; j < polys2.length; j++) {
@@ -44117,7 +44404,7 @@ function sketchEdgeGeometry(layout, offsets) {
44117
44404
  const pj = polys2[j];
44118
44405
  if (pj) edgeCross += polyCrossings(poly, pj);
44119
44406
  }
44120
- return pathCrossings(g, c.obstacleRects) * W_NODE + edgeCross * W_EDGE + portClashCount(self, s, t) * W_PORT + facingCost(c.source, c.target, s) + facingCost(c.target, c.source, t);
44407
+ return pathCrossings(g, c.obstacleRects) * W_NODE + edgeCross * W_EDGE + portClashCount(self, s, t) * W_PORT + portStackCount(self, s, t) * W_PORT_SAME + curveCostPoly(poly) + facingCost(c.source, c.target, s) + facingCost(c.target, c.source, t) + backFacingCost(c.source, c.target, s) + backFacingCost(c.target, c.source, t);
44121
44408
  };
44122
44409
  const chosen = layout.edges.map(
44123
44410
  (_, i) => sides[i] ?? { s: "R", t: "L" }
@@ -44142,7 +44429,8 @@ function sketchEdgeGeometry(layout, offsets) {
44142
44429
  if (!c || !g || !p) continue;
44143
44430
  const cur = chosen[i];
44144
44431
  const curScore = scoreOf(c, g, p, i, polys, cur.s, cur.t);
44145
- if (curScore < W_EDGE && portClashCount(i, cur.s, cur.t) === 0) continue;
44432
+ if (curScore < W_EDGE && portClashCount(i, cur.s, cur.t) === 0 && portStackCount(i, cur.s, cur.t) === 0 && curveCostPoly(p) < CURVE_STRAIGHT && backFacingCost(c.source, c.target, cur.s) === 0 && backFacingCost(c.target, c.source, cur.t) === 0)
44433
+ continue;
44146
44434
  let bestScore = curScore;
44147
44435
  let bestG = g;
44148
44436
  let bestP = p;
@@ -44219,8 +44507,8 @@ var init_renderer10 = __esm({
44219
44507
  NODE_STROKE_WIDTH2 = 2;
44220
44508
  EDGE_STROKE_WIDTH2 = 2;
44221
44509
  EDGE_HIT_WIDTH = 18;
44222
- ARROWHEAD_W2 = 12;
44223
- ARROWHEAD_H2 = 8;
44510
+ ARROWHEAD_W2 = 18;
44511
+ ARROWHEAD_H2 = 12;
44224
44512
  DASH = "6 3";
44225
44513
  BAND_LABEL_FONT_SIZE = 19;
44226
44514
  BAND_LABEL_OPACITY = 0.55;
@@ -44587,6 +44875,18 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
44587
44875
  for (let li = 0; li < fitted.lines.length; li++) {
44588
44876
  groupG.append("text").attr("class", "bl-group-label").attr("x", group.x).attr("y", group.y - totalH / 2 + lineH / 2 + li * lineH).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-family", FONT_FAMILY).attr("font-size", fitted.fontSize).attr("font-weight", "600").attr("fill", palette.text).text(fitted.lines[li]);
44589
44877
  }
44878
+ if (group.childCount !== void 0 && group.childCount > 0) {
44879
+ const chipFont = Math.max(9, sMinNodeFontSize - 2);
44880
+ const chipH = chipFont + 7;
44881
+ const chipW = Math.max(
44882
+ chipH,
44883
+ String(group.childCount).length * chipFont * 0.62 + 10
44884
+ );
44885
+ const chipCx = gx + group.width - chipW / 2 - 6;
44886
+ const chipCy = gy + chipH / 2 + 6;
44887
+ groupG.append("rect").attr("class", "bl-collapse-count").attr("x", chipCx - chipW / 2).attr("y", chipCy - chipH / 2).attr("width", chipW).attr("height", chipH).attr("rx", chipH / 2).attr("ry", chipH / 2).attr("fill", palette.textMuted).attr("fill-opacity", 0.18);
44888
+ groupG.append("text").attr("class", "bl-collapse-count").attr("x", chipCx).attr("y", chipCy).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-family", FONT_FAMILY).attr("font-size", chipFont).attr("font-weight", "600").attr("fill", palette.text).text(String(group.childCount));
44889
+ }
44590
44890
  } else {
44591
44891
  groupG.append("rect").attr("x", gx).attr("y", gy).attr("width", group.width).attr("height", groupHeight).attr("rx", GROUP_RX).attr("ry", GROUP_RX).attr("fill", mix(palette.surface, palette.bg, 40)).attr("stroke", palette.textMuted).attr("stroke-width", 1).attr("stroke-opacity", 0.35);
44592
44892
  groupG.append("text").attr("class", "bl-group-label").attr("x", gx + group.width / 2).attr("y", gy + 18).attr("text-anchor", "middle").attr("font-family", FONT_FAMILY).attr("font-size", sGroupLabelFontSize).attr("font-weight", "600").attr("fill", palette.text).text(group.label);
@@ -44736,7 +45036,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
44736
45036
  maxTextWidth / (sDescFontSize * CHAR_WIDTH_RATIO)
44737
45037
  );
44738
45038
  const descLineH = sDescFontSize * DESC_LINE_HEIGHT;
44739
- const displayLen2 = (text) => text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*(.+?)\*\*/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/`(.+?)`/g, "$1").replace(/https?:\/\/\S+/g, (u) => u.slice(0, 20)).length;
45039
+ const displayLen2 = (text) => stripInlineMarkdown(text).length;
44740
45040
  const normalizedLines = [];
44741
45041
  for (const descLine of desc) {
44742
45042
  let normalized = descLine.startsWith("- ") ? "\u2022 " + descLine.slice(2) : descLine;
@@ -45003,6 +45303,17 @@ var init_renderer11 = __esm({
45003
45303
  }
45004
45304
  });
45005
45305
 
45306
+ // src/boxes-and-lines/node-metrics.ts
45307
+ var PHI, NODE_HEIGHT, NODE_WIDTH;
45308
+ var init_node_metrics = __esm({
45309
+ "src/boxes-and-lines/node-metrics.ts"() {
45310
+ "use strict";
45311
+ PHI = 1.618;
45312
+ NODE_HEIGHT = 60;
45313
+ NODE_WIDTH = Math.round(NODE_HEIGHT * PHI);
45314
+ }
45315
+ });
45316
+
45006
45317
  // src/boxes-and-lines/label-placement.ts
45007
45318
  function measureEdgeLabel(label, fontSize = EDGE_LABEL_FONT_SIZE7, maxWidth = LABEL_MAX_WIDTH) {
45008
45319
  let lines = wrapTextToWidth(label, fontSize, maxWidth, { hardBreak: true });
@@ -45384,9 +45695,9 @@ function layeredCandidates(parsed, sizes, opts) {
45384
45695
  const m = Math.floor(vals.length / 2);
45385
45696
  if (vals.length % 2 === 1) return vals[m];
45386
45697
  if (vals.length === 2) return (vals[0] + vals[1]) / 2;
45387
- const left = vals[m - 1] - vals[0];
45388
- const right = vals[vals.length - 1] - vals[m];
45389
- return left + right === 0 ? (vals[m - 1] + vals[m]) / 2 : (vals[m - 1] * right + vals[m] * left) / (left + right);
45698
+ const left2 = vals[m - 1] - vals[0];
45699
+ const right2 = vals[vals.length - 1] - vals[m];
45700
+ return left2 + right2 === 0 ? (vals[m - 1] + vals[m]) / 2 : (vals[m - 1] * right2 + vals[m] * left2) / (left2 + right2);
45390
45701
  };
45391
45702
  const wmedianRank = (r, useUp) => {
45392
45703
  const ids = ranks[r];
@@ -45712,7 +46023,7 @@ var NODESEP, RANKSEP, DUMMY_THICK, MARGIN4, W_REAL_REAL, W_REAL_DUMMY, W_DUMMY_D
45712
46023
  var init_layout_layered = __esm({
45713
46024
  "src/boxes-and-lines/layout-layered.ts"() {
45714
46025
  "use strict";
45715
- init_layout6();
46026
+ init_node_metrics();
45716
46027
  NODESEP = 50;
45717
46028
  RANKSEP = 60;
45718
46029
  DUMMY_THICK = 10;
@@ -45739,9 +46050,9 @@ function median(vals) {
45739
46050
  const m = Math.floor(vals.length / 2);
45740
46051
  if (vals.length % 2 === 1) return vals[m];
45741
46052
  if (vals.length === 2) return (vals[0] + vals[1]) / 2;
45742
- const left = vals[m - 1] - vals[0];
45743
- const right = vals[vals.length - 1] - vals[m];
45744
- return left + right === 0 ? (vals[m - 1] + vals[m]) / 2 : (vals[m - 1] * right + vals[m] * left) / (left + right);
46053
+ const left2 = vals[m - 1] - vals[0];
46054
+ const right2 = vals[vals.length - 1] - vals[m];
46055
+ return left2 + right2 === 0 ? (vals[m - 1] + vals[m]) / 2 : (vals[m - 1] * right2 + vals[m] * left2) / (left2 + right2);
45745
46056
  }
45746
46057
  function acyclicOrient(ids, edges) {
45747
46058
  const adj = /* @__PURE__ */ new Map();
@@ -46397,7 +46708,7 @@ var NODESEP2, RANKSEP2, DUMMY_THICK2, MARGIN5, GROUP_PAD, GROUP_LABEL_ZONE2, GRO
46397
46708
  var init_layout_grouped = __esm({
46398
46709
  "src/boxes-and-lines/layout-grouped.ts"() {
46399
46710
  "use strict";
46400
- init_layout6();
46711
+ init_node_metrics();
46401
46712
  NODESEP2 = 50;
46402
46713
  RANKSEP2 = 60;
46403
46714
  DUMMY_THICK2 = 10;
@@ -46412,6 +46723,282 @@ var init_layout_grouped = __esm({
46412
46723
  }
46413
46724
  });
46414
46725
 
46726
+ // src/boxes-and-lines/layout-stable-collapse.ts
46727
+ function bboxOf(rects) {
46728
+ let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;
46729
+ for (const r of rects) {
46730
+ x0 = Math.min(x0, left(r));
46731
+ y0 = Math.min(y0, top(r));
46732
+ x1 = Math.max(x1, right(r));
46733
+ y1 = Math.max(y1, bottom(r));
46734
+ }
46735
+ return {
46736
+ x: (x0 + x1) / 2,
46737
+ y: (y0 + y1) / 2,
46738
+ width: x1 - x0,
46739
+ height: y1 - y0
46740
+ };
46741
+ }
46742
+ function borderPoint(rect2, toward) {
46743
+ const dx = toward.x - rect2.x;
46744
+ const dy = toward.y - rect2.y;
46745
+ const sx = dx === 0 ? Infinity : rect2.width / 2 / Math.abs(dx);
46746
+ const sy = dy === 0 ? Infinity : rect2.height / 2 / Math.abs(dy);
46747
+ const s = Math.min(sx, sy);
46748
+ if (!Number.isFinite(s)) return { x: rect2.x, y: rect2.y };
46749
+ return { x: rect2.x + dx * s, y: rect2.y + dy * s };
46750
+ }
46751
+ function tryStableCollapseLayout(input) {
46752
+ const {
46753
+ parsed,
46754
+ collapseInfo,
46755
+ collapsedGroupLabels,
46756
+ previousPositions,
46757
+ sizes
46758
+ } = input;
46759
+ const prev = previousPositions;
46760
+ const rects = /* @__PURE__ */ new Map();
46761
+ for (const n of parsed.nodes) {
46762
+ const p = prev.get(n.label);
46763
+ const s = sizes.get(n.label);
46764
+ if (!p || !s) return null;
46765
+ rects.set(n.label, { x: p.x, y: p.y, width: s.width, height: s.height });
46766
+ }
46767
+ const ogByLabel = /* @__PURE__ */ new Map();
46768
+ for (const g of collapseInfo.originalGroups) ogByLabel.set(g.label, g);
46769
+ const descendantNodes = (label, seen = /* @__PURE__ */ new Set()) => {
46770
+ if (seen.has(label)) return [];
46771
+ seen.add(label);
46772
+ const g = ogByLabel.get(label);
46773
+ if (!g) return [];
46774
+ const out = [];
46775
+ for (const c of g.children) {
46776
+ if (ogByLabel.has(c)) out.push(...descendantNodes(c, seen));
46777
+ else out.push(c);
46778
+ }
46779
+ return out;
46780
+ };
46781
+ const newlyCollapsed = [];
46782
+ for (const label of collapsedGroupLabels) {
46783
+ const own = prev.get(gid(label));
46784
+ if (own) {
46785
+ rects.set(gid(label), {
46786
+ x: own.x,
46787
+ y: own.y,
46788
+ width: NODE_WIDTH,
46789
+ height: NODE_HEIGHT
46790
+ });
46791
+ continue;
46792
+ }
46793
+ const members = descendantNodes(label);
46794
+ if (members.length === 0) return null;
46795
+ const memberRects = [];
46796
+ for (const m of members) {
46797
+ const p = prev.get(m);
46798
+ if (!p) return null;
46799
+ memberRects.push({
46800
+ x: p.x,
46801
+ y: p.y,
46802
+ width: NODE_WIDTH,
46803
+ height: NODE_HEIGHT
46804
+ });
46805
+ }
46806
+ const bbox = bboxOf(memberRects);
46807
+ rects.set(gid(label), {
46808
+ x: bbox.x,
46809
+ y: bbox.y,
46810
+ width: NODE_WIDTH,
46811
+ height: NODE_HEIGHT
46812
+ });
46813
+ newlyCollapsed.push({ label, memberBbox: bbox });
46814
+ }
46815
+ const groupByLabel = new Map(parsed.groups.map((g) => [g.label, g]));
46816
+ const inUnit = /* @__PURE__ */ new Set();
46817
+ const unitKeys = (label, seen = /* @__PURE__ */ new Set()) => {
46818
+ if (seen.has(label)) return [];
46819
+ seen.add(label);
46820
+ const g = groupByLabel.get(label);
46821
+ if (!g) return [];
46822
+ const out = [];
46823
+ for (const c of g.children) {
46824
+ if (groupByLabel.has(c)) out.push(...unitKeys(c, seen));
46825
+ else if (rects.has(c)) out.push(c);
46826
+ else if (rects.has(gid(c))) out.push(gid(c));
46827
+ }
46828
+ return out;
46829
+ };
46830
+ const units = [];
46831
+ for (const g of parsed.groups) {
46832
+ if (g.parentGroup) continue;
46833
+ const keys = unitKeys(g.label);
46834
+ if (keys.length === 0) continue;
46835
+ for (const k of keys) inUnit.add(k);
46836
+ units.push(keys);
46837
+ }
46838
+ for (const key of rects.keys()) if (!inUnit.has(key)) units.push([key]);
46839
+ const axes = ["x", "y"];
46840
+ for (const { label, memberBbox } of newlyCollapsed) {
46841
+ const pill = rects.get(gid(label));
46842
+ for (const axis of axes) {
46843
+ const size = axis === "x" ? "width" : "height";
46844
+ const perpMin = axis === "x" ? top : left;
46845
+ const perpMax = axis === "x" ? bottom : right;
46846
+ const axMin = axis === "x" ? left : top;
46847
+ const axMax = axis === "x" ? right : bottom;
46848
+ const reclaim = memberBbox[size] - pill[size];
46849
+ if (reclaim <= 0) continue;
46850
+ const unitBbox = (keys) => bboxOf(keys.map((k) => rects.get(k)));
46851
+ const sliding = [];
46852
+ const staticRects = [];
46853
+ for (const u of units) {
46854
+ const b = unitBbox(u);
46855
+ if (axMin(b) >= pill[axis] && !u.includes(gid(label))) sliding.push(u);
46856
+ else staticRects.push(...u.map((k) => rects.get(k)));
46857
+ }
46858
+ if (sliding.length === 0) continue;
46859
+ let delta = reclaim;
46860
+ for (const u of sliding) {
46861
+ const b = unitBbox(u);
46862
+ for (const s of staticRects) {
46863
+ const overlaps = perpMin(b) < perpMax(s) - 4 && perpMax(b) > perpMin(s) + 4;
46864
+ if (!overlaps || axMax(s) > axMin(b)) continue;
46865
+ delta = Math.min(delta, axMin(b) - axMax(s) - MIN_GAP);
46866
+ }
46867
+ }
46868
+ if (delta <= 0) continue;
46869
+ for (const u of sliding)
46870
+ for (const k of u) {
46871
+ const r = rects.get(k);
46872
+ rects.set(k, { ...r, [axis]: r[axis] - delta });
46873
+ }
46874
+ }
46875
+ }
46876
+ const groupRect = /* @__PURE__ */ new Map();
46877
+ const buildGroupRect = (label, seen = /* @__PURE__ */ new Set()) => {
46878
+ if (groupRect.has(label)) return groupRect.get(label);
46879
+ if (seen.has(label)) return null;
46880
+ seen.add(label);
46881
+ const g = groupByLabel.get(label);
46882
+ if (!g) return null;
46883
+ const memberRects = [];
46884
+ for (const c of g.children) {
46885
+ if (groupByLabel.has(c)) {
46886
+ const sub = buildGroupRect(c, seen);
46887
+ if (sub) memberRects.push(sub);
46888
+ } else if (rects.has(c)) memberRects.push(rects.get(c));
46889
+ else if (rects.has(gid(c))) memberRects.push(rects.get(gid(c)));
46890
+ }
46891
+ if (memberRects.length === 0) return null;
46892
+ const b = bboxOf(memberRects);
46893
+ const rect2 = {
46894
+ x: b.x,
46895
+ y: b.y - GROUP_LABEL_ZONE3 / 2,
46896
+ width: b.width + 2 * GROUP_PAD2,
46897
+ height: b.height + 2 * GROUP_PAD2 + GROUP_LABEL_ZONE3
46898
+ };
46899
+ groupRect.set(label, rect2);
46900
+ return rect2;
46901
+ };
46902
+ for (const g of parsed.groups) if (!buildGroupRect(g.label)) return null;
46903
+ const boxes = [...rects.values()];
46904
+ for (let i = 0; i < boxes.length; i++)
46905
+ for (let j = i + 1; j < boxes.length; j++) {
46906
+ const a = boxes[i];
46907
+ const b = boxes[j];
46908
+ if (Math.abs(a.x - b.x) < (a.width + b.width) / 2 - 4 && Math.abs(a.y - b.y) < (a.height + b.height) / 2 - 4)
46909
+ return null;
46910
+ }
46911
+ const endpointRect = (key) => {
46912
+ const direct = rects.get(key);
46913
+ if (direct) return direct;
46914
+ if (key.startsWith("__group_")) {
46915
+ const label = key.slice("__group_".length);
46916
+ return groupRect.get(label) ?? null;
46917
+ }
46918
+ return groupRect.get(key) ?? null;
46919
+ };
46920
+ const edges = [];
46921
+ for (const e of parsed.edges) {
46922
+ const sr = endpointRect(e.source);
46923
+ const tr = endpointRect(e.target);
46924
+ if (!sr || !tr) return null;
46925
+ edges.push({
46926
+ source: e.source,
46927
+ target: e.target,
46928
+ ...e.label !== void 0 && { label: e.label },
46929
+ bidirectional: e.bidirectional,
46930
+ lineNumber: e.lineNumber,
46931
+ points: [borderPoint(sr, tr), borderPoint(tr, sr)],
46932
+ yOffset: 0,
46933
+ parallelCount: 1,
46934
+ metadata: e.metadata
46935
+ });
46936
+ }
46937
+ const allRects = [...rects.values(), ...groupRect.values()];
46938
+ const total = bboxOf(allRects);
46939
+ const dx = MARGIN6 - left(total);
46940
+ const dy = MARGIN6 - top(total);
46941
+ const shift = (r) => ({ ...r, x: r.x + dx, y: r.y + dy });
46942
+ const nodes = parsed.nodes.map((n) => {
46943
+ const r = shift(rects.get(n.label));
46944
+ return { label: n.label, x: r.x, y: r.y, width: r.width, height: r.height };
46945
+ });
46946
+ const groups = parsed.groups.map((g) => {
46947
+ const r = shift(groupRect.get(g.label));
46948
+ return {
46949
+ label: g.label,
46950
+ lineNumber: g.lineNumber,
46951
+ x: r.x,
46952
+ y: r.y,
46953
+ width: r.width,
46954
+ height: r.height,
46955
+ collapsed: false,
46956
+ childCount: g.children.length
46957
+ };
46958
+ });
46959
+ for (const label of collapsedGroupLabels) {
46960
+ const r = shift(rects.get(gid(label)));
46961
+ groups.push({
46962
+ label,
46963
+ lineNumber: 0,
46964
+ x: r.x,
46965
+ y: r.y,
46966
+ width: r.width,
46967
+ height: r.height,
46968
+ collapsed: true,
46969
+ childCount: collapseInfo.collapsedChildCounts.get(label) ?? 0
46970
+ });
46971
+ }
46972
+ const shiftedEdges = edges.map((e) => ({
46973
+ ...e,
46974
+ points: e.points.map((p) => ({ x: p.x + dx, y: p.y + dy }))
46975
+ }));
46976
+ const shiftedTotal = shift(total);
46977
+ return {
46978
+ nodes,
46979
+ edges: shiftedEdges,
46980
+ groups,
46981
+ width: right(shiftedTotal) + MARGIN6,
46982
+ height: bottom(shiftedTotal) + MARGIN6
46983
+ };
46984
+ }
46985
+ var GROUP_PAD2, GROUP_LABEL_ZONE3, MARGIN6, MIN_GAP, gid, left, right, top, bottom;
46986
+ var init_layout_stable_collapse = __esm({
46987
+ "src/boxes-and-lines/layout-stable-collapse.ts"() {
46988
+ "use strict";
46989
+ init_node_metrics();
46990
+ GROUP_PAD2 = 16;
46991
+ GROUP_LABEL_ZONE3 = 32;
46992
+ MARGIN6 = 40;
46993
+ MIN_GAP = 36;
46994
+ gid = (label) => `__group_${label}`;
46995
+ left = (r) => r.x - r.width / 2;
46996
+ right = (r) => r.x + r.width / 2;
46997
+ top = (r) => r.y - r.height / 2;
46998
+ bottom = (r) => r.y + r.height / 2;
46999
+ }
47000
+ });
47001
+
46415
47002
  // src/boxes-and-lines/layout-search.ts
46416
47003
  var layout_search_exports = {};
46417
47004
  __export(layout_search_exports, {
@@ -46784,7 +47371,7 @@ function detectGroupOverlaps(layout, opts) {
46784
47371
  const contains = (outer, inner) => outer.l <= inner.l + margin && outer.r >= inner.r - margin && outer.t <= inner.t + margin && outer.b >= inner.b - margin;
46785
47372
  const rend = raw.map((a, i) => {
46786
47373
  const parent = raw.some((b, j) => j !== i && contains(a, b));
46787
- return parent ? { ...a, t: a.t - GROUP_LABEL_ZONE3 } : a;
47374
+ return parent ? { ...a, t: a.t - GROUP_LABEL_ZONE4 } : a;
46788
47375
  });
46789
47376
  const hit = /* @__PURE__ */ new Set();
46790
47377
  for (let i = 0; i < raw.length; i++)
@@ -46811,7 +47398,7 @@ function countGroupOverlaps(layout, opts) {
46811
47398
  const contains = (outer, inner) => outer.l <= inner.l + margin && outer.r >= inner.r - margin && outer.t <= inner.t + margin && outer.b >= inner.b - margin;
46812
47399
  const rend = raw.map((a, i) => {
46813
47400
  const parent = raw.some((b, j) => j !== i && contains(a, b));
46814
- return parent ? { ...a, t: a.t - GROUP_LABEL_ZONE3 } : a;
47401
+ return parent ? { ...a, t: a.t - GROUP_LABEL_ZONE4 } : a;
46815
47402
  });
46816
47403
  let count = 0;
46817
47404
  for (let i = 0; i < raw.length; i++)
@@ -46854,7 +47441,7 @@ function separateGroupBands(layout, parsed) {
46854
47441
  let lo = (axis === "y" ? g.y : g.x) - half2;
46855
47442
  const hi = (axis === "y" ? g.y : g.x) + half2;
46856
47443
  const isParent = parsed.groups.some((c) => c.parentGroup === label);
46857
- if (axis === "y" && isParent) lo -= GROUP_LABEL_ZONE3;
47444
+ if (axis === "y" && isParent) lo -= GROUP_LABEL_ZONE4;
46858
47445
  return { label, lo, hi, c: (lo + hi) / 2 };
46859
47446
  });
46860
47447
  bands.sort((a, b) => a.c - b.c);
@@ -46890,8 +47477,8 @@ function separateGroupBands(layout, parsed) {
46890
47477
  const nodeDelta = (label) => {
46891
47478
  if (label.startsWith("__group_"))
46892
47479
  return delta.get(topOf(label.slice("__group_".length))) ?? 0;
46893
- const top = nodeTop.get(label);
46894
- return top ? delta.get(top) ?? 0 : 0;
47480
+ const top2 = nodeTop.get(label);
47481
+ return top2 ? delta.get(top2) ?? 0 : 0;
46895
47482
  };
46896
47483
  const shift = (p, d) => axis === "y" ? { x: p.x, y: p.y + d } : { x: p.x + d, y: p.y };
46897
47484
  const nodes = layout.nodes.map((n) => {
@@ -46925,7 +47512,7 @@ function separateGroupBands(layout, parsed) {
46925
47512
  acc(n.x + n.width / 2, n.y + n.height / 2);
46926
47513
  }
46927
47514
  for (const g of groups) {
46928
- acc(g.x - g.width / 2, g.y - g.height / 2 - GROUP_LABEL_ZONE3);
47515
+ acc(g.x - g.width / 2, g.y - g.height / 2 - GROUP_LABEL_ZONE4);
46929
47516
  acc(g.x + g.width / 2, g.y + g.height / 2);
46930
47517
  }
46931
47518
  for (const e of edges) for (const p of e.points) acc(p.x, p.y);
@@ -47044,8 +47631,19 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
47044
47631
  sizes.set(node.label, { width: s.width, height: maxDescH });
47045
47632
  }
47046
47633
  }
47047
- const gid = (label) => `__group_${label}`;
47634
+ const gid2 = (label) => `__group_${label}`;
47048
47635
  const rankdir = parsed.direction === "TB" ? "TB" : "LR";
47636
+ if (opts?.stableCollapse && collapseInfo && collapsedGroupLabels.size > 0 && opts.previousPositions) {
47637
+ const stable = tryStableCollapseLayout({
47638
+ parsed,
47639
+ collapseInfo,
47640
+ collapsedGroupLabels,
47641
+ previousPositions: opts.previousPositions,
47642
+ sizes,
47643
+ rankdir
47644
+ });
47645
+ if (stable) return stable;
47646
+ }
47049
47647
  const nodeLabelSet = new Set(parsed.nodes.map((n2) => n2.label));
47050
47648
  const directNodeChildren = /* @__PURE__ */ new Map();
47051
47649
  const childGroupsOf = /* @__PURE__ */ new Map();
@@ -47103,8 +47701,8 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
47103
47701
  if (rankOf(mem) > rankOf(exit)) exit = mem;
47104
47702
  if (rankOf(mem) < rankOf(entry)) entry = mem;
47105
47703
  }
47106
- gidSourceRep.set(gid(grp.label), exit);
47107
- gidTargetRep.set(gid(grp.label), entry);
47704
+ gidSourceRep.set(gid2(grp.label), exit);
47705
+ gidTargetRep.set(gid2(grp.label), entry);
47108
47706
  }
47109
47707
  const srcRep = (label) => gidSourceRep.get(label) ?? label;
47110
47708
  const tgtRep = (label) => gidTargetRep.get(label) ?? label;
@@ -47134,25 +47732,25 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
47134
47732
  });
47135
47733
  g.setDefaultEdgeLabel(() => ({}));
47136
47734
  for (const grp of ord(parsed.groups))
47137
- g.setNode(gid(grp.label), { label: grp.label });
47735
+ g.setNode(gid2(grp.label), { label: grp.label });
47138
47736
  for (const node of ord(parsed.nodes)) {
47139
47737
  const s = sizes.get(node.label);
47140
47738
  g.setNode(node.label, { width: s.width, height: s.height });
47141
47739
  }
47142
47740
  for (const label of collapsedGroupLabels)
47143
- g.setNode(gid(label), { width: NODE_WIDTH, height: NODE_HEIGHT });
47741
+ g.setNode(gid2(label), { width: NODE_WIDTH, height: NODE_HEIGHT });
47144
47742
  for (const grp of parsed.groups) {
47145
- if (grp.parentGroup && g.hasNode(gid(grp.parentGroup)))
47146
- g.setParent(gid(grp.label), gid(grp.parentGroup));
47743
+ if (grp.parentGroup && g.hasNode(gid2(grp.parentGroup)))
47744
+ g.setParent(gid2(grp.label), gid2(grp.parentGroup));
47147
47745
  for (const c of ord(grp.children)) {
47148
- if (g.hasNode(c)) g.setParent(c, gid(grp.label));
47746
+ if (g.hasNode(c)) g.setParent(c, gid2(grp.label));
47149
47747
  }
47150
47748
  }
47151
47749
  if (collapseInfo)
47152
47750
  for (const label of collapsedGroupLabels) {
47153
47751
  const og = collapseInfo.originalGroups.find((x) => x.label === label);
47154
- if (og?.parentGroup && !collapsedGroupLabels.has(og.parentGroup) && g.hasNode(gid(og.parentGroup)))
47155
- g.setParent(gid(label), gid(og.parentGroup));
47752
+ if (og?.parentGroup && !collapsedGroupLabels.has(og.parentGroup) && g.hasNode(gid2(og.parentGroup)))
47753
+ g.setParent(gid2(label), gid2(og.parentGroup));
47156
47754
  }
47157
47755
  for (const e of ord(parsed.edges)) {
47158
47756
  const s = srcRep(e.source);
@@ -47179,7 +47777,7 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
47179
47777
  });
47180
47778
  const groups = parsed.groups.map(
47181
47779
  (grp) => {
47182
- const p = g.node(gid(grp.label));
47780
+ const p = g.node(gid2(grp.label));
47183
47781
  return {
47184
47782
  label: grp.label,
47185
47783
  lineNumber: grp.lineNumber,
@@ -47193,7 +47791,7 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
47193
47791
  }
47194
47792
  );
47195
47793
  for (const label of collapsedGroupLabels) {
47196
- const p = g.node(gid(label));
47794
+ const p = g.node(gid2(label));
47197
47795
  groups.push({
47198
47796
  label,
47199
47797
  lineNumber: 0,
@@ -47207,9 +47805,9 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
47207
47805
  }
47208
47806
  const groupRectByGid = /* @__PURE__ */ new Map();
47209
47807
  for (const grp of parsed.groups) {
47210
- const p = g.node(gid(grp.label));
47808
+ const p = g.node(gid2(grp.label));
47211
47809
  if (p)
47212
- groupRectByGid.set(gid(grp.label), {
47810
+ groupRectByGid.set(gid2(grp.label), {
47213
47811
  x: p.x,
47214
47812
  y: p.y,
47215
47813
  w: p.width,
@@ -47409,14 +48007,16 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
47409
48007
  opts?.onTopConfigs?.(topConfigs);
47410
48008
  return best;
47411
48009
  }
47412
- var DEFAULT_LAMBDA, ESCALATE_THRESHOLD, ESCALATE_MAX_N, ESCALATE_SEEDS, ESCALATE_REFINE, DEFAULT_SEARCH_BUDGET_MS, splineGen, PATH_TOKEN_RE, FLAT_CACHE, GROUP_LABEL_ZONE3;
48010
+ var DEFAULT_LAMBDA, ESCALATE_THRESHOLD, ESCALATE_MAX_N, ESCALATE_SEEDS, ESCALATE_REFINE, DEFAULT_SEARCH_BUDGET_MS, splineGen, PATH_TOKEN_RE, FLAT_CACHE, GROUP_LABEL_ZONE4;
47413
48011
  var init_layout_search = __esm({
47414
48012
  "src/boxes-and-lines/layout-search.ts"() {
47415
48013
  "use strict";
48014
+ init_node_metrics();
47416
48015
  init_layout6();
47417
48016
  init_layout_layered();
47418
48017
  init_layout_grouped();
47419
48018
  init_label_placement();
48019
+ init_layout_stable_collapse();
47420
48020
  DEFAULT_LAMBDA = 4;
47421
48021
  ESCALATE_THRESHOLD = 4;
47422
48022
  ESCALATE_MAX_N = 45;
@@ -47426,15 +48026,13 @@ var init_layout_search = __esm({
47426
48026
  splineGen = d3line3().x((d) => d.x).y((d) => d.y).curve(curveBasis5);
47427
48027
  PATH_TOKEN_RE = /[MLQC]|-?\d*\.?\d+(?:e-?\d+)?/gi;
47428
48028
  FLAT_CACHE = /* @__PURE__ */ new WeakMap();
47429
- GROUP_LABEL_ZONE3 = 32;
48029
+ GROUP_LABEL_ZONE4 = 32;
47430
48030
  }
47431
48031
  });
47432
48032
 
47433
48033
  // src/boxes-and-lines/layout.ts
47434
48034
  var layout_exports6 = {};
47435
48035
  __export(layout_exports6, {
47436
- NODE_HEIGHT: () => NODE_HEIGHT,
47437
- NODE_WIDTH: () => NODE_WIDTH,
47438
48036
  computeNodeSize: () => computeNodeSize,
47439
48037
  layoutBoxesAndLines: () => layoutBoxesAndLines
47440
48038
  });
@@ -47517,6 +48115,9 @@ async function layoutBoxesAndLines(parsed, collapseInfo, layoutOptions) {
47517
48115
  ...layoutOptions?.previousPositions !== void 0 && {
47518
48116
  previousPositions: layoutOptions.previousPositions
47519
48117
  },
48118
+ ...layoutOptions?.stableCollapse !== void 0 && {
48119
+ stableCollapse: layoutOptions.stableCollapse
48120
+ },
47520
48121
  ...layoutOptions?.onProgress !== void 0 && {
47521
48122
  onProgress: layoutOptions.onProgress
47522
48123
  }
@@ -47621,8 +48222,8 @@ function attachNotes(layout, parsed, collapsedNotes) {
47621
48222
  nodes: finalNodes,
47622
48223
  edges: finalEdges,
47623
48224
  groups: finalGroups,
47624
- width: bbMaxX + shiftX + MARGIN6,
47625
- height: bbMaxY + shiftY + MARGIN6
48225
+ width: bbMaxX + shiftX + MARGIN7,
48226
+ height: bbMaxY + shiftY + MARGIN7
47626
48227
  };
47627
48228
  }
47628
48229
  function applyParallelEdgeOffsets(layout) {
@@ -47655,19 +48256,17 @@ function applyParallelEdgeOffsets(layout) {
47655
48256
  }))
47656
48257
  };
47657
48258
  }
47658
- var MARGIN6, MAX_PARALLEL_EDGES, PARALLEL_SPACING, PHI, NODE_HEIGHT, NODE_WIDTH, DESC_NODE_WIDTH, DESC_FONT_SIZE2, DESC_LINE_HEIGHT2, DESC_PADDING, SEPARATOR_GAP4, MAX_DESC_LINES2, MAX_LABEL_LINES2, LABEL_LINE_HEIGHT2, LABEL_PAD, VALUE_ROW_FONT, VALUE_ROW_H;
48259
+ var MARGIN7, MAX_PARALLEL_EDGES, PARALLEL_SPACING, DESC_NODE_WIDTH, DESC_FONT_SIZE2, DESC_LINE_HEIGHT2, DESC_PADDING, SEPARATOR_GAP4, MAX_DESC_LINES2, MAX_LABEL_LINES2, LABEL_LINE_HEIGHT2, LABEL_PAD, VALUE_ROW_FONT, VALUE_ROW_H;
47659
48260
  var init_layout6 = __esm({
47660
48261
  "src/boxes-and-lines/layout.ts"() {
47661
48262
  "use strict";
48263
+ init_node_metrics();
47662
48264
  init_text_measure();
47663
48265
  init_label_placement();
47664
48266
  init_notes();
47665
- MARGIN6 = 40;
48267
+ MARGIN7 = 40;
47666
48268
  MAX_PARALLEL_EDGES = 5;
47667
48269
  PARALLEL_SPACING = 22;
47668
- PHI = 1.618;
47669
- NODE_HEIGHT = 60;
47670
- NODE_WIDTH = Math.round(NODE_HEIGHT * PHI);
47671
48270
  DESC_NODE_WIDTH = 140;
47672
48271
  DESC_FONT_SIZE2 = 10;
47673
48272
  DESC_LINE_HEIGHT2 = 1.4;
@@ -47793,7 +48392,7 @@ function layoutSwimlane(parsed) {
47793
48392
  const rankIndex = new Map(usedRanks.map((r, i) => [r, i]));
47794
48393
  const R = usedRanks.length;
47795
48394
  const riOf = (id) => rankIndex.get(finalRank.get(id)) ?? 0;
47796
- const contentFlowStart = LANE_HEADER + MARGIN7;
48395
+ const contentFlowStart = LANE_HEADER + MARGIN8;
47797
48396
  const colFlowLen = Array.from({ length: R }, () => 0);
47798
48397
  for (const id of ids) {
47799
48398
  const ri = riOf(id);
@@ -47811,8 +48410,8 @@ function layoutSwimlane(parsed) {
47811
48410
  }
47812
48411
  }
47813
48412
  const gapMid = (gi) => flowCenter[gi] + colLen[gi] / 2 + COL_GAP / 2;
47814
- const totalFlow = (R > 0 ? flowCenter[R - 1] + Math.max(colFlowLen[R - 1], NODE_W2) / 2 : contentFlowStart) + MARGIN7;
47815
- const contentCrossStart = (parsed.phases.length ? PHASE_HEADER : 0) + MARGIN7;
48413
+ const totalFlow = (R > 0 ? flowCenter[R - 1] + Math.max(colFlowLen[R - 1], NODE_W2) / 2 : contentFlowStart) + MARGIN8;
48414
+ const contentCrossStart = (parsed.phases.length ? PHASE_HEADER : 0) + MARGIN8;
47816
48415
  const cellNodes = /* @__PURE__ */ new Map();
47817
48416
  for (const n of parsed.nodes) {
47818
48417
  const key = `${n.lane}\0${riOf(n.id)}`;
@@ -47864,7 +48463,7 @@ function layoutSwimlane(parsed) {
47864
48463
  if ((finalRank.get(e.to) ?? 0) < (finalRank.get(e.from) ?? 0)) backCount++;
47865
48464
  const needsBack = backCount > 0;
47866
48465
  const backReserve = needsBack ? BACK_CHANNEL + BACK_STEP * (backCount - 1) : 0;
47867
- const totalCross = laneCrossEnd + backReserve + MARGIN7;
48466
+ const totalCross = laneCrossEnd + backReserve + MARGIN8;
47868
48467
  const project = (flow, cross) => isLR ? { x: flow, y: cross } : { x: cross, y: flow };
47869
48468
  const layoutNodes = parsed.nodes.map((n) => {
47870
48469
  const s = size.get(n.id);
@@ -48086,12 +48685,12 @@ function layoutSwimlane(parsed) {
48086
48685
  height: isLR ? totalCross : totalFlow
48087
48686
  };
48088
48687
  }
48089
- var MARGIN7, COL_GAP, NODE_W2, NODE_H, DIAMOND, TERM_D, INTRA_GAP, LANE_PAD, MIN_LANE, LANE_HEADER, PHASE_HEADER, BACK_CHANNEL, BACK_STEP;
48688
+ var MARGIN8, COL_GAP, NODE_W2, NODE_H, DIAMOND, TERM_D, INTRA_GAP, LANE_PAD, MIN_LANE, LANE_HEADER, PHASE_HEADER, BACK_CHANNEL, BACK_STEP;
48090
48689
  var init_layout7 = __esm({
48091
48690
  "src/swimlane/layout.ts"() {
48092
48691
  "use strict";
48093
48692
  init_layout_grouped();
48094
- MARGIN7 = 30;
48693
+ MARGIN8 = 30;
48095
48694
  COL_GAP = 64;
48096
48695
  NODE_W2 = 124;
48097
48696
  NODE_H = 44;
@@ -48386,9 +48985,9 @@ function renderSwimlaneForExport(container, parsed, layout, palette, isDark, opt
48386
48985
  anchor = "middle";
48387
48986
  baseline = below ? "hanging" : "auto";
48388
48987
  } else {
48389
- const right = clearance(mid.x + LABEL_GAP2, mid.y, 1);
48390
- const left = clearance(mid.x - LABEL_GAP2, mid.y, -1);
48391
- const toLeft = right < CROWD && left > right;
48988
+ const right2 = clearance(mid.x + LABEL_GAP2, mid.y, 1);
48989
+ const left2 = clearance(mid.x - LABEL_GAP2, mid.y, -1);
48990
+ const toLeft = right2 < CROWD && left2 > right2;
48392
48991
  tx = mid.x + (toLeft ? -LABEL_GAP2 : LABEL_GAP2);
48393
48992
  ty = mid.y;
48394
48993
  anchor = toLeft ? "end" : "start";
@@ -48609,8 +49208,8 @@ function cardSize(p) {
48609
49208
  const valueX = KEY_X + maxKeyW + KEY_VALUE_GAP;
48610
49209
  let contentRight = 0;
48611
49210
  for (const r of rows) {
48612
- const right = r.year ? KEY_X + measureText(r.value, META_FONT_SIZE) : valueX + measureText(r.value, META_FONT_SIZE);
48613
- contentRight = Math.max(contentRight, right);
49211
+ const right2 = r.year ? KEY_X + measureText(r.value, META_FONT_SIZE) : valueX + measureText(r.value, META_FONT_SIZE);
49212
+ contentRight = Math.max(contentRight, right2);
48614
49213
  }
48615
49214
  const labelW = measureText(p.label, LABEL_FONT_SIZE);
48616
49215
  const width = Math.max(
@@ -48784,7 +49383,7 @@ function layoutFamily(parsed, focusId) {
48784
49383
  }
48785
49384
  const rowY = /* @__PURE__ */ new Map();
48786
49385
  {
48787
- let acc = MARGIN8 + ANCESTOR_BAND;
49386
+ let acc = MARGIN9 + ANCESTOR_BAND;
48788
49387
  for (let r = 0; r <= maxRow; r++) {
48789
49388
  rowY.set(r, acc);
48790
49389
  acc += (rowHeight.get(r) ?? 0) + ROW_GAP2;
@@ -48859,11 +49458,11 @@ function layoutFamily(parsed, focusId) {
48859
49458
  if (kids.length === 0 || u.parents.every((p) => !centerX.has(p)))
48860
49459
  continue;
48861
49460
  const blockW = kids.reduce((s, id) => s + sizes.get(id).width, 0) + H_GAP2 * (kids.length - 1);
48862
- let left = unionMid(u) - blockW / 2;
49461
+ let left2 = unionMid(u) - blockW / 2;
48863
49462
  for (const id of kids) {
48864
49463
  const w = sizes.get(id).width;
48865
- desired.set(id, left + w / 2);
48866
- left += w + H_GAP2;
49464
+ desired.set(id, left2 + w / 2);
49465
+ left2 += w + H_GAP2;
48867
49466
  }
48868
49467
  }
48869
49468
  resolveRow(rowPersons.get(r) ?? [], desired);
@@ -48873,7 +49472,7 @@ function layoutFamily(parsed, focusId) {
48873
49472
  for (const id of persons.keys())
48874
49473
  minLeft = Math.min(minLeft, centerX.get(id) - sizes.get(id).width / 2);
48875
49474
  const gutter = showGen ? GUTTER_WIDTH : 0;
48876
- const dx = (Number.isFinite(minLeft) ? MARGIN8 - minLeft : MARGIN8) + gutter;
49475
+ const dx = (Number.isFinite(minLeft) ? MARGIN9 - minLeft : MARGIN9) + gutter;
48877
49476
  const nodes = [];
48878
49477
  const topY = /* @__PURE__ */ new Map();
48879
49478
  const bottomY = /* @__PURE__ */ new Map();
@@ -48987,13 +49586,13 @@ function layoutFamily(parsed, focusId) {
48987
49586
  sex: p.sex,
48988
49587
  ...p.color !== void 0 && { color: p.color },
48989
49588
  x: fx,
48990
- y: MARGIN8 + 10 + i * ANCESTOR_STAGGER
49589
+ y: MARGIN9 + 10 + i * ANCESTOR_STAGGER
48991
49590
  });
48992
49591
  });
48993
49592
  }
48994
- const width = contentRightEdge + MARGIN8;
49593
+ const width = contentRightEdge + MARGIN9;
48995
49594
  const lastR = maxRow;
48996
- const height = (rowY.get(lastR) ?? MARGIN8) + (rowHeight.get(lastR) ?? 0) + MARGIN8;
49595
+ const height = (rowY.get(lastR) ?? MARGIN9) + (rowHeight.get(lastR) ?? 0) + MARGIN9;
48997
49596
  const rows = [];
48998
49597
  for (let r = 0; r <= maxRow; r++) {
48999
49598
  if (!rowPersons.get(r)?.length) continue;
@@ -49010,7 +49609,7 @@ function layoutFamily(parsed, focusId) {
49010
49609
  height
49011
49610
  };
49012
49611
  }
49013
- var MARGIN8, MIN_CARD_W, CARD_H_PAD3, CARD_TEXT_PAD, H_GAP2, ROW_GAP2, KEY_VALUE_GAP, KEY_X, GUTTER_WIDTH;
49612
+ var MARGIN9, MIN_CARD_W, CARD_H_PAD3, CARD_TEXT_PAD, H_GAP2, ROW_GAP2, KEY_VALUE_GAP, KEY_X, GUTTER_WIDTH;
49014
49613
  var init_layout8 = __esm({
49015
49614
  "src/family/layout.ts"() {
49016
49615
  "use strict";
@@ -49018,7 +49617,7 @@ var init_layout8 = __esm({
49018
49617
  init_visual_conventions();
49019
49618
  init_couple_rank();
49020
49619
  init_card_model();
49021
- MARGIN8 = 30;
49620
+ MARGIN9 = 30;
49022
49621
  MIN_CARD_W = 132;
49023
49622
  CARD_H_PAD3 = 12;
49024
49623
  CARD_TEXT_PAD = 12;
@@ -49461,7 +50060,7 @@ function layoutMindmap(parsed, _palette, options) {
49461
50060
  leafWidth: ctx.structural(LEAF_WIDTH),
49462
50061
  hGap: ctx.aesthetic(H_GAP3),
49463
50062
  vGap: ctx.aesthetic(V_GAP2),
49464
- margin: ctx.aesthetic(MARGIN9),
50063
+ margin: ctx.aesthetic(MARGIN10),
49465
50064
  multiRootGap: ctx.aesthetic(MULTI_ROOT_GAP)
49466
50065
  };
49467
50066
  populateDepthCache(roots);
@@ -49781,20 +50380,20 @@ function balancedSplitS(children, hideDescriptions, sc) {
49781
50380
  node: c,
49782
50381
  height: computeSubtreeHeightS(c, 1, hideDescriptions, sc)
49783
50382
  }));
49784
- const right = [];
49785
- const left = [];
50383
+ const right2 = [];
50384
+ const left2 = [];
49786
50385
  let rightWeight = 0;
49787
50386
  let leftWeight = 0;
49788
50387
  for (const w of weights) {
49789
50388
  if (rightWeight <= leftWeight) {
49790
- right.push(w.node);
50389
+ right2.push(w.node);
49791
50390
  rightWeight += w.height;
49792
50391
  } else {
49793
- left.push(w.node);
50392
+ left2.push(w.node);
49794
50393
  leftWeight += w.height;
49795
50394
  }
49796
50395
  }
49797
- return { right, left };
50396
+ return { right: right2, left: left2 };
49798
50397
  }
49799
50398
  function offsetPath(path, dx, dy) {
49800
50399
  if (dx === 0 && dy === 0) return path;
@@ -49839,7 +50438,7 @@ function populateDepthCache(roots) {
49839
50438
  };
49840
50439
  walk(roots, 0);
49841
50440
  }
49842
- var ROOT_WIDTH, DEPTH1_WIDTH, LEAF_WIDTH, SINGLE_LABEL_HEIGHT, LABEL_LINE_HEIGHT3, DESC_LINE_HEIGHT3, NODE_V_PAD, H_GAP3, V_GAP2, MARGIN9, MULTI_ROOT_GAP, nodeDepthCache;
50441
+ var ROOT_WIDTH, DEPTH1_WIDTH, LEAF_WIDTH, SINGLE_LABEL_HEIGHT, LABEL_LINE_HEIGHT3, DESC_LINE_HEIGHT3, NODE_V_PAD, H_GAP3, V_GAP2, MARGIN10, MULTI_ROOT_GAP, nodeDepthCache;
49843
50442
  var init_layout9 = __esm({
49844
50443
  "src/mindmap/layout.ts"() {
49845
50444
  "use strict";
@@ -49855,7 +50454,7 @@ var init_layout9 = __esm({
49855
50454
  NODE_V_PAD = 10;
49856
50455
  H_GAP3 = 40;
49857
50456
  V_GAP2 = 12;
49858
- MARGIN9 = 40;
50457
+ MARGIN10 = 40;
49859
50458
  MULTI_ROOT_GAP = 60;
49860
50459
  nodeDepthCache = /* @__PURE__ */ new Map();
49861
50460
  }
@@ -51678,14 +52277,14 @@ function layoutC4Context(parsed, activeTagGroup) {
51678
52277
  );
51679
52278
  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
51680
52279
  for (const node of nodes) {
51681
- const left = node.x - node.width / 2;
51682
- const top = node.y - node.height / 2;
51683
- const right = node.x + node.width / 2;
51684
- const bottom = node.y + node.height / 2;
51685
- if (left < minX) minX = left;
51686
- if (top < minY) minY = top;
51687
- if (right > maxX) maxX = right;
51688
- if (bottom > maxY) maxY = bottom;
52280
+ const left2 = node.x - node.width / 2;
52281
+ const top2 = node.y - node.height / 2;
52282
+ const right2 = node.x + node.width / 2;
52283
+ const bottom2 = node.y + node.height / 2;
52284
+ if (left2 < minX) minX = left2;
52285
+ if (top2 < minY) minY = top2;
52286
+ if (right2 > maxX) maxX = right2;
52287
+ if (bottom2 > maxY) maxY = bottom2;
51689
52288
  }
51690
52289
  for (const edge of edges) {
51691
52290
  for (const pt of edge.points) {
@@ -51696,8 +52295,8 @@ function layoutC4Context(parsed, activeTagGroup) {
51696
52295
  }
51697
52296
  }
51698
52297
  if (nodes.length > 0) {
51699
- const shiftX = MARGIN10 - minX;
51700
- const shiftY = MARGIN10 - minY;
52298
+ const shiftX = MARGIN11 - minX;
52299
+ const shiftY = MARGIN11 - minY;
51701
52300
  for (const node of nodes) {
51702
52301
  node.x += shiftX;
51703
52302
  node.y += shiftY;
@@ -51709,14 +52308,14 @@ function layoutC4Context(parsed, activeTagGroup) {
51709
52308
  }
51710
52309
  }
51711
52310
  }
51712
- let totalWidth = nodes.length > 0 ? maxX - minX + MARGIN10 * 2 : 0;
51713
- let totalHeight = nodes.length > 0 ? maxY - minY + MARGIN10 * 2 : 0;
52311
+ let totalWidth = nodes.length > 0 ? maxX - minX + MARGIN11 * 2 : 0;
52312
+ let totalHeight = nodes.length > 0 ? maxY - minY + MARGIN11 * 2 : 0;
51714
52313
  const legendGroups = computeLegendGroups3(
51715
52314
  legendSuppressed(parsed.options) ? [] : parsed.tagGroups
51716
52315
  );
51717
52316
  if (legendGroups.length > 0) {
51718
- const legendY = totalHeight + MARGIN10;
51719
- let legendX = MARGIN10;
52317
+ const legendY = totalHeight + MARGIN11;
52318
+ let legendX = MARGIN11;
51720
52319
  for (const lg of legendGroups) {
51721
52320
  lg.x = legendX;
51722
52321
  lg.y = legendY;
@@ -51967,14 +52566,14 @@ function layoutC4Containers(parsed, systemName, activeTagGroup) {
51967
52566
  const containerNodes = nodes.filter((n) => n.type === "container");
51968
52567
  let bMinX = Infinity, bMinY = Infinity, bMaxX = -Infinity, bMaxY = -Infinity;
51969
52568
  for (const n of containerNodes) {
51970
- const left = n.x - n.width / 2;
51971
- const top = n.y - n.height / 2;
51972
- const right = n.x + n.width / 2;
51973
- const bottom = n.y + n.height / 2;
51974
- if (left < bMinX) bMinX = left;
51975
- if (top < bMinY) bMinY = top;
51976
- if (right > bMaxX) bMaxX = right;
51977
- if (bottom > bMaxY) bMaxY = bottom;
52569
+ const left2 = n.x - n.width / 2;
52570
+ const top2 = n.y - n.height / 2;
52571
+ const right2 = n.x + n.width / 2;
52572
+ const bottom2 = n.y + n.height / 2;
52573
+ if (left2 < bMinX) bMinX = left2;
52574
+ if (top2 < bMinY) bMinY = top2;
52575
+ if (right2 > bMaxX) bMaxX = right2;
52576
+ if (bottom2 > bMaxY) bMaxY = bottom2;
51978
52577
  }
51979
52578
  const boundary = {
51980
52579
  label: system.name,
@@ -52001,14 +52600,14 @@ function layoutC4Containers(parsed, systemName, activeTagGroup) {
52001
52600
  if (members.length === 0) continue;
52002
52601
  let gMinX = Infinity, gMinY = Infinity, gMaxX = -Infinity, gMaxY = -Infinity;
52003
52602
  for (const m of members) {
52004
- const left = m.x - m.width / 2;
52005
- const top = m.y - m.height / 2;
52006
- const right = m.x + m.width / 2;
52007
- const bottom = m.y + m.height / 2;
52008
- if (left < gMinX) gMinX = left;
52009
- if (top < gMinY) gMinY = top;
52010
- if (right > gMaxX) gMaxX = right;
52011
- if (bottom > gMaxY) gMaxY = bottom;
52603
+ const left2 = m.x - m.width / 2;
52604
+ const top2 = m.y - m.height / 2;
52605
+ const right2 = m.x + m.width / 2;
52606
+ const bottom2 = m.y + m.height / 2;
52607
+ if (left2 < gMinX) gMinX = left2;
52608
+ if (top2 < gMinY) gMinY = top2;
52609
+ if (right2 > gMaxX) gMaxX = right2;
52610
+ if (bottom2 > gMaxY) gMaxY = bottom2;
52012
52611
  }
52013
52612
  groupBoundaries.push({
52014
52613
  label: groupName,
@@ -52023,14 +52622,14 @@ function layoutC4Containers(parsed, systemName, activeTagGroup) {
52023
52622
  }
52024
52623
  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
52025
52624
  for (const node of nodes) {
52026
- const left = node.x - node.width / 2;
52027
- const top = node.y - node.height / 2;
52028
- const right = node.x + node.width / 2;
52029
- const bottom = node.y + node.height / 2;
52030
- if (left < minX) minX = left;
52031
- if (top < minY) minY = top;
52032
- if (right > maxX) maxX = right;
52033
- if (bottom > maxY) maxY = bottom;
52625
+ const left2 = node.x - node.width / 2;
52626
+ const top2 = node.y - node.height / 2;
52627
+ const right2 = node.x + node.width / 2;
52628
+ const bottom2 = node.y + node.height / 2;
52629
+ if (left2 < minX) minX = left2;
52630
+ if (top2 < minY) minY = top2;
52631
+ if (right2 > maxX) maxX = right2;
52632
+ if (bottom2 > maxY) maxY = bottom2;
52034
52633
  }
52035
52634
  if (boundary.x < minX) minX = boundary.x;
52036
52635
  if (boundary.y < minY) minY = boundary.y;
@@ -52050,8 +52649,8 @@ function layoutC4Containers(parsed, systemName, activeTagGroup) {
52050
52649
  if (pt.y > maxY) maxY = pt.y;
52051
52650
  }
52052
52651
  }
52053
- const shiftX = MARGIN10 - minX;
52054
- const shiftY = MARGIN10 - minY;
52652
+ const shiftX = MARGIN11 - minX;
52653
+ const shiftY = MARGIN11 - minY;
52055
52654
  for (const node of nodes) {
52056
52655
  node.x += shiftX;
52057
52656
  node.y += shiftY;
@@ -52068,14 +52667,14 @@ function layoutC4Containers(parsed, systemName, activeTagGroup) {
52068
52667
  pt.y += shiftY;
52069
52668
  }
52070
52669
  }
52071
- let totalWidth = maxX - minX + MARGIN10 * 2;
52072
- let totalHeight = maxY - minY + MARGIN10 * 2;
52670
+ let totalWidth = maxX - minX + MARGIN11 * 2;
52671
+ let totalHeight = maxY - minY + MARGIN11 * 2;
52073
52672
  const legendGroups = computeLegendGroups3(
52074
52673
  legendSuppressed(parsed.options) ? [] : parsed.tagGroups
52075
52674
  );
52076
52675
  if (legendGroups.length > 0) {
52077
- const legendY = totalHeight + MARGIN10;
52078
- let legendX = MARGIN10;
52676
+ const legendY = totalHeight + MARGIN11;
52677
+ let legendX = MARGIN11;
52079
52678
  for (const lg of legendGroups) {
52080
52679
  lg.x = legendX;
52081
52680
  lg.y = legendY;
@@ -52386,14 +52985,14 @@ function layoutC4Components(parsed, systemName, containerName, activeTagGroup) {
52386
52985
  const componentNodes = nodes.filter((n) => n.type === "component");
52387
52986
  let bMinX = Infinity, bMinY = Infinity, bMaxX = -Infinity, bMaxY = -Infinity;
52388
52987
  for (const n of componentNodes) {
52389
- const left = n.x - n.width / 2;
52390
- const top = n.y - n.height / 2;
52391
- const right = n.x + n.width / 2;
52392
- const bottom = n.y + n.height / 2;
52393
- if (left < bMinX) bMinX = left;
52394
- if (top < bMinY) bMinY = top;
52395
- if (right > bMaxX) bMaxX = right;
52396
- if (bottom > bMaxY) bMaxY = bottom;
52988
+ const left2 = n.x - n.width / 2;
52989
+ const top2 = n.y - n.height / 2;
52990
+ const right2 = n.x + n.width / 2;
52991
+ const bottom2 = n.y + n.height / 2;
52992
+ if (left2 < bMinX) bMinX = left2;
52993
+ if (top2 < bMinY) bMinY = top2;
52994
+ if (right2 > bMaxX) bMaxX = right2;
52995
+ if (bottom2 > bMaxY) bMaxY = bottom2;
52397
52996
  }
52398
52997
  const boundary = {
52399
52998
  label: targetContainer.name,
@@ -52420,14 +53019,14 @@ function layoutC4Components(parsed, systemName, containerName, activeTagGroup) {
52420
53019
  if (members.length === 0) continue;
52421
53020
  let gMinX = Infinity, gMinY = Infinity, gMaxX = -Infinity, gMaxY = -Infinity;
52422
53021
  for (const m of members) {
52423
- const left = m.x - m.width / 2;
52424
- const top = m.y - m.height / 2;
52425
- const right = m.x + m.width / 2;
52426
- const bottom = m.y + m.height / 2;
52427
- if (left < gMinX) gMinX = left;
52428
- if (top < gMinY) gMinY = top;
52429
- if (right > gMaxX) gMaxX = right;
52430
- if (bottom > gMaxY) gMaxY = bottom;
53022
+ const left2 = m.x - m.width / 2;
53023
+ const top2 = m.y - m.height / 2;
53024
+ const right2 = m.x + m.width / 2;
53025
+ const bottom2 = m.y + m.height / 2;
53026
+ if (left2 < gMinX) gMinX = left2;
53027
+ if (top2 < gMinY) gMinY = top2;
53028
+ if (right2 > gMaxX) gMaxX = right2;
53029
+ if (bottom2 > gMaxY) gMaxY = bottom2;
52431
53030
  }
52432
53031
  groupBoundaries.push({
52433
53032
  label: groupName,
@@ -52442,14 +53041,14 @@ function layoutC4Components(parsed, systemName, containerName, activeTagGroup) {
52442
53041
  }
52443
53042
  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
52444
53043
  for (const node of nodes) {
52445
- const left = node.x - node.width / 2;
52446
- const top = node.y - node.height / 2;
52447
- const right = node.x + node.width / 2;
52448
- const bottom = node.y + node.height / 2;
52449
- if (left < minX) minX = left;
52450
- if (top < minY) minY = top;
52451
- if (right > maxX) maxX = right;
52452
- if (bottom > maxY) maxY = bottom;
53044
+ const left2 = node.x - node.width / 2;
53045
+ const top2 = node.y - node.height / 2;
53046
+ const right2 = node.x + node.width / 2;
53047
+ const bottom2 = node.y + node.height / 2;
53048
+ if (left2 < minX) minX = left2;
53049
+ if (top2 < minY) minY = top2;
53050
+ if (right2 > maxX) maxX = right2;
53051
+ if (bottom2 > maxY) maxY = bottom2;
52453
53052
  }
52454
53053
  if (boundary.x < minX) minX = boundary.x;
52455
53054
  if (boundary.y < minY) minY = boundary.y;
@@ -52469,8 +53068,8 @@ function layoutC4Components(parsed, systemName, containerName, activeTagGroup) {
52469
53068
  if (pt.y > maxY) maxY = pt.y;
52470
53069
  }
52471
53070
  }
52472
- const shiftX = MARGIN10 - minX;
52473
- const shiftY = MARGIN10 - minY;
53071
+ const shiftX = MARGIN11 - minX;
53072
+ const shiftY = MARGIN11 - minY;
52474
53073
  for (const node of nodes) {
52475
53074
  node.x += shiftX;
52476
53075
  node.y += shiftY;
@@ -52487,14 +53086,14 @@ function layoutC4Components(parsed, systemName, containerName, activeTagGroup) {
52487
53086
  pt.y += shiftY;
52488
53087
  }
52489
53088
  }
52490
- let totalWidth = maxX - minX + MARGIN10 * 2;
52491
- let totalHeight = maxY - minY + MARGIN10 * 2;
53089
+ let totalWidth = maxX - minX + MARGIN11 * 2;
53090
+ let totalHeight = maxY - minY + MARGIN11 * 2;
52492
53091
  const legendGroups = computeLegendGroups3(
52493
53092
  legendSuppressed(parsed.options) ? [] : parsed.tagGroups
52494
53093
  );
52495
53094
  if (legendGroups.length > 0) {
52496
- const legendY = totalHeight + MARGIN10;
52497
- let legendX = MARGIN10;
53095
+ const legendY = totalHeight + MARGIN11;
53096
+ let legendX = MARGIN11;
52498
53097
  for (const lg of legendGroups) {
52499
53098
  lg.x = legendX;
52500
53099
  lg.y = legendY;
@@ -52713,14 +53312,14 @@ function layoutC4Deployment(parsed, activeTagGroup) {
52713
53312
  const members = infraMembers.get(infraId) ?? [];
52714
53313
  for (const m of members) {
52715
53314
  hasContent = true;
52716
- const left = m.x - m.width / 2;
52717
- const top = m.y - m.height / 2;
52718
- const right = m.x + m.width / 2;
52719
- const bottom = m.y + m.height / 2;
52720
- if (left < bMinX) bMinX = left;
52721
- if (top < bMinY) bMinY = top;
52722
- if (right > bMaxX) bMaxX = right;
52723
- if (bottom > bMaxY) bMaxY = bottom;
53315
+ const left2 = m.x - m.width / 2;
53316
+ const top2 = m.y - m.height / 2;
53317
+ const right2 = m.x + m.width / 2;
53318
+ const bottom2 = m.y + m.height / 2;
53319
+ if (left2 < bMinX) bMinX = left2;
53320
+ if (top2 < bMinY) bMinY = top2;
53321
+ if (right2 > bMaxX) bMaxX = right2;
53322
+ if (bottom2 > bMaxY) bMaxY = bottom2;
52724
53323
  }
52725
53324
  for (const [childId, parentId] of infraParents) {
52726
53325
  if (parentId === infraId) {
@@ -52761,14 +53360,14 @@ function layoutC4Deployment(parsed, activeTagGroup) {
52761
53360
  groupBoundaries.sort((a, b) => b.width * b.height - a.width * a.height);
52762
53361
  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
52763
53362
  for (const node of nodes) {
52764
- const left = node.x - node.width / 2;
52765
- const top = node.y - node.height / 2;
52766
- const right = node.x + node.width / 2;
52767
- const bottom = node.y + node.height / 2;
52768
- if (left < minX) minX = left;
52769
- if (top < minY) minY = top;
52770
- if (right > maxX) maxX = right;
52771
- if (bottom > maxY) maxY = bottom;
53363
+ const left2 = node.x - node.width / 2;
53364
+ const top2 = node.y - node.height / 2;
53365
+ const right2 = node.x + node.width / 2;
53366
+ const bottom2 = node.y + node.height / 2;
53367
+ if (left2 < minX) minX = left2;
53368
+ if (top2 < minY) minY = top2;
53369
+ if (right2 > maxX) maxX = right2;
53370
+ if (bottom2 > maxY) maxY = bottom2;
52772
53371
  }
52773
53372
  for (const gb of groupBoundaries) {
52774
53373
  if (gb.x < minX) minX = gb.x;
@@ -52784,8 +53383,8 @@ function layoutC4Deployment(parsed, activeTagGroup) {
52784
53383
  if (pt.y > maxY) maxY = pt.y;
52785
53384
  }
52786
53385
  }
52787
- const shiftX = MARGIN10 - minX;
52788
- const shiftY = MARGIN10 - minY;
53386
+ const shiftX = MARGIN11 - minX;
53387
+ const shiftY = MARGIN11 - minY;
52789
53388
  for (const node of nodes) {
52790
53389
  node.x += shiftX;
52791
53390
  node.y += shiftY;
@@ -52800,14 +53399,14 @@ function layoutC4Deployment(parsed, activeTagGroup) {
52800
53399
  pt.y += shiftY;
52801
53400
  }
52802
53401
  }
52803
- let totalWidth = maxX - minX + MARGIN10 * 2;
52804
- let totalHeight = maxY - minY + MARGIN10 * 2;
53402
+ let totalWidth = maxX - minX + MARGIN11 * 2;
53403
+ let totalHeight = maxY - minY + MARGIN11 * 2;
52805
53404
  const legendGroups = computeLegendGroups3(
52806
53405
  legendSuppressed(parsed.options) ? [] : parsed.tagGroups
52807
53406
  );
52808
53407
  if (legendGroups.length > 0) {
52809
- const legendY = totalHeight + MARGIN10;
52810
- let legendX = MARGIN10;
53408
+ const legendY = totalHeight + MARGIN11;
53409
+ let legendX = MARGIN11;
52811
53410
  for (const lg of legendGroups) {
52812
53411
  lg.x = legendX;
52813
53412
  lg.y = legendY;
@@ -52827,7 +53426,7 @@ function layoutC4Deployment(parsed, activeTagGroup) {
52827
53426
  height: totalHeight
52828
53427
  };
52829
53428
  }
52830
- var gNode, gEdge, MIN_NODE_WIDTH, MAX_NODE_WIDTH, TYPE_LABEL_HEIGHT, DIVIDER_GAP, NAME_HEIGHT, NAME_FONT_SIZE, DESC_LINE_HEIGHT5, DESC_FONT_SIZE4, CARD_V_PAD3, CARD_H_PAD4, META_LINE_HEIGHT4, META_FONT_SIZE4, MARGIN10, BOUNDARY_PAD, GROUP_BOUNDARY_PAD, EDGE_NODE_COLLISION_WEIGHT, META_EXCLUDE_KEYS;
53429
+ var gNode, gEdge, MIN_NODE_WIDTH, MAX_NODE_WIDTH, TYPE_LABEL_HEIGHT, DIVIDER_GAP, NAME_HEIGHT, NAME_FONT_SIZE, DESC_LINE_HEIGHT5, DESC_FONT_SIZE4, CARD_V_PAD3, CARD_H_PAD4, META_LINE_HEIGHT4, META_FONT_SIZE4, MARGIN11, BOUNDARY_PAD, GROUP_BOUNDARY_PAD, EDGE_NODE_COLLISION_WEIGHT, META_EXCLUDE_KEYS;
52831
53430
  var init_layout11 = __esm({
52832
53431
  "src/c4/layout.ts"() {
52833
53432
  "use strict";
@@ -52849,7 +53448,7 @@ var init_layout11 = __esm({
52849
53448
  CARD_H_PAD4 = 20;
52850
53449
  META_LINE_HEIGHT4 = 16;
52851
53450
  META_FONT_SIZE4 = 11;
52852
- MARGIN10 = 40;
53451
+ MARGIN11 = 40;
52853
53452
  BOUNDARY_PAD = 40;
52854
53453
  GROUP_BOUNDARY_PAD = 24;
52855
53454
  EDGE_NODE_COLLISION_WEIGHT = 5e3;
@@ -53125,7 +53724,7 @@ function renderC4ContextForExport(content, theme, palette) {
53125
53724
  }
53126
53725
  svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
53127
53726
  svgEl.style.fontFamily = FONT_FAMILY;
53128
- return svgEl.outerHTML;
53727
+ return serializeSvg(svgEl);
53129
53728
  } finally {
53130
53729
  document.body.removeChild(container);
53131
53730
  }
@@ -53741,7 +54340,7 @@ function renderC4ContainersForExport(content, systemName, theme, palette) {
53741
54340
  }
53742
54341
  svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
53743
54342
  svgEl.style.fontFamily = FONT_FAMILY;
53744
- return svgEl.outerHTML;
54343
+ return serializeSvg(svgEl);
53745
54344
  } finally {
53746
54345
  document.body.removeChild(el);
53747
54346
  }
@@ -53773,7 +54372,7 @@ function renderC4ComponentsForExport(content, systemName, containerName, theme,
53773
54372
  }
53774
54373
  svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
53775
54374
  svgEl.style.fontFamily = FONT_FAMILY;
53776
- return svgEl.outerHTML;
54375
+ return serializeSvg(svgEl);
53777
54376
  } finally {
53778
54377
  document.body.removeChild(el);
53779
54378
  }
@@ -53818,7 +54417,7 @@ function renderC4DeploymentForExport(content, theme, palette) {
53818
54417
  }
53819
54418
  svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
53820
54419
  svgEl.style.fontFamily = FONT_FAMILY;
53821
- return svgEl.outerHTML;
54420
+ return serializeSvg(svgEl);
53822
54421
  } finally {
53823
54422
  document.body.removeChild(el);
53824
54423
  }
@@ -53827,6 +54426,7 @@ var DIAGRAM_PADDING9, MAX_SCALE5, TITLE_HEIGHT6, TYPE_FONT_SIZE, NAME_FONT_SIZE2
53827
54426
  var init_renderer16 = __esm({
53828
54427
  "src/c4/renderer.ts"() {
53829
54428
  "use strict";
54429
+ init_svg_serialize();
53830
54430
  init_tag_groups();
53831
54431
  init_parsing();
53832
54432
  init_fonts();
@@ -54095,14 +54695,14 @@ function layoutGraph(graph, options) {
54095
54695
  let maxX = -Infinity;
54096
54696
  let maxY = -Infinity;
54097
54697
  for (const member of members) {
54098
- const left = member.x - member.width / 2;
54099
- const right = member.x + member.width / 2;
54100
- const top = member.y - member.height / 2;
54101
- const bottom = member.y + member.height / 2;
54102
- if (left < minX) minX = left;
54103
- if (right > maxX) maxX = right;
54104
- if (top < minY) minY = top;
54105
- if (bottom > maxY) maxY = bottom;
54698
+ const left2 = member.x - member.width / 2;
54699
+ const right2 = member.x + member.width / 2;
54700
+ const top2 = member.y - member.height / 2;
54701
+ const bottom2 = member.y + member.height / 2;
54702
+ if (left2 < minX) minX = left2;
54703
+ if (right2 > maxX) maxX = right2;
54704
+ if (top2 < minY) minY = top2;
54705
+ if (bottom2 > maxY) maxY = bottom2;
54106
54706
  }
54107
54707
  layoutGroups.push({
54108
54708
  id: group.id,
@@ -54371,15 +54971,15 @@ function renderDocument(g, node, palette, isDark, colorOff, fillMode, sNodeStrok
54371
54971
  const w = node.width;
54372
54972
  const h = node.height;
54373
54973
  const waveH = sDocWaveHeight;
54374
- const left = -w / 2;
54375
- const right = w / 2;
54376
- const top = -h / 2;
54377
- const bottom = h / 2 - waveH;
54974
+ const left2 = -w / 2;
54975
+ const right2 = w / 2;
54976
+ const top2 = -h / 2;
54977
+ const bottom2 = h / 2 - waveH;
54378
54978
  const d = [
54379
- `M ${left} ${top}`,
54380
- `L ${right} ${top}`,
54381
- `L ${right} ${bottom}`,
54382
- `C ${right - w * 0.25} ${bottom + waveH * 2}, ${left + w * 0.25} ${bottom - waveH}, ${left} ${bottom}`,
54979
+ `M ${left2} ${top2}`,
54980
+ `L ${right2} ${top2}`,
54981
+ `L ${right2} ${bottom2}`,
54982
+ `C ${right2 - w * 0.25} ${bottom2 + waveH * 2}, ${left2 + w * 0.25} ${bottom2 - waveH}, ${left2} ${bottom2}`,
54383
54983
  "Z"
54384
54984
  ].join(" ");
54385
54985
  g.append("path").attr("d", d).attr(
@@ -54745,7 +55345,7 @@ function renderFlowchartForExport(content, theme, palette) {
54745
55345
  }
54746
55346
  svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
54747
55347
  svgEl.style.fontFamily = FONT_FAMILY;
54748
- return svgEl.outerHTML;
55348
+ return serializeSvg(svgEl);
54749
55349
  } finally {
54750
55350
  document.body.removeChild(container);
54751
55351
  }
@@ -54754,6 +55354,7 @@ var DIAGRAM_PADDING10, MAX_SCALE6, NODE_FONT_SIZE3, EDGE_LABEL_FONT_SIZE9, ARROW
54754
55354
  var init_flowchart_renderer = __esm({
54755
55355
  "src/graph/flowchart-renderer.ts"() {
54756
55356
  "use strict";
55357
+ init_svg_serialize();
54757
55358
  init_parsing();
54758
55359
  init_arrow_markers();
54759
55360
  init_fit_canvas();
@@ -56160,14 +56761,14 @@ function layoutInfra(computed, expandedNodeIds, collapsedNodes) {
56160
56761
  }
56161
56762
  let minX2 = Infinity, minY2 = Infinity, maxX2 = -Infinity, maxY2 = -Infinity;
56162
56763
  for (const child of childNodes) {
56163
- const left = child.x - child.width / 2;
56164
- const right = child.x + child.width / 2;
56165
- const top = child.y - child.height / 2;
56166
- const bottom = child.y + child.height / 2;
56167
- if (left < minX2) minX2 = left;
56168
- if (right > maxX2) maxX2 = right;
56169
- if (top < minY2) minY2 = top;
56170
- if (bottom > maxY2) maxY2 = bottom;
56764
+ const left2 = child.x - child.width / 2;
56765
+ const right2 = child.x + child.width / 2;
56766
+ const top2 = child.y - child.height / 2;
56767
+ const bottom2 = child.y + child.height / 2;
56768
+ if (left2 < minX2) minX2 = left2;
56769
+ if (right2 > maxX2) maxX2 = right2;
56770
+ if (top2 < minY2) minY2 = top2;
56771
+ if (bottom2 > maxY2) maxY2 = bottom2;
56171
56772
  }
56172
56773
  return {
56173
56774
  id: group.id,
@@ -56185,14 +56786,14 @@ function layoutInfra(computed, expandedNodeIds, collapsedNodes) {
56185
56786
  fixEdgeWaypoints(layoutEdges, layoutNodes, groupDeltas);
56186
56787
  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
56187
56788
  for (const node of layoutNodes) {
56188
- const left = node.x - node.width / 2;
56189
- const right = node.x + node.width / 2;
56190
- const top = node.y - node.height / 2;
56191
- const bottom = node.y + node.height / 2;
56192
- if (left < minX) minX = left;
56193
- if (right > maxX) maxX = right;
56194
- if (top < minY) minY = top;
56195
- if (bottom > maxY) maxY = bottom;
56789
+ const left2 = node.x - node.width / 2;
56790
+ const right2 = node.x + node.width / 2;
56791
+ const top2 = node.y - node.height / 2;
56792
+ const bottom2 = node.y + node.height / 2;
56793
+ if (left2 < minX) minX = left2;
56794
+ if (right2 > maxX) maxX = right2;
56795
+ if (top2 < minY) minY = top2;
56796
+ if (bottom2 > maxY) maxY = bottom2;
56196
56797
  }
56197
56798
  for (const group of layoutGroups) {
56198
56799
  if (group.x < minX) minX = group.x;
@@ -56512,7 +57113,7 @@ function findRoutingLane(blocking, targetY, margin) {
56512
57113
  }
56513
57114
  }
56514
57115
  if (merged.length === 0) return targetY;
56515
- const MIN_GAP = 10;
57116
+ const MIN_GAP2 = 10;
56516
57117
  const candidates = [
56517
57118
  // In-bounds: merged.length > 0 guarded above.
56518
57119
  merged[0][0] - margin,
@@ -56523,7 +57124,7 @@ function findRoutingLane(blocking, targetY, margin) {
56523
57124
  for (let i = 0; i < merged.length - 1; i++) {
56524
57125
  const gapLo = merged[i][1];
56525
57126
  const gapHi = merged[i + 1][0];
56526
- if (gapHi - gapLo >= MIN_GAP) {
57127
+ if (gapHi - gapLo >= MIN_GAP2) {
56527
57128
  candidates.push((gapLo + gapHi) / 2);
56528
57129
  }
56529
57130
  }
@@ -59172,14 +59773,14 @@ function relayoutPert(resolved, overrides, collapsedGroupIds = /* @__PURE__ */ n
59172
59773
  let maxX = -Infinity;
59173
59774
  let maxY = -Infinity;
59174
59775
  for (const m of members) {
59175
- const left = m.x - m.width / 2;
59176
- const right = m.x + m.width / 2;
59177
- const top = m.y - m.height / 2;
59178
- const bottom = m.y + m.height / 2;
59179
- if (left < minX) minX = left;
59180
- if (right > maxX) maxX = right;
59181
- if (top < minY) minY = top;
59182
- if (bottom > maxY) maxY = bottom;
59776
+ const left2 = m.x - m.width / 2;
59777
+ const right2 = m.x + m.width / 2;
59778
+ const top2 = m.y - m.height / 2;
59779
+ const bottom2 = m.y + m.height / 2;
59780
+ if (left2 < minX) minX = left2;
59781
+ if (right2 > maxX) maxX = right2;
59782
+ if (top2 < minY) minY = top2;
59783
+ if (bottom2 > maxY) maxY = bottom2;
59183
59784
  }
59184
59785
  return {
59185
59786
  id: rg.group.id,
@@ -59193,10 +59794,10 @@ function relayoutPert(resolved, overrides, collapsedGroupIds = /* @__PURE__ */ n
59193
59794
  let totalW = 0;
59194
59795
  let totalH = 0;
59195
59796
  for (const n of nodes) {
59196
- const right = n.x + n.width / 2;
59197
- const bottom = n.y + n.height / 2;
59198
- if (right > totalW) totalW = right;
59199
- if (bottom > totalH) totalH = bottom;
59797
+ const right2 = n.x + n.width / 2;
59798
+ const bottom2 = n.y + n.height / 2;
59799
+ if (right2 > totalW) totalW = right2;
59800
+ if (bottom2 > totalH) totalH = bottom2;
59200
59801
  }
59201
59802
  for (const grp of groups) {
59202
59803
  if (grp.x + grp.width > totalW) totalW = grp.x + grp.width;
@@ -59369,15 +59970,15 @@ function centerByCriticality(g, resolved, memberToGroup, collapsedGroupIds) {
59369
59970
  if (cb !== ca) return cb - ca;
59370
59971
  return (currentSlot.get(a) ?? 0) - (currentSlot.get(b) ?? 0);
59371
59972
  });
59372
- const top = [];
59373
- const bottom = [];
59973
+ const top2 = [];
59974
+ const bottom2 = [];
59374
59975
  let middle = null;
59375
59976
  sortedDesc.forEach((id, i) => {
59376
59977
  if (i === 0) middle = id;
59377
- else if (i % 2 === 1) top.unshift(id);
59378
- else bottom.push(id);
59978
+ else if (i % 2 === 1) top2.unshift(id);
59979
+ else bottom2.push(id);
59379
59980
  });
59380
- const newOrder = middle ? [...top, middle, ...bottom] : [...top, ...bottom];
59981
+ const newOrder = middle ? [...top2, middle, ...bottom2] : [...top2, ...bottom2];
59381
59982
  newOrder.forEach((id, i) => {
59382
59983
  const node = g.node(id);
59383
59984
  const oldVal = node[slotAxis];
@@ -59805,7 +60406,7 @@ function renderPertForExport(content, theme, palette, now) {
59805
60406
  else svgEl.style.background = palette.bg;
59806
60407
  svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
59807
60408
  svgEl.style.fontFamily = FONT_FAMILY;
59808
- return svgEl.outerHTML;
60409
+ return serializeSvg(svgEl);
59809
60410
  } finally {
59810
60411
  document.body.removeChild(container);
59811
60412
  }
@@ -60690,10 +61291,10 @@ function drawMilestonePill(g, a) {
60690
61291
  drawCenteredText(x + w / 2, y + h - botRowH / 2, a.slack, "normal", sNCFS);
60691
61292
  }
60692
61293
  }
60693
- function drawAnchorPin(g, left, centerY, color, pinW = PIN_ICON_W, pinH = PIN_ICON_H) {
61294
+ function drawAnchorPin(g, left2, centerY, color, pinW = PIN_ICON_W, pinH = PIN_ICON_H) {
60694
61295
  const scale = pinW / 24;
60695
- const top = centerY - pinH / 2;
60696
- const pin = g.append("g").attr("class", "pert-pin").attr("data-pert-pin", "").attr("transform", `translate(${left}, ${top}) scale(${scale})`);
61296
+ const top2 = centerY - pinH / 2;
61297
+ const pin = g.append("g").attr("class", "pert-pin").attr("data-pert-pin", "").attr("transform", `translate(${left2}, ${top2}) scale(${scale})`);
60697
61298
  pin.append("path").attr("d", "M12 22V8 M5 12H2a10 10 0 0 0 20 0h-3").attr("fill", "none").attr("stroke", color).attr("stroke-width", 2).attr("stroke-linecap", "round").attr("stroke-linejoin", "round");
60698
61299
  pin.append("circle").attr("cx", 12).attr("cy", 5).attr("r", 3).attr("fill", "none").attr("stroke", color).attr("stroke-width", 2);
60699
61300
  }
@@ -61227,6 +61828,7 @@ var DIAGRAM_PADDING12, NODE_FONT_SIZE6, NODE_CELL_FONT_SIZE2, NODE_RADIUS2, NODE
61227
61828
  var init_renderer18 = __esm({
61228
61829
  "src/pert/renderer.ts"() {
61229
61830
  "use strict";
61831
+ init_svg_serialize();
61230
61832
  init_fonts();
61231
61833
  init_color_utils();
61232
61834
  init_scaling();
@@ -64640,7 +65242,7 @@ function renderStateForExport(content, theme, palette) {
64640
65242
  }
64641
65243
  svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
64642
65244
  svgEl.style.fontFamily = FONT_FAMILY;
64643
- return svgEl.outerHTML;
65245
+ return serializeSvg(svgEl);
64644
65246
  } finally {
64645
65247
  document.body.removeChild(container);
64646
65248
  }
@@ -64649,6 +65251,7 @@ var DIAGRAM_PADDING13, MAX_SCALE7, NODE_FONT_SIZE7, EDGE_LABEL_FONT_SIZE12, GROU
64649
65251
  var init_state_renderer = __esm({
64650
65252
  "src/graph/state-renderer.ts"() {
64651
65253
  "use strict";
65254
+ init_svg_serialize();
64652
65255
  init_parsing();
64653
65256
  init_inline_header();
64654
65257
  init_arrow_markers();
@@ -65975,14 +66578,14 @@ function positionPopover(popover, event) {
65975
66578
  const cursorY = event.clientY - rect2.top;
65976
66579
  const centerX = rect2.width / 2;
65977
66580
  const centerY = rect2.height / 2;
65978
- let left = cursorX < centerX ? cursorX + 16 : cursorX - tipW - 16;
65979
- let top = cursorY < centerY ? cursorY + 16 : cursorY - tipH - 16;
65980
- if (left + tipW > rect2.width - 4) left = rect2.width - tipW - 4;
65981
- if (left < 4) left = 4;
65982
- if (top + tipH > rect2.height - 4) top = rect2.height - tipH - 4;
65983
- if (top < 4) top = 4;
65984
- popover.style.left = `${left}px`;
65985
- popover.style.top = `${top}px`;
66581
+ let left2 = cursorX < centerX ? cursorX + 16 : cursorX - tipW - 16;
66582
+ let top2 = cursorY < centerY ? cursorY + 16 : cursorY - tipH - 16;
66583
+ if (left2 + tipW > rect2.width - 4) left2 = rect2.width - tipW - 4;
66584
+ if (left2 < 4) left2 = 4;
66585
+ if (top2 + tipH > rect2.height - 4) top2 = rect2.height - tipH - 4;
66586
+ if (top2 < 4) top2 = 4;
66587
+ popover.style.left = `${left2}px`;
66588
+ popover.style.top = `${top2}px`;
65986
66589
  }
65987
66590
  function hideBlipPopover(popover) {
65988
66591
  popover.style.display = "none";
@@ -67193,12 +67796,13 @@ function renderJourneyMapForExport(content, theme, palette) {
67193
67796
  const bgRect = svgEl.querySelector("rect:first-child");
67194
67797
  if (bgRect) bgRect.remove();
67195
67798
  }
67196
- return svgEl.outerHTML;
67799
+ return serializeSvg(svgEl);
67197
67800
  }
67198
67801
  var DIAGRAM_PADDING14, PADDING2, CARD_PADDING_X3, CARD_PADDING_Y3, CARD_HEADER_HEIGHT3, CARD_STROKE_WIDTH2, CARD_META_LINE_HEIGHT3, CARD_GAP_INTERNAL, COLUMN_RADIUS2, COLUMN_HEADER_HEIGHT2, COLUMN_PADDING3, FONT_SIZE_TITLE, FONT_SIZE_PHASE, FONT_SIZE_STEP, FONT_SIZE_META, GRID_LINE_OPACITY, CURVE_STROKE_WIDTH, FACE_RADIUS, CURVE_AREA_BOTTOM_GAP, FACE_HOVER_SCALE, FACE_HOVER_R, DIM_HOVER, TITLE_LINE_HEIGHT, EMOTION_LABEL_MAX_WIDTH, EMOTION_LABEL_FONT_SIZE, ICON_THUMBS_DOWN, ICON_THUMBS_UP, ICON_THOUGHT;
67199
67802
  var init_renderer21 = __esm({
67200
67803
  "src/journey-map/renderer.ts"() {
67201
67804
  "use strict";
67805
+ init_svg_serialize();
67202
67806
  init_tag_groups();
67203
67807
  init_parsing();
67204
67808
  init_color_utils();
@@ -69893,13 +70497,13 @@ function placeContextLabels(args) {
69893
70497
  if (!rectFits(rect2, width, height)) return null;
69894
70498
  if (cand.italic && overLand) {
69895
70499
  const inset = 2;
69896
- const top = cy - (cand.lines.length - 1) / 2 * LINE_HEIGHT;
70500
+ const top2 = cy - (cand.lines.length - 1) / 2 * LINE_HEIGHT;
69897
70501
  const touchesLand = cand.lines.some((line11, li) => {
69898
70502
  const lw = labelWidth(line11, cand.letterSpacing);
69899
70503
  const x0 = cx - lw / 2 + inset;
69900
70504
  const x1 = cx + lw / 2 - inset;
69901
70505
  const xs = [x0, (x0 + cx) / 2, cx, (cx + x1) / 2, x1];
69902
- const base = top + li * LINE_HEIGHT;
70506
+ const base = top2 + li * LINE_HEIGHT;
69903
70507
  return [base, base - FONT * 0.4, base - FONT * 0.8].some(
69904
70508
  (y) => xs.some((x) => overLand(x, y))
69905
70509
  );
@@ -70724,12 +71328,12 @@ function layoutMap(resolvedIn, data, size, opts) {
70724
71328
  const sh = Number.isFinite(bb[0][0]) ? bb[1][1] - bb[0][1] : iw;
70725
71329
  const needH = sh + 2 * PAD3;
70726
71330
  let topFit = topGuess;
70727
- const bottom = Math.min(topFit + needH, yB);
70728
- if (bottom - topFit < needH) topFit = bottom - needH;
71331
+ const bottom2 = Math.min(topFit + needH, yB);
71332
+ if (bottom2 - topFit < needH) topFit = bottom2 - needH;
70729
71333
  proj.fitExtent(
70730
71334
  [
70731
71335
  [x0 + PAD3, topFit + PAD3],
70732
- [xr - PAD3, bottom - PAD3]
71336
+ [xr - PAD3, bottom2 - PAD3]
70733
71337
  ],
70734
71338
  f
70735
71339
  );
@@ -70757,12 +71361,12 @@ function layoutMap(resolvedIn, data, size, opts) {
70757
71361
  x: x0,
70758
71362
  y: topFit,
70759
71363
  w: xr - x0,
70760
- h: bottom - topFit,
71364
+ h: bottom2 - topFit,
70761
71365
  points: [
70762
71366
  [x0, topFit],
70763
71367
  [xr, topFit],
70764
- [xr, bottom],
70765
- [x0, bottom]
71368
+ [xr, bottom2],
71369
+ [x0, bottom2]
70766
71370
  ],
70767
71371
  // The FITTED inset projection (just fit to this box) — captured so the
70768
71372
  // geo-query can invert pixels inside the frame back to AK/HI coords.
@@ -72083,11 +72687,11 @@ function layoutMap(resolvedIn, data, size, opts) {
72083
72687
  const COL_GAP2 = 16;
72084
72688
  const makeItems = (group) => group.map((p) => ({ p, ...labelInfo(p) })).sort((a, b) => a.p.cy - b.p.cy || (a.text < b.text ? -1 : 1));
72085
72689
  const columnRows = (items, side) => {
72086
- const left = Math.min(...items.map((o) => o.p.cx - o.p.r));
72087
- const right = Math.max(...items.map((o) => o.p.cx + o.p.r));
72690
+ const left2 = Math.min(...items.map((o) => o.p.cx - o.p.r));
72691
+ const right2 = Math.max(...items.map((o) => o.p.cx + o.p.r));
72088
72692
  const maxW = Math.max(...items.map((o) => o.w));
72089
72693
  const cyMid = (Math.min(...items.map((o) => o.p.cy)) + Math.max(...items.map((o) => o.p.cy))) / 2;
72090
- const colX = side === "right" ? Math.min(right + COL_GAP2, width - POI_EDGE_CLEAR - maxW) : Math.max(left - COL_GAP2, POI_EDGE_CLEAR + maxW);
72694
+ const colX = side === "right" ? Math.min(right2 + COL_GAP2, width - POI_EDGE_CLEAR - maxW) : Math.max(left2 - COL_GAP2, POI_EDGE_CLEAR + maxW);
72091
72695
  const totalH = items.length * step;
72092
72696
  let startY = cyMid - totalH / 2;
72093
72697
  startY = Math.max(
@@ -72285,11 +72889,11 @@ function layoutMap(resolvedIn, data, size, opts) {
72285
72889
  pushInline(p, text, w, side);
72286
72890
  continue;
72287
72891
  }
72288
- const left = Math.min(...items.map((o) => o.p.cx - o.p.r));
72289
- const right = Math.max(...items.map((o) => o.p.cx + o.p.r));
72892
+ const left2 = Math.min(...items.map((o) => o.p.cx - o.p.r));
72893
+ const right2 = Math.max(...items.map((o) => o.p.cx + o.p.r));
72290
72894
  const minCy = Math.min(...items.map((o) => o.p.cy));
72291
72895
  const maxCy = Math.max(...items.map((o) => o.p.cy));
72292
- const diag = Math.hypot(right - left, maxCy - minCy);
72896
+ const diag = Math.hypot(right2 - left2, maxCy - minCy);
72293
72897
  if (diag > maxExtent || items.length > MAX_COLUMN_ROWS) {
72294
72898
  items.forEach((o) => pushHidden(o.p));
72295
72899
  } else {
@@ -72349,18 +72953,18 @@ function layoutMap(resolvedIn, data, size, opts) {
72349
72953
  needBottom = Math.min(Math.max(0, Math.ceil(needBottom)), capV);
72350
72954
  if (needLeft >= 1 || needRight >= 1 || needTop >= 1 || needBottom >= 1) {
72351
72955
  const prev = opts._calloutReserve;
72352
- const left = Math.min((prev?.left ?? 0) + needLeft, capH);
72353
- const right = Math.min((prev?.right ?? 0) + needRight, capH);
72354
- const top = Math.min((prev?.top ?? 0) + needTop, capV);
72355
- const bottom = Math.min((prev?.bottom ?? 0) + needBottom, capV);
72956
+ const left2 = Math.min((prev?.left ?? 0) + needLeft, capH);
72957
+ const right2 = Math.min((prev?.right ?? 0) + needRight, capH);
72958
+ const top2 = Math.min((prev?.top ?? 0) + needTop, capV);
72959
+ const bottom2 = Math.min((prev?.bottom ?? 0) + needBottom, capV);
72356
72960
  return layoutMap(resolved, data, size, {
72357
72961
  ...opts,
72358
72962
  _poiClearancePass: clearancePass + 1,
72359
72963
  _calloutReserve: {
72360
- ...left > 0 && { left },
72361
- ...right > 0 && { right },
72362
- ...top > 0 && { top },
72363
- ...bottom > 0 && { bottom }
72964
+ ...left2 > 0 && { left: left2 },
72965
+ ...right2 > 0 && { right: right2 },
72966
+ ...top2 > 0 && { top: top2 },
72967
+ ...bottom2 > 0 && { bottom: bottom2 }
72364
72968
  }
72365
72969
  });
72366
72970
  }
@@ -73960,15 +74564,7 @@ function wrapDescription2(lines, maxWidth, fontSize) {
73960
74564
  const normalized = lines.map(
73961
74565
  (l) => l.startsWith("- ") ? "\u2022 " + l.slice(2) : l
73962
74566
  );
73963
- const out = [];
73964
- for (const line11 of normalized) {
73965
- if (line11 === "") {
73966
- out.push({ text: "", kind: "plain" });
73967
- continue;
73968
- }
73969
- out.push(...wrapDescriptionLines([line11], maxChars));
73970
- }
73971
- return out;
74567
+ return wrapDescriptionLines(normalized, maxChars);
73972
74568
  }
73973
74569
  function clamp2(x, lo, hi) {
73974
74570
  return Math.max(lo, Math.min(hi, x));
@@ -74350,8 +74946,8 @@ function layoutTreemapRadial(roots, opts) {
74350
74946
  );
74351
74947
  const ringSpan = Math.max(1, radius - discRadius);
74352
74948
  const ringWidth = ringSpan / Math.max(1, treeDepth);
74353
- (hroot.children ?? []).forEach((top, i) => {
74354
- top.each((d) => {
74949
+ (hroot.children ?? []).forEach((top2, i) => {
74950
+ top2.each((d) => {
74355
74951
  d._topIndex = i;
74356
74952
  });
74357
74953
  });
@@ -74785,14 +75381,14 @@ function fitFs(text, maxFs, availLen) {
74785
75381
  return Math.max(MIN_LABEL_FS, Math.floor(maxFs * availLen / w));
74786
75382
  }
74787
75383
  function drawCurvedLine(g, defs, pathId, cell, centerR, fs, weight, text, ink) {
74788
- const bottom = isBottomHalf(cell);
74789
- const rPath = bottom ? centerR + fs * 0.32 : centerR - fs * 0.32;
74790
- const [a0, a1] = bottom ? [cell.endAngle, cell.startAngle] : [cell.startAngle, cell.endAngle];
75384
+ const bottom2 = isBottomHalf(cell);
75385
+ const rPath = bottom2 ? centerR + fs * 0.32 : centerR - fs * 0.32;
75386
+ const [a0, a1] = bottom2 ? [cell.endAngle, cell.startAngle] : [cell.startAngle, cell.endAngle];
74791
75387
  const p0x = Math.sin(a0) * rPath;
74792
75388
  const p0y = -Math.cos(a0) * rPath;
74793
75389
  const p1x = Math.sin(a1) * rPath;
74794
75390
  const p1y = -Math.cos(a1) * rPath;
74795
- const sweepFlag = bottom ? 0 : 1;
75391
+ const sweepFlag = bottom2 ? 0 : 1;
74796
75392
  const largeArc = cell.endAngle - cell.startAngle > Math.PI ? 1 : 0;
74797
75393
  const d = `M ${p0x.toFixed(2)} ${p0y.toFixed(2)} A ${rPath.toFixed(2)} ${rPath.toFixed(2)} 0 ${largeArc} ${sweepFlag} ${p1x.toFixed(2)} ${p1y.toFixed(2)}`;
74798
75394
  defs.append("path").attr("id", pathId).attr("d", d);
@@ -74917,8 +75513,8 @@ function layoutTreemap(roots, opts) {
74917
75513
  const h = hierarchy3(rootDatum).sum((d) => d.children?.length ? 0 : d.value ?? 0).sort((a, b) => (b.value ?? 0) - (a.value ?? 0));
74918
75514
  const hroot = treemap().tile(treemapSquarify).size([opts.width, opts.height]).paddingOuter(opts.paddingOuter ?? 3).paddingTop(opts.headerH > 0 ? opts.headerH : opts.paddingInner ?? 2).paddingInner(opts.paddingInner ?? 2).round(true)(h);
74919
75515
  const total = hroot.value ?? 0;
74920
- (hroot.children ?? []).forEach((top, i) => {
74921
- top.each((d) => {
75516
+ (hroot.children ?? []).forEach((top2, i) => {
75517
+ top2.each((d) => {
74922
75518
  d._topIndex = i;
74923
75519
  });
74924
75520
  });
@@ -75790,13 +76386,13 @@ function renderWrappedMarkdown(textEl, lines, lineH) {
75790
76386
  }
75791
76387
  });
75792
76388
  }
75793
- function drawNote(svg, description, paint, left, top, width) {
76389
+ function drawNote(svg, description, paint, left2, top2, width) {
75794
76390
  const descSize = 15;
75795
76391
  const lineH = descSize * 1.4;
75796
76392
  const maxChars = Math.max(8, Math.floor(width / (descSize * 0.46)));
75797
- const firstY = top + descSize;
75798
- const lines = layoutDescription(description, left, maxChars);
75799
- const desc = svg.append("text").attr("x", left).attr("y", firstY).attr("text-anchor", "start").attr("fill", paint.muted).attr("font-family", FONT_FAMILY).attr("font-size", descSize).attr("font-weight", 500);
76393
+ const firstY = top2 + descSize;
76394
+ const lines = layoutDescription(description, left2, maxChars);
76395
+ const desc = svg.append("text").attr("x", left2).attr("y", firstY).attr("text-anchor", "start").attr("fill", paint.muted).attr("font-family", FONT_FAMILY).attr("font-size", descSize).attr("font-weight", 500);
75800
76396
  renderWrappedMarkdown(desc, lines, lineH);
75801
76397
  return firstY + lines.length * lineH;
75802
76398
  }
@@ -75834,15 +76430,15 @@ function renderBar2(svg, parsed, metrics, paint) {
75834
76430
  if (parsed.hasTarget) {
75835
76431
  g.append("text").attr("x", barRight + gap).attr("y", barCy + 26 * 0.35).attr("text-anchor", "start").attr("fill", paint.text).attr("font-family", FONT_FAMILY).attr("font-size", 26).attr("font-weight", 700).text(compactNumber2(parsed.target));
75836
76432
  }
75837
- let bottom = y + trackH;
76433
+ let bottom2 = y + trackH;
75838
76434
  if (parsed.description && !parsed.options.noNote) {
75839
- bottom = drawNote(svg, parsed.description, paint, x, bottom + 40, trackW);
76435
+ bottom2 = drawNote(svg, parsed.description, paint, x, bottom2 + 40, trackW);
75840
76436
  }
75841
76437
  return {
75842
76438
  minX: 0,
75843
76439
  minY: 0,
75844
76440
  maxX: barRight + gap + targetLabelW,
75845
- maxY: bottom
76441
+ maxY: bottom2
75846
76442
  };
75847
76443
  }
75848
76444
  function renderThermometer(svg, parsed, metrics, paint) {
@@ -75943,12 +76539,12 @@ function renderGauge(svg, parsed, metrics, paint) {
75943
76539
  let colBottom = crestTop;
75944
76540
  if (hasNote) {
75945
76541
  const titleSize = GOAL_TITLE_SIZE;
75946
- let top = crestTop;
76542
+ let top2 = crestTop;
75947
76543
  if (parsed.title && !parsed.options.noTitle) {
75948
- svg.append("text").attr("class", "chart-title").attr("x", colLeft).attr("y", top + titleSize * 0.78).attr("text-anchor", "start").attr("fill", paint.text).attr("font-family", FONT_FAMILY).attr("font-size", titleSize).attr("font-weight", TITLE_FONT_WEIGHT).attr("data-line-number", parsed.titleLineNumber).text(parsed.title);
75949
- top += titleSize * 0.78 + 16;
76544
+ svg.append("text").attr("class", "chart-title").attr("x", colLeft).attr("y", top2 + titleSize * 0.78).attr("text-anchor", "start").attr("fill", paint.text).attr("font-family", FONT_FAMILY).attr("font-size", titleSize).attr("font-weight", TITLE_FONT_WEIGHT).attr("data-line-number", parsed.titleLineNumber).text(parsed.title);
76545
+ top2 += titleSize * 0.78 + 16;
75950
76546
  }
75951
- colBottom = drawNote(svg, parsed.description, paint, colLeft, top, colW);
76547
+ colBottom = drawNote(svg, parsed.description, paint, colLeft, top2, colW);
75952
76548
  } else if (hasTopTitle) {
75953
76549
  faceTitle(svg, parsed, paint, cx, GOAL_TITLE_SIZE);
75954
76550
  }
@@ -76474,7 +77070,7 @@ function vizMonthGrid(svg, g, nowMs, resolvedMs, C) {
76474
77070
  const gridW = mw - 2 * padX;
76475
77071
  const cols = 7;
76476
77072
  const cellW = gridW / cols;
76477
- const top = g.top;
77073
+ const top2 = g.top;
76478
77074
  const headH = 26;
76479
77075
  const cellH = (g.height - headH - 8) / 6;
76480
77076
  const gridH = 6 * cellH;
@@ -76484,8 +77080,8 @@ function vizMonthGrid(svg, g, nowMs, resolvedMs, C) {
76484
77080
  months.forEach((m, mi) => {
76485
77081
  const mt = isContext[mi] ? svg.append("g").attr("opacity", 0.42) : svg;
76486
77082
  const mx = g.left + mi * (mw + gap);
76487
- aRect(mt, mx, top, mw, g.height, 14, C.inert, C.inertBorder, 1.25);
76488
- const gy = top + headH;
77083
+ aRect(mt, mx, top2, mw, g.height, 14, C.inert, C.inertBorder, 1.25);
77084
+ const gy = top2 + headH;
76489
77085
  for (const wcol of [0, 6])
76490
77086
  aRect(
76491
77087
  mt,
@@ -76499,14 +77095,14 @@ function vizMonthGrid(svg, g, nowMs, resolvedMs, C) {
76499
77095
  aText(
76500
77096
  mt,
76501
77097
  mx + mw / 2,
76502
- top + 16,
77098
+ top2 + 16,
76503
77099
  14,
76504
77100
  C.text,
76505
77101
  700,
76506
77102
  "middle",
76507
77103
  `${MON_ABBR[m.getMonth()]} ${m.getFullYear()}`
76508
77104
  );
76509
- aLine(mt, mx, top + headH - 6, mx + mw, top + headH - 6, C.rule, 1.25);
77105
+ aLine(mt, mx, top2 + headH - 6, mx + mw, top2 + headH - 6, C.rule, 1.25);
76510
77106
  const first = new Date(m.getFullYear(), m.getMonth(), 1).getDay();
76511
77107
  const dim = new Date(m.getFullYear(), m.getMonth() + 1, 0).getDate();
76512
77108
  for (let day = 1; day <= dim; day++) {
@@ -76820,7 +77416,7 @@ function renderCountdown(container, parsed, palette, isDark, exportDims) {
76820
77416
  const w = estWidth2(t, base);
76821
77417
  return w <= maxW ? base : Math.max(min, Math.floor(base * maxW / w));
76822
77418
  };
76823
- const dispLen = (s) => parseInlineMarkdown(s).reduce((n, sp) => n + sp.text.length, 0);
77419
+ const dispLen = (s) => stripInlineMarkdown(s).length;
76824
77420
  const padX = Math.max(30, Math.round(width * 0.045));
76825
77421
  const padY = Math.max(26, Math.round(width * 0.03));
76826
77422
  const contentW = width - 2 * padX;
@@ -77348,9 +77944,9 @@ function drawRow(svg, entry, index, parsed, now, rowTop, rowH, geom, col) {
77348
77944
  if (status) lines.push({ kind: "avail" });
77349
77945
  if (sun) lines.push({ kind: "sun" });
77350
77946
  const lh = 23;
77351
- const top = center + 10 - (lines.length - 1) * lh / 2;
77947
+ const top2 = center + 10 - (lines.length - 1) * lh / 2;
77352
77948
  lines.forEach((ln, i) => {
77353
- const yy = top + i * lh;
77949
+ const yy = top2 + i * lh;
77354
77950
  if (ln.kind === "place") {
77355
77951
  g.append("path").attr("transform", `translate(${iconX},${yy - 5}) scale(1.25)`).attr("d", "M0,4 L-2.3,-0.6 A2.6,2.6 0 1 1 2.3,-0.6 Z").attr("fill", muted);
77356
77952
  g.append("text").attr("x", textX).attr("y", yy).attr("fill", muted).attr("font-family", FONT_FAMILY).attr("font-size", 14).attr("font-weight", 500).text(ellipsize(entry.place, 14, textMax));
@@ -77390,15 +77986,15 @@ function bakeAnchors(g, entry, parsed, sun, sw) {
77390
77986
  );
77391
77987
  }
77392
77988
  }
77393
- function drawColumns(body, parsed, now, top, geom, col) {
77989
+ function drawColumns(body, parsed, now, top2, geom, col) {
77394
77990
  const { width, cardM } = geom;
77395
77991
  const { text, muted, line2: line22, tick, cardFill, sw } = col;
77396
77992
  const n = Math.max(1, parsed.entries.length);
77397
77993
  const colW = (width - 2 * cardM) / n;
77398
77994
  const tints = [];
77399
- let maxBottom = top;
77995
+ let maxBottom = top2;
77400
77996
  const deferred = [];
77401
- let detailTop = top;
77997
+ let detailTop = top2;
77402
77998
  parsed.entries.forEach((entry, i) => {
77403
77999
  const x0 = cardM + i * colW;
77404
78000
  const cx = x0 + colW / 2;
@@ -77437,13 +78033,13 @@ function drawColumns(body, parsed, now, top, geom, col) {
77437
78033
  bakeAnchors(g, entry, parsed, sun, sw);
77438
78034
  if (auto)
77439
78035
  tints.push(
77440
- g.append("rect").attr("data-dgmo-clock-lane", "").attr("x", x0).attr("y", top).attr("width", colW).attr("fill", fm === "outline" ? col.baseBg : auto.laneTint)
78036
+ g.append("rect").attr("data-dgmo-clock-lane", "").attr("x", x0).attr("y", top2).attr("width", colW).attr("fill", fm === "outline" ? col.baseBg : auto.laneTint)
77441
78037
  );
77442
78038
  if (auto) {
77443
78039
  g.attr("data-dgmo-clock-auto-solid", auto.solid).attr("data-dgmo-clock-auto-face", faceFill).attr("data-dgmo-clock-auto-mode", parsed.colorBy).attr("data-dgmo-clock-cardfill", cardFill);
77444
78040
  }
77445
78041
  if (fm) g.attr("data-dgmo-clock-fill-mode", fm);
77446
- let cy = top + (parsed.face === "analog" ? 22 : 36);
78042
+ let cy = top2 + (parsed.face === "analog" ? 22 : 36);
77447
78043
  const innerW = colW - 16;
77448
78044
  if (parsed.face === "analog") {
77449
78045
  const size = Math.min(innerW, 96);
@@ -77534,17 +78130,17 @@ function drawColumns(body, parsed, now, top, geom, col) {
77534
78130
  });
77535
78131
  deferred.forEach((d) => {
77536
78132
  d.draw(detailTop);
77537
- const bottom = d.kinds ? detailTop + (d.kinds - 1) * 20 + 8 : detailTop;
77538
- if (bottom > maxBottom) maxBottom = bottom;
78133
+ const bottom2 = d.kinds ? detailTop + (d.kinds - 1) * 20 + 8 : detailTop;
78134
+ if (bottom2 > maxBottom) maxBottom = bottom2;
77539
78135
  });
77540
- const colBodyH = maxBottom - top + 14;
78136
+ const colBodyH = maxBottom - top2 + 14;
77541
78137
  tints.forEach((r) => r.attr("height", colBodyH));
77542
78138
  const dividerColor = mix(col.palette.text, col.palette.bg, 40);
77543
78139
  for (let i = 1; i < n; i++) {
77544
78140
  const x = cardM + i * colW;
77545
- body.append("line").attr("data-dgmo-clock-col-divider", "").attr("x1", x).attr("x2", x).attr("y1", top).attr("y2", top + colBodyH).attr("stroke", dividerColor).attr("stroke-width", 1);
78141
+ body.append("line").attr("data-dgmo-clock-col-divider", "").attr("x1", x).attr("x2", x).attr("y1", top2).attr("y2", top2 + colBodyH).attr("stroke", dividerColor).attr("stroke-width", 1);
77546
78142
  }
77547
- return top + colBodyH + cardM;
78143
+ return top2 + colBodyH + cardM;
77548
78144
  }
77549
78145
  function renderClockForExport(container, parsed, palette, isDark, exportDims) {
77550
78146
  renderClock(container, parsed, palette, isDark, exportDims);
@@ -77960,36 +78556,36 @@ function layoutBracket(parsed) {
77960
78556
  champion = winnerNameOf(finalNode);
77961
78557
  }
77962
78558
  } else {
77963
- const left = groups[0];
77964
- const right = groups[1];
77965
- const L = left.built.rounds;
77966
- const R = right.built.rounds;
78559
+ const left2 = groups[0];
78560
+ const right2 = groups[1];
78561
+ const L = left2.built.rounds;
78562
+ const R = right2.built.rounds;
77967
78563
  const centerX = L * COL_W + BOX_W / 2;
77968
- for (const n of left.built.nodes) {
78564
+ for (const n of left2.built.nodes) {
77969
78565
  n.x = (n.round - 1) * COL_W + BOX_W / 2;
77970
78566
  n.y = n.y * rowScale;
77971
78567
  allNodes.push(n);
77972
78568
  nodeById.set(n.id, n);
77973
78569
  addColLabel(n.x, roundLabel(n.round, L, parsed.roundNames, true));
77974
78570
  }
77975
- for (const n of right.built.nodes) {
78571
+ for (const n of right2.built.nodes) {
77976
78572
  n.x = centerX + (R - n.round + 1) * COL_W;
77977
78573
  n.y = n.y * rowScale;
77978
78574
  allNodes.push(n);
77979
78575
  nodeById.set(n.id, n);
77980
78576
  addColLabel(n.x, roundLabel(n.round, R, parsed.roundNames, true));
77981
78577
  }
77982
- if (left.label)
77983
- pushSide(0, (L - 1) * COL_W + BOX_W, left.label, left.color);
77984
- if (right.label)
78578
+ if (left2.label)
78579
+ pushSide(0, (L - 1) * COL_W + BOX_W, left2.label, left2.color);
78580
+ if (right2.label)
77985
78581
  pushSide(
77986
78582
  centerX + COL_W - BOX_W / 2,
77987
78583
  centerX + R * COL_W + BOX_W / 2,
77988
- right.label,
77989
- right.color
78584
+ right2.label,
78585
+ right2.color
77990
78586
  );
77991
- const leftRoot = left.built.rootId !== null ? nodeById.get(left.built.rootId) : null;
77992
- const rightRoot = right.built.rootId !== null ? nodeById.get(right.built.rootId) : null;
78587
+ const leftRoot = left2.built.rootId !== null ? nodeById.get(left2.built.rootId) : null;
78588
+ const rightRoot = right2.built.rootId !== null ? nodeById.get(right2.built.rootId) : null;
77993
78589
  const cid = nextId();
77994
78590
  const champNode = {
77995
78591
  id: cid,
@@ -78323,9 +78919,9 @@ function renderBracket(container, parsed, palette, isDark, exportDims) {
78323
78919
  const covered = layout.sideLabels.some(
78324
78920
  (s) => col.x >= s.x0 && col.x <= s.x1
78325
78921
  );
78326
- const top = covered ? bandTop : 2;
78922
+ const top2 = covered ? bandTop : 2;
78327
78923
  const c = resolveColor(col.color, palette) ?? col.color;
78328
- root.append("rect").attr("x", col.x - BOX_W / 2 - 10).attr("y", top).attr("width", BOX_W + 20).attr("height", Math.max(0, layout.height - top)).attr("rx", 10).attr(
78924
+ root.append("rect").attr("x", col.x - BOX_W / 2 - 10).attr("y", top2).attr("width", BOX_W + 20).attr("height", Math.max(0, layout.height - top2)).attr("rx", 10).attr(
78329
78925
  "fill",
78330
78926
  fillMode === "outline" ? themeBaseBg(palette, isDark) : mix(c, palette.bg, isDark ? 12 : 8)
78331
78927
  ).call((sel) => {
@@ -79671,20 +80267,20 @@ function buildRenderSequence(messages) {
79671
80267
  for (let mi = 0; mi < messages.length; mi++) {
79672
80268
  const msg = messages[mi];
79673
80269
  while (stack.length > 0) {
79674
- const top = stack[stack.length - 1];
79675
- if (top.to === msg.from) break;
80270
+ const top2 = stack[stack.length - 1];
80271
+ if (top2.to === msg.from) break;
79676
80272
  stack.pop();
79677
80273
  steps.push({
79678
80274
  type: "return",
79679
- from: top.to,
79680
- to: top.from,
80275
+ from: top2.to,
80276
+ to: top2.from,
79681
80277
  label: "",
79682
- messageIndex: top.messageIndex
80278
+ messageIndex: top2.messageIndex
79683
80279
  });
79684
80280
  }
79685
80281
  if (stack.length > 0 && !msg.async && msg.from !== msg.to) {
79686
- const top = stack[stack.length - 1];
79687
- if (top.from === msg.to && top.to === msg.from) {
80282
+ const top2 = stack[stack.length - 1];
80283
+ if (top2.from === msg.to && top2.to === msg.from) {
79688
80284
  stack.pop();
79689
80285
  steps.push({
79690
80286
  type: "return",
@@ -79724,13 +80320,13 @@ function buildRenderSequence(messages) {
79724
80320
  }
79725
80321
  }
79726
80322
  while (stack.length > 0) {
79727
- const top = stack.pop();
80323
+ const top2 = stack.pop();
79728
80324
  steps.push({
79729
80325
  type: "return",
79730
- from: top.to,
79731
- to: top.from,
80326
+ from: top2.to,
80327
+ to: top2.from,
79732
80328
  label: "",
79733
- messageIndex: top.messageIndex
80329
+ messageIndex: top2.messageIndex
79734
80330
  });
79735
80331
  }
79736
80332
  return steps;
@@ -79836,11 +80432,11 @@ function applyGroupOrdering(participants, groups, messages = []) {
79836
80432
  const group = idToGroup.get(id);
79837
80433
  if (group && !placedGroups.has(group)) {
79838
80434
  placedGroups.add(group);
79839
- for (const gid of group.participantIds) {
79840
- const p = participants.find((pp) => pp.id === gid);
79841
- if (p && !placed.has(gid)) {
80435
+ for (const gid2 of group.participantIds) {
80436
+ const p = participants.find((pp) => pp.id === gid2);
80437
+ if (p && !placed.has(gid2)) {
79842
80438
  result.push(p);
79843
- placed.add(gid);
80439
+ placed.add(gid2);
79844
80440
  }
79845
80441
  }
79846
80442
  } else if (!group) {
@@ -81687,12 +82283,12 @@ function resolveVerticalCollisions(items, minGap, maxY) {
81687
82283
  let prevBottom = -Infinity;
81688
82284
  for (const item of sorted) {
81689
82285
  const halfH = item.height / 2;
81690
- let top = Math.max(item.naturalY - halfH, prevBottom + minGap);
82286
+ let top2 = Math.max(item.naturalY - halfH, prevBottom + minGap);
81691
82287
  if (maxY !== void 0) {
81692
- top = Math.min(top, maxY - item.height);
82288
+ top2 = Math.min(top2, maxY - item.height);
81693
82289
  }
81694
- adjustedY[item.idx] = top + halfH;
81695
- prevBottom = top + item.height;
82290
+ adjustedY[item.idx] = top2 + halfH;
82291
+ prevBottom = top2 + item.height;
81696
82292
  }
81697
82293
  return adjustedY;
81698
82294
  }
@@ -82753,8 +83349,8 @@ function renderVenn(container, parsed, palette, _isDark, onClickItem, exportDims
82753
83349
  const cci = circles[ci];
82754
83350
  const dy = py - cci.y;
82755
83351
  const halfChord = Math.sqrt(Math.max(0, cci.r * cci.r - dy * dy));
82756
- let left = cci.x - halfChord;
82757
- let right = cci.x + halfChord;
83352
+ let left2 = cci.x - halfChord;
83353
+ let right2 = cci.x + halfChord;
82758
83354
  for (let j = 0; j < n; j++) {
82759
83355
  if (j === ci) continue;
82760
83356
  const cj = circles[j];
@@ -82763,11 +83359,11 @@ function renderVenn(container, parsed, palette, _isDark, onClickItem, exportDims
82763
83359
  const hc = Math.sqrt(cj.r * cj.r - djy * djy);
82764
83360
  const jLeft = cj.x - hc;
82765
83361
  const jRight = cj.x + hc;
82766
- if (jLeft <= left && jRight >= right) return 0;
82767
- if (jLeft <= left && jRight > left) left = jRight;
82768
- if (jRight >= right && jLeft < right) right = jLeft;
83362
+ if (jLeft <= left2 && jRight >= right2) return 0;
83363
+ if (jLeft <= left2 && jRight > left2) left2 = jRight;
83364
+ if (jRight >= right2 && jLeft < right2) right2 = jLeft;
82769
83365
  }
82770
- return Math.max(0, right - left);
83366
+ return Math.max(0, right2 - left2);
82771
83367
  }
82772
83368
  const MIN_FONT = ctx.text(10);
82773
83369
  const MAX_FONT = ctx.text(22);
@@ -86583,6 +87179,30 @@ var BLOCK_CSS = `
86583
87179
  color: #616e88;
86584
87180
  font-style: italic;
86585
87181
  }
87182
+
87183
+ /* === Cloud references ===
87184
+ * A withdrawn reference's placeholder, and the "this moved" affordance a host's
87185
+ * client script falls back to when it can see a diagram has changed but cannot
87186
+ * safely swap it in. Both are deliberately quiet: a page peppered with badges
87187
+ * is worse than one that is a few days behind. */
87188
+ .dgmo--tombstone {
87189
+ border: 1px dashed currentColor;
87190
+ border-radius: 6px;
87191
+ opacity: 0.6;
87192
+ padding: 1.5rem;
87193
+ text-align: center;
87194
+ }
87195
+ .dgmo-tombstone-text {
87196
+ font-size: 0.9em;
87197
+ margin: 0;
87198
+ }
87199
+ .dgmo-updated {
87200
+ display: block;
87201
+ font-size: 0.8em;
87202
+ margin-top: 0.4rem;
87203
+ opacity: 0.7;
87204
+ text-align: right;
87205
+ }
86586
87206
  `;
86587
87207
 
86588
87208
  // src/embed/index.ts
@@ -86603,6 +87223,7 @@ function resolveBlockOptions(opts) {
86603
87223
  wrapper: opts.wrapper ?? "figure",
86604
87224
  className: opts.className ?? "dgmo",
86605
87225
  legacyClassNames: opts.legacyClassNames ?? [],
87226
+ dataAttributes: opts.dataAttributes ?? {},
86606
87227
  title: opts.title,
86607
87228
  onWarn: opts.onWarn ?? ((message) => console.warn(message))
86608
87229
  };
@@ -86628,8 +87249,12 @@ function assembleBlock(source, svgsHtml, opts) {
86628
87249
  const showcase = opts.mode === "showcase";
86629
87250
  const variant = showcase ? "showcase" : "diagram";
86630
87251
  const ariaAttr = opts.title ? ` aria-label="${escapeAttr(opts.title)}"` : "";
87252
+ const dataAttrs = dataAttributeString(opts.dataAttributes);
86631
87253
  const sourceHtml = sourceDisclosure(source, opts);
86632
- return `<${Wrapper} class="${escapeAttr(wrapperClasses(opts, variant))}"${ariaAttr}>` + svgsHtml + sourceHtml + `</${Wrapper}>`;
87254
+ return `<${Wrapper} class="${escapeAttr(wrapperClasses(opts, variant))}"${ariaAttr}${dataAttrs}>` + svgsHtml + sourceHtml + `</${Wrapper}>`;
87255
+ }
87256
+ function dataAttributeString(attrs) {
87257
+ return Object.entries(attrs).filter(([name]) => /^[a-z][a-z0-9-]*$/.test(name)).map(([name, value]) => ` data-${name}="${escapeAttr(value)}"`).join("");
86633
87258
  }
86634
87259
  var CODE_ICON = `<svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m10 4.5 4 3.5-4 3.5"/><path d="m6 4.5-4 3.5 4 3.5"/></svg>`;
86635
87260
  var COPY_ICON = `<svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="5.5" y="5.5" width="8" height="8" rx="1.5"/><path d="M10.5 5.5V3a1.5 1.5 0 0 0-1.5-1.5H3A1.5 1.5 0 0 0 1.5 3v6A1.5 1.5 0 0 0 3 10.5h2.5"/></svg>`;
@@ -86702,7 +87327,7 @@ var CSS = AUTO_BASE_CSS + "\n" + BLOCK_CSS + "\n" + darkScopedBlockCss(BLOCK_CSS
86702
87327
 
86703
87328
  // src/auto/shared.ts
86704
87329
  init_safe_href();
86705
- var VERSION = "0.55.0";
87330
+ var VERSION = "0.57.0";
86706
87331
  var ARIA_LABEL_MAX = 200;
86707
87332
  var COPIED_INTERACTION_MS = 1500;
86708
87333
  var LOG_PREFIX = "[dgmo]";