@diagrammo/dgmo 0.46.0 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (534) hide show
  1. package/dist/advanced.d.ts +3 -855
  2. package/dist/advanced.js +541 -70107
  3. package/dist/analyzer-UYKBXAKR.js +15 -0
  4. package/dist/auto.js +1 -1
  5. package/dist/auto.mjs +1 -1
  6. package/dist/block.js +83 -69417
  7. package/dist/calculator-LDYQCDDY.js +11 -0
  8. package/dist/charts-d3-QOZHKTCT.js +25 -0
  9. package/dist/chunk-2DXMZRWJ.js +800 -0
  10. package/dist/chunk-2LACINWN.js +786 -0
  11. package/dist/chunk-33LCUH4H.js +893 -0
  12. package/dist/chunk-3CIOJ5YJ.js +35 -0
  13. package/dist/chunk-3HDBAXF5.js +86 -0
  14. package/dist/chunk-3JLKYGBQ.js +290 -0
  15. package/dist/chunk-3MQQNXPD.js +415 -0
  16. package/dist/chunk-3R5POCTZ.js +967 -0
  17. package/dist/chunk-3SMGIJDD.js +112 -0
  18. package/dist/chunk-44CM72SQ.js +409 -0
  19. package/dist/chunk-4GRI7MEB.js +1604 -0
  20. package/dist/chunk-4OHACBGX.js +606 -0
  21. package/dist/chunk-5DH3KYFH.js +21 -0
  22. package/dist/chunk-5MLYVTYM.js +76 -0
  23. package/dist/chunk-5QXL4NYS.js +553 -0
  24. package/dist/chunk-5WRI5ZAA.js +31 -0
  25. package/dist/chunk-6EK55ART.js +117 -0
  26. package/dist/chunk-6FZYCKXB.js +2065 -0
  27. package/dist/chunk-6HO5ZTXK.js +277 -0
  28. package/dist/chunk-6KFWC4CO.js +7 -0
  29. package/dist/chunk-6MTWIQVO.js +121 -0
  30. package/dist/chunk-6NYWYNBI.js +329 -0
  31. package/dist/chunk-6SM5NJQH.js +620 -0
  32. package/dist/chunk-725LDASD.js +422 -0
  33. package/dist/chunk-76OWZ3BA.js +130 -0
  34. package/{src/block/parser.ts → dist/chunk-7JEGTRLD.js} +100 -189
  35. package/dist/chunk-A44USUV7.js +923 -0
  36. package/dist/chunk-A4GOY3PE.js +25 -0
  37. package/dist/chunk-A4VFQH5G.js +251 -0
  38. package/dist/chunk-AELOBFW5.js +375 -0
  39. package/dist/chunk-AN2MOO5T.js +522 -0
  40. package/dist/chunk-BMR4CIEO.js +41 -0
  41. package/dist/chunk-BS7SV7C3.js +51 -0
  42. package/dist/chunk-BUPDIHML.js +613 -0
  43. package/dist/chunk-BUVJFRPY.js +887 -0
  44. package/dist/chunk-C3Z4DX3V.js +112 -0
  45. package/dist/chunk-CI2G3OEB.js +1818 -0
  46. package/dist/chunk-CKNVO24D.js +54 -0
  47. package/dist/chunk-CUVHQHZ7.js +391 -0
  48. package/dist/chunk-CXK4DZH3.js +114 -0
  49. package/dist/{editor.cjs → chunk-DKEPS5LH.js} +14 -225
  50. package/dist/chunk-DU7W62N5.js +487 -0
  51. package/dist/chunk-DZAQBW35.js +751 -0
  52. package/dist/chunk-EB6FPQUP.js +316 -0
  53. package/dist/chunk-EMS2SK26.js +376 -0
  54. package/dist/chunk-ERLBPDGU.js +510 -0
  55. package/dist/chunk-EVCVDTXE.js +732 -0
  56. package/dist/chunk-FCIIHT24.js +384 -0
  57. package/dist/chunk-FFUN5D66.js +97 -0
  58. package/dist/chunk-FITOLXSX.js +714 -0
  59. package/dist/chunk-FMDSF3OV.js +68 -0
  60. package/dist/chunk-FNB3PNGF.js +410 -0
  61. package/dist/chunk-G2H74XJZ.js +2104 -0
  62. package/dist/chunk-GMR5MFHJ.js +339 -0
  63. package/dist/chunk-H6PI3KJT.js +305 -0
  64. package/dist/chunk-I46X5VUA.js +59 -0
  65. package/dist/chunk-I5IGB56C.js +255 -0
  66. package/dist/chunk-IH6ZMVQ5.js +3950 -0
  67. package/dist/chunk-IJZFN3HM.js +463 -0
  68. package/dist/chunk-IPWPWM6R.js +3079 -0
  69. package/dist/chunk-IYULMRBE.js +23 -0
  70. package/dist/chunk-IZMRON6C.js +167 -0
  71. package/dist/chunk-J5FIXQRT.js +813 -0
  72. package/dist/chunk-JED6ZDEE.js +73 -0
  73. package/dist/chunk-JEUJOX5X.js +136 -0
  74. package/dist/chunk-JM4LEPY3.js +436 -0
  75. package/dist/chunk-L3UHP6TD.js +101 -0
  76. package/dist/chunk-L66GEFB6.js +524 -0
  77. package/dist/chunk-LIOHW36Z.js +469 -0
  78. package/dist/chunk-LP7EC4MI.js +16 -0
  79. package/dist/chunk-MITI6NOL.js +548 -0
  80. package/dist/chunk-MO5YHHMQ.js +168 -0
  81. package/dist/chunk-MZSBFAPJ.js +885 -0
  82. package/dist/chunk-NNAAJVBU.js +9 -0
  83. package/dist/chunk-NOTA6TEI.js +47 -0
  84. package/dist/chunk-NURGB5Z4.js +335 -0
  85. package/dist/chunk-NX4EQS3U.js +1062 -0
  86. package/dist/chunk-NXMESY4J.js +1 -0
  87. package/dist/chunk-OJR3MQYV.js +1458 -0
  88. package/dist/chunk-OURHMODR.js +454 -0
  89. package/dist/chunk-P235SVAH.js +1057 -0
  90. package/dist/chunk-P4RH4OSP.js +1038 -0
  91. package/dist/chunk-P6T66CCZ.js +226 -0
  92. package/dist/chunk-PBAHEPLQ.js +223 -0
  93. package/dist/chunk-PBHE5UG6.js +1530 -0
  94. package/dist/chunk-PDKUANDZ.js +35 -0
  95. package/dist/chunk-PWIHZ6NJ.js +296 -0
  96. package/{src/c4/layout.ts → dist/chunk-QEBUY5NY.js} +384 -1140
  97. package/dist/chunk-QLCCJEJI.js +253 -0
  98. package/dist/chunk-QOOUC2J5.js +52 -0
  99. package/dist/chunk-QYTPPDAO.js +402 -0
  100. package/dist/chunk-R3XI2VC7.js +801 -0
  101. package/dist/chunk-RCERWOJR.js +154 -0
  102. package/dist/chunk-RJE5JTVK.js +362 -0
  103. package/dist/chunk-RTLBSQ3G.js +1155 -0
  104. package/dist/chunk-RUNNI6VE.js +448 -0
  105. package/dist/chunk-RVMRZAPB.js +354 -0
  106. package/dist/chunk-RYEGFMUO.js +955 -0
  107. package/dist/chunk-RZCF2VVM.js +528 -0
  108. package/dist/chunk-SML67VPV.js +1025 -0
  109. package/dist/chunk-SQ7IY53Q.js +44 -0
  110. package/dist/chunk-SQAG3UXH.js +161 -0
  111. package/dist/chunk-SRTU6HMQ.js +1851 -0
  112. package/dist/chunk-T2OE3YQB.js +550 -0
  113. package/dist/chunk-T3UBLACL.js +299 -0
  114. package/dist/chunk-TLVIHFRO.js +296 -0
  115. package/dist/chunk-TYS6CSS5.js +52 -0
  116. package/dist/chunk-U6EQI3U6.js +130 -0
  117. package/dist/chunk-UJ4FJLBF.js +86 -0
  118. package/dist/chunk-ULOEATBZ.js +347 -0
  119. package/dist/chunk-UNCCZ3NU.js +127 -0
  120. package/dist/chunk-USZW2HHU.js +197 -0
  121. package/dist/chunk-UWN33VNX.js +1610 -0
  122. package/dist/chunk-UZ7EZW3B.js +40 -0
  123. package/dist/chunk-VOKGH627.js +37 -0
  124. package/dist/chunk-WBRZJOEC.js +204 -0
  125. package/dist/chunk-WCSOJFU3.js +380 -0
  126. package/dist/chunk-WCT3NYCV.js +160 -0
  127. package/dist/chunk-WVAJFAIA.js +529 -0
  128. package/dist/chunk-X5LCYCL5.js +394 -0
  129. package/dist/chunk-XAKEUMEJ.js +1256 -0
  130. package/dist/chunk-Y2ZE3MSG.js +590 -0
  131. package/dist/chunk-Y3J7VR52.js +646 -0
  132. package/dist/chunk-Y5QGVTVC.js +33 -0
  133. package/dist/chunk-YAA6IID3.js +548 -0
  134. package/dist/chunk-YGJTDXVR.js +692 -0
  135. package/{src/utils/time-ticks.ts → dist/chunk-YRYKTYMQ.js} +45 -112
  136. package/dist/chunk-YYVTBZZC.js +61 -0
  137. package/dist/chunk-Z5CGSFJB.js +647 -0
  138. package/{src/gantt/calculator.ts → dist/chunk-Z72XRXD4.js} +236 -428
  139. package/dist/chunk-ZGR7ULFJ.js +978 -0
  140. package/dist/chunk-ZJEL4H2R.js +851 -0
  141. package/dist/chunk-ZO27FGJS.js +554 -0
  142. package/dist/collapse-CLPJD2RL.js +11 -0
  143. package/dist/collapse-SLINJQW6.js +9 -0
  144. package/dist/collapse-ZWUFFCK2.js +9 -0
  145. package/dist/compute-G55RG53N.js +8 -0
  146. package/dist/dgmo-router-DZCIDUO5.js +73 -0
  147. package/dist/dimensions-J3FHIMJ6.js +22 -0
  148. package/dist/element.js +1 -1
  149. package/dist/element.mjs +1 -1
  150. package/dist/flowchart-parser-ZNSKIBVR.js +21 -0
  151. package/dist/flowchart-renderer-ZAEOL4DX.js +35 -0
  152. package/dist/index.d.ts +3 -469
  153. package/dist/index.js +137 -69685
  154. package/dist/layout-46N4JJYK.js +17 -0
  155. package/dist/layout-5RA6QWR6.js +26 -0
  156. package/dist/layout-5T6RH5M6.js +14 -0
  157. package/dist/layout-7QXCNOVS.js +13 -0
  158. package/dist/layout-EE6GE46Y.js +17 -0
  159. package/dist/layout-G23F7LDH.js +9 -0
  160. package/dist/layout-HRBZPFCN.js +23 -0
  161. package/dist/layout-HWDSRX5E.js +20 -0
  162. package/dist/layout-HYZPWAK5.js +18 -0
  163. package/dist/layout-N76NR4ZO.js +19 -0
  164. package/dist/layout-OB3RI63S.js +14 -0
  165. package/dist/layout-S2QBYSK2.js +15 -0
  166. package/dist/layout-UM5F4DJB.js +15 -0
  167. package/dist/layout-search-OYV77HHS.js +1655 -0
  168. package/dist/load-data-EHDDZ5ZS.js +8 -0
  169. package/dist/palettes-PRJ2RI6D.js +56 -0
  170. package/dist/parser-2MFP2H2E.js +11 -0
  171. package/dist/parser-3STE62GB.js +21 -0
  172. package/dist/parser-4FL2CMDG.js +18 -0
  173. package/dist/parser-4OGOBJJ4.js +13 -0
  174. package/dist/parser-6BTRLKRZ.js +15 -0
  175. package/dist/parser-AQETEVRW.js +21 -0
  176. package/dist/parser-CFZD5IBL.js +12 -0
  177. package/dist/parser-FUSKFGZN.js +16 -0
  178. package/dist/parser-I6KXEYFK.js +13 -0
  179. package/dist/parser-IXSZZQHY.js +18 -0
  180. package/dist/parser-JAL2HD4I.js +13 -0
  181. package/dist/parser-KNSQSKQO.js +20 -0
  182. package/dist/parser-N5O4IHUN.js +13 -0
  183. package/dist/parser-NGU3ETO6.js +16 -0
  184. package/dist/parser-NRAI6O25.js +19 -0
  185. package/dist/parser-O5J4VBII.js +11 -0
  186. package/dist/parser-OV7NOBW6.js +21 -0
  187. package/dist/parser-PQ3POX45.js +23 -0
  188. package/dist/parser-TFZFBVWN.js +11 -0
  189. package/dist/parser-TRTHDFPP.js +18 -0
  190. package/dist/parser-VQP2UJ6W.js +11 -0
  191. package/dist/parser-XDVELHRK.js +13 -0
  192. package/dist/parser-XKRP7QKP.js +11 -0
  193. package/dist/parser-Y6WTBU76.js +14 -0
  194. package/dist/parser-ZSDPZYQP.js +12 -0
  195. package/dist/renderer-2XQQQ6QR.js +28 -0
  196. package/dist/renderer-5NDVNDAZ.js +26 -0
  197. package/dist/renderer-6EEZHMH4.js +26 -0
  198. package/dist/renderer-6W5462RB.js +43 -0
  199. package/dist/renderer-7MVLWWQD.js +22 -0
  200. package/dist/renderer-AWWAF6XD.js +33 -0
  201. package/dist/renderer-BYCNMBF7.js +34 -0
  202. package/dist/renderer-CLJHQPBJ.js +29 -0
  203. package/dist/renderer-GHPZMFU2.js +15 -0
  204. package/dist/renderer-JGBKUCZD.js +16 -0
  205. package/dist/renderer-KQB7UGDS.js +19 -0
  206. package/dist/renderer-PGX2TKVS.js +24 -0
  207. package/dist/renderer-QIWVHWZO.js +15 -0
  208. package/dist/renderer-RPOA5YPZ.js +35 -0
  209. package/dist/renderer-SMIBCRVB.js +24 -0
  210. package/dist/renderer-T7YKC5VP.js +28 -0
  211. package/dist/renderer-TOCOVLHS.js +37 -0
  212. package/dist/renderer-UWA5XS74.js +39 -0
  213. package/dist/renderer-VACVQYML.js +25 -0
  214. package/dist/renderer-W4M6QLIJ.js +37 -0
  215. package/dist/renderer-WZRREQ2P.js +23 -0
  216. package/dist/renderer-YY2OSF6E.js +27 -0
  217. package/dist/renderer-Z7I3W2PP.js +24 -0
  218. package/dist/renderer-ZGNTUWC4.js +22 -0
  219. package/dist/renderer-ZTR3DER3.js +19 -0
  220. package/dist/renderer-radial-C32GPJQ7.js +21 -0
  221. package/dist/resolver-NOAA7ID7.js +13 -0
  222. package/dist/state-collapse-HCGD6IVJ.js +8 -0
  223. package/dist/state-parser-Z2V23ATR.js +18 -0
  224. package/dist/state-renderer-RFYHSP4K.js +34 -0
  225. package/dist/themes-1-CuKpeH.d.ts +908 -0
  226. package/package.json +19 -70
  227. package/dist/advanced.cjs +0 -71648
  228. package/dist/advanced.d.cts +0 -6571
  229. package/dist/auto.cjs +0 -70648
  230. package/dist/auto.d.cts +0 -54
  231. package/dist/block.cjs +0 -70208
  232. package/dist/block.d.cts +0 -115
  233. package/dist/editor.d.cts +0 -26
  234. package/dist/element.cjs +0 -70530
  235. package/dist/element.d.cts +0 -62
  236. package/dist/highlight.cjs +0 -852
  237. package/dist/highlight.d.cts +0 -49
  238. package/dist/index.cjs +0 -70491
  239. package/dist/index.d.cts +0 -626
  240. package/dist/pert.cjs +0 -325
  241. package/dist/pert.d.cts +0 -559
  242. package/src/advanced.ts +0 -873
  243. package/src/arc/parser.ts +0 -15
  244. package/src/arc/renderer.ts +0 -633
  245. package/src/auto/index.ts +0 -621
  246. package/src/auto/shared.ts +0 -370
  247. package/src/auto/styles.ts +0 -73
  248. package/src/block/layout.ts +0 -198
  249. package/src/block/renderer.ts +0 -484
  250. package/src/block/types.ts +0 -67
  251. package/src/boxes-and-lines/collapse.ts +0 -96
  252. package/src/boxes-and-lines/focus.ts +0 -257
  253. package/src/boxes-and-lines/label-placement.ts +0 -339
  254. package/src/boxes-and-lines/layout-grouped.ts +0 -912
  255. package/src/boxes-and-lines/layout-layered.ts +0 -722
  256. package/src/boxes-and-lines/layout-search.ts +0 -1678
  257. package/src/boxes-and-lines/layout.ts +0 -398
  258. package/src/boxes-and-lines/parser.ts +0 -1181
  259. package/src/boxes-and-lines/renderer.ts +0 -1465
  260. package/src/boxes-and-lines/types.ts +0 -66
  261. package/src/c4/parser.ts +0 -1158
  262. package/src/c4/renderer.ts +0 -2008
  263. package/src/c4/types.ts +0 -89
  264. package/src/chart-type-registry.ts +0 -529
  265. package/src/chart-types.ts +0 -225
  266. package/src/chart.ts +0 -685
  267. package/src/charts-d3/bar.ts +0 -338
  268. package/src/charts-d3/chord.ts +0 -140
  269. package/src/charts-d3/function.ts +0 -147
  270. package/src/charts-d3/funnel.ts +0 -104
  271. package/src/charts-d3/heatmap.ts +0 -145
  272. package/src/charts-d3/index.ts +0 -337
  273. package/src/charts-d3/interactions.ts +0 -477
  274. package/src/charts-d3/line.ts +0 -344
  275. package/src/charts-d3/mount.ts +0 -151
  276. package/src/charts-d3/pie.ts +0 -117
  277. package/src/charts-d3/polar.ts +0 -89
  278. package/src/charts-d3/radar.ts +0 -0
  279. package/src/charts-d3/sankey.ts +0 -0
  280. package/src/charts-d3/scatter.ts +0 -185
  281. package/src/charts-d3/shared.ts +0 -208
  282. package/src/class/layout.ts +0 -326
  283. package/src/class/parser.ts +0 -635
  284. package/src/class/renderer.ts +0 -793
  285. package/src/class/types.ts +0 -58
  286. package/src/cli-banner.ts +0 -106
  287. package/src/cli.ts +0 -1080
  288. package/src/colors-diagnostics.ts +0 -35
  289. package/src/colors.ts +0 -379
  290. package/src/completion-types.ts +0 -27
  291. package/src/completion.ts +0 -2668
  292. package/src/cycle/layout.ts +0 -1026
  293. package/src/cycle/parser.ts +0 -387
  294. package/src/cycle/renderer.ts +0 -653
  295. package/src/cycle/types.ts +0 -101
  296. package/src/d3.ts +0 -1434
  297. package/src/data-chart-parser.ts +0 -1007
  298. package/src/dgmo-router.ts +0 -296
  299. package/src/diagnostics-registry.ts +0 -108
  300. package/src/diagnostics.ts +0 -0
  301. package/src/dimensions.ts +0 -20
  302. package/src/directives-registry.ts +0 -396
  303. package/src/editor/dgmo.grammar +0 -76
  304. package/src/editor/dgmo.grammar.d.ts +0 -2
  305. package/src/editor/dgmo.grammar.js +0 -18
  306. package/src/editor/dgmo.grammar.terms.d.ts +0 -5
  307. package/src/editor/dgmo.grammar.terms.js +0 -35
  308. package/src/editor/highlight-api.ts +0 -596
  309. package/src/editor/highlight.ts +0 -36
  310. package/src/editor/index.ts +0 -27
  311. package/src/editor/keywords.ts +0 -128
  312. package/src/editor/tokens.ts +0 -30
  313. package/src/element/index.ts +0 -432
  314. package/src/embed/css.ts +0 -312
  315. package/src/embed/escape.ts +0 -15
  316. package/src/embed/index.ts +0 -280
  317. package/src/er/classify.ts +0 -228
  318. package/src/er/layout.ts +0 -530
  319. package/src/er/parser.ts +0 -750
  320. package/src/er/renderer.ts +0 -725
  321. package/src/er/types.ts +0 -52
  322. package/src/error-card.ts +0 -269
  323. package/src/event-line/diagnostics.ts +0 -117
  324. package/src/event-line/parser.ts +0 -643
  325. package/src/event-line/renderer.ts +0 -1742
  326. package/src/event-line/types.ts +0 -74
  327. package/src/fonts.ts +0 -3
  328. package/src/gantt/parser.ts +0 -1641
  329. package/src/gantt/renderer.ts +0 -3787
  330. package/src/gantt/resolver.ts +0 -172
  331. package/src/gantt/types.ts +0 -206
  332. package/src/graph/diagnostics.ts +0 -64
  333. package/src/graph/edge-spline.ts +0 -29
  334. package/src/graph/flowchart-parser.ts +0 -759
  335. package/src/graph/flowchart-renderer.ts +0 -817
  336. package/src/graph/layout.ts +0 -472
  337. package/src/graph/notes.ts +0 -21
  338. package/src/graph/state-collapse.ts +0 -78
  339. package/src/graph/state-parser.ts +0 -574
  340. package/src/graph/state-renderer.ts +0 -653
  341. package/src/graph/types.ts +0 -65
  342. package/src/index.ts +0 -261
  343. package/src/infra/compute.ts +0 -1385
  344. package/src/infra/layout.ts +0 -888
  345. package/src/infra/parser.ts +0 -1234
  346. package/src/infra/renderer.ts +0 -2534
  347. package/src/infra/roles.ts +0 -75
  348. package/src/infra/types.ts +0 -216
  349. package/src/infra/validation.ts +0 -201
  350. package/src/journey-map/layout.ts +0 -490
  351. package/src/journey-map/parser.ts +0 -557
  352. package/src/journey-map/renderer.ts +0 -1580
  353. package/src/journey-map/types.ts +0 -47
  354. package/src/kanban/mutations.ts +0 -175
  355. package/src/kanban/parser.ts +0 -509
  356. package/src/kanban/renderer.ts +0 -1449
  357. package/src/kanban/types.ts +0 -39
  358. package/src/label-layout.ts +0 -368
  359. package/src/map/colorize.ts +0 -54
  360. package/src/map/completion.ts +0 -316
  361. package/src/map/context-labels.ts +0 -609
  362. package/src/map/data/PROVENANCE.json +0 -1
  363. package/src/map/data/README.md +0 -40
  364. package/src/map/data/airport-collisions.json +0 -1
  365. package/src/map/data/airports.json +0 -1
  366. package/src/map/data/gazetteer.json +0 -1
  367. package/src/map/data/lakes.json +0 -1
  368. package/src/map/data/mountain-ranges.json +0 -1
  369. package/src/map/data/na-lakes.json +0 -1
  370. package/src/map/data/na-land.json +0 -1
  371. package/src/map/data/region-names.json +0 -1
  372. package/src/map/data/rivers.json +0 -1
  373. package/src/map/data/types.ts +0 -121
  374. package/src/map/data/us-states.json +0 -1
  375. package/src/map/data/water-bodies.json +0 -1
  376. package/src/map/data/world-coarse.json +0 -1
  377. package/src/map/data/world-detail.json +0 -1
  378. package/src/map/diagnostics.ts +0 -134
  379. package/src/map/dimensions.ts +0 -150
  380. package/src/map/geo-query.ts +0 -295
  381. package/src/map/geo.ts +0 -438
  382. package/src/map/invert.ts +0 -111
  383. package/src/map/layout.ts +0 -5069
  384. package/src/map/legend-band.ts +0 -127
  385. package/src/map/load-data.ts +0 -186
  386. package/src/map/parser.ts +0 -783
  387. package/src/map/renderer.ts +0 -1445
  388. package/src/map/resolved-types.ts +0 -160
  389. package/src/map/resolver.ts +0 -1146
  390. package/src/map/types.ts +0 -194
  391. package/src/mindmap/collapse.ts +0 -67
  392. package/src/mindmap/layout.ts +0 -649
  393. package/src/mindmap/parser.ts +0 -430
  394. package/src/mindmap/renderer.ts +0 -637
  395. package/src/mindmap/text-wrap.ts +0 -218
  396. package/src/mindmap/types.ts +0 -56
  397. package/src/org/collapse.ts +0 -151
  398. package/src/org/layout.ts +0 -1262
  399. package/src/org/parser.ts +0 -519
  400. package/src/org/renderer.ts +0 -866
  401. package/src/org/resolver.ts +0 -636
  402. package/src/palettes/atlas.ts +0 -77
  403. package/src/palettes/blueprint.ts +0 -73
  404. package/src/palettes/catppuccin.ts +0 -84
  405. package/src/palettes/color-utils.ts +0 -443
  406. package/src/palettes/index.ts +0 -67
  407. package/src/palettes/nord.ts +0 -67
  408. package/src/palettes/registry.ts +0 -114
  409. package/src/palettes/slate.ts +0 -73
  410. package/src/palettes/tidewater.ts +0 -73
  411. package/src/palettes/tokyo-night.ts +0 -86
  412. package/src/palettes/types.ts +0 -88
  413. package/src/pert/analyzer.ts +0 -1183
  414. package/src/pert/diagnostics.ts +0 -110
  415. package/src/pert/index.ts +0 -43
  416. package/src/pert/internal.ts +0 -252
  417. package/src/pert/layout.ts +0 -971
  418. package/src/pert/monte-carlo.ts +0 -446
  419. package/src/pert/parser.ts +0 -1606
  420. package/src/pert/renderer.ts +0 -4009
  421. package/src/pert/share-normalize.ts +0 -62
  422. package/src/pert/types.ts +0 -604
  423. package/src/pyramid/parser.ts +0 -185
  424. package/src/pyramid/renderer.ts +0 -768
  425. package/src/pyramid/types.ts +0 -28
  426. package/src/quadrant/parser.ts +0 -18
  427. package/src/quadrant/renderer.ts +0 -638
  428. package/src/raci/diagnostics.ts +0 -213
  429. package/src/raci/index.ts +0 -23
  430. package/src/raci/mutations.ts +0 -321
  431. package/src/raci/parser.ts +0 -699
  432. package/src/raci/renderer.ts +0 -1627
  433. package/src/raci/types.ts +0 -82
  434. package/src/raci/variants.ts +0 -320
  435. package/src/render.ts +0 -268
  436. package/src/ring/parser.ts +0 -212
  437. package/src/ring/renderer.ts +0 -490
  438. package/src/ring/types.ts +0 -27
  439. package/src/sequence/collapse.ts +0 -174
  440. package/src/sequence/parser.ts +0 -1596
  441. package/src/sequence/participant-inference.ts +0 -152
  442. package/src/sequence/renderer.ts +0 -3168
  443. package/src/sequence/tag-resolution.ts +0 -164
  444. package/src/sharing.ts +0 -211
  445. package/src/sitemap/collapse.ts +0 -100
  446. package/src/sitemap/layout.ts +0 -925
  447. package/src/sitemap/parser.ts +0 -755
  448. package/src/sitemap/renderer.ts +0 -828
  449. package/src/sitemap/types.ts +0 -42
  450. package/src/slope/parser.ts +0 -18
  451. package/src/slope/renderer.ts +0 -378
  452. package/src/swimlane/diagnostics.ts +0 -94
  453. package/src/swimlane/layout.ts +0 -597
  454. package/src/swimlane/parser.ts +0 -613
  455. package/src/swimlane/renderer.ts +0 -681
  456. package/src/swimlane/types.ts +0 -151
  457. package/src/tech-radar/interactive.ts +0 -1129
  458. package/src/tech-radar/layout.ts +0 -197
  459. package/src/tech-radar/parser.ts +0 -436
  460. package/src/tech-radar/renderer.ts +0 -1239
  461. package/src/tech-radar/shared.ts +0 -151
  462. package/src/tech-radar/types.ts +0 -86
  463. package/src/themes.ts +0 -22
  464. package/src/timeline/parser.ts +0 -472
  465. package/src/timeline/renderer.ts +0 -3024
  466. package/src/timeline/types.ts +0 -33
  467. package/src/timeline/viz-parser.ts +0 -21
  468. package/src/treemap/diagnostics.ts +0 -62
  469. package/src/treemap/layout-radial.ts +0 -233
  470. package/src/treemap/layout.ts +0 -189
  471. package/src/treemap/parser.ts +0 -463
  472. package/src/treemap/renderer-radial.ts +0 -438
  473. package/src/treemap/renderer.ts +0 -572
  474. package/src/treemap/treemap-shared.ts +0 -309
  475. package/src/treemap/types.ts +0 -60
  476. package/src/utils/arrow-markers.ts +0 -51
  477. package/src/utils/arrows-diagnostics.ts +0 -62
  478. package/src/utils/arrows.ts +0 -227
  479. package/src/utils/brand.ts +0 -61
  480. package/src/utils/card.ts +0 -183
  481. package/src/utils/collapse-engine/tree-edges.ts +0 -115
  482. package/src/utils/collapse-engine/tree.ts +0 -117
  483. package/src/utils/d3-helpers.ts +0 -219
  484. package/src/utils/d3-types.ts +0 -9
  485. package/src/utils/description-helpers.ts +0 -38
  486. package/src/utils/duration.ts +0 -312
  487. package/src/utils/export-container.ts +0 -41
  488. package/src/utils/expr-eval.ts +0 -27
  489. package/src/utils/fit-canvas.ts +0 -64
  490. package/src/utils/hover-styles.ts +0 -673
  491. package/src/utils/inline-markdown.ts +0 -96
  492. package/src/utils/legend-constants.ts +0 -48
  493. package/src/utils/legend-d3.ts +0 -618
  494. package/src/utils/legend-integration.ts +0 -107
  495. package/src/utils/legend-layout.ts +0 -776
  496. package/src/utils/legend-svg.ts +0 -214
  497. package/src/utils/legend-types.ts +0 -272
  498. package/src/utils/name-normalize.ts +0 -163
  499. package/src/utils/note-box/constants.ts +0 -25
  500. package/src/utils/note-box/index.ts +0 -11
  501. package/src/utils/note-box/metrics.ts +0 -90
  502. package/src/utils/note-box/svg.ts +0 -331
  503. package/src/utils/notes/bounds.ts +0 -30
  504. package/src/utils/notes/build.ts +0 -131
  505. package/src/utils/notes/index.ts +0 -18
  506. package/src/utils/notes/model.ts +0 -19
  507. package/src/utils/notes/parse.ts +0 -131
  508. package/src/utils/notes/place.ts +0 -177
  509. package/src/utils/notes/resolve.ts +0 -88
  510. package/src/utils/number-format.ts +0 -36
  511. package/src/utils/parsing.ts +0 -953
  512. package/src/utils/reserved-key-registry.ts +0 -239
  513. package/src/utils/safe-href.ts +0 -38
  514. package/src/utils/scaling.ts +0 -97
  515. package/src/utils/svg-embed.ts +0 -251
  516. package/src/utils/tag-groups.ts +0 -607
  517. package/src/utils/text-measure.ts +0 -122
  518. package/src/utils/title-constants.ts +0 -24
  519. package/src/utils/visual-conventions.ts +0 -61
  520. package/src/utils/wrapped-desc.ts +0 -87
  521. package/src/venn/parser.ts +0 -18
  522. package/src/venn/renderer.ts +0 -1047
  523. package/src/version-control/diagnostics.ts +0 -67
  524. package/src/version-control/parser.ts +0 -544
  525. package/src/version-control/renderer.ts +0 -724
  526. package/src/version-control/types.ts +0 -100
  527. package/src/visualizations/parse.ts +0 -1560
  528. package/src/visualizations/types.ts +0 -262
  529. package/src/wireframe/layout.ts +0 -479
  530. package/src/wireframe/parser.ts +0 -1114
  531. package/src/wireframe/renderer.ts +0 -1318
  532. package/src/wireframe/types.ts +0 -110
  533. package/src/wordcloud/parser.ts +0 -18
  534. package/src/wordcloud/renderer.ts +0 -357
@@ -1,609 +0,0 @@
1
- // Context-label placement (step 4, part of layout). Produces a sparse,
2
- // density-thinned ORIENTATION layer — water-body names + unreferenced notable
3
- // country names — distinct from `region-labels`. PURE + SYNC + DETERMINISTIC.
4
- //
5
- // Design (tech-spec §map-context-labels): a deliberately LOW per-view label
6
- // BUDGET is the primary noise lever; a span-derived TIER BAND orders candidates
7
- // into it; each candidate is committed only if it survives COLLISION against
8
- // every already-placed data/region/POI/route label (the `collides` closure) AND
9
- // the other context labels. Context labels place DEAD LAST and never displace
10
- // data — they only fill leftover space, degrading gracefully to zero. See
11
- // Decisions 6 (budget), 7 (dead-last), 8 (viewport/projection guards).
12
- import { mix } from '../palettes/color-utils';
13
- import type { PaletteColors } from '../palettes/types';
14
- import type { LabelRect } from '../label-layout';
15
- import { measureLegendText } from '../utils/legend-constants';
16
- import type { ProjectionFamily } from './resolved-types';
17
- import type { WaterBodies, WaterKind } from './data/types';
18
- import type { PlacedLabel } from './layout';
19
-
20
- /** A view span band → priority ordering (NOT a hard zoom cutoff, Decision 6). */
21
- export type TierBand = 'world' | 'continental' | 'regional' | 'local';
22
-
23
- /** An unreferenced country, pre-projected by layout (geo work stays in layout;
24
- * area-rank + name-fit + collision live here so the module is unit-testable). */
25
- export interface CountryCandidate {
26
- readonly name: string;
27
- /** Projected screen bbox `[x0, y0, x1, y1]` (from `path.bounds`). */
28
- readonly bbox: readonly [number, number, number, number];
29
- /** Projected screen anchor `[x, y]` (mainland anchor or `path.centroid`), or
30
- * null when the feature doesn't project to a finite point. */
31
- readonly anchor: readonly [number, number] | null;
32
- /** True when `anchor` came from a curated WORLD_LABEL_ANCHORS entry (a trusted
33
- * mainland point) rather than the area-weighted centroid. Such a country
34
- * bypasses the both-axes smear gate (its full-canvas bbox is an antimeridian
35
- * artifact, not a real footprint, so the unreliable-centroid concern is moot). */
36
- readonly curatedAnchor?: boolean;
37
- /** True for a sovereign NATION touching the viewport (Canada, Mexico) — as
38
- * opposed to a state/subdivision. Nations are labeled UNCONDITIONALLY and
39
- * OUTSIDE the budget so orientation is symmetric (a US view shows Canada AND
40
- * Mexico together, never one-arbitrarily). States/subdivisions leave this
41
- * absent and compete for the rationed budget. */
42
- readonly bordering?: boolean;
43
- /** Ordered interior placement positions (screen coords), best-first: the commit
44
- * loop tries each in turn and places at the first that clears all collisions, so
45
- * a country can dodge a data cluster onto open ground on its own land
46
- * (map-context-neighbor-labels, D7/D12). INVARIANT: either ABSENT or NON-EMPTY,
47
- * and `anchor === positions[0]` always (an empty array is illegal — F7).
48
- * Absent ⇒ single-anchor behaviour (`positions ?? [anchor]`). */
49
- readonly positions?: readonly (readonly [number, number])[];
50
- }
51
-
52
- export interface ContextLabelArgs {
53
- readonly projection: ProjectionFamily;
54
- readonly dLonSpan: number;
55
- readonly dLatSpan: number;
56
- readonly width: number;
57
- readonly height: number;
58
- readonly waterBodies?: WaterBodies | undefined;
59
- readonly countries: readonly CountryCandidate[];
60
- /** Muted, contrast-floored land tone for country labels — computed in layout
61
- * against the neutral basemap and shared with the orientation backdrop so a
62
- * context country and an orientation region read identically. Absent ⇒ the
63
- * legacy `palette.textMuted`. */
64
- readonly countryTone?: string | undefined;
65
- /** Muted, contrast-floored tone for water labels (against the water fill).
66
- * Absent ⇒ the legacy `mix(blue, textMuted, 50)`. */
67
- readonly waterTone?: string | undefined;
68
- readonly palette: PaletteColors;
69
- readonly project: (lon: number, lat: number) => [number, number] | null;
70
- /** Collision test against every committed data/region/POI/route obstacle. */
71
- readonly collides: (rect: LabelRect) => boolean;
72
- /** True when the screen point sits over LAND (a country/state fill) rather than
73
- * open water. WATER labels are rejected when their footprint touches land — an
74
- * ocean name belongs over the ocean (they're optional orientation aids, so drop
75
- * rather than misplace). Country labels are exempt (they label land). Optional
76
- * for unit tests; absent ⇒ no land rejection. */
77
- readonly overLand?: (x: number, y: number) => boolean;
78
- }
79
-
80
- const FONT = 11; // matches layout's on-map label font
81
- const LINE_HEIGHT = FONT + 2; // px per wrapped line — MUST match the renderer's
82
- const PADX = 4; // half-padding around a context label rect
83
- const PADY = 3;
84
- const WATER_LETTER_SPACING = 1.5; // px — cartographic spread for water names
85
- const CONTEXT_PAD = 4; // extra gap enforced between two context labels
86
- const EDGE_CLAMP_MARGIN = 8; // px inset for edge-clamped ocean labels
87
- const EDGE_CLAMP_OVERSHOOT = 0.35; // max off-frame overshoot (× dim) to still clamp
88
-
89
- // Country labels scale with their projected footprint: a big landmass (Canada,
90
- // Mexico on a US view) reads as a larger backdrop name; a small one stays at the
91
- // base font. Size metric is the footprint's linear extent (√bbox-area) as a
92
- // fraction of the canvas's linear extent (√canvas-area), so the ramp is
93
- // resolution-independent. Below MIN ⇒ base font; at/above MAX ⇒ max font; linear
94
- // between. Colour does NOT change with size — subordination is by muting (the
95
- // contrast-floored tone) + size only, never by fading toward bg (Phase 1).
96
- const COUNTRY_FONT_MAX = 22; // px ceiling for the largest footprint
97
- const COUNTRY_SIZE_FRAC_MIN = 0.06; // footprint linear-frac at base font
98
- const COUNTRY_SIZE_FRAC_MAX = 0.32; // footprint linear-frac at max font
99
-
100
- // Multi-position country dodging (map-context-neighbor-labels). A country gets
101
- // several interior on-its-own-land positions so its label can dodge a colliding
102
- // data cluster into open space instead of being dropped. Layout generates the
103
- // positions (geo work stays in layout); the commit loop below walks them
104
- // best-first and places at the first that clears all collisions.
105
- export const MAX_COUNTRY_POSITIONS = 4; // ordered positions per country (cap; D7/D15)
106
- export const COUNTRY_POS_GRID = 5; // lon/lat sampling grid resolution N (N×N cells; D9)
107
- export const COUNTRY_POS_TOPN_MARGIN = 3; // generate positions for top budget+margin (D15)
108
-
109
- // Water-kind priority within a tier (oceans first, then seas, then the rest) so
110
- // a thin budget always spends on the highest-orientation-value names.
111
- const KIND_ORDER: Record<WaterKind, number> = {
112
- ocean: 0,
113
- sea: 1,
114
- gulf: 2,
115
- bay: 3,
116
- strait: 4,
117
- channel: 5,
118
- sound: 6,
119
- };
120
-
121
- /** Span band from the larger of the two view spans (Decision 6 — priority, not
122
- * a hard gate). */
123
- export function tierBand(maxSpanDeg: number): TierBand {
124
- if (maxSpanDeg >= 90) return 'world';
125
- if (maxSpanDeg >= 20) return 'continental';
126
- if (maxSpanDeg >= 5) return 'regional';
127
- return 'local';
128
- }
129
-
130
- /** Deliberately-LOW combined label budget = f(canvas area, band). Floors to ~1
131
- * on a thumbnail and 0 on a tiny canvas (Decision 6, ADR-3; AC9). Caps the
132
- * TOTAL context labels (water + country), so `relief`/data don't get extra
133
- * headroom (Decision 13). */
134
- export function labelBudget(
135
- width: number,
136
- height: number,
137
- band: TierBand
138
- ): number {
139
- const bandCap: Record<TierBand, number> = {
140
- world: 10,
141
- continental: 9,
142
- regional: 7,
143
- local: 6,
144
- };
145
- // Area divisor lowered 150→105 (map-context-neighbor-labels, budget knob): the
146
- // old budget was so thin a regional view spent every slot on a couple of giant
147
- // landmasses, leaving the countries that ring the story unlabeled. The lower
148
- // divisor + raised band caps roughly +50% the slots so the proximity rank has
149
- // room to surface the neighbourhood. Still floors to ~1 on a thumbnail / 0 on a
150
- // tiny canvas (AC9).
151
- const area = Math.floor(Math.sqrt(Math.max(0, width * height)) / 105);
152
- return Math.max(0, Math.min(area, bandCap[band]));
153
- }
154
-
155
- /** Which water tiers/kinds are eligible at a band. World view is oceans + major
156
- * seas ONLY (never bays/sounds/minor gulfs, AC3); broader views progressively
157
- * admit smaller features by `scalerank` (AC4). */
158
- function waterEligible(tier: number, kind: WaterKind, band: TierBand): boolean {
159
- switch (band) {
160
- case 'world':
161
- return tier <= 1 && (kind === 'ocean' || kind === 'sea');
162
- case 'continental':
163
- return tier <= 2;
164
- case 'regional':
165
- return tier <= 3;
166
- case 'local':
167
- return tier <= 4;
168
- }
169
- }
170
-
171
- function insideViewport(
172
- p: readonly [number, number] | null,
173
- width: number,
174
- height: number
175
- ): p is [number, number] {
176
- return (
177
- !!p &&
178
- Number.isFinite(p[0]) &&
179
- Number.isFinite(p[1]) &&
180
- p[0] >= 0 &&
181
- p[0] <= width &&
182
- p[1] >= 0 &&
183
- p[1] <= height
184
- );
185
- }
186
-
187
- /** Rendered label width INCLUDING letter-spacing — `measureLegendText` ignores
188
- * the per-gap `letter-spacing` the renderer applies to water names, so without
189
- * this the fit/clamp math under-measures by ~`(len-1)*spacing` and the label
190
- * clips at the canvas edge. */
191
- export function labelWidth(
192
- text: string,
193
- letterSpacing: number,
194
- font: number = FONT
195
- ): number {
196
- const spacing =
197
- letterSpacing > 0 ? Math.max(0, text.length - 1) * letterSpacing : 0;
198
- return measureLegendText(text, font) + spacing + 2 * PADX;
199
- }
200
-
201
- /** Wrap a multi-word name into balanced lines, biased to wrap READILY — water
202
- * names ("North Pacific Ocean") read better stacked, and a narrower footprint
203
- * is far likelier to clear surrounding land (the hard rule below). Of every
204
- * contiguous split into ≤`maxLines`, picks the one minimising the widest line
205
- * (so it shrinks horizontally whenever a break helps); ties break to fewer
206
- * lines, then top-heavy ("North Pacific" / "Ocean", not "North" / "Pacific
207
- * Ocean"). Single-word names pass through unwrapped. */
208
- export function wrapLabel(text: string, letterSpacing: number): string[] {
209
- const words = text.split(/\s+/).filter(Boolean);
210
- if (words.length <= 1) return [text];
211
- const maxLines = words.length >= 4 ? 3 : 2;
212
- const n = words.length;
213
- type Split = { lines: string[]; cost: number; head: number };
214
- let best: Split | null = null;
215
- for (let mask = 0; mask < 1 << (n - 1); mask++) {
216
- const lines: string[] = [];
217
- let cur = [words[0]!];
218
- for (let i = 1; i < n; i++) {
219
- if (mask & (1 << (i - 1))) {
220
- lines.push(cur.join(' '));
221
- cur = [words[i]!];
222
- } else cur.push(words[i]!);
223
- }
224
- lines.push(cur.join(' '));
225
- if (lines.length > maxLines) continue;
226
- const cost = Math.round(
227
- Math.max(...lines.map((l) => labelWidth(l, letterSpacing)))
228
- );
229
- const head = labelWidth(lines[0]!, letterSpacing);
230
- if (
231
- !best ||
232
- cost < best.cost ||
233
- (cost === best.cost && lines.length < best.lines.length) ||
234
- (cost === best.cost &&
235
- lines.length === best.lines.length &&
236
- head > best.head)
237
- )
238
- best = { lines, cost, head };
239
- }
240
- return best?.lines ?? [text];
241
- }
242
-
243
- function rectAround(
244
- cx: number,
245
- cy: number,
246
- lines: readonly string[],
247
- letterSpacing: number,
248
- font: number = FONT
249
- ): LabelRect {
250
- const lineHeight = font + 2; // MUST match the renderer's per-line stride
251
- const w = Math.max(...lines.map((l) => labelWidth(l, letterSpacing, font)));
252
- const h = (lines.length - 1) * lineHeight + font + 2 * PADY;
253
- return { x: cx - w / 2, y: cy - h / 2, w, h };
254
- }
255
-
256
- function rectFits(r: LabelRect, width: number, height: number): boolean {
257
- return r.x >= 0 && r.y >= 0 && r.x + r.w <= width && r.y + r.h <= height;
258
- }
259
-
260
- function overlapsPadded(a: LabelRect, b: LabelRect, pad: number): boolean {
261
- return (
262
- a.x - pad < b.x + b.w &&
263
- a.x + a.w + pad > b.x &&
264
- a.y - pad < b.y + b.h &&
265
- a.y + a.h + pad > b.y
266
- );
267
- }
268
-
269
- /** Place the orientation backdrop. Returns committed labels in priority order;
270
- * caller pushes them onto `labels` LAST so they never displace data. */
271
- export function placeContextLabels(args: ContextLabelArgs): PlacedLabel[] {
272
- const {
273
- projection,
274
- dLonSpan,
275
- dLatSpan,
276
- width,
277
- height,
278
- waterBodies,
279
- countries,
280
- palette,
281
- countryTone,
282
- waterTone,
283
- project,
284
- collides,
285
- overLand,
286
- } = args;
287
-
288
- // albers-usa is supported: the CONUS conic projects CONUS-area water (Gulf of
289
- // America, the Pacific/Atlantic margins) correctly, and the viewport-visibility
290
- // check below drops the off-frame anchors (Gulf of Alaska, mid-Pacific) that the
291
- // AK/HI inset relocation would otherwise mislabel. The caller additionally feeds
292
- // the AK/HI inset frames into `collides` so a label never lands on an inset box.
293
- // (Supersedes the original blanket albers-usa disable — the US map is the
294
- // flagship orientation case.)
295
- void projection;
296
-
297
- const band = tierBand(Math.max(dLonSpan, dLatSpan));
298
- const budget = labelBudget(width, height, band);
299
- if (budget <= 0) return [];
300
-
301
- // Subordinate cartographic colours. Both are muted but CONTRAST-FLOORED in the
302
- // caller (layout) against the substrate they sit on, and shared with the
303
- // orientation backdrop so a context country and an orientation region match.
304
- // Water stays the blue-gray italic convention; country = the muted land tone.
305
- // Fallbacks keep the pre-floor behaviour for unit tests that omit the tones.
306
- const waterColor =
307
- waterTone ?? mix(palette.colors.blue, palette.textMuted, 50);
308
- const countryColor = countryTone ?? palette.textMuted;
309
- const haloColor = palette.bg;
310
-
311
- type Candidate = {
312
- text: string;
313
- lines: string[];
314
- cx: number;
315
- cy: number;
316
- italic: boolean;
317
- letterSpacing: number;
318
- color: string;
319
- fontSize: number;
320
- sort: number; // priority key (lower first)
321
- // A sovereign nation (Canada/Mexico): committed unconditionally, outside the
322
- // budget (Option A symmetric orientation). Absent on water + states.
323
- bordering?: boolean;
324
- // Ordered dodge positions (screen coords), best-first. Absent on water (single
325
- // anchor); on a country, mirrors CountryCandidate.positions (anchor === [0]).
326
- positions?: readonly (readonly [number, number])[];
327
- };
328
- const candidates: Candidate[] = [];
329
-
330
- // -- Water candidates (priority core: oceans → seas → minor water) --
331
- const center: [number, number] = [width / 2, height / 2];
332
- for (const e of waterBodies?.entries ?? []) {
333
- const [lat, lon, name, tier, kind, alt] = e;
334
- if (!waterEligible(tier, kind, band)) continue;
335
- // Wrap eagerly (Decision: water names stack readily) so the clamp/fit math
336
- // below sees the real, narrower wrapped footprint, not the one-line width.
337
- const wlines = wrapLabel(name, WATER_LETTER_SPACING);
338
- // Multi-anchor (Decision 5 / ADR-4): of the anchors that project inside the
339
- // viewport, pick the one nearest the viewport centre.
340
- const anchorsLngLat: Array<[number, number]> = [[lon, lat]];
341
- for (const a of alt ?? []) anchorsLngLat.push([a[1], a[0]]);
342
- let best: [number, number] | null = null;
343
- let bestD = Infinity;
344
- let nearestProj: [number, number] | null = null; // best finite proj (any side)
345
- let nearestProjD = Infinity;
346
- for (const [aLon, aLat] of anchorsLngLat) {
347
- const p = project(aLon, aLat);
348
- if (!p || !Number.isFinite(p[0]) || !Number.isFinite(p[1])) continue;
349
- const d = (p[0] - center[0]) ** 2 + (p[1] - center[1]) ** 2;
350
- if (d < nearestProjD) {
351
- nearestProjD = d;
352
- nearestProj = p;
353
- }
354
- if (!insideViewport(p, width, height)) continue;
355
- if (d < bestD) {
356
- bestD = d;
357
- best = p;
358
- }
359
- }
360
- // Oceans (tier 0) are large enough that a frame-edge label still reads
361
- // correctly, so when their anchor falls off-screen on a zoomed-in view
362
- // (e.g. the mid-Atlantic/Pacific centroid on a US map) we CLAMP it to the
363
- // viewport margin rather than drop it — the standard cartographic "ocean
364
- // name hugs the edge" behaviour. Smaller basins keep the strict drop-if-
365
- // off-screen rule (AC10) to avoid mislabelling an adjacent basin.
366
- if (!best && tier === 0 && nearestProj) {
367
- // Only clamp an ocean ADJACENT to the frame: if its centroid overshoots
368
- // the viewport by more than ~half a dimension it's a distant ocean (e.g.
369
- // the South Atlantic / Arctic relative to a US view) and edge-clamping it
370
- // would mislabel that margin — drop instead. The surviving oceans are the
371
- // ones the frame actually borders (Pacific to the west, Atlantic east).
372
- const overX = Math.max(0, -nearestProj[0], nearestProj[0] - width);
373
- const overY = Math.max(0, -nearestProj[1], nearestProj[1] - height);
374
- if (
375
- overX <= width * EDGE_CLAMP_OVERSHOOT &&
376
- overY <= height * EDGE_CLAMP_OVERSHOOT
377
- ) {
378
- // Clamp the CENTRE inward by half the label so the whole (centre-
379
- // anchored) rect stays on-canvas — clamping to the bare margin would
380
- // overflow a wide name like "North Atlantic Ocean" off the edge.
381
- // letter-spacing IS counted (labelWidth) so the clamp matches render.
382
- const halfW =
383
- Math.max(...wlines.map((l) => labelWidth(l, WATER_LETTER_SPACING))) /
384
- 2;
385
- const halfH = ((wlines.length - 1) * LINE_HEIGHT + FONT + 2 * PADY) / 2;
386
- const m = EDGE_CLAMP_MARGIN;
387
- best = [
388
- Math.min(Math.max(nearestProj[0], halfW + m), width - halfW - m),
389
- Math.min(Math.max(nearestProj[1], halfH + m), height - halfH - m),
390
- ];
391
- }
392
- }
393
- if (!best) continue;
394
- candidates.push({
395
- text: name,
396
- lines: wlines,
397
- cx: best[0],
398
- cy: best[1],
399
- italic: true,
400
- letterSpacing: WATER_LETTER_SPACING,
401
- color: waterColor,
402
- fontSize: FONT, // water names keep the base font (no footprint to scale on)
403
- // Orientation-value bands (lower = earlier): MAJOR water (oceans + major
404
- // seas, tier ≤ 1) leads at `tier*10+kind` (0..~16); MINOR water (tier ≥ 2:
405
- // smaller seas, bays, gulfs, straits) drops to band 2 (2000+) — BELOW the
406
- // country band (1000+), so a big country outranks a minor basin.
407
- sort: (tier <= 1 ? 0 : 2000) + tier * 10 + KIND_ORDER[kind],
408
- });
409
- }
410
-
411
- // -- Country candidates (unreferenced) --
412
- // Rank by biggest-area-first — a deterministic, position-independent order (no
413
- // proximity-to-POI weighting, which read as arbitrary: near-identical neighbours
414
- // like Wyoming vs Texas won or lost a slot on a hair of distance). Nations are
415
- // pulled out of the budget entirely at commit; among the budgeted states, the
416
- // largest in-frame footprints win the rationed slots. Area also drives the
417
- // font/fade ramp and the smear gate below.
418
- const ranked = countries
419
- .map((c) => {
420
- const [x0, y0, x1, y1] = c.bbox;
421
- const w = x1 - x0;
422
- const h = y1 - y0;
423
- return { c, w, h, area: w * h };
424
- })
425
- .filter((r) => Number.isFinite(r.area) && r.area > 0)
426
- .sort((a, b) => b.area - a.area);
427
- // Canvas linear extent — the denominator for the footprint size ramp below.
428
- const canvasLinear = Math.sqrt(Math.max(1, width * height));
429
- let ci = 0;
430
- for (const r of ranked) {
431
- const { c, w, h, area } = r;
432
- // F2: an antimeridian-crossing / global-smear country fills the canvas in
433
- // BOTH dimensions while its real landmass is split — the `path.centroid`
434
- // anchor is then unreliable (mid-map, wrong basin). Reject only that
435
- // both-axes canvas-smear: a country that is merely wide-but-short (Canada
436
- // hugging the top of a US frame) or tall-but-narrow (Chile) is a legitimate
437
- // landmass whose clipExtent-clipped centroid still lands over its own ground,
438
- // so it must NOT be dropped for footprint shape alone. A `curatedAnchor`
439
- // (WORLD_LABEL_ANCHORS, e.g. Russia → European Russia) is trustworthy by
440
- // construction — the smear concern is moot, so it bypasses this gate (the
441
- // `insideViewport` check below still drops an anchor that projects off-frame).
442
- if (!c.curatedAnchor && w > width * 0.66 && h > height * 0.66) continue;
443
- if (!insideViewport(c.anchor, width, height)) continue;
444
- // Footprint-driven scale (Decision: big landmass = large, faded backdrop
445
- // name). t∈[0,1] over the [MIN,MAX] linear-fraction band; font ramps up and
446
- // ink rises in lockstep, so a bigger name reads as a large, softly-inked
447
- // backdrop. A curated-anchor giant (Russia) keeps the standard big-country
448
- // styling — its full-canvas bbox lands at the top of the ramp (font/ink like
449
- // any large in-frame country), which is the intended subdued-backdrop look.
450
- const sizeFrac = Math.sqrt(area) / canvasLinear;
451
- const t = Math.min(
452
- 1,
453
- Math.max(
454
- 0,
455
- (sizeFrac - COUNTRY_SIZE_FRAC_MIN) /
456
- (COUNTRY_SIZE_FRAC_MAX - COUNTRY_SIZE_FRAC_MIN)
457
- )
458
- );
459
- const fontSize = Math.round(FONT + t * (COUNTRY_FONT_MAX - FONT));
460
- // No fade. Subordination is by MUTING (the floored tone) + smaller size, not
461
- // by fading toward bg — fading a floored tone toward the background would
462
- // re-break the contrast it was floored to guarantee (the old behaviour washed
463
- // big names like Canada toward illegibility). Footprint still drives font size.
464
- const color = countryColor;
465
- // Always the full country name — never an ISO abbreviation. If the name
466
- // doesn't fit the footprint, drop the label rather than abbreviate.
467
- const text = c.name;
468
- const tw = labelWidth(text, 0, fontSize);
469
- // Approximate fit (Decision 4): the (scaled) name fits inside the footprint
470
- // bbox. NOT true point-in-polygon — cartographic labels routinely overrun
471
- // coastlines. The bigger the font, the bigger the box it must clear.
472
- if (tw > w || fontSize + 2 * PADY > h) continue;
473
- candidates.push({
474
- text,
475
- lines: [text],
476
- cx: c.anchor[0],
477
- cy: c.anchor[1],
478
- italic: false,
479
- letterSpacing: 0,
480
- color,
481
- fontSize,
482
- ...(c.bordering ? { bordering: true } : {}),
483
- // Multi-position dodging: carry the ordered interior positions through to the
484
- // commit loop. Invariant anchor === positions[0], so `cx/cy` is positions[0].
485
- ...(c.positions ? { positions: c.positions } : {}),
486
- // Band 1 (orientation-value ranking): above MINOR water (band 2, 2000+) but
487
- // below MAJOR water — oceans + major seas (band 0, ≤~16). So a big country
488
- // (US, Canada, Russia) outranks a minor sea/bay (Sargasso, Bahía de
489
- // Campeche) yet never displaces an ocean. Larger area = earlier within the
490
- // band (`ci` is the area-desc rank index).
491
- sort: 1000 + ci++,
492
- });
493
- }
494
-
495
- // -- Commit dead-last, highest-priority-first, into leftover space only --
496
- candidates.sort((a, b) => a.sort - b.sort);
497
- const placed: PlacedLabel[] = [];
498
- const placedRects: LabelRect[] = [];
499
- // Guarantee state room: water can otherwise monopolise a small budget (a coastal
500
- // view borders many oceans/seas), so reserve up to 2 slots for STATES whenever
501
- // any state candidate exists. Nations don't draw from the budget (committed in
502
- // pass 1 below), so they're excluded from this count. No effect on pure-water
503
- // views (`stateCount` 0 ⇒ cap = budget).
504
- const stateCount = candidates.reduce(
505
- (n, c) => n + (!c.italic && !c.bordering ? 1 : 0),
506
- 0
507
- );
508
- const waterCap = budget - Math.min(2, stateCount);
509
- let waterPlaced = 0;
510
- let budgetUsed = 0;
511
- // Test one trial position for a candidate against every gate (fit, water-on-land,
512
- // committed-obstacle collision, context-overlap). Returns the placed rect when the
513
- // position clears, else null. Country candidates carry several ordered positions
514
- // (map-context-neighbor-labels); we walk them best-first and commit the first that
515
- // clears, so a label dodges a colliding cluster instead of being dropped. Water
516
- // candidates have a single position, so behaviour is unchanged for them.
517
- const gateAt = (
518
- cx: number,
519
- cy: number,
520
- cand: Candidate
521
- ): LabelRect | null => {
522
- const rect = rectAround(
523
- cx,
524
- cy,
525
- cand.lines,
526
- cand.letterSpacing,
527
- cand.fontSize
528
- );
529
- if (!rectFits(rect, width, height)) return null;
530
- // Water labels must sit over OPEN WATER and NEVER touch land — sample a grid
531
- // over every wrapped line (each line's own horizontal extent at five points);
532
- // drop the whole label if ANY sample hits land (Decision: optional orientation
533
- // aids, so exclude rather than misplace over a coastline). Country labels are
534
- // exempt — they belong on their country.
535
- if (cand.italic && overLand) {
536
- const inset = 2;
537
- const top = cy - ((cand.lines.length - 1) / 2) * LINE_HEIGHT;
538
- const touchesLand = cand.lines.some((line, li) => {
539
- const lw = labelWidth(line, cand.letterSpacing);
540
- const x0 = cx - lw / 2 + inset;
541
- const x1 = cx + lw / 2 - inset;
542
- const xs = [x0, (x0 + cx) / 2, cx, (cx + x1) / 2, x1];
543
- const base = top + li * LINE_HEIGHT;
544
- // Sample the glyph body top→baseline (text rises above the baseline) so a
545
- // label whose ascenders clip a coastline is rejected, not just one whose
546
- // baseline sits on land.
547
- return [base, base - FONT * 0.4, base - FONT * 0.8].some((y) =>
548
- xs.some((x) => overLand(x, y))
549
- );
550
- });
551
- if (touchesLand) return null;
552
- }
553
- if (collides(rect)) return null;
554
- if (placedRects.some((r) => overlapsPadded(rect, r, CONTEXT_PAD)))
555
- return null;
556
- return rect;
557
- };
558
- // Walk a candidate's ordered positions best-first; commit at the first that
559
- // clears every gate. F8: `positions ?? [[cx,cy]]` keeps single-anchor (water +
560
- // non-top-N country) behaviour identical. If none clears → drop (no halo, no
561
- // overlap — D16). Returns true when the label was placed.
562
- const tryPlace = (cand: Candidate): boolean => {
563
- const positions = cand.positions ?? [[cand.cx, cand.cy]];
564
- for (const [px, py] of positions) {
565
- const rect = gateAt(px!, py!, cand);
566
- if (!rect) continue;
567
- placedRects.push(rect);
568
- placed.push({
569
- x: px!,
570
- y: py!,
571
- text: cand.text,
572
- anchor: 'middle',
573
- color: cand.color,
574
- // No halo: the bg-coloured outline reads as a ghost box behind the text
575
- // over the tinted water/land. Context labels are muted enough to sit
576
- // cleanly on the basemap without one.
577
- halo: false,
578
- haloColor,
579
- fontSize: cand.fontSize,
580
- italic: cand.italic,
581
- letterSpacing: cand.letterSpacing,
582
- ...(cand.lines.length > 1 ? { lines: cand.lines } : {}),
583
- lineNumber: 0,
584
- });
585
- return true;
586
- }
587
- return false;
588
- };
589
-
590
- // Pass 1 — sovereign NATIONS touching the viewport, labeled UNCONDITIONALLY and
591
- // OUTSIDE the budget (Option A: symmetric orientation — a US view shows Canada
592
- // AND Mexico together, never one arbitrarily). Still gated on fit/collision, so a
593
- // nation label never lands on data or off-canvas; it just isn't rationed. Placed
594
- // FIRST so nations claim their ground before states/water fill the leftover.
595
- for (const cand of candidates) if (cand.bordering) tryPlace(cand);
596
-
597
- // Pass 2 — water + states, rationed by the budget (the nations placed above do
598
- // not count against it).
599
- for (const cand of candidates) {
600
- if (cand.bordering) continue;
601
- if (budgetUsed >= budget) break;
602
- if (cand.italic && waterPlaced >= waterCap) continue;
603
- if (tryPlace(cand)) {
604
- budgetUsed++;
605
- if (cand.italic) waterPlaced++;
606
- }
607
- }
608
- return placed;
609
- }
@@ -1 +0,0 @@
1
- {"assets":{"airport-collisions.json":{"bytes":29,"gzBytes":49,"sha256":"a7d0107c5fcc6d787e010ea100ce1946bb724f7ae1a79eb1b862a8cf822ed1d8"},"airports.json":{"bytes":104083,"gzBytes":38159,"sha256":"c17294d4e3fd259e02c63c49c36c02d9ff34f4462103ff54516d29e93667cd76"},"gazetteer.json":{"bytes":130767,"gzBytes":56261,"sha256":"5ad56e5ba0b3a4f9a6dc8bd3bf8b0fda0e7b86cbe4d85d231114f5dd967d65f7"},"lakes.json":{"bytes":6315,"gzBytes":1487,"sha256":"5840ffd49b8dbf30183a9534a72adf80b6e77ceec224665393fa94e956220323"},"mountain-ranges.json":{"bytes":90845,"gzBytes":26493,"sha256":"a698b3f296e61712fb39b3d8d42ec7c4699f8aadecb549367feb7d09f7785580"},"na-lakes.json":{"bytes":39387,"gzBytes":11281,"sha256":"2a41c04969209380d544a09efe354277e12d704458af95955201eb4f698d16c6"},"na-land.json":{"bytes":114082,"gzBytes":32375,"sha256":"7b94c9bb4e809c22813da5ae939e1ff6a781fd77a04d9c1585a9a82d2a195388"},"region-names.json":{"bytes":11667,"gzBytes":2235,"sha256":"059662d30b6ee8572c5943096905e05218e5f337e6973a9d43d6b41b7313a9ac"},"rivers.json":{"bytes":6707,"gzBytes":2158,"sha256":"3912508469099b1c37360c5505ea033c4ffa30ce95f7428e668e9d824cb81407"},"us-states.json":{"bytes":23313,"gzBytes":7413,"sha256":"0fe3a8937bc7566192662439f29a7866e8823d687290bcb003433ad5edd86567"},"water-bodies.json":{"bytes":4854,"gzBytes":2123,"sha256":"6d1a407a376c63518329c52189e2887053c4b61062af0597e060050ae8469635"},"world-coarse.json":{"bytes":55436,"gzBytes":18397,"sha256":"5cb42e3c8975dde56504ca5c68ece0a1e71d0929680b5fc8cdab758c8666dbf8"},"world-detail.json":{"bytes":163562,"gzBytes":46767,"sha256":"39f1736eaabe9e21190972be3157822be22ee84fdc41751237f2b516f09a7586"}},"counts":{"airportCollisions":2,"airports":1565,"countries":175,"gazetteerAliases":8,"gazetteerCities":2119,"mountainRanges":205,"usStates":56,"waterBodies":113},"generatedBy":"scripts/build-map-data.mjs","sourceHashes":{"file:scripts/airports-snapshot.csv":{"bytes":308536,"sha256":"58b6e45bb91045c2897f1e7e14430aecc3b5eca911bcb389855495ff66ab9599"},"https://cdn.jsdelivr.net/gh/martynafford/natural-earth-geojson@master/10m/physical/ne_10m_lakes.json":{"bytes":6648697,"sha256":"93c8fdf0e591e113f449d0d466e15c7a9841b9b6571c7afe41f95ba51b322452"},"https://cdn.jsdelivr.net/gh/martynafford/natural-earth-geojson@master/110m/physical/ne_110m_lakes.json":{"bytes":27711,"sha256":"6f315b60488e0cf5da9c360e3ce593babf64c2f44cc21e2820c536f7a2aff606"},"https://cdn.jsdelivr.net/gh/martynafford/natural-earth-geojson@master/110m/physical/ne_110m_rivers_lake_centerlines.json":{"bytes":54146,"sha256":"959e13128e4eb5a6ee530b8270c5017bcee9149ce48a97f6fe7fee1fce600b5d"},"https://cdn.jsdelivr.net/gh/nvkelso/natural-earth-vector@master/geojson/ne_10m_admin_0_countries.geojson":{"bytes":13287234,"sha256":"239eec57ac17f100a11e2536cffc56752c318b50ae765b0918ff7aab4ce8f255"},"https://cdn.jsdelivr.net/gh/nvkelso/natural-earth-vector@master/geojson/ne_10m_geography_regions_polys.geojson":{"bytes":5583870,"sha256":"b7b26e50ea917d3696aec87f932def2bf5f890f5770e441d59c162c6f4c92a77"},"https://cdn.jsdelivr.net/gh/nvkelso/natural-earth-vector@master/geojson/ne_110m_geography_marine_polys.geojson":{"bytes":534055,"sha256":"b9c3f7f557d0ff5217906adc82b66ecdac14aa7438df7e518cf6675d037bceb8"},"https://cdn.jsdelivr.net/gh/nvkelso/natural-earth-vector@master/geojson/ne_50m_geography_marine_polys.geojson":{"bytes":1163418,"sha256":"6fe58083e0cc5c7fad9e396970e28a8580bbd8770cfa4d1d7b5a34423e912f97"},"https://cdn.jsdelivr.net/npm/us-atlas@3.0.1/states-10m.json":{"bytes":114554,"sha256":"d76b391ccfa8bff601d51e3e3da5d43a89fa46cd5caca72ce731b383be5596d0"},"https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-110m.json":{"bytes":107761,"sha256":"2516c915867c7baf18ddec727aec46c315541a07cfb3d79a6559b05d5e94eee8"},"https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-50m.json":{"bytes":756420,"sha256":"04342cdc1e3016bcd7db1630de95684d67b79fe3c8c460321e87aef469502394"},"https://download.geonames.org/export/dump/cities5000.zip":{"bytes":5549002,"sha256":"d20e28b2f610da34c21fd82ff6a8e4d24ebe67eba2dccf65bd2c4332ff0f380a"}},"sources":{"geonames":{"citiesUrl":"https://download.geonames.org/export/dump/cities5000.zip","license":"CC BY 4.0 — https://creativecommons.org/licenses/by/4.0/","modificationDateRange":"2006-01-17..2026-06-02 (filtered subset)"},"lakes":{"url":"https://cdn.jsdelivr.net/gh/martynafford/natural-earth-geojson@master/110m/physical/ne_110m_lakes.json","version":"natural-earth 110m (martynafford snapshot)"},"marineCoarse":{"url":"https://cdn.jsdelivr.net/gh/nvkelso/natural-earth-vector@master/geojson/ne_110m_geography_marine_polys.geojson","version":"natural-earth 110m (nvkelso vector snapshot)"},"marineDetail":{"url":"https://cdn.jsdelivr.net/gh/nvkelso/natural-earth-vector@master/geojson/ne_50m_geography_marine_polys.geojson","version":"natural-earth 50m (nvkelso vector snapshot)"},"mountainRanges":{"url":"https://cdn.jsdelivr.net/gh/nvkelso/natural-earth-vector@master/geojson/ne_10m_geography_regions_polys.geojson","version":"natural-earth 10m (nvkelso vector snapshot)"},"naLakes":{"url":"https://cdn.jsdelivr.net/gh/martynafford/natural-earth-geojson@master/10m/physical/ne_10m_lakes.json","version":"natural-earth 10m (martynafford snapshot)"},"naLand":{"url":"https://cdn.jsdelivr.net/gh/nvkelso/natural-earth-vector@master/geojson/ne_10m_admin_0_countries.geojson","version":"natural-earth 10m (nvkelso vector snapshot)"},"ourairports":{"license":"Public Domain — https://ourairports.com/data/","note":"Lean committed slice (scheduled_service=yes + 3-letter iata_code). Regenerate is a deliberate, reviewed bump (ADR-4).","snapshot":"scripts/airports-snapshot.csv","source":"https://davidmegginson.github.io/ourairports-data/airports.csv"},"rivers":{"url":"https://cdn.jsdelivr.net/gh/martynafford/natural-earth-geojson@master/110m/physical/ne_110m_rivers_lake_centerlines.json","version":"natural-earth 110m (martynafford snapshot)"},"usAtlas":{"url":"https://cdn.jsdelivr.net/npm/us-atlas@3.0.1/states-10m.json","version":"3.0.1"},"worldCoarse":{"url":"https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-110m.json","version":"2.0.2"},"worldDetail":{"url":"https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-50m.json","version":"2.0.2"}},"tooling":{"mapshaper":"0.7.22"}}
@@ -1,40 +0,0 @@
1
- # map chart-type data assets
2
-
3
- Generated by `scripts/build-map-data.mjs` (run `pnpm build:map-data`). These
4
- committed JSON files are the runtime artifacts for the `map` chart type. Do not
5
- hand-edit — regenerate from source.
6
-
7
- ## Files
8
- - `world-coarse.json` / `world-detail.json` — world country boundaries (TopoJSON),
9
- keyed by ISO 3166-1 alpha-2. Coarse = world-scale; detail = regional/zoom.
10
- - `us-states.json` — US states + DC + territories (TopoJSON), keyed by ISO 3166-2.
11
- - `lakes.json` — major lakes (Natural Earth 110m, TopoJSON), drawn as water over land.
12
- - `rivers.json` — major river centerlines (Natural Earth 110m, TopoJSON), drawn as thin water lines.
13
- - `na-land.json` — NA-clipped 10m country land (TopoJSON, ISO-keyed): crisp neighbour context under the albers-usa US view.
14
- - `na-lakes.json` — NA-clipped 10m major lakes (TopoJSON): the lakes counterpart to `na-land.json` for the US view.
15
- - `mountain-ranges.json` — notable mountain ranges (Natural Earth 50m geography regions, FEATURECLA "Range/mtn", TopoJSON), drawn as a subtle gradient relief cue when the `relief` directive is on. Optional; single tier (no elevation).
16
- - `water-bodies.json` — water-body orientation labels (`{ entries: [lat, lon, name, tier, kind] }`) from Natural Earth 110m+50m geography marine polys (oceans/seas/gulfs/bays/straits/channels/sounds; rivers + reefs excluded). Anchors are mapshaper inner points; `tier` is the NE scalerank. Drawn only when the `context-labels` directive is on. Optional.
17
- - `gazetteer.json` — `{ cities, byName, alt }` city index (see `types.ts`).
18
- `byName`/`alt` reference `cities` by array index (normalized).
19
- - `PROVENANCE.json` — source versions + per-asset sha256/sizes + GeoNames date range.
20
- - `types.ts` — the typed data contract consumed by the parser/resolver/renderer.
21
-
22
- ## Sources & attribution
23
- - **Country boundaries:** Natural Earth via `world-atlas@2.0.2` (public domain).
24
- - **US states:** US Census via `us-atlas@3.0.1` (public domain).
25
- - **Mountain ranges:** Natural Earth 50m `geography_regions_polys` via `nvkelso/natural-earth-vector` (public domain).
26
- - **Water bodies:** Natural Earth 110m+50m `geography_marine_polys` via `nvkelso/natural-earth-vector` (public domain). One editorial override applied (`Gulf of Mexico` → `Gulf of America`).
27
- - **Cities:** Data © **GeoNames**, licensed under **CC BY 4.0**
28
- (https://creativecommons.org/licenses/by/4.0/) — https://www.geonames.org/.
29
-
30
- ## Determinism & GeoNames drift
31
- Geometry assets are byte-reproducible from the pinned atlas versions (same machine
32
- + `mapshaper@0.7.22`). The GeoNames dump is **rebuilt daily and has no pinnable
33
- snapshot**, so the committed `gazetteer.json` is the source of truth; a regenerate
34
- may pick up upstream city changes. `PROVENANCE.json` is the audit trail. The
35
- modification-date range it reports is over the *filtered* (kept) city subset.
36
-
37
- ## Regenerate
38
- ```
39
- pnpm build:map-data
40
- ```
@@ -1 +0,0 @@
1
- {"collisions":["aba","ufa"]}