@diagrammo/dgmo 0.46.0 → 0.47.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 (232) hide show
  1. package/dist/advanced.d.cts +3 -855
  2. package/dist/advanced.d.ts +3 -855
  3. package/dist/advanced.js +541 -70107
  4. package/dist/analyzer-UYKBXAKR.js +15 -0
  5. package/dist/auto.cjs +1 -1
  6. package/dist/auto.js +1 -1
  7. package/dist/auto.mjs +1 -1
  8. package/dist/block.js +83 -69417
  9. package/dist/calculator-LDYQCDDY.js +11 -0
  10. package/dist/charts-d3-QOZHKTCT.js +25 -0
  11. package/dist/chunk-2DXMZRWJ.js +800 -0
  12. package/dist/chunk-2LACINWN.js +786 -0
  13. package/dist/chunk-33LCUH4H.js +893 -0
  14. package/dist/chunk-3CIOJ5YJ.js +35 -0
  15. package/dist/chunk-3HDBAXF5.js +86 -0
  16. package/dist/chunk-3JLKYGBQ.js +290 -0
  17. package/dist/chunk-3MQQNXPD.js +415 -0
  18. package/dist/chunk-3R5POCTZ.js +967 -0
  19. package/dist/chunk-3SMGIJDD.js +112 -0
  20. package/dist/chunk-44CM72SQ.js +409 -0
  21. package/dist/chunk-4GRI7MEB.js +1604 -0
  22. package/dist/chunk-4OHACBGX.js +606 -0
  23. package/dist/chunk-5DH3KYFH.js +21 -0
  24. package/dist/chunk-5MLYVTYM.js +76 -0
  25. package/dist/chunk-5QXL4NYS.js +553 -0
  26. package/dist/chunk-5WRI5ZAA.js +31 -0
  27. package/dist/chunk-6EK55ART.js +117 -0
  28. package/dist/chunk-6FZYCKXB.js +2065 -0
  29. package/dist/chunk-6HO5ZTXK.js +277 -0
  30. package/dist/chunk-6KFWC4CO.js +7 -0
  31. package/dist/chunk-6MTWIQVO.js +121 -0
  32. package/dist/chunk-6NYWYNBI.js +329 -0
  33. package/dist/chunk-6SM5NJQH.js +620 -0
  34. package/dist/chunk-725LDASD.js +422 -0
  35. package/dist/chunk-76OWZ3BA.js +130 -0
  36. package/dist/chunk-7JEGTRLD.js +338 -0
  37. package/dist/chunk-A44USUV7.js +923 -0
  38. package/dist/chunk-A4GOY3PE.js +25 -0
  39. package/dist/chunk-A4VFQH5G.js +251 -0
  40. package/dist/chunk-AELOBFW5.js +375 -0
  41. package/dist/chunk-AN2MOO5T.js +522 -0
  42. package/dist/chunk-BMR4CIEO.js +41 -0
  43. package/dist/chunk-BS7SV7C3.js +51 -0
  44. package/dist/chunk-BUPDIHML.js +613 -0
  45. package/dist/chunk-BUVJFRPY.js +887 -0
  46. package/dist/chunk-C3Z4DX3V.js +112 -0
  47. package/dist/chunk-CI2G3OEB.js +1818 -0
  48. package/dist/chunk-CKNVO24D.js +54 -0
  49. package/dist/chunk-CUVHQHZ7.js +391 -0
  50. package/dist/chunk-CXK4DZH3.js +114 -0
  51. package/dist/chunk-DKEPS5LH.js +315 -0
  52. package/dist/chunk-DU7W62N5.js +487 -0
  53. package/dist/chunk-DZAQBW35.js +751 -0
  54. package/dist/chunk-EB6FPQUP.js +316 -0
  55. package/dist/chunk-EMS2SK26.js +376 -0
  56. package/dist/chunk-ERLBPDGU.js +510 -0
  57. package/dist/chunk-EVCVDTXE.js +732 -0
  58. package/dist/chunk-FCIIHT24.js +384 -0
  59. package/dist/chunk-FFUN5D66.js +97 -0
  60. package/dist/chunk-FITOLXSX.js +714 -0
  61. package/dist/chunk-FMDSF3OV.js +68 -0
  62. package/dist/chunk-FNB3PNGF.js +410 -0
  63. package/dist/chunk-G2H74XJZ.js +2104 -0
  64. package/dist/chunk-GMR5MFHJ.js +339 -0
  65. package/dist/chunk-H6PI3KJT.js +305 -0
  66. package/dist/chunk-I46X5VUA.js +59 -0
  67. package/dist/chunk-I5IGB56C.js +255 -0
  68. package/dist/chunk-IH6ZMVQ5.js +3950 -0
  69. package/dist/chunk-IJZFN3HM.js +463 -0
  70. package/dist/chunk-IPWPWM6R.js +3079 -0
  71. package/dist/chunk-IYULMRBE.js +23 -0
  72. package/dist/chunk-IZMRON6C.js +167 -0
  73. package/dist/chunk-J5FIXQRT.js +813 -0
  74. package/dist/chunk-JED6ZDEE.js +73 -0
  75. package/dist/chunk-JEUJOX5X.js +136 -0
  76. package/dist/chunk-JM4LEPY3.js +436 -0
  77. package/dist/chunk-L3UHP6TD.js +101 -0
  78. package/dist/chunk-L66GEFB6.js +524 -0
  79. package/dist/chunk-LIOHW36Z.js +469 -0
  80. package/dist/chunk-LP7EC4MI.js +16 -0
  81. package/dist/chunk-MITI6NOL.js +548 -0
  82. package/dist/chunk-MO5YHHMQ.js +168 -0
  83. package/dist/chunk-MZSBFAPJ.js +885 -0
  84. package/dist/chunk-NNAAJVBU.js +9 -0
  85. package/dist/chunk-NOTA6TEI.js +47 -0
  86. package/dist/chunk-NURGB5Z4.js +335 -0
  87. package/dist/chunk-NX4EQS3U.js +1062 -0
  88. package/dist/chunk-NXMESY4J.js +1 -0
  89. package/dist/chunk-OJR3MQYV.js +1458 -0
  90. package/dist/chunk-OURHMODR.js +454 -0
  91. package/dist/chunk-P235SVAH.js +1057 -0
  92. package/dist/chunk-P4RH4OSP.js +1038 -0
  93. package/dist/chunk-P6T66CCZ.js +226 -0
  94. package/dist/chunk-PBAHEPLQ.js +223 -0
  95. package/dist/chunk-PBHE5UG6.js +1530 -0
  96. package/dist/chunk-PDKUANDZ.js +35 -0
  97. package/dist/chunk-PWIHZ6NJ.js +296 -0
  98. package/dist/chunk-QEBUY5NY.js +1685 -0
  99. package/dist/chunk-QLCCJEJI.js +253 -0
  100. package/dist/chunk-QOOUC2J5.js +52 -0
  101. package/dist/chunk-QYTPPDAO.js +402 -0
  102. package/dist/chunk-R3XI2VC7.js +801 -0
  103. package/dist/chunk-RCERWOJR.js +154 -0
  104. package/dist/chunk-RJE5JTVK.js +362 -0
  105. package/dist/chunk-RTLBSQ3G.js +1155 -0
  106. package/dist/chunk-RUNNI6VE.js +448 -0
  107. package/dist/chunk-RVMRZAPB.js +354 -0
  108. package/dist/chunk-RYEGFMUO.js +955 -0
  109. package/dist/chunk-RZCF2VVM.js +528 -0
  110. package/dist/chunk-SML67VPV.js +1025 -0
  111. package/dist/chunk-SQ7IY53Q.js +44 -0
  112. package/dist/chunk-SQAG3UXH.js +161 -0
  113. package/dist/chunk-SRTU6HMQ.js +1851 -0
  114. package/dist/chunk-T2OE3YQB.js +550 -0
  115. package/dist/chunk-T3UBLACL.js +299 -0
  116. package/dist/chunk-TLVIHFRO.js +296 -0
  117. package/dist/chunk-TYS6CSS5.js +52 -0
  118. package/dist/chunk-U6EQI3U6.js +130 -0
  119. package/dist/chunk-UJ4FJLBF.js +86 -0
  120. package/dist/chunk-ULOEATBZ.js +347 -0
  121. package/dist/chunk-UNCCZ3NU.js +127 -0
  122. package/dist/chunk-USZW2HHU.js +197 -0
  123. package/dist/chunk-UWN33VNX.js +1610 -0
  124. package/dist/chunk-UZ7EZW3B.js +40 -0
  125. package/dist/chunk-VOKGH627.js +37 -0
  126. package/dist/chunk-WBRZJOEC.js +204 -0
  127. package/dist/chunk-WCSOJFU3.js +380 -0
  128. package/dist/chunk-WCT3NYCV.js +160 -0
  129. package/dist/chunk-WVAJFAIA.js +529 -0
  130. package/dist/chunk-X5LCYCL5.js +394 -0
  131. package/dist/chunk-XAKEUMEJ.js +1256 -0
  132. package/dist/chunk-Y2ZE3MSG.js +590 -0
  133. package/dist/chunk-Y3J7VR52.js +646 -0
  134. package/dist/chunk-Y5QGVTVC.js +33 -0
  135. package/dist/chunk-YAA6IID3.js +548 -0
  136. package/dist/chunk-YGJTDXVR.js +692 -0
  137. package/dist/chunk-YRYKTYMQ.js +186 -0
  138. package/dist/chunk-YYVTBZZC.js +61 -0
  139. package/dist/chunk-Z5CGSFJB.js +647 -0
  140. package/dist/chunk-Z72XRXD4.js +787 -0
  141. package/dist/chunk-ZGR7ULFJ.js +978 -0
  142. package/dist/chunk-ZJEL4H2R.js +851 -0
  143. package/dist/chunk-ZO27FGJS.js +554 -0
  144. package/dist/collapse-CLPJD2RL.js +11 -0
  145. package/dist/collapse-SLINJQW6.js +9 -0
  146. package/dist/collapse-ZWUFFCK2.js +9 -0
  147. package/dist/compute-G55RG53N.js +8 -0
  148. package/dist/dgmo-router-DZCIDUO5.js +73 -0
  149. package/dist/dimensions-J3FHIMJ6.js +22 -0
  150. package/dist/element.cjs +1 -1
  151. package/dist/element.js +1 -1
  152. package/dist/element.mjs +1 -1
  153. package/dist/flowchart-parser-ZNSKIBVR.js +21 -0
  154. package/dist/flowchart-renderer-ZAEOL4DX.js +35 -0
  155. package/dist/index.cjs +3 -3
  156. package/dist/index.d.cts +3 -469
  157. package/dist/index.d.ts +3 -469
  158. package/dist/index.js +137 -69685
  159. package/dist/layout-46N4JJYK.js +17 -0
  160. package/dist/layout-5RA6QWR6.js +26 -0
  161. package/dist/layout-5T6RH5M6.js +14 -0
  162. package/dist/layout-7QXCNOVS.js +13 -0
  163. package/dist/layout-EE6GE46Y.js +17 -0
  164. package/dist/layout-G23F7LDH.js +9 -0
  165. package/dist/layout-HRBZPFCN.js +23 -0
  166. package/dist/layout-HWDSRX5E.js +20 -0
  167. package/dist/layout-HYZPWAK5.js +18 -0
  168. package/dist/layout-N76NR4ZO.js +19 -0
  169. package/dist/layout-OB3RI63S.js +14 -0
  170. package/dist/layout-S2QBYSK2.js +15 -0
  171. package/dist/layout-UM5F4DJB.js +15 -0
  172. package/dist/layout-search-OYV77HHS.js +1655 -0
  173. package/dist/load-data-EHDDZ5ZS.js +8 -0
  174. package/dist/palettes-PRJ2RI6D.js +56 -0
  175. package/dist/parser-2MFP2H2E.js +11 -0
  176. package/dist/parser-3STE62GB.js +21 -0
  177. package/dist/parser-4FL2CMDG.js +18 -0
  178. package/dist/parser-4OGOBJJ4.js +13 -0
  179. package/dist/parser-6BTRLKRZ.js +15 -0
  180. package/dist/parser-AQETEVRW.js +21 -0
  181. package/dist/parser-CFZD5IBL.js +12 -0
  182. package/dist/parser-FUSKFGZN.js +16 -0
  183. package/dist/parser-I6KXEYFK.js +13 -0
  184. package/dist/parser-IXSZZQHY.js +18 -0
  185. package/dist/parser-JAL2HD4I.js +13 -0
  186. package/dist/parser-KNSQSKQO.js +20 -0
  187. package/dist/parser-N5O4IHUN.js +13 -0
  188. package/dist/parser-NGU3ETO6.js +16 -0
  189. package/dist/parser-NRAI6O25.js +19 -0
  190. package/dist/parser-O5J4VBII.js +11 -0
  191. package/dist/parser-OV7NOBW6.js +21 -0
  192. package/dist/parser-PQ3POX45.js +23 -0
  193. package/dist/parser-TFZFBVWN.js +11 -0
  194. package/dist/parser-TRTHDFPP.js +18 -0
  195. package/dist/parser-VQP2UJ6W.js +11 -0
  196. package/dist/parser-XDVELHRK.js +13 -0
  197. package/dist/parser-XKRP7QKP.js +11 -0
  198. package/dist/parser-Y6WTBU76.js +14 -0
  199. package/dist/parser-ZSDPZYQP.js +12 -0
  200. package/dist/renderer-2XQQQ6QR.js +28 -0
  201. package/dist/renderer-5NDVNDAZ.js +26 -0
  202. package/dist/renderer-6EEZHMH4.js +26 -0
  203. package/dist/renderer-6W5462RB.js +43 -0
  204. package/dist/renderer-7MVLWWQD.js +22 -0
  205. package/dist/renderer-AWWAF6XD.js +33 -0
  206. package/dist/renderer-BYCNMBF7.js +34 -0
  207. package/dist/renderer-CLJHQPBJ.js +29 -0
  208. package/dist/renderer-GHPZMFU2.js +15 -0
  209. package/dist/renderer-JGBKUCZD.js +16 -0
  210. package/dist/renderer-KQB7UGDS.js +19 -0
  211. package/dist/renderer-PGX2TKVS.js +24 -0
  212. package/dist/renderer-QIWVHWZO.js +15 -0
  213. package/dist/renderer-RPOA5YPZ.js +35 -0
  214. package/dist/renderer-SMIBCRVB.js +24 -0
  215. package/dist/renderer-T7YKC5VP.js +28 -0
  216. package/dist/renderer-TOCOVLHS.js +37 -0
  217. package/dist/renderer-UWA5XS74.js +39 -0
  218. package/dist/renderer-VACVQYML.js +25 -0
  219. package/dist/renderer-W4M6QLIJ.js +37 -0
  220. package/dist/renderer-WZRREQ2P.js +23 -0
  221. package/dist/renderer-YY2OSF6E.js +27 -0
  222. package/dist/renderer-Z7I3W2PP.js +24 -0
  223. package/dist/renderer-ZGNTUWC4.js +22 -0
  224. package/dist/renderer-ZTR3DER3.js +19 -0
  225. package/dist/renderer-radial-C32GPJQ7.js +21 -0
  226. package/dist/resolver-NOAA7ID7.js +13 -0
  227. package/dist/state-collapse-HCGD6IVJ.js +8 -0
  228. package/dist/state-parser-Z2V23ATR.js +18 -0
  229. package/dist/state-renderer-RFYHSP4K.js +34 -0
  230. package/dist/themes-1-CuKpeH.d.cts +908 -0
  231. package/dist/themes-1-CuKpeH.d.ts +908 -0
  232. package/package.json +1 -1
@@ -0,0 +1,2065 @@
1
+ import {
2
+ EXTENDED_CHART_DOORS,
3
+ parseChart,
4
+ parseFunctionChart,
5
+ parseFunnel,
6
+ parseHeatmap,
7
+ parseSankey,
8
+ parseScatter
9
+ } from "./chunk-P235SVAH.js";
10
+ import {
11
+ parseCycle
12
+ } from "./chunk-6HO5ZTXK.js";
13
+ import {
14
+ parseJourneyMap
15
+ } from "./chunk-44CM72SQ.js";
16
+ import {
17
+ parsePyramid
18
+ } from "./chunk-76OWZ3BA.js";
19
+ import {
20
+ parseRing
21
+ } from "./chunk-MO5YHHMQ.js";
22
+ import {
23
+ parseTreemap
24
+ } from "./chunk-WCSOJFU3.js";
25
+ import {
26
+ parseBlock
27
+ } from "./chunk-7JEGTRLD.js";
28
+ import {
29
+ allTasks,
30
+ parseRaci
31
+ } from "./chunk-RYEGFMUO.js";
32
+ import {
33
+ parseInfra
34
+ } from "./chunk-33LCUH4H.js";
35
+ import {
36
+ parseGantt
37
+ } from "./chunk-XAKEUMEJ.js";
38
+ import {
39
+ parseMap
40
+ } from "./chunk-BUPDIHML.js";
41
+ import {
42
+ parseBoxesAndLines
43
+ } from "./chunk-BUVJFRPY.js";
44
+ import {
45
+ parseSwimlane
46
+ } from "./chunk-WVAJFAIA.js";
47
+ import {
48
+ parseMindmap
49
+ } from "./chunk-EB6FPQUP.js";
50
+ import {
51
+ parseWireframe
52
+ } from "./chunk-EVCVDTXE.js";
53
+ import {
54
+ parseTechRadar
55
+ } from "./chunk-NURGB5Z4.js";
56
+ import {
57
+ looksLikeERDiagram,
58
+ parseERDiagram
59
+ } from "./chunk-L66GEFB6.js";
60
+ import {
61
+ looksLikeOrg,
62
+ parseOrg
63
+ } from "./chunk-RVMRZAPB.js";
64
+ import {
65
+ looksLikeSitemap,
66
+ parseSitemap
67
+ } from "./chunk-AN2MOO5T.js";
68
+ import {
69
+ looksLikePert,
70
+ parsePert
71
+ } from "./chunk-RTLBSQ3G.js";
72
+ import {
73
+ parseEventLine
74
+ } from "./chunk-5QXL4NYS.js";
75
+ import {
76
+ parseTimelineEventLine
77
+ } from "./chunk-GMR5MFHJ.js";
78
+ import {
79
+ parseVersionControl
80
+ } from "./chunk-ERLBPDGU.js";
81
+ import {
82
+ parseKanban
83
+ } from "./chunk-AELOBFW5.js";
84
+ import {
85
+ parseC4
86
+ } from "./chunk-2DXMZRWJ.js";
87
+ import {
88
+ looksLikeSequence,
89
+ parseSequenceDgmo
90
+ } from "./chunk-SML67VPV.js";
91
+ import {
92
+ matchTagBlockHeading,
93
+ stripDefaultModifier,
94
+ tagAttrKey,
95
+ validateTagGroupNames,
96
+ validateTagValues
97
+ } from "./chunk-QLCCJEJI.js";
98
+ import {
99
+ looksLikeFlowchart,
100
+ parseFlowchart
101
+ } from "./chunk-LIOHW36Z.js";
102
+ import {
103
+ looksLikeState,
104
+ parseState
105
+ } from "./chunk-3MQQNXPD.js";
106
+ import {
107
+ looksLikeClassDiagram,
108
+ parseClassDiagram
109
+ } from "./chunk-RUNNI6VE.js";
110
+ import {
111
+ TIMELINE_REGISTRY,
112
+ collectIndentedValues,
113
+ extractColor,
114
+ measureIndent,
115
+ normalizeNumericToken,
116
+ parseFirstLine,
117
+ peelTrailingColorName,
118
+ splitNameAndMeta,
119
+ withTagAliases
120
+ } from "./chunk-Y3J7VR52.js";
121
+ import {
122
+ resolveColorWithDiagnostic
123
+ } from "./chunk-TLVIHFRO.js";
124
+ import {
125
+ dedupeDiagnostics,
126
+ formatDgmoError,
127
+ makeDgmoError,
128
+ suggest
129
+ } from "./chunk-CXK4DZH3.js";
130
+
131
+ // src/visualizations/types.ts
132
+ var DEFAULT_CLOUD_OPTIONS = {
133
+ rotate: "none",
134
+ max: 0,
135
+ minSize: 14,
136
+ maxSize: 80
137
+ };
138
+
139
+ // src/visualizations/parse.ts
140
+ function parseVisualization(content, palette) {
141
+ return parseVisualizationFull(content, palette);
142
+ }
143
+ function parseVisualizationFull(content, palette) {
144
+ const result = {
145
+ type: null,
146
+ title: null,
147
+ titleLineNumber: null,
148
+ orientation: "horizontal",
149
+ periods: [],
150
+ data: [],
151
+ words: [],
152
+ cloudOptions: { ...DEFAULT_CLOUD_OPTIONS },
153
+ links: [],
154
+ arcOrder: "appearance",
155
+ arcNodeGroups: [],
156
+ timelineEvents: [],
157
+ timelineGroups: [],
158
+ timelineEras: [],
159
+ timelineMarkers: [],
160
+ timelineTagGroups: [],
161
+ timelineSort: null,
162
+ timelineScale: true,
163
+ timelineSwimlanes: false,
164
+ vennSets: [],
165
+ vennOverlaps: [],
166
+ quadrantLabels: {
167
+ topRight: null,
168
+ topLeft: null,
169
+ bottomLeft: null,
170
+ bottomRight: null
171
+ },
172
+ quadrantPoints: [],
173
+ quadrantXAxis: null,
174
+ quadrantXAxisLineNumber: null,
175
+ quadrantYAxis: null,
176
+ quadrantYAxisLineNumber: null,
177
+ quadrantTitleLineNumber: null,
178
+ diagnostics: [],
179
+ error: null
180
+ };
181
+ const fail = (line, message) => {
182
+ const diag = makeDgmoError(line, message);
183
+ result.diagnostics.push(diag);
184
+ result.error = formatDgmoError(diag);
185
+ return result;
186
+ };
187
+ const warn = (line, message) => {
188
+ result.diagnostics.push(makeDgmoError(line, message, "warning"));
189
+ };
190
+ if (!content?.trim()) {
191
+ return fail(0, "Empty content");
192
+ }
193
+ const lines = content.split("\n");
194
+ const freeformLines = [];
195
+ let currentArcGroup = null;
196
+ let currentTimelineGroup = null;
197
+ let currentTimelineGroupMeta = {};
198
+ let currentTimelineTagGroup = null;
199
+ let inTimelineEraBlock = false;
200
+ let timelineEraBlockIndent = 0;
201
+ let inTimelineMarkerBlock = false;
202
+ let timelineMarkerBlockIndent = 0;
203
+ let inSlopePeriodBlock = false;
204
+ const timelineAliasMap = /* @__PURE__ */ new Map();
205
+ const VALID_D3_TYPES = /* @__PURE__ */ new Set([
206
+ "slope",
207
+ "wordcloud",
208
+ "arc",
209
+ "timeline",
210
+ "venn",
211
+ "quadrant",
212
+ "sequence"
213
+ ]);
214
+ let firstLineParsed = false;
215
+ for (let i = 0; i < lines.length; i++) {
216
+ const rawLine = lines[i];
217
+ const line = rawLine.trim();
218
+ const indent = measureIndent(rawLine);
219
+ const lineNumber = i + 1;
220
+ if (!line) continue;
221
+ if (line.startsWith("//")) continue;
222
+ if (!firstLineParsed) {
223
+ firstLineParsed = true;
224
+ const firstLineResult = parseFirstLine(line);
225
+ if (firstLineResult && VALID_D3_TYPES.has(firstLineResult.chartType)) {
226
+ result.type = firstLineResult.chartType;
227
+ if (firstLineResult.title) {
228
+ result.title = firstLineResult.title;
229
+ result.titleLineNumber = lineNumber;
230
+ }
231
+ continue;
232
+ }
233
+ }
234
+ if (result.type === "timeline" && indent === 0) {
235
+ const tagBlockMatch = matchTagBlockHeading(line);
236
+ if (tagBlockMatch) {
237
+ const newGroup = {
238
+ name: tagBlockMatch.name,
239
+ ...tagBlockMatch.alias !== void 0 && {
240
+ alias: tagBlockMatch.alias
241
+ },
242
+ entries: [],
243
+ lineNumber
244
+ };
245
+ currentTimelineTagGroup = newGroup;
246
+ if (tagBlockMatch.alias) {
247
+ timelineAliasMap.set(
248
+ tagBlockMatch.alias.toLowerCase(),
249
+ tagBlockMatch.name.toLowerCase()
250
+ );
251
+ } else {
252
+ timelineAliasMap.set(
253
+ tagBlockMatch.name.toLowerCase(),
254
+ tagBlockMatch.name.toLowerCase()
255
+ );
256
+ }
257
+ result.timelineTagGroups.push(newGroup);
258
+ continue;
259
+ }
260
+ }
261
+ if (currentTimelineTagGroup && indent > 0) {
262
+ const { text: entryText, isDefault } = stripDefaultModifier(line);
263
+ const { label, color } = extractColor(
264
+ entryText,
265
+ palette,
266
+ result.diagnostics,
267
+ lineNumber
268
+ );
269
+ if (color) {
270
+ if (isDefault) {
271
+ currentTimelineTagGroup.defaultValue = label;
272
+ } else if (currentTimelineTagGroup.entries.length === 0) {
273
+ currentTimelineTagGroup.defaultValue = label;
274
+ }
275
+ currentTimelineTagGroup.entries.push({
276
+ value: label,
277
+ color,
278
+ lineNumber
279
+ });
280
+ continue;
281
+ }
282
+ }
283
+ if (currentTimelineTagGroup && indent === 0) {
284
+ currentTimelineTagGroup = null;
285
+ }
286
+ if (result.type === "timeline") {
287
+ const tlGroupMatch = line.match(/^\[(.+?)\]\s*(.*?)\s*$/);
288
+ if (tlGroupMatch) {
289
+ const name = tlGroupMatch[1].trim();
290
+ const trailing = tlGroupMatch[2] ?? "";
291
+ let color = null;
292
+ let groupMeta = {};
293
+ if (trailing) {
294
+ const { label: peeled, colorName } = peelTrailingColorName(
295
+ " " + trailing
296
+ );
297
+ if (colorName && peeled.trim() === "") {
298
+ color = resolveColorWithDiagnostic(
299
+ colorName,
300
+ lineNumber,
301
+ result.diagnostics,
302
+ palette
303
+ ) ?? null;
304
+ } else {
305
+ const tlRegistry = withTagAliases(
306
+ TIMELINE_REGISTRY,
307
+ /* @__PURE__ */ new Set([
308
+ ...timelineAliasMap.keys(),
309
+ ...timelineAliasMap.values()
310
+ ])
311
+ );
312
+ const split = splitNameAndMeta(
313
+ trailing,
314
+ tlRegistry,
315
+ timelineAliasMap
316
+ );
317
+ if (split.color) {
318
+ color = resolveColorWithDiagnostic(
319
+ split.color,
320
+ lineNumber,
321
+ result.diagnostics,
322
+ palette
323
+ ) ?? null;
324
+ }
325
+ groupMeta = { ...split.meta };
326
+ if (groupMeta["color"]) {
327
+ color = resolveColorWithDiagnostic(
328
+ groupMeta["color"],
329
+ lineNumber,
330
+ result.diagnostics,
331
+ palette
332
+ ) ?? null;
333
+ delete groupMeta["color"];
334
+ }
335
+ }
336
+ }
337
+ result.timelineGroups.push({
338
+ name,
339
+ color,
340
+ metadata: groupMeta,
341
+ lineNumber
342
+ });
343
+ currentTimelineGroup = name;
344
+ currentTimelineGroupMeta = groupMeta;
345
+ continue;
346
+ }
347
+ }
348
+ const groupMatch = line.match(
349
+ /^\[(.+?)\](?:\s+(red|orange|yellow|green|blue|purple|teal|cyan|gray|black|white))?\s*$/
350
+ );
351
+ if (groupMatch) {
352
+ if (result.type === "arc") {
353
+ const name = groupMatch[1].trim();
354
+ const color = groupMatch[2] ? resolveColorWithDiagnostic(
355
+ groupMatch[2].trim(),
356
+ lineNumber,
357
+ result.diagnostics,
358
+ palette
359
+ ) ?? null : null;
360
+ result.arcNodeGroups.push({ name, nodes: [], color, lineNumber });
361
+ currentArcGroup = name;
362
+ }
363
+ continue;
364
+ }
365
+ if (/^#{2,}\s+/.test(line) && (result.type === "arc" || result.type === "timeline")) {
366
+ const name = line.replace(/^#{2,}\s+/, "").replace(/\s*\([^)]*\)\s*$/, "").trim();
367
+ result.diagnostics.push(
368
+ makeDgmoError(
369
+ lineNumber,
370
+ `'## ${name}' is no longer supported. Use '[${name}]' instead`,
371
+ "warning"
372
+ )
373
+ );
374
+ continue;
375
+ }
376
+ if (indent === 0) {
377
+ currentArcGroup = null;
378
+ currentTimelineGroup = null;
379
+ currentTimelineGroupMeta = {};
380
+ }
381
+ if (result.type === "arc") {
382
+ const linkMatch = line.match(
383
+ /^(.+?)\s*->\s*(.+?)(?:\s+(red|orange|yellow|green|blue|purple|teal|cyan|gray|black|white))?(?:\s+(-?[\d,_]+(?:\.[\d]+)?))?$/
384
+ );
385
+ if (linkMatch) {
386
+ const source = linkMatch[1].trim();
387
+ const target = linkMatch[2].trim();
388
+ if (source.endsWith(":") || target.endsWith(":")) {
389
+ result.diagnostics.push(
390
+ makeDgmoError(
391
+ lineNumber,
392
+ `Trailing colon is not valid in arc edges \u2014 write '${source.replace(/:$/, "")} -> ${target.replace(/:$/, "")}' instead`
393
+ )
394
+ );
395
+ continue;
396
+ }
397
+ const linkColor = linkMatch[3] ? resolveColorWithDiagnostic(
398
+ linkMatch[3].trim(),
399
+ lineNumber,
400
+ result.diagnostics,
401
+ palette
402
+ ) ?? null : null;
403
+ const arcValue = linkMatch[4] ? parseFloat(normalizeNumericToken(linkMatch[4]) ?? linkMatch[4]) : 1;
404
+ result.links.push({
405
+ source,
406
+ target,
407
+ value: arcValue,
408
+ color: linkColor,
409
+ lineNumber
410
+ });
411
+ if (currentArcGroup !== null) {
412
+ const group = result.arcNodeGroups.find(
413
+ (g) => g.name === currentArcGroup
414
+ );
415
+ if (group) {
416
+ const allGrouped = new Set(
417
+ result.arcNodeGroups.flatMap((g) => g.nodes)
418
+ );
419
+ if (!allGrouped.has(source)) group.nodes.push(source);
420
+ if (!allGrouped.has(target)) group.nodes.push(target);
421
+ }
422
+ }
423
+ continue;
424
+ }
425
+ }
426
+ if (result.type === "timeline" && inTimelineEraBlock) {
427
+ if (indent <= timelineEraBlockIndent) {
428
+ inTimelineEraBlock = false;
429
+ } else {
430
+ if (line.startsWith("//")) continue;
431
+ const eraEntryMatch = line.match(
432
+ /^(\d{4}(?:-\d{2})?(?:-\d{2}(?: \d{2}:\d{2})?)?)\s*(?:->|\u2013>)\s*(\d{4}(?:-\d{2})?(?:-\d{2}(?: \d{2}:\d{2})?)?)\s+(.+?)(?:\s+(red|orange|yellow|green|blue|purple|teal|cyan|gray|black|white))?\s*$/
433
+ );
434
+ if (eraEntryMatch) {
435
+ const colorAnnotation = eraEntryMatch[4]?.trim() || null;
436
+ result.timelineEras.push({
437
+ // Capture groups 1-3 guaranteed by the regex match.
438
+ startDate: eraEntryMatch[1],
439
+ endDate: eraEntryMatch[2],
440
+ label: eraEntryMatch[3].trim(),
441
+ color: colorAnnotation ? resolveColorWithDiagnostic(
442
+ colorAnnotation,
443
+ lineNumber,
444
+ result.diagnostics,
445
+ palette
446
+ ) ?? null : null,
447
+ lineNumber
448
+ });
449
+ } else {
450
+ warn(
451
+ lineNumber,
452
+ `Unrecognized era entry: "${line}" \u2014 use '<start> -> <end> Label [color]' (e.g. '1716 -> 1717 Reign').`
453
+ );
454
+ }
455
+ continue;
456
+ }
457
+ }
458
+ if (result.type === "timeline" && inTimelineMarkerBlock) {
459
+ if (indent <= timelineMarkerBlockIndent) {
460
+ inTimelineMarkerBlock = false;
461
+ } else {
462
+ if (line.startsWith("//")) continue;
463
+ const markerEntryMatch = line.match(
464
+ /^(\d{4}(?:-\d{2})?(?:-\d{2}(?: \d{2}:\d{2})?)?)\s+(.+?)(?:\s+(red|orange|yellow|green|blue|purple|teal|cyan|gray|black|white))?\s*$/
465
+ );
466
+ if (markerEntryMatch) {
467
+ const colorAnnotation = markerEntryMatch[3]?.trim() || null;
468
+ result.timelineMarkers.push({
469
+ // Capture groups 1-2 guaranteed by the regex match.
470
+ date: markerEntryMatch[1],
471
+ label: markerEntryMatch[2].trim(),
472
+ color: colorAnnotation ? resolveColorWithDiagnostic(
473
+ colorAnnotation,
474
+ lineNumber,
475
+ result.diagnostics,
476
+ palette
477
+ ) ?? null : null,
478
+ lineNumber
479
+ });
480
+ } else {
481
+ warn(
482
+ lineNumber,
483
+ `Unrecognized marker entry: "${line}" \u2014 use '<date> Label [color]' (e.g. '1776 Independence').`
484
+ );
485
+ }
486
+ continue;
487
+ }
488
+ }
489
+ if (result.type === "timeline") {
490
+ if (line.toLowerCase() === "era") {
491
+ inTimelineEraBlock = true;
492
+ timelineEraBlockIndent = indent;
493
+ continue;
494
+ }
495
+ if (line.toLowerCase() === "marker") {
496
+ inTimelineMarkerBlock = true;
497
+ timelineMarkerBlockIndent = indent;
498
+ continue;
499
+ }
500
+ const eraMatch = line.match(
501
+ /^era\s+(\d{4}(?:-\d{2})?(?:-\d{2}(?: \d{2}:\d{2})?)?)\s*(?:->|\u2013>)\s*(\d{4}(?:-\d{2})?(?:-\d{2}(?: \d{2}:\d{2})?)?)\s+(.+?)(?:\s+(red|orange|yellow|green|blue|purple|teal|cyan|gray|black|white))?\s*$/
502
+ );
503
+ if (eraMatch) {
504
+ const colorAnnotation = eraMatch[4]?.trim() || null;
505
+ result.timelineEras.push({
506
+ // Capture groups 1-3 guaranteed by the regex match.
507
+ startDate: eraMatch[1],
508
+ endDate: eraMatch[2],
509
+ label: eraMatch[3].trim(),
510
+ color: colorAnnotation ? resolveColorWithDiagnostic(
511
+ colorAnnotation,
512
+ lineNumber,
513
+ result.diagnostics,
514
+ palette
515
+ ) ?? null : null,
516
+ lineNumber
517
+ });
518
+ continue;
519
+ }
520
+ const markerMatch = line.match(
521
+ /^marker\s+(\d{4}(?:-\d{2})?(?:-\d{2}(?: \d{2}:\d{2})?)?)\s+(.+?)(?:\s+(red|orange|yellow|green|blue|purple|teal|cyan|gray|black|white))?\s*$/
522
+ );
523
+ if (markerMatch) {
524
+ const colorAnnotation = markerMatch[3]?.trim() || null;
525
+ result.timelineMarkers.push({
526
+ // Capture groups 1-2 guaranteed by the regex match.
527
+ date: markerMatch[1],
528
+ label: markerMatch[2].trim(),
529
+ color: colorAnnotation ? resolveColorWithDiagnostic(
530
+ colorAnnotation,
531
+ lineNumber,
532
+ result.diagnostics,
533
+ palette
534
+ ) ?? null : null,
535
+ lineNumber
536
+ });
537
+ continue;
538
+ }
539
+ }
540
+ if (result.type === "timeline") {
541
+ const sortMatch = line.match(/^sort\s+(time|group|tag:(.+))$/i);
542
+ if (sortMatch) {
543
+ const kind = sortMatch[1].toLowerCase();
544
+ if (kind === "time") result.timelineSort = "time";
545
+ else if (kind === "group") result.timelineSort = "group";
546
+ else {
547
+ result.timelineSort = "tag";
548
+ result.timelineDefaultSwimlaneTG = sortMatch[2].trim();
549
+ }
550
+ continue;
551
+ }
552
+ }
553
+ if (result.type === "timeline") {
554
+ const lower = line.toLowerCase();
555
+ if (lower === "no-scale") {
556
+ result.timelineScale = false;
557
+ continue;
558
+ }
559
+ if (lower === "swimlanes") {
560
+ result.timelineSwimlanes = true;
561
+ continue;
562
+ }
563
+ const laneByMatch = line.match(/^lane-by\s+(.+)$/i);
564
+ if (laneByMatch) {
565
+ result.timelineSort = "tag";
566
+ result.timelineDefaultSwimlaneTG = laneByMatch[1].trim();
567
+ continue;
568
+ }
569
+ const activeTagMatch = line.match(/^active-tag\s+(.+)$/i);
570
+ if (activeTagMatch) {
571
+ result.timelineActiveTag = activeTagMatch[1].trim();
572
+ continue;
573
+ }
574
+ }
575
+ if (result.type === "timeline") {
576
+ const tlRegistry = withTagAliases(
577
+ TIMELINE_REGISTRY,
578
+ /* @__PURE__ */ new Set([...timelineAliasMap.keys(), ...timelineAliasMap.values()])
579
+ );
580
+ const eventResult = parseTimelineEventLine(
581
+ line,
582
+ lineNumber,
583
+ currentTimelineGroup,
584
+ currentTimelineGroupMeta,
585
+ timelineAliasMap,
586
+ tlRegistry
587
+ );
588
+ if (eventResult) {
589
+ result.diagnostics.push(...eventResult.diagnostics);
590
+ if (eventResult.event) {
591
+ result.timelineEvents.push(eventResult.event);
592
+ }
593
+ continue;
594
+ }
595
+ if (!/^(era|marker|tag|sort|active-tag|swimlanes|no-scale|lane-by)\b/i.test(
596
+ line
597
+ ) && !line.startsWith("[")) {
598
+ warn(lineNumber, `Expected a date at the start \u2014 e.g., '1718 ${line}'`);
599
+ continue;
600
+ }
601
+ }
602
+ if (result.type === "venn") {
603
+ if (/^(solid-fill|no-name|no-value|no-percent|no-title)$/i.test(line)) {
604
+ } else if (/\+/.test(line)) {
605
+ const knownSetRefs = /* @__PURE__ */ new Set();
606
+ for (const s of result.vennSets) {
607
+ knownSetRefs.add(s.name.toLowerCase());
608
+ if (s.alias) knownSetRefs.add(s.alias.toLowerCase());
609
+ }
610
+ const segments = line.split("+").map((s) => s.trim()).filter(Boolean);
611
+ if (segments.length >= 2) {
612
+ const rawSets = segments.slice(0, -1);
613
+ const lastSeg = segments[segments.length - 1];
614
+ const words = lastSeg.split(/\s+/);
615
+ let matchLen = 0;
616
+ for (let w = words.length; w >= 1; w--) {
617
+ const candidate = words.slice(0, w).join(" ");
618
+ if (knownSetRefs.has(candidate.toLowerCase())) {
619
+ matchLen = w;
620
+ break;
621
+ }
622
+ }
623
+ let lastSetRef;
624
+ let label;
625
+ if (matchLen > 0) {
626
+ lastSetRef = words.slice(0, matchLen).join(" ");
627
+ label = words.length > matchLen ? words.slice(matchLen).join(" ") : null;
628
+ } else {
629
+ lastSetRef = words[0];
630
+ label = words.length > 1 ? words.slice(1).join(" ") : null;
631
+ }
632
+ rawSets.push(lastSetRef);
633
+ result.vennOverlaps.push({ sets: rawSets, label, lineNumber });
634
+ continue;
635
+ }
636
+ }
637
+ if (!/^(solid-fill|no-name|no-value|no-percent|no-title)$/i.test(line)) {
638
+ const { label: lineWithoutColor, colorName } = peelTrailingColorName(line);
639
+ let color = null;
640
+ if (colorName) {
641
+ color = resolveColorWithDiagnostic(
642
+ colorName,
643
+ lineNumber,
644
+ result.diagnostics,
645
+ palette
646
+ ) ?? null;
647
+ }
648
+ const setDeclMatch = lineWithoutColor.match(
649
+ /^(.+?)(?:\s+as\s+([A-Za-z][A-Za-z0-9_]{0,11}))?\s*$/i
650
+ );
651
+ if (setDeclMatch) {
652
+ const name = setDeclMatch[1].trim();
653
+ const alias = setDeclMatch[2]?.trim() ?? null;
654
+ result.vennSets.push({ name, alias, color, lineNumber });
655
+ continue;
656
+ }
657
+ }
658
+ }
659
+ if (result.type === "quadrant") {
660
+ const xAxisMatch = line.match(/^x-label\s+(.*)/i);
661
+ if (xAxisMatch) {
662
+ const val = xAxisMatch[1].trim();
663
+ let parts;
664
+ if (val) {
665
+ parts = val.split(",").map((s) => s.trim());
666
+ } else {
667
+ const collected = collectIndentedValues(lines, i);
668
+ i = collected.newIndex;
669
+ parts = collected.values;
670
+ }
671
+ if (parts.length >= 2) {
672
+ result.quadrantXAxis = [parts[0], parts[1]];
673
+ result.quadrantXAxisLineNumber = lineNumber;
674
+ }
675
+ continue;
676
+ }
677
+ const yAxisMatch = line.match(/^y-label\s+(.*)/i);
678
+ if (yAxisMatch) {
679
+ const val = yAxisMatch[1].trim();
680
+ let parts;
681
+ if (val) {
682
+ parts = val.split(",").map((s) => s.trim());
683
+ } else {
684
+ const collected = collectIndentedValues(lines, i);
685
+ i = collected.newIndex;
686
+ parts = collected.values;
687
+ }
688
+ if (parts.length >= 2) {
689
+ result.quadrantYAxis = [parts[0], parts[1]];
690
+ result.quadrantYAxisLineNumber = lineNumber;
691
+ }
692
+ continue;
693
+ }
694
+ const quadrantLabelRe = /^(top-right|top-left|bottom-left|bottom-right)\s+(.+)/i;
695
+ const quadrantMatch = line.match(quadrantLabelRe);
696
+ if (quadrantMatch) {
697
+ const position = quadrantMatch[1].toLowerCase();
698
+ const labelPart = quadrantMatch[2].trim();
699
+ const { label: text, colorName } = peelTrailingColorName(labelPart);
700
+ const color = colorName ? resolveColorWithDiagnostic(
701
+ colorName,
702
+ lineNumber,
703
+ result.diagnostics,
704
+ palette
705
+ ) ?? null : null;
706
+ const label = { text, color, lineNumber };
707
+ if (position === "top-right") result.quadrantLabels.topRight = label;
708
+ else if (position === "top-left") result.quadrantLabels.topLeft = label;
709
+ else if (position === "bottom-left")
710
+ result.quadrantLabels.bottomLeft = label;
711
+ else if (position === "bottom-right")
712
+ result.quadrantLabels.bottomRight = label;
713
+ continue;
714
+ }
715
+ const pointMatch = line.match(
716
+ /^(.+?)\s+(-?[0-9][0-9,_]*(?:\.[0-9]+)?)\s*([,\s])\s*(-?[0-9][0-9,_]*(?:\.[0-9]+)?)\s*$/
717
+ );
718
+ if (pointMatch) {
719
+ const label = pointMatch[1].trim();
720
+ const lowerLabel = label.toLowerCase();
721
+ if (lowerLabel !== "top-right" && lowerLabel !== "top-left" && lowerLabel !== "bottom-left" && lowerLabel !== "bottom-right") {
722
+ const x = parseFloat(
723
+ normalizeNumericToken(pointMatch[2]) ?? pointMatch[2]
724
+ );
725
+ const y = parseFloat(
726
+ normalizeNumericToken(pointMatch[4]) ?? pointMatch[4]
727
+ );
728
+ result.quadrantPoints.push({
729
+ label,
730
+ x,
731
+ y,
732
+ lineNumber
733
+ });
734
+ }
735
+ continue;
736
+ }
737
+ }
738
+ const spaceIdx = line.indexOf(" ");
739
+ if (spaceIdx >= 0) {
740
+ const firstToken = line.substring(0, spaceIdx).toLowerCase();
741
+ const restValue = line.substring(spaceIdx + 1).trim();
742
+ if (firstToken === "chart" && VALID_D3_TYPES.has(restValue.toLowerCase())) {
743
+ result.type = restValue.toLowerCase();
744
+ continue;
745
+ }
746
+ if (firstToken === "title") {
747
+ result.title = restValue;
748
+ result.titleLineNumber = lineNumber;
749
+ if (result.type === "quadrant") {
750
+ result.quadrantTitleLineNumber = lineNumber;
751
+ }
752
+ continue;
753
+ }
754
+ if (firstToken === "order") {
755
+ const v = restValue.toLowerCase();
756
+ if (v === "name" || v === "group" || v === "degree") {
757
+ result.arcOrder = v;
758
+ }
759
+ continue;
760
+ }
761
+ if (firstToken === "layout") {
762
+ const v = restValue.toLowerCase();
763
+ if (v === "arc" || v === "chord") result.layout = v;
764
+ continue;
765
+ }
766
+ if (firstToken === "rotate") {
767
+ const v = restValue.toLowerCase();
768
+ if (v === "none" || v === "mixed" || v === "angled") {
769
+ result.cloudOptions.rotate = v;
770
+ }
771
+ continue;
772
+ }
773
+ if (firstToken === "max") {
774
+ const v = parseInt(restValue, 10);
775
+ if (!isNaN(v) && v > 0) {
776
+ result.cloudOptions.max = v;
777
+ }
778
+ continue;
779
+ }
780
+ if (firstToken === "size") {
781
+ const parts = restValue.split(",").map((s) => parseInt(s.trim(), 10));
782
+ if (parts.length === 2 && parts.every((n) => !isNaN(n) && n > 0) && // In-bounds by length === 2 check.
783
+ parts[0] < parts[1]) {
784
+ result.cloudOptions.minSize = parts[0];
785
+ result.cloudOptions.maxSize = parts[1];
786
+ }
787
+ continue;
788
+ }
789
+ }
790
+ {
791
+ const bareToken = line.toLowerCase();
792
+ if (bareToken === "no-name") {
793
+ result.noName = true;
794
+ continue;
795
+ }
796
+ if (bareToken === "no-value") {
797
+ result.noValue = true;
798
+ continue;
799
+ }
800
+ if (bareToken === "no-percent") {
801
+ result.noPercent = true;
802
+ continue;
803
+ }
804
+ if (bareToken === "solid-fill") {
805
+ result.solidFill = true;
806
+ continue;
807
+ }
808
+ if (bareToken === "no-title") {
809
+ result.noTitle = true;
810
+ continue;
811
+ }
812
+ if (bareToken.startsWith("no-")) {
813
+ continue;
814
+ }
815
+ }
816
+ if (result.type === "slope") {
817
+ if (inSlopePeriodBlock) {
818
+ if (indent > 0) {
819
+ result.periods.push(line);
820
+ continue;
821
+ }
822
+ inSlopePeriodBlock = false;
823
+ }
824
+ if (result.data.length === 0) {
825
+ const periodMatch = line.match(/^period\b(.*)$/i);
826
+ if (periodMatch) {
827
+ if (result.periods.length > 0 && !inSlopePeriodBlock) {
828
+ warn(
829
+ lineNumber,
830
+ `Duplicate 'period' directive \u2014 periods are already defined`
831
+ );
832
+ }
833
+ const rest = periodMatch[1].trim();
834
+ if (rest) {
835
+ const periodLabels = rest.split(/\s+/);
836
+ result.periods.push(...periodLabels);
837
+ } else {
838
+ inSlopePeriodBlock = true;
839
+ }
840
+ continue;
841
+ }
842
+ }
843
+ if (result.periods.length === 0 && line.includes(",") && !line.includes(":")) {
844
+ const tokens = line.split(",").map((t) => t.trim()).filter(Boolean);
845
+ const looksLikePeriods = tokens.length >= 2 && tokens.every((t) => t.length <= 20);
846
+ if (looksLikePeriods) {
847
+ return fail(
848
+ lineNumber,
849
+ `Period lines require the 'period' keyword \u2014 use 'period ${tokens.join(" ")}'`
850
+ );
851
+ }
852
+ }
853
+ if (line.includes(":")) {
854
+ const colonPos = line.indexOf(":");
855
+ const afterColon = line.substring(colonPos + 1).trim();
856
+ const numericTokens = afterColon.split(/[,\s]+/).filter((v) => /^-?\d/.test(v));
857
+ if (numericTokens.length >= 1) {
858
+ const allTokens = afterColon.split(/[,\s]+/).filter(Boolean);
859
+ if (numericTokens.length >= allTokens.length * 0.5) {
860
+ const label = line.substring(0, colonPos).trim();
861
+ return fail(
862
+ lineNumber,
863
+ `Colons are no longer used in slope data rows \u2014 use '${label} ${numericTokens.join(" ")}'`
864
+ );
865
+ }
866
+ }
867
+ }
868
+ if (result.periods.length >= 2) {
869
+ const P = result.periods.length;
870
+ const tokens = line.split(/\s+/);
871
+ const values = [];
872
+ let rightIdx = tokens.length - 1;
873
+ while (rightIdx >= 0 && values.length < P) {
874
+ const tok = tokens[rightIdx];
875
+ const raw = normalizeNumericToken(tok) ?? tok;
876
+ const num = parseFloat(raw);
877
+ if (!isNaN(num) && /^-?\d/.test(raw)) {
878
+ values.unshift(num);
879
+ rightIdx--;
880
+ } else {
881
+ break;
882
+ }
883
+ }
884
+ if (values.length < P) {
885
+ warn(
886
+ lineNumber,
887
+ `Data row has ${values.length} numeric value(s) but ${P} period(s) are defined \u2014 expected ${P} values`
888
+ );
889
+ continue;
890
+ }
891
+ const labelTokens = tokens.slice(0, rightIdx + 1);
892
+ const joinedLabel = labelTokens.join(" ");
893
+ if (!joinedLabel) {
894
+ warn(
895
+ lineNumber,
896
+ `Data row has no label \u2014 add a label before the numeric values`
897
+ );
898
+ continue;
899
+ }
900
+ const { label: labelPart, colorName: colorWord } = peelTrailingColorName(joinedLabel);
901
+ const colorPart = colorWord ? resolveColorWithDiagnostic(
902
+ colorWord,
903
+ lineNumber,
904
+ result.diagnostics,
905
+ palette
906
+ ) ?? null : null;
907
+ if (!labelPart) {
908
+ warn(
909
+ lineNumber,
910
+ `Data row has no label \u2014 add a label before the numeric values`
911
+ );
912
+ continue;
913
+ }
914
+ if (/^\d[\d,.]*$/.test(labelPart)) {
915
+ warn(
916
+ lineNumber,
917
+ `Label '${labelPart}' looks numeric \u2014 this may indicate too many values or a missing label`
918
+ );
919
+ }
920
+ result.data.push({
921
+ label: labelPart,
922
+ values,
923
+ color: colorPart,
924
+ lineNumber
925
+ });
926
+ continue;
927
+ }
928
+ if (firstLineParsed) {
929
+ warn(lineNumber, `Unexpected line: '${line}'.`);
930
+ }
931
+ continue;
932
+ }
933
+ const colonIndex = line.indexOf(":");
934
+ if (colonIndex !== -1) {
935
+ const rawKey = line.substring(0, colonIndex).trim();
936
+ const key = rawKey.toLowerCase();
937
+ const colorMatch = rawKey.match(/^(.+?)\(([^)]+)\)\s*$/);
938
+ if (key === "title") {
939
+ result.title = line.substring(colonIndex + 1).trim();
940
+ result.titleLineNumber = lineNumber;
941
+ if (result.type === "quadrant") {
942
+ result.quadrantTitleLineNumber = lineNumber;
943
+ }
944
+ continue;
945
+ }
946
+ if (key === "order") {
947
+ const v = line.substring(colonIndex + 1).trim().toLowerCase();
948
+ if (v === "name" || v === "group" || v === "degree") {
949
+ result.arcOrder = v;
950
+ }
951
+ continue;
952
+ }
953
+ if (key === "rotate") {
954
+ const v = line.substring(colonIndex + 1).trim().toLowerCase();
955
+ if (v === "none" || v === "mixed" || v === "angled") {
956
+ result.cloudOptions.rotate = v;
957
+ }
958
+ continue;
959
+ }
960
+ if (key === "max") {
961
+ const v = parseInt(line.substring(colonIndex + 1).trim(), 10);
962
+ if (!isNaN(v) && v > 0) {
963
+ result.cloudOptions.max = v;
964
+ }
965
+ continue;
966
+ }
967
+ if (key === "size") {
968
+ const v = line.substring(colonIndex + 1).trim();
969
+ const parts = v.split(",").map((s) => parseInt(s.trim(), 10));
970
+ if (parts.length === 2 && parts.every((n) => !isNaN(n) && n > 0) && // In-bounds by length === 2 check.
971
+ parts[0] < parts[1]) {
972
+ result.cloudOptions.minSize = parts[0];
973
+ result.cloudOptions.maxSize = parts[1];
974
+ }
975
+ continue;
976
+ }
977
+ const labelPart = colorMatch ? colorMatch[1].trim() : rawKey;
978
+ const colorPart = colorMatch ? resolveColorWithDiagnostic(
979
+ colorMatch[2].trim(),
980
+ lineNumber,
981
+ result.diagnostics,
982
+ palette
983
+ ) ?? null : null;
984
+ const valuePart = line.substring(colonIndex + 1).trim();
985
+ const values = valuePart.split(",").map((v) => v.trim());
986
+ const numericValues = [];
987
+ let allNumeric = true;
988
+ for (const v of values) {
989
+ const num = parseFloat(v);
990
+ if (isNaN(num)) {
991
+ allNumeric = false;
992
+ break;
993
+ }
994
+ numericValues.push(num);
995
+ }
996
+ if (allNumeric && numericValues.length > 0) {
997
+ if (result.type !== "wordcloud") {
998
+ result.data.push({
999
+ label: labelPart,
1000
+ values: numericValues,
1001
+ color: colorPart,
1002
+ lineNumber
1003
+ });
1004
+ continue;
1005
+ }
1006
+ }
1007
+ }
1008
+ if (result.type === "wordcloud") {
1009
+ if (colonIndex === -1 && !line.includes(" ")) {
1010
+ result.words.push({ text: line, weight: 10, lineNumber });
1011
+ } else if (colonIndex === -1) {
1012
+ const lastSpace = line.lastIndexOf(" ");
1013
+ const rawWeight = lastSpace >= 0 ? line.substring(lastSpace + 1) : "";
1014
+ const maybeWeight = lastSpace >= 0 ? parseFloat(normalizeNumericToken(rawWeight) ?? rawWeight) : NaN;
1015
+ if (lastSpace >= 0 && !isNaN(maybeWeight) && maybeWeight > 0) {
1016
+ const wordText = line.substring(0, lastSpace).trim();
1017
+ result.words.push({
1018
+ text: wordText,
1019
+ weight: maybeWeight,
1020
+ lineNumber
1021
+ });
1022
+ } else {
1023
+ freeformLines.push(line);
1024
+ }
1025
+ } else {
1026
+ freeformLines.push(line);
1027
+ }
1028
+ continue;
1029
+ }
1030
+ if (firstLineParsed) {
1031
+ warn(lineNumber, `Unexpected line: '${line}'.`);
1032
+ }
1033
+ }
1034
+ if (!result.type) {
1035
+ const validD3Types = [...VALID_D3_TYPES];
1036
+ const firstNonEmpty = lines.find((l) => l.trim() && !l.trim().startsWith("//"))?.trim() ?? "";
1037
+ const hint = suggest(
1038
+ firstNonEmpty.split(/\s/)[0].toLowerCase(),
1039
+ validD3Types
1040
+ );
1041
+ let msg = `Unsupported chart type: "${firstNonEmpty.split(/\s/)[0]}". Supported types: ${validD3Types.join(", ")}`;
1042
+ if (hint) msg += `. ${hint}`;
1043
+ return fail(1, msg);
1044
+ }
1045
+ if (result.type === "sequence") {
1046
+ return result;
1047
+ }
1048
+ if (result.type === "wordcloud") {
1049
+ if (result.words.length === 0 && freeformLines.length > 0) {
1050
+ result.words = tokenizeFreeformText(freeformLines.join(" "));
1051
+ }
1052
+ if (result.words.length === 0) {
1053
+ warn(
1054
+ 1,
1055
+ 'No words found. Add words as "word weight" (space-separated), one per line, or paste freeform text'
1056
+ );
1057
+ }
1058
+ if (result.cloudOptions.max > 0 && result.words.length > result.cloudOptions.max) {
1059
+ result.words = result.words.slice().sort((a, b) => b.weight - a.weight).slice(0, result.cloudOptions.max);
1060
+ }
1061
+ return result;
1062
+ }
1063
+ if (result.type === "arc") {
1064
+ if (result.links.length === 0) {
1065
+ warn(
1066
+ 1,
1067
+ 'No links found. Add links as "Source -> Target weight" (e.g., "Alice -> Bob 5")'
1068
+ );
1069
+ }
1070
+ if (result.arcNodeGroups.length > 0) {
1071
+ if (result.arcOrder === "name" || result.arcOrder === "degree") {
1072
+ warn(
1073
+ 1,
1074
+ `Cannot use "order ${result.arcOrder}" with [Group] headers. Use "order group" or remove group headers.`
1075
+ );
1076
+ result.arcOrder = "group";
1077
+ }
1078
+ if (result.arcOrder === "appearance") {
1079
+ result.arcOrder = "group";
1080
+ }
1081
+ }
1082
+ return result;
1083
+ }
1084
+ if (result.type === "timeline") {
1085
+ if (result.timelineEvents.length === 0) {
1086
+ warn(
1087
+ 1,
1088
+ 'No events found. Add events like "1718 Event Name" or "1716 -> 1717 Event Name"'
1089
+ );
1090
+ }
1091
+ if (result.timelineTagGroups.length > 0) {
1092
+ validateTagValues(
1093
+ result.timelineEvents,
1094
+ result.timelineTagGroups,
1095
+ (line, msg) => result.diagnostics.push(makeDgmoError(line, msg, "warning")),
1096
+ suggest
1097
+ );
1098
+ validateTagGroupNames(
1099
+ result.timelineTagGroups,
1100
+ (line, msg) => result.diagnostics.push(makeDgmoError(line, msg, "warning")),
1101
+ (line, msg) => {
1102
+ const diag = makeDgmoError(line, msg);
1103
+ result.diagnostics.push(diag);
1104
+ if (!result.error) result.error = formatDgmoError(diag);
1105
+ }
1106
+ );
1107
+ for (const group of result.timelineTagGroups) {
1108
+ if (!group.defaultValue) continue;
1109
+ const key = tagAttrKey(group.name);
1110
+ for (const event of result.timelineEvents) {
1111
+ if (!event.metadata[key]) {
1112
+ event.metadata[key] = group.defaultValue;
1113
+ }
1114
+ }
1115
+ }
1116
+ }
1117
+ return result;
1118
+ }
1119
+ if (result.type === "venn") {
1120
+ if (result.vennSets.length < 2) {
1121
+ return fail(
1122
+ 1,
1123
+ 'At least 2 sets are required. Add set names (e.g., "Apples", "Oranges")'
1124
+ );
1125
+ }
1126
+ if (result.vennSets.length > 3) {
1127
+ return fail(1, "Venn diagrams support 2\u20133 sets");
1128
+ }
1129
+ const setNameLower = new Map(
1130
+ result.vennSets.map((s) => [s.name.toLowerCase(), s.name])
1131
+ );
1132
+ const aliasLower = /* @__PURE__ */ new Map();
1133
+ for (const s of result.vennSets) {
1134
+ if (s.alias) aliasLower.set(s.alias.toLowerCase(), s.name);
1135
+ }
1136
+ const resolveSetRef = (ref) => setNameLower.get(ref.toLowerCase()) ?? aliasLower.get(ref.toLowerCase()) ?? null;
1137
+ const validOverlaps = [];
1138
+ for (const ov of result.vennOverlaps) {
1139
+ const resolvedSets = [];
1140
+ let valid = true;
1141
+ for (const ref of ov.sets) {
1142
+ const resolved = resolveSetRef(ref);
1143
+ if (!resolved) {
1144
+ result.diagnostics.push(
1145
+ makeDgmoError(
1146
+ ov.lineNumber,
1147
+ `Intersection references unknown set or alias "${ref}" \u2014 declare the set first on its own line ('Name [as <alias>] [color]', e.g. 'Navigation as nav blue'), then reference it by that name or alias. (\xA716.4)`
1148
+ )
1149
+ );
1150
+ if (!result.error)
1151
+ result.error = formatDgmoError(
1152
+ result.diagnostics[result.diagnostics.length - 1]
1153
+ );
1154
+ valid = false;
1155
+ break;
1156
+ }
1157
+ resolvedSets.push(resolved);
1158
+ }
1159
+ if (valid) validOverlaps.push({ ...ov, sets: resolvedSets.sort() });
1160
+ }
1161
+ result.vennOverlaps = validOverlaps;
1162
+ return result;
1163
+ }
1164
+ if (result.type === "quadrant") {
1165
+ if (result.quadrantPoints.length === 0) {
1166
+ warn(
1167
+ 1,
1168
+ 'No data points found. Add points as "Label x, y" (e.g., "Item A 0.5, 0.7")'
1169
+ );
1170
+ }
1171
+ return result;
1172
+ }
1173
+ if (result.periods.length < 2) {
1174
+ return fail(
1175
+ 1,
1176
+ "Missing 'period' directive. Add 'period 2020 2024' before data rows (minimum 2 periods required)"
1177
+ );
1178
+ }
1179
+ if (result.data.length === 0) {
1180
+ warn(
1181
+ 1,
1182
+ "No data lines found. Add data as 'Label value1 value2' (e.g., 'Blackbeard 40 4')"
1183
+ );
1184
+ }
1185
+ for (const item of result.data) {
1186
+ if (item.values.length !== result.periods.length) {
1187
+ warn(
1188
+ item.lineNumber,
1189
+ `Data item "${item.label}" has ${item.values.length} value(s) but ${result.periods.length} period(s) are defined`
1190
+ );
1191
+ }
1192
+ }
1193
+ result.data = result.data.filter(
1194
+ (item) => item.values.length === result.periods.length
1195
+ );
1196
+ return result;
1197
+ }
1198
+ var STOP_WORDS = /* @__PURE__ */ new Set([
1199
+ "a",
1200
+ "an",
1201
+ "the",
1202
+ "and",
1203
+ "or",
1204
+ "but",
1205
+ "in",
1206
+ "on",
1207
+ "at",
1208
+ "to",
1209
+ "for",
1210
+ "of",
1211
+ "with",
1212
+ "by",
1213
+ "is",
1214
+ "am",
1215
+ "are",
1216
+ "was",
1217
+ "were",
1218
+ "be",
1219
+ "been",
1220
+ "being",
1221
+ "have",
1222
+ "has",
1223
+ "had",
1224
+ "do",
1225
+ "does",
1226
+ "did",
1227
+ "will",
1228
+ "would",
1229
+ "could",
1230
+ "should",
1231
+ "may",
1232
+ "might",
1233
+ "shall",
1234
+ "can",
1235
+ "it",
1236
+ "its",
1237
+ "this",
1238
+ "that",
1239
+ "these",
1240
+ "those",
1241
+ "i",
1242
+ "me",
1243
+ "my",
1244
+ "we",
1245
+ "us",
1246
+ "our",
1247
+ "you",
1248
+ "your",
1249
+ "he",
1250
+ "him",
1251
+ "his",
1252
+ "she",
1253
+ "her",
1254
+ "they",
1255
+ "them",
1256
+ "their",
1257
+ "what",
1258
+ "which",
1259
+ "who",
1260
+ "whom",
1261
+ "how",
1262
+ "when",
1263
+ "where",
1264
+ "why",
1265
+ "not",
1266
+ "no",
1267
+ "nor",
1268
+ "so",
1269
+ "if",
1270
+ "then",
1271
+ "than",
1272
+ "too",
1273
+ "very",
1274
+ "just",
1275
+ "about",
1276
+ "up",
1277
+ "out",
1278
+ "from",
1279
+ "into",
1280
+ "over",
1281
+ "after",
1282
+ "before",
1283
+ "between",
1284
+ "under",
1285
+ "again",
1286
+ "there",
1287
+ "here",
1288
+ "all",
1289
+ "each",
1290
+ "every",
1291
+ "both",
1292
+ "few",
1293
+ "more",
1294
+ "most",
1295
+ "other",
1296
+ "some",
1297
+ "such",
1298
+ "only",
1299
+ "own",
1300
+ "same",
1301
+ "also",
1302
+ "as",
1303
+ "because",
1304
+ "until",
1305
+ "while",
1306
+ "during",
1307
+ "through"
1308
+ ]);
1309
+ function tokenizeFreeformText(text) {
1310
+ const counts = /* @__PURE__ */ new Map();
1311
+ const tokens = text.toLowerCase().split(/[^a-zA-Z']+/).filter(Boolean);
1312
+ for (const raw of tokens) {
1313
+ const word = raw.replace(/^'+|'+$/g, "");
1314
+ if (word.length < 2 || STOP_WORDS.has(word)) continue;
1315
+ counts.set(word, (counts.get(word) ?? 0) + 1);
1316
+ }
1317
+ return Array.from(counts.entries()).map(([text2, count]) => ({ text: text2, weight: count, lineNumber: 0 })).sort((a, b) => b.weight - a.weight);
1318
+ }
1319
+
1320
+ // src/chart-types.ts
1321
+ var chartTypes = [
1322
+ // ── Tier 1 — Narrative / architecture diagrams ────────────
1323
+ {
1324
+ id: "journey-map",
1325
+ description: "User experience flow with emotion scores, phases, and annotations"
1326
+ },
1327
+ {
1328
+ id: "c4",
1329
+ description: "System architecture (context, container, component, deployment)"
1330
+ },
1331
+ {
1332
+ id: "er",
1333
+ description: "Database schemas and relationships"
1334
+ },
1335
+ {
1336
+ id: "class",
1337
+ description: "UML class hierarchies"
1338
+ },
1339
+ {
1340
+ id: "sequence",
1341
+ description: "Message request and response interaction flows",
1342
+ fallback: true
1343
+ },
1344
+ {
1345
+ id: "state",
1346
+ description: "State machine / lifecycle transitions"
1347
+ },
1348
+ {
1349
+ id: "infra",
1350
+ description: "Infrastructure traffic flow with RPS computation"
1351
+ },
1352
+ {
1353
+ id: "gantt",
1354
+ description: "Project scheduling with task dependencies and milestones"
1355
+ },
1356
+ {
1357
+ id: "pert",
1358
+ description: "Project network with three-point estimates, critical path, and uncertainty (Beta-PERT, Monte Carlo)"
1359
+ },
1360
+ {
1361
+ id: "swimlane",
1362
+ description: "Cross-functional process flow with lanes, phases and gateways (BPMN-style)"
1363
+ },
1364
+ {
1365
+ id: "version-control",
1366
+ description: "Git / version-control branch-and-merge graph: commits, branches, merges, rebase, HEAD and remote-tracking (gitGraph-style)"
1367
+ },
1368
+ // ── Tier 2 — Specialized structural diagrams ──────────────
1369
+ {
1370
+ id: "timeline",
1371
+ description: "Events, eras, and date ranges"
1372
+ },
1373
+ {
1374
+ id: "event-line",
1375
+ description: "Annotated narrative timeline \u2014 events on a horizontal line with descriptions (not the date-scaled timeline)"
1376
+ },
1377
+ {
1378
+ id: "org",
1379
+ description: "Reporting hierarchy"
1380
+ },
1381
+ {
1382
+ id: "sitemap",
1383
+ description: "Site / app navigation structure"
1384
+ },
1385
+ {
1386
+ id: "kanban",
1387
+ description: "Task board columns"
1388
+ },
1389
+ {
1390
+ id: "raci",
1391
+ description: "Tasks \xD7 roles responsibility matrix with constraint linting"
1392
+ },
1393
+ {
1394
+ id: "tech-radar",
1395
+ description: "Technology adoption quadrants (adopt/trial/assess/hold)"
1396
+ },
1397
+ {
1398
+ id: "mindmap",
1399
+ description: "Radial hierarchy of ideas branching from a central topic"
1400
+ },
1401
+ {
1402
+ id: "wireframe",
1403
+ description: "Low-fidelity UI layout with panels, controls, and annotations"
1404
+ },
1405
+ {
1406
+ id: "cycle",
1407
+ description: "Cyclical process visualization (PDCA, OODA, DevOps loops)"
1408
+ },
1409
+ {
1410
+ id: "pyramid",
1411
+ description: "Stacked hierarchy of layers with descriptions (Maslow, DIKW)"
1412
+ },
1413
+ {
1414
+ id: "ring",
1415
+ description: "Concentric rings showing nested or hierarchical categories (read core-out)"
1416
+ },
1417
+ {
1418
+ id: "treemap",
1419
+ description: "Nested rectangles sized by value \u2014 show a hierarchy\u2019s proportions (budgets, disk usage, portfolios) with color by category, value heatmap, or branch"
1420
+ },
1421
+ {
1422
+ id: "block",
1423
+ description: "Block diagram: an author-controlled grid of rectangular blocks with nested, collapsible containers \u2014 system/hardware/architecture layouts where the 2-D arrangement is the meaning"
1424
+ },
1425
+ {
1426
+ id: "map",
1427
+ description: "Geographic concept map: highlight/score regions, drop points of interest, connect with routes or edges"
1428
+ },
1429
+ // ── Tier 3 — Specialized analytical charts ────────────────
1430
+ {
1431
+ id: "quadrant",
1432
+ description: "2x2 positioning matrix"
1433
+ },
1434
+ {
1435
+ id: "venn",
1436
+ description: "Set overlaps"
1437
+ },
1438
+ {
1439
+ id: "funnel",
1440
+ description: "Conversion pipeline"
1441
+ },
1442
+ {
1443
+ id: "slope",
1444
+ description: "Change between 2 time periods"
1445
+ },
1446
+ {
1447
+ id: "sankey",
1448
+ description: "Flow / allocation visualization"
1449
+ },
1450
+ {
1451
+ id: "arc",
1452
+ description: "Network relationships (linear or circular via `layout`)"
1453
+ },
1454
+ {
1455
+ id: "wordcloud",
1456
+ description: "Term frequency visualization"
1457
+ },
1458
+ {
1459
+ id: "heatmap",
1460
+ description: "Matrix intensity visualization"
1461
+ },
1462
+ {
1463
+ id: "function",
1464
+ description: "Mathematical expressions"
1465
+ },
1466
+ // ── Tier 4 — General-purpose data charts ──────────────────
1467
+ {
1468
+ id: "bar",
1469
+ description: "Categorical comparisons for 3 - 5 figures",
1470
+ fallback: true
1471
+ },
1472
+ {
1473
+ id: "line",
1474
+ description: "Trends over time",
1475
+ fallback: true
1476
+ },
1477
+ {
1478
+ id: "pie",
1479
+ description: "Part-to-whole proportions"
1480
+ },
1481
+ {
1482
+ id: "radar",
1483
+ description: "Multi-dimensional metrics"
1484
+ },
1485
+ {
1486
+ id: "polar-area",
1487
+ description: "Radial bar chart"
1488
+ },
1489
+ {
1490
+ id: "scatter",
1491
+ description: "2D data points or bubble chart"
1492
+ },
1493
+ // ── Tier 5 — Generic catch-alls (listed last on purpose) ──
1494
+ {
1495
+ id: "flowchart",
1496
+ description: "Decision trees and process flows",
1497
+ fallback: true
1498
+ },
1499
+ {
1500
+ id: "boxes-and-lines",
1501
+ description: "General-purpose node-edge diagrams with groups and tags",
1502
+ fallback: true
1503
+ }
1504
+ ];
1505
+
1506
+ // src/slope/parser.ts
1507
+ function parseSlope(content, palette) {
1508
+ return parseVisualization(content, palette);
1509
+ }
1510
+
1511
+ // src/arc/parser.ts
1512
+ function parseArc(content, palette) {
1513
+ return parseVisualization(content, palette);
1514
+ }
1515
+
1516
+ // src/timeline/viz-parser.ts
1517
+ function parseTimeline(content, palette) {
1518
+ return parseVisualization(content, palette);
1519
+ }
1520
+
1521
+ // src/wordcloud/parser.ts
1522
+ function parseWordcloud(content, palette) {
1523
+ return parseVisualization(content, palette);
1524
+ }
1525
+
1526
+ // src/venn/parser.ts
1527
+ function parseVenn(content, palette) {
1528
+ return parseVisualization(content, palette);
1529
+ }
1530
+
1531
+ // src/quadrant/parser.ts
1532
+ function parseQuadrant(content, palette) {
1533
+ return parseVisualization(content, palette);
1534
+ }
1535
+
1536
+ // src/chart-type-registry.ts
1537
+ function measureSequence(content) {
1538
+ const parsed = parseSequenceDgmo(content);
1539
+ return {
1540
+ participants: parsed.participants.length,
1541
+ messages: parsed.messages.length
1542
+ };
1543
+ }
1544
+ function measureRaci(content) {
1545
+ const parsed = parseRaci(content);
1546
+ let taskCount = 0;
1547
+ for (const _task of allTasks(parsed)) taskCount++;
1548
+ return {
1549
+ roles: parsed.roles.length,
1550
+ tasks: taskCount
1551
+ };
1552
+ }
1553
+ function walkTree(nodes, depth, acc) {
1554
+ for (const node of nodes) {
1555
+ acc.nodes++;
1556
+ if (depth > acc.depth) acc.depth = depth;
1557
+ walkTree(
1558
+ node.children,
1559
+ depth + 1,
1560
+ acc
1561
+ );
1562
+ }
1563
+ }
1564
+ function measureMindmap(content) {
1565
+ const parsed = parseMindmap(content);
1566
+ const acc = { nodes: 0, depth: 0 };
1567
+ walkTree(parsed.roots, 1, acc);
1568
+ return { nodes: acc.nodes, depth: acc.depth };
1569
+ }
1570
+ function measureTechRadar(content) {
1571
+ const parsed = parseTechRadar(content);
1572
+ let blipCount = 0;
1573
+ for (const q of parsed.quadrants) blipCount += q.blips.length;
1574
+ return { blips: blipCount };
1575
+ }
1576
+ function measureHeatmap(content) {
1577
+ const parsed = parseHeatmap(content);
1578
+ return {
1579
+ columns: parsed.columns?.length ?? 0,
1580
+ rows: parsed.heatmapRows?.length ?? parsed.rows?.length ?? 0
1581
+ };
1582
+ }
1583
+ function measureArc(content) {
1584
+ const parsed = parseArc(content);
1585
+ const allNodes = /* @__PURE__ */ new Set();
1586
+ for (const g of parsed.arcNodeGroups) {
1587
+ for (const n of g.nodes) allNodes.add(n);
1588
+ }
1589
+ return { nodes: allNodes.size };
1590
+ }
1591
+ function measureOrg(content) {
1592
+ const parsed = parseOrg(content);
1593
+ const acc = { nodes: 0, depth: 0 };
1594
+ walkTree(parsed.roots, 1, acc);
1595
+ return { nodes: acc.nodes, depth: acc.depth };
1596
+ }
1597
+ function measureGantt(content) {
1598
+ const parsed = parseGantt(content);
1599
+ const taskCount = parsed.nodes.filter(
1600
+ (n) => n.kind === "task"
1601
+ ).length;
1602
+ return { tasks: taskCount };
1603
+ }
1604
+ function measureKanban(content) {
1605
+ const parsed = parseKanban(content);
1606
+ return { columns: parsed.columns.length };
1607
+ }
1608
+ function measureER(content) {
1609
+ const parsed = parseERDiagram(content);
1610
+ return { nodes: parsed.tables.length };
1611
+ }
1612
+ function measureClass(content) {
1613
+ const parsed = parseClassDiagram(content);
1614
+ return { nodes: parsed.classes.length };
1615
+ }
1616
+ function measureFlowchart(content) {
1617
+ const parsed = parseFlowchart(content);
1618
+ return { nodes: parsed.nodes.length };
1619
+ }
1620
+ function measureStateGraph(content) {
1621
+ const parsed = parseState(content);
1622
+ return { nodes: parsed.nodes.length };
1623
+ }
1624
+ function measurePert(content) {
1625
+ const parsed = parsePert(content);
1626
+ return { tasks: parsed.activities.length };
1627
+ }
1628
+ function measureInfra(content) {
1629
+ const parsed = parseInfra(content);
1630
+ return { nodes: parsed.nodes.length };
1631
+ }
1632
+ function measureSwimlane(content) {
1633
+ const parsed = parseSwimlane(content);
1634
+ return { lanes: parsed.lanes.length, nodes: parsed.nodes.length };
1635
+ }
1636
+ function minDimsSequence(c) {
1637
+ return {
1638
+ width: Math.max((c.participants ?? 2) * 80, 320),
1639
+ height: Math.max((c.messages ?? 1) * 20 + 120, 200)
1640
+ };
1641
+ }
1642
+ function minDimsRaci(c) {
1643
+ return {
1644
+ width: Math.max((c.roles ?? 2) * 50 + 180, 300),
1645
+ height: Math.max((c.tasks ?? 1) * 28 + 80, 200)
1646
+ };
1647
+ }
1648
+ function minDimsMindmap(c) {
1649
+ return {
1650
+ width: Math.max((c.nodes ?? 3) * 30, 300),
1651
+ height: Math.max((c.depth ?? 2) * 60, 200)
1652
+ };
1653
+ }
1654
+ function minDimsTechRadar() {
1655
+ return { width: 360, height: 400 };
1656
+ }
1657
+ function minDimsHeatmap(c) {
1658
+ return {
1659
+ width: Math.max((c.columns ?? 3) * 40, 300),
1660
+ height: Math.max((c.rows ?? 3) * 30 + 60, 200)
1661
+ };
1662
+ }
1663
+ function minDimsArc(c) {
1664
+ return {
1665
+ width: 300,
1666
+ height: Math.max((c.nodes ?? 3) * 20 + 120, 200)
1667
+ };
1668
+ }
1669
+ function measureEventLine(content) {
1670
+ return { items: parseEventLine(content).events.length };
1671
+ }
1672
+ function minDimsEventLine(c) {
1673
+ return {
1674
+ width: Math.max(640, 120 + (c.items ?? 3) * 100),
1675
+ height: 420
1676
+ };
1677
+ }
1678
+ function measureVersionControl(content) {
1679
+ return { nodes: parseVersionControl(content).nodes.length };
1680
+ }
1681
+ function minDimsVersionControl(c) {
1682
+ return {
1683
+ width: Math.max(480, 160 + (c.nodes ?? 3) * 86),
1684
+ height: 360
1685
+ };
1686
+ }
1687
+ function minDimsOrg(c) {
1688
+ return {
1689
+ width: Math.max((c.nodes ?? 3) * 60, 300),
1690
+ height: Math.max((c.depth ?? 2) * 80, 200)
1691
+ };
1692
+ }
1693
+ function minDimsGantt(c) {
1694
+ return {
1695
+ width: 400,
1696
+ height: Math.max((c.tasks ?? 3) * 24 + 80, 200)
1697
+ };
1698
+ }
1699
+ function minDimsKanban(c) {
1700
+ return {
1701
+ width: Math.max((c.columns ?? 3) * 120, 360),
1702
+ height: 300
1703
+ };
1704
+ }
1705
+ function minDimsEntities(c) {
1706
+ return {
1707
+ width: Math.max((c.nodes ?? 2) * 140, 300),
1708
+ height: Math.max((c.nodes ?? 2) * 80, 200)
1709
+ };
1710
+ }
1711
+ function minDimsGraph(c) {
1712
+ return {
1713
+ width: Math.max((c.nodes ?? 3) * 60, 300),
1714
+ height: Math.max((c.nodes ?? 3) * 50, 200)
1715
+ };
1716
+ }
1717
+ function minDimsPert(c) {
1718
+ return {
1719
+ width: Math.max((c.tasks ?? 3) * 80, 340),
1720
+ height: Math.max((c.tasks ?? 3) * 40 + 80, 200)
1721
+ };
1722
+ }
1723
+ function minDimsInfra(c) {
1724
+ return {
1725
+ width: Math.max((c.nodes ?? 3) * 80, 300),
1726
+ height: Math.max((c.nodes ?? 3) * 60, 200)
1727
+ };
1728
+ }
1729
+ function minDimsSwimlane(c) {
1730
+ return {
1731
+ width: Math.max((c.nodes ?? 4) * 90, 480),
1732
+ height: Math.max((c.lanes ?? 3) * 100 + 60, 240)
1733
+ };
1734
+ }
1735
+ var CHART_TYPE_REGISTRY = [
1736
+ // ── Structured diagrams ───────────────────────────────────
1737
+ {
1738
+ id: "sequence",
1739
+ category: "diagram",
1740
+ parse: parseSequenceDgmo,
1741
+ measure: measureSequence,
1742
+ minDims: minDimsSequence
1743
+ },
1744
+ {
1745
+ id: "flowchart",
1746
+ category: "diagram",
1747
+ parse: parseFlowchart,
1748
+ measure: measureFlowchart,
1749
+ minDims: minDimsGraph
1750
+ },
1751
+ {
1752
+ id: "class",
1753
+ category: "diagram",
1754
+ parse: parseClassDiagram,
1755
+ measure: measureClass,
1756
+ minDims: minDimsEntities
1757
+ },
1758
+ {
1759
+ id: "er",
1760
+ category: "diagram",
1761
+ parse: parseERDiagram,
1762
+ measure: measureER,
1763
+ minDims: minDimsEntities
1764
+ },
1765
+ {
1766
+ id: "state",
1767
+ category: "diagram",
1768
+ parse: parseState,
1769
+ measure: measureStateGraph,
1770
+ minDims: minDimsGraph
1771
+ },
1772
+ {
1773
+ id: "org",
1774
+ category: "diagram",
1775
+ parse: parseOrg,
1776
+ measure: measureOrg,
1777
+ minDims: minDimsOrg
1778
+ },
1779
+ {
1780
+ id: "kanban",
1781
+ category: "diagram",
1782
+ parse: parseKanban,
1783
+ measure: measureKanban,
1784
+ minDims: minDimsKanban
1785
+ },
1786
+ { id: "c4", category: "diagram", parse: parseC4 },
1787
+ { id: "sitemap", category: "diagram", parse: parseSitemap },
1788
+ {
1789
+ id: "infra",
1790
+ category: "diagram",
1791
+ parse: parseInfra,
1792
+ measure: measureInfra,
1793
+ minDims: minDimsInfra
1794
+ },
1795
+ {
1796
+ id: "gantt",
1797
+ category: "diagram",
1798
+ parse: parseGantt,
1799
+ measure: measureGantt,
1800
+ minDims: minDimsGantt
1801
+ },
1802
+ {
1803
+ id: "pert",
1804
+ category: "diagram",
1805
+ parse: parsePert,
1806
+ measure: measurePert,
1807
+ minDims: minDimsPert
1808
+ },
1809
+ { id: "boxes-and-lines", category: "diagram", parse: parseBoxesAndLines },
1810
+ {
1811
+ id: "swimlane",
1812
+ category: "diagram",
1813
+ parse: parseSwimlane,
1814
+ measure: measureSwimlane,
1815
+ minDims: minDimsSwimlane
1816
+ },
1817
+ {
1818
+ id: "version-control",
1819
+ category: "diagram",
1820
+ parse: parseVersionControl,
1821
+ measure: measureVersionControl,
1822
+ minDims: minDimsVersionControl
1823
+ },
1824
+ {
1825
+ id: "mindmap",
1826
+ category: "diagram",
1827
+ parse: parseMindmap,
1828
+ measure: measureMindmap,
1829
+ minDims: minDimsMindmap
1830
+ },
1831
+ { id: "wireframe", category: "diagram", parse: parseWireframe },
1832
+ { id: "journey-map", category: "diagram", parse: parseJourneyMap },
1833
+ {
1834
+ id: "raci",
1835
+ category: "diagram",
1836
+ parse: parseRaci,
1837
+ measure: measureRaci,
1838
+ minDims: minDimsRaci
1839
+ },
1840
+ // ── Standard ECharts charts (parseChart) ──────────────────
1841
+ { id: "bar", category: "data-chart", parse: parseChart },
1842
+ { id: "line", category: "data-chart", parse: parseChart },
1843
+ { id: "pie", category: "data-chart", parse: parseChart },
1844
+ { id: "radar", category: "data-chart", parse: parseChart },
1845
+ { id: "polar-area", category: "data-chart", parse: parseChart },
1846
+ // ── Extended ECharts charts — own per-type parser door (Story 109.2a) ──
1847
+ { id: "scatter", category: "data-chart", parse: parseScatter },
1848
+ { id: "sankey", category: "data-chart", parse: parseSankey },
1849
+ { id: "function", category: "data-chart", parse: parseFunctionChart },
1850
+ {
1851
+ id: "heatmap",
1852
+ category: "data-chart",
1853
+ parse: parseHeatmap,
1854
+ measure: measureHeatmap,
1855
+ minDims: minDimsHeatmap
1856
+ },
1857
+ { id: "funnel", category: "data-chart", parse: parseFunnel },
1858
+ // ── D3 visualizations — own per-viz parser door (Story 109.2) ──
1859
+ { id: "slope", category: "visualization", parse: parseSlope },
1860
+ { id: "wordcloud", category: "visualization", parse: parseWordcloud },
1861
+ {
1862
+ id: "arc",
1863
+ category: "visualization",
1864
+ parse: parseArc,
1865
+ measure: measureArc,
1866
+ minDims: minDimsArc
1867
+ },
1868
+ { id: "timeline", category: "visualization", parse: parseTimeline },
1869
+ {
1870
+ id: "event-line",
1871
+ category: "visualization",
1872
+ parse: parseEventLine,
1873
+ measure: measureEventLine,
1874
+ minDims: minDimsEventLine
1875
+ },
1876
+ { id: "venn", category: "visualization", parse: parseVenn },
1877
+ { id: "quadrant", category: "visualization", parse: parseQuadrant },
1878
+ // ── Visualizations with their own parsers ─────────────────
1879
+ {
1880
+ id: "tech-radar",
1881
+ category: "visualization",
1882
+ parse: parseTechRadar,
1883
+ measure: measureTechRadar,
1884
+ minDims: minDimsTechRadar
1885
+ },
1886
+ { id: "cycle", category: "visualization", parse: parseCycle },
1887
+ { id: "pyramid", category: "visualization", parse: parsePyramid },
1888
+ { id: "ring", category: "visualization", parse: parseRing },
1889
+ // Treemap: squarified hierarchy. No measure/minDims — a treemap fills whatever
1890
+ // rectangle it's given and has no intrinsic aspect/size (F11).
1891
+ { id: "treemap", category: "visualization", parse: parseTreemap },
1892
+ // Block diagram: deterministic grid (no measure/minDims — it sizes to content
1893
+ // and is scaled to fit whatever rectangle it's given).
1894
+ { id: "block", category: "visualization", parse: parseBlock },
1895
+ // ── Geographic map (own parser → resolver → layout → renderer) ──
1896
+ { id: "map", category: "visualization", parse: parseMap }
1897
+ ];
1898
+ var REGISTRY_BY_ID = new Map(
1899
+ CHART_TYPE_REGISTRY.map((d) => [d.id, d])
1900
+ );
1901
+ function isExtendedChartParser(parse) {
1902
+ return EXTENDED_CHART_DOORS.has(parse);
1903
+ }
1904
+
1905
+ // src/dgmo-router.ts
1906
+ var GANTT_DURATION_RE = /^\d+(?:\.\d+)?(?:min|bd|d|w|m|q|y|h)(?:\?)?\s+/;
1907
+ var GANTT_DATE_RE = /^\d{4}-\d{2}-\d{2}(?:\s\d{2}:\d{2})?\s+/;
1908
+ function looksLikeGantt(content) {
1909
+ const lines = content.split("\n");
1910
+ for (const line of lines) {
1911
+ const trimmed = line.trim();
1912
+ if (!trimmed || trimmed.startsWith("//")) continue;
1913
+ if (GANTT_DURATION_RE.test(trimmed) || GANTT_DATE_RE.test(trimmed)) {
1914
+ return true;
1915
+ }
1916
+ }
1917
+ return false;
1918
+ }
1919
+ var C4_TYPE_RE = /\bis\s+an?\s+(person|system|container|component)\b/i;
1920
+ function looksLikeC4(content) {
1921
+ const lines = content.split("\n");
1922
+ for (const line of lines) {
1923
+ const trimmed = line.trim();
1924
+ if (!trimmed || trimmed.startsWith("//")) continue;
1925
+ if (C4_TYPE_RE.test(trimmed)) {
1926
+ return true;
1927
+ }
1928
+ }
1929
+ return false;
1930
+ }
1931
+ function parseDgmoChartType(content) {
1932
+ const lines = content.split("\n");
1933
+ for (const line of lines) {
1934
+ const trimmed = line.trim();
1935
+ if (!trimmed || trimmed.startsWith("//")) continue;
1936
+ const firstLineResult = parseFirstLine(trimmed);
1937
+ if (firstLineResult) return firstLineResult.chartType;
1938
+ break;
1939
+ }
1940
+ if (looksLikeSequence(content)) return "sequence";
1941
+ if (looksLikeFlowchart(content)) return "flowchart";
1942
+ if (looksLikeClassDiagram(content)) return "class";
1943
+ if (looksLikeERDiagram(content)) return "er";
1944
+ if (looksLikeState(content)) return "state";
1945
+ if (looksLikeSitemap(content)) return "sitemap";
1946
+ if (looksLikeOrg(content)) return "org";
1947
+ if (looksLikeC4(content)) return "c4";
1948
+ if (looksLikeGantt(content)) return "gantt";
1949
+ if (looksLikePert(content)) return "pert";
1950
+ return null;
1951
+ }
1952
+ function getRenderCategory(chartType) {
1953
+ return REGISTRY_BY_ID.get(chartType.toLowerCase())?.category ?? null;
1954
+ }
1955
+ function isExtendedChartType(chartType) {
1956
+ const descriptor = REGISTRY_BY_ID.get(chartType.toLowerCase());
1957
+ return descriptor ? isExtendedChartParser(descriptor.parse) : false;
1958
+ }
1959
+ function getAllChartTypes() {
1960
+ return chartTypes.map((c) => c.id);
1961
+ }
1962
+ var CHART_TYPE_DESCRIPTIONS = Object.fromEntries(chartTypes.map((c) => [c.id, c.description]));
1963
+ var chartTypeParsers = CHART_TYPE_REGISTRY.map((d) => [d.id, d.parse]);
1964
+ var knownChartTypeIds = chartTypeParsers.map(
1965
+ ([id]) => id
1966
+ );
1967
+ var PARSER_BY_ID = new Map(chartTypeParsers);
1968
+ var ALL_KNOWN_TYPES = new Set(knownChartTypeIds);
1969
+ function parseDgmo(content) {
1970
+ const result = parseDgmoUndeduped(content);
1971
+ return {
1972
+ diagnostics: dedupeDiagnostics(result.diagnostics),
1973
+ chartType: result.chartType
1974
+ };
1975
+ }
1976
+ function parseDgmoUndeduped(content) {
1977
+ const chartType = parseDgmoChartType(content);
1978
+ if (!chartType) {
1979
+ const colonDiag = detectColonChartType(content);
1980
+ if (colonDiag) {
1981
+ const fallback = parseVisualization(content).diagnostics;
1982
+ return { diagnostics: [colonDiag, ...fallback], chartType: null };
1983
+ }
1984
+ return {
1985
+ diagnostics: parseVisualization(content).diagnostics,
1986
+ chartType: null
1987
+ };
1988
+ }
1989
+ const parser = PARSER_BY_ID.get(chartType);
1990
+ if (parser) {
1991
+ const result2 = parser(content);
1992
+ return {
1993
+ diagnostics: [...result2.diagnostics, ...detectEmptyContent(content)],
1994
+ chartType
1995
+ };
1996
+ }
1997
+ const result = parseVisualization(content);
1998
+ return {
1999
+ diagnostics: [...result.diagnostics, ...detectEmptyContent(content)],
2000
+ chartType
2001
+ };
2002
+ }
2003
+ function detectColonChartType(content) {
2004
+ const lines = content.split("\n");
2005
+ for (let i = 0; i < lines.length; i++) {
2006
+ const trimmed = lines[i].trim();
2007
+ if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith("//"))
2008
+ continue;
2009
+ const match = trimmed.match(/^(\w[\w-]*)\s*:\s*(.*)$/);
2010
+ if (!match) return null;
2011
+ const word = match[1].toLowerCase();
2012
+ const rest = match[2].trim();
2013
+ if (ALL_KNOWN_TYPES.has(word)) {
2014
+ const example = rest ? `${word} ${rest}` : word;
2015
+ return makeDgmoError(
2016
+ i + 1,
2017
+ `Remove the colon \u2014 use '${example}' instead of '${trimmed}'. DGMO chart types don't use colons.`
2018
+ );
2019
+ }
2020
+ const hint = suggest(word, [...ALL_KNOWN_TYPES]);
2021
+ if (hint) {
2022
+ return makeDgmoError(
2023
+ i + 1,
2024
+ `Unknown chart type: ${word}. ${hint} Also, DGMO chart types don't use colons.`
2025
+ );
2026
+ }
2027
+ return null;
2028
+ }
2029
+ return null;
2030
+ }
2031
+ function detectEmptyContent(content) {
2032
+ const lines = content.split("\n");
2033
+ const nonEmpty = lines.filter(
2034
+ (l) => l.trim() && !l.trim().startsWith("#") && !l.trim().startsWith("//")
2035
+ );
2036
+ if (nonEmpty.length <= 1) {
2037
+ return [
2038
+ makeDgmoError(1, "No content after chart type declaration.", "warning")
2039
+ ];
2040
+ }
2041
+ return [];
2042
+ }
2043
+
2044
+ export {
2045
+ parseVisualization,
2046
+ parseSlope,
2047
+ parseArc,
2048
+ parseTimeline,
2049
+ parseWordcloud,
2050
+ parseVenn,
2051
+ parseQuadrant,
2052
+ chartTypes,
2053
+ REGISTRY_BY_ID,
2054
+ looksLikeGantt,
2055
+ looksLikeC4,
2056
+ parseDgmoChartType,
2057
+ getRenderCategory,
2058
+ isExtendedChartType,
2059
+ getAllChartTypes,
2060
+ CHART_TYPE_DESCRIPTIONS,
2061
+ chartTypeParsers,
2062
+ knownChartTypeIds,
2063
+ parseDgmo
2064
+ };
2065
+ //# sourceMappingURL=chunk-6FZYCKXB.js.map