@diagrammo/dgmo 0.14.1 → 0.15.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.
package/dist/index.cjs CHANGED
@@ -33,328 +33,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
33
33
  ));
34
34
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
35
35
 
36
- // src/diagnostics.ts
37
- function makeDgmoError(line12, message, severity = "error", code) {
38
- return code !== void 0 ? { line: line12, message, severity, code } : { line: line12, message, severity };
39
- }
40
- function formatDgmoError(err) {
41
- return err.line > 0 ? `Line ${err.line}: ${err.message}` : err.message;
42
- }
43
- function levenshtein(a, b) {
44
- const m = a.length;
45
- const n = b.length;
46
- const dp = Array(n + 1).fill(0).map((_, i) => i);
47
- for (let i = 1; i <= m; i++) {
48
- let prev = dp[0];
49
- dp[0] = i;
50
- for (let j = 1; j <= n; j++) {
51
- const tmp = dp[j];
52
- dp[j] = a[i - 1] === b[j - 1] ? prev : 1 + Math.min(prev, dp[j], dp[j - 1]);
53
- prev = tmp;
54
- }
55
- }
56
- return dp[n];
57
- }
58
- function suggest(input, candidates) {
59
- if (!input || candidates.length === 0) return null;
60
- const lower = input.toLowerCase();
61
- const threshold = Math.max(2, Math.floor(lower.length / 3));
62
- let best = null;
63
- let bestDist = Infinity;
64
- for (const c of candidates) {
65
- const dist = levenshtein(lower, c.toLowerCase());
66
- if (dist < bestDist && dist <= threshold && dist > 0) {
67
- bestDist = dist;
68
- best = c;
69
- }
70
- }
71
- return best ? `Did you mean '${best}'?` : null;
72
- }
73
- function nameMergedMessage(args) {
74
- return `merged '${args.incomingDisplay}' (line ${args.incomingLine}) into '${args.existingDisplay}' (line ${args.existingLine}) \u2014 names differ only in case/whitespace`;
75
- }
76
- function akaRemovedMessage() {
77
- return `'aka' is no longer supported \u2014 use the participant name directly`;
78
- }
79
- function tagShorthandRemovedMessage(args) {
80
- return `Bare tag shorthand 'tag ${args.name} ${args.alias}' was removed. Use 'tag ${args.name} as ${args.alias}' instead.`;
81
- }
82
- function vennAliasKeywordRemovedMessage(args) {
83
- return `Venn 'alias' keyword was removed. Use 'as' instead \u2014 '${args.name} as ${args.alias}'.`;
84
- }
85
- var NAME_DIAGNOSTIC_CODES, ALIAS_DIAGNOSTIC_CODES;
86
- var init_diagnostics = __esm({
87
- "src/diagnostics.ts"() {
88
- "use strict";
89
- NAME_DIAGNOSTIC_CODES = {
90
- /**
91
- * Warning: two source-distinct names normalized to the same key
92
- * (case- or whitespace-only difference). The first occurrence wins
93
- * for display; subsequent occurrences fold into it. Suppressible
94
- * per-line via `# allow-merge` annotation when intentional.
95
- *
96
- * Note: the `I_` prefix is intentionally preserved for stability —
97
- * callers may have pinned this string. The diagnostic emits at
98
- * `warning` severity (no `info` severity exists in DgmoError).
99
- */
100
- NAME_MERGED: "I_NAME_MERGED",
101
- /**
102
- * Error: a name contains a reserved character (`|`, `:`, edge
103
- * sigils `-> <- ~> <~ -- ..`, shape brackets `[] () {} <>`,
104
- * leading/trailing whitespace) without being wrapped in `"..."`.
105
- */
106
- NAME_RESERVED_CHAR: "E_NAME_RESERVED_CHAR",
107
- /**
108
- * Error: the removed `aka` keyword was used in a sequence
109
- * participant declaration. Forgiving normalization makes aliasing
110
- * unnecessary; the diagnostic directs users to the new syntax.
111
- */
112
- AKA_REMOVED: "E_AKA_REMOVED"
113
- };
114
- ALIAS_DIAGNOSTIC_CODES = {
115
- /** Alias token used before its declaration (strict-ordering rule). */
116
- ALIAS_BEFORE_DECL: "E_ALIAS_BEFORE_DECL",
117
- /** Same alias bound to two different canonicals. */
118
- ALIAS_COLLISION: "E_ALIAS_COLLISION",
119
- /** Alias literal matches an existing canonical name. */
120
- ALIAS_SHADOWS_NAME: "E_ALIAS_SHADOWS_NAME",
121
- /** Same canonical re-declared with a different alias. */
122
- ALIAS_REBINDING: "E_ALIAS_REBINDING",
123
- /** `pm as p` where `pm` is itself an alias — must alias the canonical. */
124
- ALIAS_OF_ALIAS: "E_ALIAS_OF_ALIAS",
125
- /** Alias matches a reserved keyword (`as`, `is`, chart-type tokens, etc.). */
126
- ALIAS_RESERVED_KEYWORD: "E_ALIAS_RESERVED_KEYWORD",
127
- /** `as` matched but token doesn't fit `[A-Za-z][A-Za-z0-9_]{0,11}`. */
128
- ALIAS_INVALID_FORMAT: "E_ALIAS_INVALID_FORMAT",
129
- /** Canonical name was used plainly before its alias declaration. */
130
- ALIAS_AFTER_CANONICAL: "E_ALIAS_AFTER_CANONICAL",
131
- /** Legacy `tag Name x` shorthand encountered — use `tag Name as x`. */
132
- TAG_SHORTHAND_REMOVED: "E_TAG_SHORTHAND_REMOVED",
133
- /** Legacy venn `Name(color) alias X` encountered — use `as`. */
134
- VENN_ALIAS_KEYWORD_REMOVED: "E_VENN_ALIAS_KEYWORD_REMOVED",
135
- /** Reference token differs from a declared alias only in case. */
136
- ALIAS_CASE_NEAR_MATCH: "W_ALIAS_CASE_NEAR_MATCH",
137
- /** Alias declared but referenced ≤1 time. */
138
- ALIAS_UNDERUSED: "W_ALIAS_UNDERUSED"
139
- };
140
- }
141
- });
142
-
143
- // src/colors.ts
144
- function isRecognizedColorName(name) {
145
- return Object.prototype.hasOwnProperty.call(colorNames, name.toLowerCase());
146
- }
147
- function resolveColor(color, palette) {
148
- if (!color) return null;
149
- if (color.startsWith("#")) return null;
150
- const lower = color.toLowerCase();
151
- if (!isRecognizedColorName(lower)) return null;
152
- if (palette) {
153
- const named = palette.colors[lower];
154
- if (named) return named;
155
- }
156
- return colorNames[lower];
157
- }
158
- function resolveColorWithDiagnostic(color, line12, diagnostics, palette) {
159
- const resolved = resolveColor(color, palette);
160
- if (resolved !== null) return resolved;
161
- const hint = suggest(color, RECOGNIZED_COLOR_NAMES);
162
- const suggestion = hint ? ` ${hint}` : "";
163
- diagnostics.push(
164
- makeDgmoError(
165
- line12,
166
- `Unknown color "${color}". Allowed: ${RECOGNIZED_COLOR_NAMES.join(", ")}.${suggestion}`,
167
- "warning"
168
- )
169
- );
170
- return void 0;
171
- }
172
- var nord, colorNames, RECOGNIZED_COLOR_NAMES, seriesColors;
173
- var init_colors = __esm({
174
- "src/colors.ts"() {
175
- "use strict";
176
- init_diagnostics();
177
- nord = {
178
- // Polar Night (dark)
179
- nord0: "#2e3440",
180
- nord1: "#3b4252",
181
- nord2: "#434c5e",
182
- nord3: "#4c566a",
183
- // Snow Storm (light)
184
- nord4: "#d8dee9",
185
- nord5: "#e5e9f0",
186
- nord6: "#eceff4",
187
- // Frost (accent blues)
188
- nord7: "#8fbcbb",
189
- nord8: "#88c0d0",
190
- nord9: "#81a1c1",
191
- nord10: "#5e81ac",
192
- // Aurora (colors)
193
- nord11: "#bf616a",
194
- // red
195
- nord12: "#d08770",
196
- // orange
197
- nord13: "#ebcb8b",
198
- // yellow
199
- nord14: "#a3be8c",
200
- // green
201
- nord15: "#b48ead"
202
- // purple
203
- };
204
- colorNames = {
205
- red: nord.nord11,
206
- orange: nord.nord12,
207
- yellow: nord.nord13,
208
- green: nord.nord14,
209
- blue: nord.nord10,
210
- purple: nord.nord15,
211
- teal: nord.nord7,
212
- cyan: nord.nord8,
213
- gray: nord.nord3,
214
- black: nord.nord0,
215
- white: nord.nord6
216
- };
217
- RECOGNIZED_COLOR_NAMES = Object.freeze([
218
- "red",
219
- "orange",
220
- "yellow",
221
- "green",
222
- "blue",
223
- "purple",
224
- "teal",
225
- "cyan",
226
- "gray",
227
- "black",
228
- "white"
229
- ]);
230
- seriesColors = [
231
- nord.nord10,
232
- // blue
233
- nord.nord14,
234
- // green
235
- nord.nord13,
236
- // yellow
237
- nord.nord12,
238
- // orange
239
- nord.nord15,
240
- // purple
241
- nord.nord11,
242
- // red
243
- nord.nord7,
244
- // teal
245
- nord.nord8
246
- // light blue
247
- ];
248
- }
249
- });
250
-
251
- // src/utils/arrows.ts
252
- function validateLabelCharacters(label, lineNumber) {
253
- const out = [];
254
- if (label.includes("->") || label.includes("~>")) {
255
- out.push(
256
- makeDgmoError(
257
- lineNumber,
258
- 'Arrow symbols (-> or ~>) are not allowed inside a label. Move the label after the arrow: "A -> B: uses -> to chain". See "In-Arrow Message Labels" \u2192 Forbidden.',
259
- "error",
260
- ARROW_DIAGNOSTIC_CODES.ARROW_SUBSTRING_IN_LABEL
261
- )
262
- );
263
- }
264
- for (const ch of label) {
265
- const cp = ch.codePointAt(0);
266
- const isC0 = cp >= 0 && cp <= 31 && cp !== 9;
267
- const isDel = cp === 127;
268
- if (isC0 || isDel) {
269
- const hex = cp.toString(16).toUpperCase().padStart(4, "0");
270
- out.push(
271
- makeDgmoError(
272
- lineNumber,
273
- `Label contains a control character (U+${hex}). Remove it and use plain text.`,
274
- "error",
275
- ARROW_DIAGNOSTIC_CODES.CONTROL_CHAR_IN_LABEL
276
- )
277
- );
278
- break;
279
- }
280
- }
281
- return out;
282
- }
283
- function parseInArrowLabel(rawLabel, lineNumber) {
284
- const trimmed = rawLabel.trim();
285
- if (trimmed.length === 0) {
286
- return { label: void 0, diagnostics: [] };
287
- }
288
- const diagnostics = validateLabelCharacters(trimmed, lineNumber);
289
- return { label: trimmed, diagnostics };
290
- }
291
- function matchColorParens(content) {
292
- const m = content.match(/^\(([A-Za-z]+)\)$/);
293
- if (!m) return null;
294
- const candidate = m[1].toLowerCase();
295
- if (RECOGNIZED_COLOR_NAMES.includes(candidate)) {
296
- return candidate;
297
- }
298
- return null;
299
- }
300
- function parseArrow(line12) {
301
- if (BIDI_SYNC_RE.test(line12) || BIDI_ASYNC_RE.test(line12)) {
302
- return {
303
- error: "Bidirectional arrows are no longer supported. Use two separate lines: 'A -msg-> B' and 'B -msg-> A'"
304
- };
305
- }
306
- if (RETURN_SYNC_LABELED_RE.test(line12) || RETURN_ASYNC_LABELED_RE.test(line12)) {
307
- const m = line12.match(RETURN_SYNC_LABELED_RE) ?? line12.match(RETURN_ASYNC_LABELED_RE);
308
- const from = m[3];
309
- const to = m[1];
310
- const label = m[2].trim();
311
- return {
312
- error: `Left-pointing arrows are no longer supported. Write '${from} -${label}-> ${to}' instead`
313
- };
314
- }
315
- const patterns = [
316
- { re: SYNC_LABELED_RE, async: false },
317
- { re: ASYNC_LABELED_RE, async: true }
318
- ];
319
- for (const { re, async: isAsync } of patterns) {
320
- const m = line12.match(re);
321
- if (!m) continue;
322
- const label = m[2].trim();
323
- if (!label) return null;
324
- return {
325
- from: m[1],
326
- to: m[3],
327
- label,
328
- async: isAsync
329
- };
330
- }
331
- return null;
332
- }
333
- var ARROW_DIAGNOSTIC_CODES, SYNC_LABELED_RE, ASYNC_LABELED_RE, RETURN_SYNC_LABELED_RE, RETURN_ASYNC_LABELED_RE, BIDI_SYNC_RE, BIDI_ASYNC_RE;
334
- var init_arrows = __esm({
335
- "src/utils/arrows.ts"() {
336
- "use strict";
337
- init_diagnostics();
338
- init_colors();
339
- ARROW_DIAGNOSTIC_CODES = {
340
- /** Active: label contains `->` or `~>` substring (TD-13). */
341
- ARROW_SUBSTRING_IN_LABEL: "E_ARROW_SUBSTRING_IN_LABEL",
342
- /** Active: label contains a forbidden control character (TD-14). */
343
- CONTROL_CHAR_IN_LABEL: "E_CONTROL_CHAR_IN_LABEL",
344
- /** Reserved: not currently emitted by any parser. See JSDoc above. */
345
- TRAILING_ARROW_TEXT: "E_TRAILING_ARROW_TEXT",
346
- /** Reserved: not currently emitted by any parser. See JSDoc above. */
347
- MIXED_ARROW_DELIMITERS: "E_MIXED_ARROW_DELIMITERS"
348
- };
349
- SYNC_LABELED_RE = /^(.+?)\s*-(.+)->\s*(.+)$/;
350
- ASYNC_LABELED_RE = /^(.+?)\s*~(.+)~>\s*(.+)$/;
351
- RETURN_SYNC_LABELED_RE = /^(.+?)\s*<-(.+)-\s*(.+)$/;
352
- RETURN_ASYNC_LABELED_RE = /^(.+?)\s*<~(.+)~\s*(.+)$/;
353
- BIDI_SYNC_RE = /^(.+?)\s*<-(.+)->\s*(.+)$/;
354
- BIDI_ASYNC_RE = /^(.+?)\s*<~(.+)~>\s*(.+)$/;
355
- }
356
- });
357
-
358
36
  // src/fonts.ts
359
37
  var FONT_FAMILY;
360
38
  var init_fonts = __esm({
@@ -697,104 +375,319 @@ var init_time_ticks = __esm({
697
375
  }
698
376
  });
699
377
 
700
- // src/palettes/registry.ts
701
- function isValidHex(value) {
702
- return /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(value);
378
+ // src/diagnostics.ts
379
+ function makeDgmoError(line12, message, severity = "error", code) {
380
+ return code !== void 0 ? { line: line12, message, severity, code } : { line: line12, message, severity };
703
381
  }
704
- function validatePaletteColors(colors, mode, paletteId) {
705
- for (const key of SEMANTIC_KEYS) {
706
- const value = colors[key];
707
- if (typeof value !== "string" || !isValidHex(value)) {
708
- throw new Error(
709
- `Palette "${paletteId}" ${mode}.${key}: invalid hex "${value}"`
710
- );
382
+ function formatDgmoError(err) {
383
+ return err.line > 0 ? `Line ${err.line}: ${err.message}` : err.message;
384
+ }
385
+ function levenshtein(a, b) {
386
+ const m = a.length;
387
+ const n = b.length;
388
+ const dp = Array(n + 1).fill(0).map((_, i) => i);
389
+ for (let i = 1; i <= m; i++) {
390
+ let prev = dp[0];
391
+ dp[0] = i;
392
+ for (let j = 1; j <= n; j++) {
393
+ const tmp = dp[j];
394
+ dp[j] = a[i - 1] === b[j - 1] ? prev : 1 + Math.min(prev, dp[j], dp[j - 1]);
395
+ prev = tmp;
711
396
  }
712
397
  }
713
- for (const key of COLOR_KEYS) {
714
- const value = colors.colors[key];
715
- if (typeof value !== "string" || !isValidHex(value)) {
716
- throw new Error(
717
- `Palette "${paletteId}" ${mode}.colors.${key}: invalid hex "${value}"`
718
- );
398
+ return dp[n];
399
+ }
400
+ function suggest(input, candidates) {
401
+ if (!input || candidates.length === 0) return null;
402
+ const lower = input.toLowerCase();
403
+ const threshold = Math.max(2, Math.floor(lower.length / 3));
404
+ let best = null;
405
+ let bestDist = Infinity;
406
+ for (const c of candidates) {
407
+ const dist = levenshtein(lower, c.toLowerCase());
408
+ if (dist < bestDist && dist <= threshold && dist > 0) {
409
+ bestDist = dist;
410
+ best = c;
719
411
  }
720
412
  }
413
+ return best ? `Did you mean '${best}'?` : null;
721
414
  }
722
- function registerPalette(palette) {
723
- validatePaletteColors(palette.light, "light", palette.id);
724
- validatePaletteColors(palette.dark, "dark", palette.id);
725
- PALETTE_REGISTRY.set(palette.id, palette);
415
+ function nameMergedMessage(args) {
416
+ return `merged '${args.incomingDisplay}' (line ${args.incomingLine}) into '${args.existingDisplay}' (line ${args.existingLine}) \u2014 names differ only in case/whitespace`;
726
417
  }
727
- function getPalette(id) {
728
- return PALETTE_REGISTRY.get(id) ?? PALETTE_REGISTRY.get(DEFAULT_PALETTE_ID);
418
+ function akaRemovedMessage() {
419
+ return `'aka' is no longer supported \u2014 use the participant name directly`;
729
420
  }
730
- function getAvailablePalettes() {
731
- return Array.from(PALETTE_REGISTRY.values()).sort(
732
- (a, b) => a.name.localeCompare(b.name)
733
- );
421
+ function tagShorthandRemovedMessage(args) {
422
+ return `Bare tag shorthand 'tag ${args.name} ${args.alias}' was removed. Use 'tag ${args.name} as ${args.alias}' instead.`;
734
423
  }
735
- var PALETTE_REGISTRY, DEFAULT_PALETTE_ID, COLOR_KEYS, SEMANTIC_KEYS;
736
- var init_registry = __esm({
737
- "src/palettes/registry.ts"() {
424
+ function vennAliasKeywordRemovedMessage(args) {
425
+ return `Venn 'alias' keyword was removed. Use 'as' instead \u2014 '${args.name} as ${args.alias}'.`;
426
+ }
427
+ var NAME_DIAGNOSTIC_CODES, ALIAS_DIAGNOSTIC_CODES;
428
+ var init_diagnostics = __esm({
429
+ "src/diagnostics.ts"() {
738
430
  "use strict";
739
- PALETTE_REGISTRY = /* @__PURE__ */ new Map();
740
- DEFAULT_PALETTE_ID = "nord";
741
- COLOR_KEYS = [
742
- "red",
743
- "orange",
744
- "yellow",
745
- "green",
746
- "blue",
747
- "purple",
748
- "teal",
749
- "cyan",
750
- "gray"
751
- ];
752
- SEMANTIC_KEYS = [
753
- "bg",
754
- "surface",
755
- "overlay",
756
- "border",
757
- "text",
758
- "textMuted",
759
- "primary",
760
- "secondary",
761
- "accent",
762
- "destructive"
763
- ];
431
+ NAME_DIAGNOSTIC_CODES = {
432
+ /**
433
+ * Warning: two source-distinct names normalized to the same key
434
+ * (case- or whitespace-only difference). The first occurrence wins
435
+ * for display; subsequent occurrences fold into it. Suppressible
436
+ * per-line via `# allow-merge` annotation when intentional.
437
+ *
438
+ * Note: the `I_` prefix is intentionally preserved for stability —
439
+ * callers may have pinned this string. The diagnostic emits at
440
+ * `warning` severity (no `info` severity exists in DgmoError).
441
+ */
442
+ NAME_MERGED: "I_NAME_MERGED",
443
+ /**
444
+ * Error: a name contains a reserved character (`|`, `:`, edge
445
+ * sigils `-> <- ~> <~ -- ..`, shape brackets `[] () {} <>`,
446
+ * leading/trailing whitespace) without being wrapped in `"..."`.
447
+ */
448
+ NAME_RESERVED_CHAR: "E_NAME_RESERVED_CHAR",
449
+ /**
450
+ * Error: the removed `aka` keyword was used in a sequence
451
+ * participant declaration. Forgiving normalization makes aliasing
452
+ * unnecessary; the diagnostic directs users to the new syntax.
453
+ */
454
+ AKA_REMOVED: "E_AKA_REMOVED"
455
+ };
456
+ ALIAS_DIAGNOSTIC_CODES = {
457
+ /** Alias token used before its declaration (strict-ordering rule). */
458
+ ALIAS_BEFORE_DECL: "E_ALIAS_BEFORE_DECL",
459
+ /** Same alias bound to two different canonicals. */
460
+ ALIAS_COLLISION: "E_ALIAS_COLLISION",
461
+ /** Alias literal matches an existing canonical name. */
462
+ ALIAS_SHADOWS_NAME: "E_ALIAS_SHADOWS_NAME",
463
+ /** Same canonical re-declared with a different alias. */
464
+ ALIAS_REBINDING: "E_ALIAS_REBINDING",
465
+ /** `pm as p` where `pm` is itself an alias — must alias the canonical. */
466
+ ALIAS_OF_ALIAS: "E_ALIAS_OF_ALIAS",
467
+ /** Alias matches a reserved keyword (`as`, `is`, chart-type tokens, etc.). */
468
+ ALIAS_RESERVED_KEYWORD: "E_ALIAS_RESERVED_KEYWORD",
469
+ /** `as` matched but token doesn't fit `[A-Za-z][A-Za-z0-9_]{0,11}`. */
470
+ ALIAS_INVALID_FORMAT: "E_ALIAS_INVALID_FORMAT",
471
+ /** Canonical name was used plainly before its alias declaration. */
472
+ ALIAS_AFTER_CANONICAL: "E_ALIAS_AFTER_CANONICAL",
473
+ /** Legacy `tag Name x` shorthand encountered — use `tag Name as x`. */
474
+ TAG_SHORTHAND_REMOVED: "E_TAG_SHORTHAND_REMOVED",
475
+ /** Legacy venn `Name(color) alias X` encountered — use `as`. */
476
+ VENN_ALIAS_KEYWORD_REMOVED: "E_VENN_ALIAS_KEYWORD_REMOVED",
477
+ /** Reference token differs from a declared alias only in case. */
478
+ ALIAS_CASE_NEAR_MATCH: "W_ALIAS_CASE_NEAR_MATCH",
479
+ /** Alias declared but referenced ≤1 time. */
480
+ ALIAS_UNDERUSED: "W_ALIAS_UNDERUSED"
481
+ };
764
482
  }
765
483
  });
766
484
 
767
- // src/palettes/color-utils.ts
768
- function hexToHSL(hex) {
769
- const raw = hex.replace("#", "");
770
- const full = raw.length === 3 ? raw[0] + raw[0] + raw[1] + raw[1] + raw[2] + raw[2] : raw;
771
- const r = parseInt(full.substring(0, 2), 16) / 255;
772
- const g = parseInt(full.substring(2, 4), 16) / 255;
773
- const b = parseInt(full.substring(4, 6), 16) / 255;
774
- const max = Math.max(r, g, b);
775
- const min = Math.min(r, g, b);
776
- const l = (max + min) / 2;
777
- if (max === min) {
778
- return { h: 0, s: 0, l: Math.round(l * 100) };
779
- }
780
- const d = max - min;
781
- const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
782
- let h;
783
- if (max === r) {
784
- h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
785
- } else if (max === g) {
786
- h = ((b - r) / d + 2) / 6;
787
- } else {
788
- h = ((r - g) / d + 4) / 6;
485
+ // src/colors.ts
486
+ function isRecognizedColorName(name) {
487
+ return Object.prototype.hasOwnProperty.call(colorNames, name.toLowerCase());
488
+ }
489
+ function resolveColor(color, palette) {
490
+ if (!color) return null;
491
+ if (color.startsWith("#")) return null;
492
+ const lower = color.toLowerCase();
493
+ if (!isRecognizedColorName(lower)) return null;
494
+ if (palette) {
495
+ const named = palette.colors[lower];
496
+ if (named) return named;
789
497
  }
790
- return {
791
- h: Math.round(h * 360),
792
- s: Math.round(s * 100),
793
- l: Math.round(l * 100)
794
- };
498
+ return colorNames[lower];
795
499
  }
796
- function hslToHex(h, s, l) {
797
- const sNorm = s / 100;
500
+ function resolveColorWithDiagnostic(color, line12, diagnostics, palette) {
501
+ const resolved = resolveColor(color, palette);
502
+ if (resolved !== null) return resolved;
503
+ const hint = suggest(color, RECOGNIZED_COLOR_NAMES);
504
+ const suggestion = hint ? ` ${hint}` : "";
505
+ diagnostics.push(
506
+ makeDgmoError(
507
+ line12,
508
+ `Unknown color "${color}". Allowed: ${RECOGNIZED_COLOR_NAMES.join(", ")}.${suggestion}`,
509
+ "warning"
510
+ )
511
+ );
512
+ return void 0;
513
+ }
514
+ var nord, colorNames, RECOGNIZED_COLOR_NAMES, seriesColors;
515
+ var init_colors = __esm({
516
+ "src/colors.ts"() {
517
+ "use strict";
518
+ init_diagnostics();
519
+ nord = {
520
+ // Polar Night (dark)
521
+ nord0: "#2e3440",
522
+ nord1: "#3b4252",
523
+ nord2: "#434c5e",
524
+ nord3: "#4c566a",
525
+ // Snow Storm (light)
526
+ nord4: "#d8dee9",
527
+ nord5: "#e5e9f0",
528
+ nord6: "#eceff4",
529
+ // Frost (accent blues)
530
+ nord7: "#8fbcbb",
531
+ nord8: "#88c0d0",
532
+ nord9: "#81a1c1",
533
+ nord10: "#5e81ac",
534
+ // Aurora (colors)
535
+ nord11: "#bf616a",
536
+ // red
537
+ nord12: "#d08770",
538
+ // orange
539
+ nord13: "#ebcb8b",
540
+ // yellow
541
+ nord14: "#a3be8c",
542
+ // green
543
+ nord15: "#b48ead"
544
+ // purple
545
+ };
546
+ colorNames = {
547
+ red: nord.nord11,
548
+ orange: nord.nord12,
549
+ yellow: nord.nord13,
550
+ green: nord.nord14,
551
+ blue: nord.nord10,
552
+ purple: nord.nord15,
553
+ teal: nord.nord7,
554
+ cyan: nord.nord8,
555
+ gray: nord.nord3,
556
+ black: nord.nord0,
557
+ white: nord.nord6
558
+ };
559
+ RECOGNIZED_COLOR_NAMES = Object.freeze([
560
+ "red",
561
+ "orange",
562
+ "yellow",
563
+ "green",
564
+ "blue",
565
+ "purple",
566
+ "teal",
567
+ "cyan",
568
+ "gray",
569
+ "black",
570
+ "white"
571
+ ]);
572
+ seriesColors = [
573
+ nord.nord10,
574
+ // blue
575
+ nord.nord14,
576
+ // green
577
+ nord.nord13,
578
+ // yellow
579
+ nord.nord12,
580
+ // orange
581
+ nord.nord15,
582
+ // purple
583
+ nord.nord11,
584
+ // red
585
+ nord.nord7,
586
+ // teal
587
+ nord.nord8
588
+ // light blue
589
+ ];
590
+ }
591
+ });
592
+
593
+ // src/palettes/registry.ts
594
+ function isValidHex(value) {
595
+ return /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(value);
596
+ }
597
+ function validatePaletteColors(colors, mode, paletteId) {
598
+ for (const key of SEMANTIC_KEYS) {
599
+ const value = colors[key];
600
+ if (typeof value !== "string" || !isValidHex(value)) {
601
+ throw new Error(
602
+ `Palette "${paletteId}" ${mode}.${key}: invalid hex "${value}"`
603
+ );
604
+ }
605
+ }
606
+ for (const key of COLOR_KEYS) {
607
+ const value = colors.colors[key];
608
+ if (typeof value !== "string" || !isValidHex(value)) {
609
+ throw new Error(
610
+ `Palette "${paletteId}" ${mode}.colors.${key}: invalid hex "${value}"`
611
+ );
612
+ }
613
+ }
614
+ }
615
+ function registerPalette(palette) {
616
+ validatePaletteColors(palette.light, "light", palette.id);
617
+ validatePaletteColors(palette.dark, "dark", palette.id);
618
+ PALETTE_REGISTRY.set(palette.id, palette);
619
+ }
620
+ function getPalette(id) {
621
+ return PALETTE_REGISTRY.get(id) ?? PALETTE_REGISTRY.get(DEFAULT_PALETTE_ID);
622
+ }
623
+ function getAvailablePalettes() {
624
+ return Array.from(PALETTE_REGISTRY.values()).sort(
625
+ (a, b) => a.name.localeCompare(b.name)
626
+ );
627
+ }
628
+ var PALETTE_REGISTRY, DEFAULT_PALETTE_ID, COLOR_KEYS, SEMANTIC_KEYS;
629
+ var init_registry = __esm({
630
+ "src/palettes/registry.ts"() {
631
+ "use strict";
632
+ PALETTE_REGISTRY = /* @__PURE__ */ new Map();
633
+ DEFAULT_PALETTE_ID = "nord";
634
+ COLOR_KEYS = [
635
+ "red",
636
+ "orange",
637
+ "yellow",
638
+ "green",
639
+ "blue",
640
+ "purple",
641
+ "teal",
642
+ "cyan",
643
+ "gray"
644
+ ];
645
+ SEMANTIC_KEYS = [
646
+ "bg",
647
+ "surface",
648
+ "overlay",
649
+ "border",
650
+ "text",
651
+ "textMuted",
652
+ "primary",
653
+ "secondary",
654
+ "accent",
655
+ "destructive"
656
+ ];
657
+ }
658
+ });
659
+
660
+ // src/palettes/color-utils.ts
661
+ function hexToHSL(hex) {
662
+ const raw = hex.replace("#", "");
663
+ const full = raw.length === 3 ? raw[0] + raw[0] + raw[1] + raw[1] + raw[2] + raw[2] : raw;
664
+ const r = parseInt(full.substring(0, 2), 16) / 255;
665
+ const g = parseInt(full.substring(2, 4), 16) / 255;
666
+ const b = parseInt(full.substring(4, 6), 16) / 255;
667
+ const max = Math.max(r, g, b);
668
+ const min = Math.min(r, g, b);
669
+ const l = (max + min) / 2;
670
+ if (max === min) {
671
+ return { h: 0, s: 0, l: Math.round(l * 100) };
672
+ }
673
+ const d = max - min;
674
+ const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
675
+ let h;
676
+ if (max === r) {
677
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
678
+ } else if (max === g) {
679
+ h = ((b - r) / d + 2) / 6;
680
+ } else {
681
+ h = ((r - g) / d + 4) / 6;
682
+ }
683
+ return {
684
+ h: Math.round(h * 360),
685
+ s: Math.round(s * 100),
686
+ l: Math.round(l * 100)
687
+ };
688
+ }
689
+ function hslToHex(h, s, l) {
690
+ const sNorm = s / 100;
798
691
  const lNorm = l / 100;
799
692
  if (sNorm === 0) {
800
693
  const v = Math.round(lNorm * 255);
@@ -1868,6 +1761,7 @@ __export(palettes_exports, {
1868
1761
  monokaiPalette: () => monokaiPalette,
1869
1762
  nordPalette: () => nordPalette,
1870
1763
  oneDarkPalette: () => oneDarkPalette,
1764
+ palettes: () => palettes,
1871
1765
  registerPalette: () => registerPalette,
1872
1766
  rosePinePalette: () => rosePinePalette,
1873
1767
  shade: () => shade,
@@ -1876,6 +1770,7 @@ __export(palettes_exports, {
1876
1770
  tint: () => tint,
1877
1771
  tokyoNightPalette: () => tokyoNightPalette
1878
1772
  });
1773
+ var palettes;
1879
1774
  var init_palettes = __esm({
1880
1775
  "src/palettes/index.ts"() {
1881
1776
  "use strict";
@@ -1891,6 +1786,28 @@ var init_palettes = __esm({
1891
1786
  init_tokyo_night();
1892
1787
  init_dracula();
1893
1788
  init_monokai();
1789
+ init_bold();
1790
+ init_catppuccin();
1791
+ init_dracula();
1792
+ init_gruvbox();
1793
+ init_monokai();
1794
+ init_nord();
1795
+ init_one_dark();
1796
+ init_rose_pine();
1797
+ init_solarized();
1798
+ init_tokyo_night();
1799
+ palettes = {
1800
+ nord: nordPalette,
1801
+ catppuccin: catppuccinPalette,
1802
+ solarized: solarizedPalette,
1803
+ gruvbox: gruvboxPalette,
1804
+ tokyoNight: tokyoNightPalette,
1805
+ oneDark: oneDarkPalette,
1806
+ rosePine: rosePinePalette,
1807
+ dracula: draculaPalette,
1808
+ monokai: monokaiPalette,
1809
+ bold: boldPalette
1810
+ };
1894
1811
  }
1895
1812
  });
1896
1813
 
@@ -2895,10 +2812,6 @@ function centerRowItems(items, containerWidth, totalControlsW, controlsGroupW =
2895
2812
  x += item.width + LEGEND_GROUP_GAP;
2896
2813
  }
2897
2814
  }
2898
- function getLegendReservedHeight(config, state, containerWidth) {
2899
- const layout = computeLegendLayout(config, state, containerWidth);
2900
- return layout.height;
2901
- }
2902
2815
  var CONTROL_PILL_PAD, CONTROL_FONT_SIZE, CONTROL_ICON_GAP, CONTROL_GAP;
2903
2816
  var init_legend_layout = __esm({
2904
2817
  "src/utils/legend-layout.ts"() {
@@ -2917,7 +2830,7 @@ function renderLegendD3(container, config, state, palette, isDark, callbacks, co
2917
2830
  let currentState = { ...state };
2918
2831
  let currentLayout;
2919
2832
  const legendG = container.append("g").attr("class", "dgmo-legend");
2920
- function render2() {
2833
+ function render3() {
2921
2834
  currentLayout = computeLegendLayout(config, currentState, width);
2922
2835
  legendG.selectAll("*").remove();
2923
2836
  if (currentLayout.height === 0) return;
@@ -2968,11 +2881,11 @@ function renderLegendD3(container, config, state, palette, isDark, callbacks, co
2968
2881
  );
2969
2882
  }
2970
2883
  }
2971
- render2();
2884
+ render3();
2972
2885
  return {
2973
2886
  setState(newState) {
2974
2887
  currentState = { ...newState };
2975
- render2();
2888
+ render3();
2976
2889
  },
2977
2890
  destroy() {
2978
2891
  legendG.remove();
@@ -3430,38 +3343,6 @@ function normalizeName(input) {
3430
3343
  function displayName(input) {
3431
3344
  return input.normalize("NFC").trim();
3432
3345
  }
3433
- function getOrCreateName(input, store, lineNumber, aliasStore) {
3434
- if (aliasStore !== void 0) {
3435
- const aliased = aliasStore.get(input.trim());
3436
- if (aliased !== void 0) {
3437
- return { entry: aliased, created: false };
3438
- }
3439
- }
3440
- const key = normalizeName(input);
3441
- const incomingDisplay = displayName(input);
3442
- const existing = store.get(key);
3443
- if (existing) {
3444
- if (existing.displayLabel !== incomingDisplay) {
3445
- return {
3446
- entry: existing,
3447
- created: false,
3448
- merged: {
3449
- existingLine: existing.declaredLine,
3450
- existingDisplay: existing.displayLabel,
3451
- incomingDisplay
3452
- }
3453
- };
3454
- }
3455
- return { entry: existing, created: false };
3456
- }
3457
- const entry = {
3458
- normalizedKey: key,
3459
- displayLabel: incomingDisplay,
3460
- declaredLine: lineNumber
3461
- };
3462
- store.set(key, entry);
3463
- return { entry, created: true };
3464
- }
3465
3346
  var WHITESPACE_RUN_RE;
3466
3347
  var init_name_normalize = __esm({
3467
3348
  "src/utils/name-normalize.ts"() {
@@ -3470,6 +3351,113 @@ var init_name_normalize = __esm({
3470
3351
  }
3471
3352
  });
3472
3353
 
3354
+ // src/utils/arrows.ts
3355
+ function validateLabelCharacters(label, lineNumber) {
3356
+ const out = [];
3357
+ if (label.includes("->") || label.includes("~>")) {
3358
+ out.push(
3359
+ makeDgmoError(
3360
+ lineNumber,
3361
+ 'Arrow symbols (-> or ~>) are not allowed inside a label. Move the label after the arrow: "A -> B: uses -> to chain". See "In-Arrow Message Labels" \u2192 Forbidden.',
3362
+ "error",
3363
+ ARROW_DIAGNOSTIC_CODES.ARROW_SUBSTRING_IN_LABEL
3364
+ )
3365
+ );
3366
+ }
3367
+ for (const ch of label) {
3368
+ const cp = ch.codePointAt(0);
3369
+ const isC0 = cp >= 0 && cp <= 31 && cp !== 9;
3370
+ const isDel = cp === 127;
3371
+ if (isC0 || isDel) {
3372
+ const hex = cp.toString(16).toUpperCase().padStart(4, "0");
3373
+ out.push(
3374
+ makeDgmoError(
3375
+ lineNumber,
3376
+ `Label contains a control character (U+${hex}). Remove it and use plain text.`,
3377
+ "error",
3378
+ ARROW_DIAGNOSTIC_CODES.CONTROL_CHAR_IN_LABEL
3379
+ )
3380
+ );
3381
+ break;
3382
+ }
3383
+ }
3384
+ return out;
3385
+ }
3386
+ function parseInArrowLabel(rawLabel, lineNumber) {
3387
+ const trimmed = rawLabel.trim();
3388
+ if (trimmed.length === 0) {
3389
+ return { label: void 0, diagnostics: [] };
3390
+ }
3391
+ const diagnostics = validateLabelCharacters(trimmed, lineNumber);
3392
+ return { label: trimmed, diagnostics };
3393
+ }
3394
+ function matchColorParens(content) {
3395
+ const m = content.match(/^\(([A-Za-z]+)\)$/);
3396
+ if (!m) return null;
3397
+ const candidate = m[1].toLowerCase();
3398
+ if (RECOGNIZED_COLOR_NAMES.includes(candidate)) {
3399
+ return candidate;
3400
+ }
3401
+ return null;
3402
+ }
3403
+ function parseArrow(line12) {
3404
+ if (BIDI_SYNC_RE.test(line12) || BIDI_ASYNC_RE.test(line12)) {
3405
+ return {
3406
+ error: "Bidirectional arrows are no longer supported. Use two separate lines: 'A -msg-> B' and 'B -msg-> A'"
3407
+ };
3408
+ }
3409
+ if (RETURN_SYNC_LABELED_RE.test(line12) || RETURN_ASYNC_LABELED_RE.test(line12)) {
3410
+ const m = line12.match(RETURN_SYNC_LABELED_RE) ?? line12.match(RETURN_ASYNC_LABELED_RE);
3411
+ const from = m[3];
3412
+ const to = m[1];
3413
+ const label = m[2].trim();
3414
+ return {
3415
+ error: `Left-pointing arrows are no longer supported. Write '${from} -${label}-> ${to}' instead`
3416
+ };
3417
+ }
3418
+ const patterns = [
3419
+ { re: SYNC_LABELED_RE, async: false },
3420
+ { re: ASYNC_LABELED_RE, async: true }
3421
+ ];
3422
+ for (const { re, async: isAsync } of patterns) {
3423
+ const m = line12.match(re);
3424
+ if (!m) continue;
3425
+ const label = m[2].trim();
3426
+ if (!label) return null;
3427
+ return {
3428
+ from: m[1],
3429
+ to: m[3],
3430
+ label,
3431
+ async: isAsync
3432
+ };
3433
+ }
3434
+ return null;
3435
+ }
3436
+ var ARROW_DIAGNOSTIC_CODES, SYNC_LABELED_RE, ASYNC_LABELED_RE, RETURN_SYNC_LABELED_RE, RETURN_ASYNC_LABELED_RE, BIDI_SYNC_RE, BIDI_ASYNC_RE;
3437
+ var init_arrows = __esm({
3438
+ "src/utils/arrows.ts"() {
3439
+ "use strict";
3440
+ init_diagnostics();
3441
+ init_colors();
3442
+ ARROW_DIAGNOSTIC_CODES = {
3443
+ /** Active: label contains `->` or `~>` substring (TD-13). */
3444
+ ARROW_SUBSTRING_IN_LABEL: "E_ARROW_SUBSTRING_IN_LABEL",
3445
+ /** Active: label contains a forbidden control character (TD-14). */
3446
+ CONTROL_CHAR_IN_LABEL: "E_CONTROL_CHAR_IN_LABEL",
3447
+ /** Reserved: not currently emitted by any parser. See JSDoc above. */
3448
+ TRAILING_ARROW_TEXT: "E_TRAILING_ARROW_TEXT",
3449
+ /** Reserved: not currently emitted by any parser. See JSDoc above. */
3450
+ MIXED_ARROW_DELIMITERS: "E_MIXED_ARROW_DELIMITERS"
3451
+ };
3452
+ SYNC_LABELED_RE = /^(.+?)\s*-(.+)->\s*(.+)$/;
3453
+ ASYNC_LABELED_RE = /^(.+?)\s*~(.+)~>\s*(.+)$/;
3454
+ RETURN_SYNC_LABELED_RE = /^(.+?)\s*<-(.+)-\s*(.+)$/;
3455
+ RETURN_ASYNC_LABELED_RE = /^(.+?)\s*<~(.+)~\s*(.+)$/;
3456
+ BIDI_SYNC_RE = /^(.+?)\s*<-(.+)->\s*(.+)$/;
3457
+ BIDI_ASYNC_RE = /^(.+?)\s*<~(.+)~>\s*(.+)$/;
3458
+ }
3459
+ });
3460
+
3473
3461
  // src/sequence/parser.ts
3474
3462
  var parser_exports = {};
3475
3463
  __export(parser_exports, {
@@ -6566,19 +6554,6 @@ function renderLegendSvg(groups, options) {
6566
6554
  const svg = `<g${classAttr}${activeAttr}>${parts.join("")}</g>`;
6567
6555
  return { svg, height: LEGEND_HEIGHT, width: totalWidth };
6568
6556
  }
6569
- function renderLegendSvgFromConfig(config, state, palette, containerWidth) {
6570
- return renderLegendSvg(config.groups, {
6571
- palette: {
6572
- bg: palette.bg,
6573
- surface: palette.surface,
6574
- text: palette.text,
6575
- textMuted: palette.textMuted
6576
- },
6577
- isDark: palette.isDark,
6578
- containerWidth,
6579
- activeGroup: state.activeGroup
6580
- });
6581
- }
6582
6557
  var init_legend_svg = __esm({
6583
6558
  "src/utils/legend-svg.ts"() {
6584
6559
  "use strict";
@@ -10941,6 +10916,17 @@ function parseInfra(content) {
10941
10916
  if (!m) return { label: trimmed };
10942
10917
  return { label: m[1].trim(), alias: m[2] };
10943
10918
  }
10919
+ const IS_A_SUFFIX = /^(.*?)\s+is\s+an?\s+[A-Za-z][\w-]*\s*$/i;
10920
+ function peelInfraDecorations(rawName, lineNumber) {
10921
+ const peeled = peelAlias2(rawName);
10922
+ const m = peeled.label.match(IS_A_SUFFIX);
10923
+ if (!m) return peeled;
10924
+ warn(
10925
+ lineNumber,
10926
+ `Infra nodes don't use 'is a <type>' \u2014 types are inferred from properties (cache-hit, buffer, drain-rate, \u2026). Drop the 'is a' suffix.`
10927
+ );
10928
+ return { label: m[1].trim(), alias: peeled.alias };
10929
+ }
10944
10930
  function resolveTargetId(rawName) {
10945
10931
  const aliasResolved = nameAliasMap.get(rawName.trim());
10946
10932
  if (aliasResolved !== void 0) return aliasResolved;
@@ -11095,7 +11081,7 @@ function parseInfra(content) {
11095
11081
  finishCurrentNode();
11096
11082
  finishCurrentTagGroup();
11097
11083
  const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
11098
- const peeled = peelAlias2(rawName);
11084
+ const peeled = peelInfraDecorations(rawName, lineNumber);
11099
11085
  const name = peeled.label;
11100
11086
  const rest = compMatch[3] || "";
11101
11087
  const { tags } = extractPipeMetadata(rest);
@@ -11166,7 +11152,7 @@ function parseInfra(content) {
11166
11152
  if (compMatch) {
11167
11153
  finishCurrentTagGroup();
11168
11154
  const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
11169
- const peeled = peelAlias2(rawName);
11155
+ const peeled = peelInfraDecorations(rawName, lineNumber);
11170
11156
  const name = peeled.label;
11171
11157
  const rest = compMatch[3] || "";
11172
11158
  const { tags: nodeTags } = extractPipeMetadata(rest);
@@ -11385,7 +11371,7 @@ function parseInfra(content) {
11385
11371
  const compMatch = trimmed.match(COMPONENT_RE);
11386
11372
  if (compMatch) {
11387
11373
  const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
11388
- const peeled = peelAlias2(rawName);
11374
+ const peeled = peelInfraDecorations(rawName, lineNumber);
11389
11375
  const name = peeled.label;
11390
11376
  const rest = compMatch[3] || "";
11391
11377
  const { tags: nodeTags } = extractPipeMetadata(rest);
@@ -11411,10 +11397,13 @@ function parseInfra(content) {
11411
11397
  finishCurrentNode();
11412
11398
  finishCurrentTagGroup();
11413
11399
  currentGroup = null;
11414
- const name = (compMatch[1] ?? compMatch[2] ?? "").trim();
11400
+ const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
11401
+ const peeled = peelInfraDecorations(rawName, lineNumber);
11402
+ const name = peeled.label;
11415
11403
  const rest = compMatch[3] || "";
11416
11404
  const { tags } = extractPipeMetadata(rest);
11417
11405
  const id = nodeId2(name);
11406
+ if (peeled.alias) nameAliasMap.set(peeled.alias, id);
11418
11407
  currentNode = {
11419
11408
  id,
11420
11409
  label: name,
@@ -11464,6 +11453,14 @@ function parseInfra(content) {
11464
11453
  validateTagGroupNames(result.tagGroups, warn, setError);
11465
11454
  return result;
11466
11455
  }
11456
+ function stripNodeDecorations(name) {
11457
+ let s = name.trim();
11458
+ const aliasMatch = s.match(/^(.*?)\s+as\s+[A-Za-z][A-Za-z0-9_]{0,11}\s*$/);
11459
+ if (aliasMatch) s = aliasMatch[1].trim();
11460
+ const isAMatch = s.match(/^(.*?)\s+is\s+an?\s+[A-Za-z][\w-]*\s*$/i);
11461
+ if (isAMatch) s = isAMatch[1].trim();
11462
+ return s;
11463
+ }
11467
11464
  function extractSymbols4(docText) {
11468
11465
  const entities = [];
11469
11466
  let inMetadata = true;
@@ -11497,7 +11494,7 @@ function extractSymbols4(docText) {
11497
11494
  if (/^\[/.test(line12)) continue;
11498
11495
  const m = COMPONENT_RE.exec(line12);
11499
11496
  if (m) {
11500
- const name = (m[1] ?? m[2] ?? "").trim();
11497
+ const name = stripNodeDecorations((m[1] ?? m[2] ?? "").trim());
11501
11498
  if (name && !entities.includes(name)) entities.push(name);
11502
11499
  }
11503
11500
  } else {
@@ -11512,7 +11509,7 @@ function extractSymbols4(docText) {
11512
11509
  continue;
11513
11510
  const m = COMPONENT_RE.exec(line12);
11514
11511
  if (m) {
11515
- const name = (m[1] ?? m[2] ?? "").trim();
11512
+ const name = stripNodeDecorations((m[1] ?? m[2] ?? "").trim());
11516
11513
  if (name && !entities.includes(name)) entities.push(name);
11517
11514
  }
11518
11515
  }
@@ -17353,7 +17350,7 @@ var init_parser19 = __esm({
17353
17350
  });
17354
17351
 
17355
17352
  // src/chart-types.ts
17356
- var chartTypes, BETA_CHART_IDS;
17353
+ var chartTypes;
17357
17354
  var init_chart_types = __esm({
17358
17355
  "src/chart-types.ts"() {
17359
17356
  "use strict";
@@ -17812,7 +17809,6 @@ var init_chart_types = __esm({
17812
17809
  fallback: true
17813
17810
  }
17814
17811
  ];
17815
- BETA_CHART_IDS = /* @__PURE__ */ new Set(["c4", "venn"]);
17816
17812
  }
17817
17813
  });
17818
17814
 
@@ -20621,106 +20617,6 @@ var init_renderer2 = __esm({
20621
20617
  });
20622
20618
 
20623
20619
  // src/kanban/mutations.ts
20624
- function computeCardMove(content, parsed, cardId, targetColumnId, targetIndex) {
20625
- let sourceCard = null;
20626
- let sourceColumn = null;
20627
- for (const col of parsed.columns) {
20628
- for (const card of col.cards) {
20629
- if (card.id === cardId) {
20630
- sourceCard = card;
20631
- sourceColumn = col;
20632
- break;
20633
- }
20634
- }
20635
- if (sourceCard) break;
20636
- }
20637
- if (!sourceCard || !sourceColumn) return null;
20638
- const targetColumn = parsed.columns.find((c) => c.id === targetColumnId);
20639
- if (!targetColumn) return null;
20640
- const lines = content.split("\n");
20641
- const startIdx = sourceCard.lineNumber - 1;
20642
- const endIdx = sourceCard.endLineNumber - 1;
20643
- const cardLines = lines.slice(startIdx, endIdx + 1);
20644
- const withoutCard = [
20645
- ...lines.slice(0, startIdx),
20646
- ...lines.slice(endIdx + 1)
20647
- ];
20648
- let insertIdx;
20649
- const removedCount = endIdx - startIdx + 1;
20650
- const adjustLine = (ln) => {
20651
- if (ln > endIdx + 1) return ln - removedCount;
20652
- return ln;
20653
- };
20654
- if (targetIndex === 0) {
20655
- const adjColLine = adjustLine(targetColumn.lineNumber);
20656
- insertIdx = adjColLine;
20657
- } else {
20658
- const targetCards = targetColumn.cards.filter((c) => c.id !== cardId);
20659
- const clampedIdx = Math.min(targetIndex, targetCards.length);
20660
- const precedingCard = targetCards[clampedIdx - 1];
20661
- if (!precedingCard) {
20662
- const adjColLine = adjustLine(targetColumn.lineNumber);
20663
- insertIdx = adjColLine;
20664
- } else {
20665
- const adjEndLine = adjustLine(precedingCard.endLineNumber);
20666
- insertIdx = adjEndLine;
20667
- }
20668
- }
20669
- const result = [
20670
- ...withoutCard.slice(0, insertIdx),
20671
- ...cardLines,
20672
- ...withoutCard.slice(insertIdx)
20673
- ];
20674
- return result.join("\n");
20675
- }
20676
- function computeCardArchive(content, parsed, cardId) {
20677
- let sourceCard = null;
20678
- for (const col of parsed.columns) {
20679
- for (const card of col.cards) {
20680
- if (card.id === cardId) {
20681
- sourceCard = card;
20682
- break;
20683
- }
20684
- }
20685
- if (sourceCard) break;
20686
- }
20687
- if (!sourceCard) return null;
20688
- const lines = content.split("\n");
20689
- const startIdx = sourceCard.lineNumber - 1;
20690
- const endIdx = sourceCard.endLineNumber - 1;
20691
- const cardLines = lines.slice(startIdx, endIdx + 1);
20692
- const withoutCard = [
20693
- ...lines.slice(0, startIdx),
20694
- ...lines.slice(endIdx + 1)
20695
- ];
20696
- const archiveCol = parsed.columns.find(
20697
- (c) => c.name.toLowerCase() === ARCHIVE_COLUMN_NAME
20698
- );
20699
- if (archiveCol) {
20700
- const removedCount = endIdx - startIdx + 1;
20701
- let archiveEndLine = archiveCol.lineNumber;
20702
- if (archiveCol.cards.length > 0) {
20703
- const lastCard = archiveCol.cards[archiveCol.cards.length - 1];
20704
- archiveEndLine = lastCard.endLineNumber;
20705
- }
20706
- if (archiveEndLine > endIdx + 1) {
20707
- archiveEndLine -= removedCount;
20708
- }
20709
- const insertIdx = archiveEndLine;
20710
- return [
20711
- ...withoutCard.slice(0, insertIdx),
20712
- ...cardLines,
20713
- ...withoutCard.slice(insertIdx)
20714
- ].join("\n");
20715
- } else {
20716
- const trimmedEnd = withoutCard.length > 0 && withoutCard[withoutCard.length - 1].trim() === "" ? withoutCard : [...withoutCard, ""];
20717
- return [
20718
- ...trimmedEnd,
20719
- "[Archive]",
20720
- ...cardLines
20721
- ].join("\n");
20722
- }
20723
- }
20724
20620
  function isArchiveColumn(name) {
20725
20621
  return name.toLowerCase() === ARCHIVE_COLUMN_NAME;
20726
20622
  }
@@ -38416,7 +38312,7 @@ function renderHtmlPanel(panel, parsed, quadrant, qColor, palette, isDark, rootC
38416
38312
  solid: parsed.options["solid-fill"] === "on"
38417
38313
  });
38418
38314
  let expandedLineNum = null;
38419
- function render2() {
38315
+ function render3() {
38420
38316
  panel.innerHTML = "";
38421
38317
  for (const ringName of ringOrder) {
38422
38318
  const blips = quadrant.blips.filter((b) => b.ring === ringName);
@@ -38526,7 +38422,7 @@ function renderHtmlPanel(panel, parsed, quadrant, qColor, palette, isDark, rootC
38526
38422
  if (hasDesc) {
38527
38423
  const wasExpanded = expandedLineNum === ln;
38528
38424
  expandedLineNum = wasExpanded ? null : ln;
38529
- render2();
38425
+ render3();
38530
38426
  if (!wasExpanded) {
38531
38427
  requestAnimationFrame(() => {
38532
38428
  dimExcept(rootContainer, ln);
@@ -38556,11 +38452,11 @@ function renderHtmlPanel(panel, parsed, quadrant, qColor, palette, isDark, rootC
38556
38452
  }
38557
38453
  }
38558
38454
  }
38559
- render2();
38455
+ render3();
38560
38456
  panel.addEventListener("click", () => {
38561
38457
  if (expandedLineNum) {
38562
38458
  expandedLineNum = null;
38563
- render2();
38459
+ render3();
38564
38460
  clearDim(rootContainer);
38565
38461
  rootContainer.querySelectorAll("svg [data-line-number]").forEach((el) => el.removeAttribute("transform"));
38566
38462
  }
@@ -38571,7 +38467,7 @@ function renderHtmlPanel(panel, parsed, quadrant, qColor, palette, isDark, rootC
38571
38467
  if (blip && blip.description.length > 0) {
38572
38468
  const wasExpanded = expandedLineNum === ln;
38573
38469
  expandedLineNum = wasExpanded ? null : ln;
38574
- render2();
38470
+ render3();
38575
38471
  const node = panel.querySelector(`[data-line-number="${ln}"]`);
38576
38472
  if (node) node.scrollIntoView({ behavior: "smooth", block: "nearest" });
38577
38473
  if (!wasExpanded) {
@@ -38647,226 +38543,6 @@ function renderInlineMarkdownHtml(text, palette) {
38647
38543
  function escapeHtml(text) {
38648
38544
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
38649
38545
  }
38650
- function renderQuadrantFocusForExport(container, parsed, quadrantPosition, palette, isDark, exportDims) {
38651
- const quadrant = parsed.quadrants.find(
38652
- (q) => q.position === quadrantPosition
38653
- );
38654
- if (!quadrant) return;
38655
- container.innerHTML = "";
38656
- const width = exportDims.width;
38657
- const height = exportDims.height;
38658
- const qColor = resolveQuadrantColor(
38659
- quadrant.position,
38660
- quadrant.color,
38661
- palette
38662
- );
38663
- const titleBar = document.createElement("div");
38664
- titleBar.style.cssText = `
38665
- display: flex; align-items: baseline; gap: 8px;
38666
- padding: 12px 16px; font-family: ${FONT_FAMILY};
38667
- font-size: ${TITLE_FONT_SIZE2 + 2}px; background: ${palette.bg};
38668
- `;
38669
- const titleText = document.createElement("span");
38670
- titleText.textContent = parsed.title || "Tech Radar";
38671
- titleText.style.cssText = `font-weight: bold; color: ${palette.text};`;
38672
- const sep = document.createElement("span");
38673
- sep.textContent = "\u203A";
38674
- sep.style.color = palette.border;
38675
- const quadrantLabel = document.createElement("span");
38676
- quadrantLabel.textContent = quadrant.name;
38677
- quadrantLabel.style.cssText = `font-weight: bold; color: ${qColor};`;
38678
- titleBar.appendChild(titleText);
38679
- titleBar.appendChild(sep);
38680
- titleBar.appendChild(quadrantLabel);
38681
- container.appendChild(titleBar);
38682
- const mainLayout = document.createElement("div");
38683
- mainLayout.style.cssText = `
38684
- display: flex; flex-direction: row;
38685
- height: ${height - 48}px; background: ${palette.bg};
38686
- `;
38687
- container.appendChild(mainLayout);
38688
- const svgContainer = document.createElement("div");
38689
- svgContainer.style.cssText = `width: 45%; min-width: 200px; flex-shrink: 0;`;
38690
- mainLayout.appendChild(svgContainer);
38691
- const panel = document.createElement("div");
38692
- panel.style.cssText = `
38693
- flex: 1; padding: 8px 16px;
38694
- font-family: ${FONT_FAMILY}; background: ${palette.bg};
38695
- `;
38696
- mainLayout.appendChild(panel);
38697
- renderStaticHtmlPanel(panel, parsed, quadrant, qColor, palette, isDark);
38698
- const svgWidth = width * 0.45;
38699
- const svgHeight = height - 48;
38700
- const svg = d3Selection15.select(svgContainer).append("svg").attr("width", svgWidth).attr("height", svgHeight).attr("viewBox", `0 0 ${svgWidth} ${svgHeight}`).style("background", palette.bg);
38701
- renderQuarterCircleStatic(
38702
- svg,
38703
- parsed,
38704
- quadrant,
38705
- qColor,
38706
- palette,
38707
- isDark,
38708
- svgWidth,
38709
- svgHeight,
38710
- palette.border
38711
- );
38712
- }
38713
- function renderQuarterCircleStatic(svg, parsed, quadrant, qColor, palette, isDark, width, height, mutedColor) {
38714
- const padding = 8;
38715
- const size = Math.min(width - padding, height - padding);
38716
- const maxRadius = size * 0.95;
38717
- const ringCount = parsed.rings.length;
38718
- const ringBandWidth = maxRadius / ringCount;
38719
- const { startAngle, endAngle } = getQuadrantArc(quadrant.position);
38720
- let cx, cy;
38721
- switch (quadrant.position) {
38722
- case "top-right":
38723
- cx = padding;
38724
- cy = size + padding;
38725
- break;
38726
- case "top-left":
38727
- cx = width - padding;
38728
- cy = size + padding;
38729
- break;
38730
- case "bottom-left":
38731
- cx = width - padding;
38732
- cy = padding;
38733
- break;
38734
- case "bottom-right":
38735
- cx = padding;
38736
- cy = padding;
38737
- break;
38738
- }
38739
- const arcGen = (innerR, outerR) => `M${cx + outerR * Math.cos(startAngle)},${cy - outerR * Math.sin(startAngle)} A${outerR},${outerR} 0 0,0 ${cx + outerR * Math.cos(endAngle)},${cy - outerR * Math.sin(endAngle)} L${cx + innerR * Math.cos(endAngle)},${cy - innerR * Math.sin(endAngle)} A${innerR},${innerR} 0 0,1 ${cx + innerR * Math.cos(startAngle)},${cy - innerR * Math.sin(startAngle)} Z`;
38740
- for (let ri = parsed.rings.length - 1; ri >= 0; ri--) {
38741
- const innerR = ri * ringBandWidth;
38742
- const outerR = (ri + 1) * ringBandWidth;
38743
- const fillColor = ri % 2 === 0 ? palette.bg : mix(palette.bg, palette.border, 0.15);
38744
- svg.append("path").attr("d", arcGen(innerR, outerR)).attr("fill", fillColor).attr("stroke", mutedColor).attr("stroke-width", 0.5);
38745
- }
38746
- for (let ri = 0; ri < parsed.rings.length; ri++) {
38747
- const rCenter = (ri + 0.5) * ringBandWidth;
38748
- const midAngle = (startAngle + endAngle) / 2;
38749
- const labelX = cx + rCenter * Math.cos(midAngle);
38750
- const labelY = cy - rCenter * Math.sin(midAngle);
38751
- svg.append("text").attr("x", labelX).attr("y", labelY).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("fill", palette.textMuted).attr("font-family", FONT_FAMILY).attr("font-size", 11).attr("font-weight", "600").attr("opacity", 0.5).text(parsed.rings[ri].name);
38752
- }
38753
- const ringOrder = parsed.rings.map((r) => r.name);
38754
- const angularPadding = 0.08;
38755
- const radialPadding = ringBandWidth * 0.12;
38756
- const usableArcStart = startAngle + angularPadding;
38757
- const usableArcEnd = endAngle - angularPadding;
38758
- const arcSpan = usableArcEnd - usableArcStart;
38759
- const blipsByRing = /* @__PURE__ */ new Map();
38760
- for (const blip of quadrant.blips) {
38761
- const list = blipsByRing.get(blip.ring) ?? [];
38762
- list.push(blip);
38763
- blipsByRing.set(blip.ring, list);
38764
- }
38765
- for (const [ringName, blips] of blipsByRing) {
38766
- const ringIndex = ringOrder.indexOf(ringName);
38767
- if (ringIndex < 0) continue;
38768
- const rInner = ringIndex * ringBandWidth + radialPadding;
38769
- const rOuter = (ringIndex + 1) * ringBandWidth - radialPadding;
38770
- const rMid = (rInner + rOuter) / 2;
38771
- for (let bi = 0; bi < blips.length; bi++) {
38772
- const blip = blips[bi];
38773
- const angle = blips.length === 1 ? (usableArcStart + usableArcEnd) / 2 : usableArcStart + (bi + 0.5) / blips.length * arcSpan;
38774
- const radius = blips.length <= 3 ? rMid : rInner + BLIP_RADIUS + bi % 3 / 2 * (rOuter - rInner - BLIP_RADIUS * 2);
38775
- const bx = cx + radius * Math.cos(angle);
38776
- const by = cy - radius * Math.sin(angle);
38777
- const blipGroup = svg.append("g");
38778
- const angleToCenter = Math.atan2(cy - by, cx - bx);
38779
- renderTrendIndicator(
38780
- blipGroup,
38781
- blip.trend,
38782
- qColor,
38783
- bx,
38784
- by,
38785
- BLIP_RADIUS,
38786
- angleToCenter
38787
- );
38788
- blipGroup.append("text").attr("x", bx).attr("y", by + 3).attr("text-anchor", "middle").attr("fill", isDark ? "#000" : "#fff").attr("font-family", FONT_FAMILY).attr("font-size", BLIP_FONT_SIZE).attr("font-weight", "bold").text(blip.globalNumber);
38789
- }
38790
- }
38791
- }
38792
- function renderStaticHtmlPanel(panel, parsed, quadrant, qColor, palette, isDark) {
38793
- const ringOrder = parsed.rings.map((r) => r.name);
38794
- const fillColor = shapeFill(palette, qColor, isDark, {
38795
- solid: parsed.options["solid-fill"] === "on"
38796
- });
38797
- for (const ringName of ringOrder) {
38798
- const blips = quadrant.blips.filter((b) => b.ring === ringName);
38799
- if (blips.length === 0) continue;
38800
- const ringGroup = document.createElement("div");
38801
- ringGroup.style.cssText = `
38802
- background: ${palette.surface};
38803
- border-radius: 8px;
38804
- padding: 10px;
38805
- margin-bottom: 12px;
38806
- `;
38807
- const header = document.createElement("div");
38808
- header.style.cssText = `
38809
- font-size: 13px; font-weight: 700; color: ${palette.textMuted};
38810
- margin-bottom: 8px;
38811
- `;
38812
- header.textContent = ringName;
38813
- ringGroup.appendChild(header);
38814
- panel.appendChild(ringGroup);
38815
- for (const blip of blips) {
38816
- const hasDesc = blip.description.length > 0;
38817
- const node = document.createElement("div");
38818
- node.style.cssText = `
38819
- background: ${fillColor}; border: 1.5px solid ${qColor};
38820
- border-radius: 6px; margin-bottom: 6px;
38821
- `;
38822
- const titleRow = document.createElement("div");
38823
- titleRow.style.cssText = `
38824
- display: flex; align-items: center; gap: 8px;
38825
- padding: 6px 10px; min-height: 28px;
38826
- `;
38827
- const indicatorSvg = document.createElementNS(
38828
- "http://www.w3.org/2000/svg",
38829
- "svg"
38830
- );
38831
- indicatorSvg.setAttribute("width", "26");
38832
- indicatorSvg.setAttribute("height", "26");
38833
- indicatorSvg.style.flexShrink = "0";
38834
- const indicatorG = d3Selection15.select(indicatorSvg).append("g");
38835
- renderTrendIndicator(
38836
- indicatorG,
38837
- blip.trend,
38838
- qColor,
38839
- 13,
38840
- 13,
38841
- 10,
38842
- -Math.PI / 2
38843
- );
38844
- d3Selection15.select(indicatorSvg).append("text").attr("x", 13).attr("y", 16).attr("text-anchor", "middle").attr("fill", isDark ? "#000" : "#fff").attr("font-family", FONT_FAMILY).attr("font-size", 9).attr("font-weight", "bold").text(blip.globalNumber);
38845
- titleRow.appendChild(indicatorSvg);
38846
- const name = document.createElement("span");
38847
- name.textContent = blip.name;
38848
- name.style.cssText = `
38849
- flex: 1; font-size: 12px; font-weight: 600;
38850
- color: ${palette.text};
38851
- `;
38852
- titleRow.appendChild(name);
38853
- node.appendChild(titleRow);
38854
- if (hasDesc) {
38855
- const sepDiv = document.createElement("div");
38856
- sepDiv.style.cssText = `border-top: 1px solid ${qColor}; opacity: 0.3;`;
38857
- node.appendChild(sepDiv);
38858
- const descDiv = document.createElement("div");
38859
- descDiv.style.cssText = `
38860
- padding: 6px 10px 8px; font-size: 11px; line-height: 1.6;
38861
- color: ${palette.textMuted};
38862
- `;
38863
- descDiv.innerHTML = renderDescriptionHtml(blip.description, palette);
38864
- node.appendChild(descDiv);
38865
- }
38866
- ringGroup.appendChild(node);
38867
- }
38868
- }
38869
- }
38870
38546
  var d3Selection15, BLIP_RADIUS, BLIP_FONT_SIZE, TITLE_FONT_SIZE2, NARROW_BREAKPOINT;
38871
38547
  var init_interactive = __esm({
38872
38548
  "src/tech-radar/interactive.ts"() {
@@ -47591,53 +47267,6 @@ function getRotateFn(mode) {
47591
47267
  if (mode === "angled") return () => Math.round(Math.random() * 30 - 15);
47592
47268
  return () => 0;
47593
47269
  }
47594
- function renderWordCloud(container, parsed, palette, _isDark, onClickItem, exportDims) {
47595
- const { words, cloudOptions } = parsed;
47596
- const title = parsed.noTitle ? null : parsed.title;
47597
- if (words.length === 0) return;
47598
- const init2 = initD3Chart(container, palette, exportDims);
47599
- if (!init2) return;
47600
- const { svg, width, height, textColor, colors } = init2;
47601
- const titleHeight = title ? 40 : 0;
47602
- const cloudHeight = height - titleHeight;
47603
- const { minSize, maxSize } = cloudOptions;
47604
- const weights = words.map((w) => w.weight);
47605
- const minWeight = Math.min(...weights);
47606
- const maxWeight = Math.max(...weights);
47607
- const range = maxWeight - minWeight || 1;
47608
- const fontSize = (weight) => {
47609
- const t = (weight - minWeight) / range;
47610
- return minSize + Math.sqrt(t) * (maxSize - minSize);
47611
- };
47612
- const rotateFn = getRotateFn(cloudOptions.rotate);
47613
- renderChartTitle(
47614
- svg,
47615
- title,
47616
- parsed.titleLineNumber,
47617
- width,
47618
- textColor,
47619
- onClickItem
47620
- );
47621
- const g = svg.append("g").attr(
47622
- "transform",
47623
- `translate(${width / 2},${titleHeight + cloudHeight / 2})`
47624
- );
47625
- (0, import_d3_cloud.default)().size([width, cloudHeight]).words(words.map((w) => ({ ...w, size: fontSize(w.weight) }))).padding(2).rotate(rotateFn).fontSize((d) => d.size).font(FONT_FAMILY).on("end", (layoutWords) => {
47626
- g.selectAll("text").data(layoutWords).join("text").style("font-size", (d) => `${d.size}px`).style("font-family", FONT_FAMILY).style("font-weight", "600").style("fill", (_d, i) => colors[i % colors.length]).style(
47627
- "cursor",
47628
- (d) => onClickItem && d.lineNumber ? "pointer" : "default"
47629
- ).attr("text-anchor", "middle").attr(
47630
- "transform",
47631
- (d) => `translate(${d.x},${d.y}) rotate(${d.rotate})`
47632
- ).attr("data-line-number", (d) => {
47633
- const ln = d.lineNumber;
47634
- return ln ? String(ln) : null;
47635
- }).text((d) => d.text).on("click", (_event, d) => {
47636
- const ln = d.lineNumber;
47637
- if (onClickItem && ln) onClickItem(ln);
47638
- });
47639
- }).start();
47640
- }
47641
47270
  function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
47642
47271
  return new Promise((resolve) => {
47643
47272
  d3Selection22.select(container).selectAll(":not([data-d3-tooltip])").remove();
@@ -49994,260 +49623,15 @@ var require_lz_string = __commonJS({
49994
49623
  // src/index.ts
49995
49624
  var index_exports = {};
49996
49625
  __export(index_exports, {
49997
- ALL_CHART_TYPES: () => ALL_CHART_TYPES,
49998
- AMBIGUITY_THRESHOLD: () => AMBIGUITY_THRESHOLD,
49999
- ARROW_DIAGNOSTIC_CODES: () => ARROW_DIAGNOSTIC_CODES,
50000
- BETA_CHART_IDS: () => BETA_CHART_IDS,
50001
- CHART_TYPES: () => CHART_TYPES,
50002
- CHART_TYPE_DESCRIPTIONS: () => CHART_TYPE_DESCRIPTIONS,
50003
- COMPLETION_REGISTRY: () => COMPLETION_REGISTRY,
50004
- ENTITY_TYPES: () => ENTITY_TYPES,
50005
- INFRA_BEHAVIOR_KEYS: () => INFRA_BEHAVIOR_KEYS,
50006
- LEGEND_GEAR_PILL_W: () => LEGEND_GEAR_PILL_W,
50007
- LEGEND_HEIGHT: () => LEGEND_HEIGHT,
50008
- METADATA_KEY_SET: () => METADATA_KEY_SET,
50009
- MIN_PRIMARY_SCORE: () => MIN_PRIMARY_SCORE,
50010
- PERT_LEGEND_PILL_HEIGHT: () => PERT_LEGEND_PILL_HEIGHT,
50011
- PIPE_METADATA: () => PIPE_METADATA,
50012
- RACI_ERROR_CODES: () => RACI_ERROR_CODES,
50013
- RACI_VARIANTS: () => VARIANTS,
50014
- RACI_WARNING_CODES: () => RACI_WARNING_CODES,
50015
- RECOGNIZED_COLOR_NAMES: () => RECOGNIZED_COLOR_NAMES,
50016
- RULE_COUNT: () => RULE_COUNT,
50017
- addDurationToDate: () => addDurationToDate,
50018
- analyzePert: () => analyzePert,
50019
- applyCollapseProjection: () => applyCollapseProjection,
50020
- applyGroupOrdering: () => applyGroupOrdering,
50021
- applyPositionOverrides: () => applyPositionOverrides,
50022
- boldPalette: () => boldPalette,
50023
- buildExtendedChartOption: () => buildExtendedChartOption,
50024
- buildNoteMessageMap: () => buildNoteMessageMap,
50025
- buildRenderSequence: () => buildRenderSequence,
50026
- buildSimpleChartOption: () => buildSimpleChartOption,
50027
- buildTagLaneRowList: () => buildTagLaneRowList,
50028
- calculateSchedule: () => calculateSchedule,
50029
- catppuccinPalette: () => catppuccinPalette,
50030
- chartTypeConfidence: () => confidence,
50031
- chartTypeParsers: () => chartTypeParsers,
50032
- chartTypes: () => chartTypes,
50033
- collapseBoxesAndLines: () => collapseBoxesAndLines,
50034
- collapseMindmapTree: () => collapseMindmapTree,
50035
- collapseOrgTree: () => collapseOrgTree,
50036
- collapseSitemapTree: () => collapseSitemapTree,
50037
- collapseStateGroups: () => collapseStateGroups,
50038
- collectDiagramRoles: () => collectDiagramRoles,
50039
- collectTasks: () => collectTasks,
50040
- colorNames: () => colorNames,
50041
- computeActivations: () => computeActivations,
50042
- computeCardArchive: () => computeCardArchive,
50043
- computeCardMove: () => computeCardMove,
50044
- computeCycleLayout: () => computeCycleLayout,
50045
- computeInfra: () => computeInfra,
50046
- computeInfraLegendGroups: () => computeInfraLegendGroups,
50047
- computeLegendLayout: () => computeLegendLayout,
50048
- computeRadarLayout: () => computeRadarLayout,
50049
- computeScatterLabelGraphics: () => computeScatterLabelGraphics,
50050
- computeTimeTicks: () => computeTimeTicks,
50051
- contrastText: () => contrastText,
50052
- controlsGroupCapsuleWidth: () => controlsGroupCapsuleWidth,
50053
- decodeDiagramUrl: () => decodeDiagramUrl,
50054
- decodeViewState: () => decodeViewState,
50055
- displayName: () => displayName,
50056
- draculaPalette: () => draculaPalette,
50057
- encodeDiagramUrl: () => encodeDiagramUrl,
50058
- encodeViewState: () => encodeViewState,
50059
- extractDiagramSymbols: () => extractDiagramSymbols,
50060
- extractPertSymbols: () => extractPertSymbols,
50061
- extractTagDeclarations: () => extractTagDeclarations,
50062
- focusOrgTree: () => focusOrgTree,
50063
- formatDateLabel: () => formatDateLabel,
49626
+ decodeDiagramUrl: () => decodeDiagramUrl2,
49627
+ encodeDiagramUrl: () => encodeDiagramUrl2,
50064
49628
  formatDgmoError: () => formatDgmoError,
50065
- getAllChartTypes: () => getAllChartTypes,
50066
- getAvailablePalettes: () => getAvailablePalettes,
50067
- getExtendedChartLegendGroups: () => getExtendedChartLegendGroups,
50068
- getLegendReservedHeight: () => getLegendReservedHeight,
50069
- getOrCreateName: () => getOrCreateName,
50070
- getPalette: () => getPalette,
50071
- getRadarGeometry: () => getRadarGeometry,
50072
- getRenderCategory: () => getRenderCategory,
50073
- getSeriesColors: () => getSeriesColors,
50074
- getSimpleChartLegendGroups: () => getSimpleChartLegendGroups,
50075
- groupMessagesBySection: () => groupMessagesBySection,
50076
- gruvboxPalette: () => gruvboxPalette,
50077
- hexToHSL: () => hexToHSL,
50078
- hexToHSLString: () => hexToHSLString,
50079
- highlightPertCriticalPath: () => highlightPertCriticalPath,
50080
- highlightPertSet: () => highlightPertSet,
50081
- hslToHex: () => hslToHex,
50082
- inferParticipantType: () => inferParticipantType,
50083
- inferRoles: () => inferRoles,
50084
- isArchiveColumn: () => isArchiveColumn,
50085
- isExtendedChartType: () => isExtendedChartType,
50086
- isRecognizedColorName: () => isRecognizedColorName,
50087
- isSequenceBlock: () => isSequenceBlock,
50088
- isSequenceNote: () => isSequenceNote,
50089
- isValidHex: () => isValidHex,
50090
- knownChartTypeIds: () => knownChartTypeIds,
50091
- layoutBoxesAndLines: () => layoutBoxesAndLines,
50092
- layoutC4Components: () => layoutC4Components,
50093
- layoutC4Containers: () => layoutC4Containers,
50094
- layoutC4Context: () => layoutC4Context,
50095
- layoutC4Deployment: () => layoutC4Deployment,
50096
- layoutClassDiagram: () => layoutClassDiagram,
50097
- layoutERDiagram: () => layoutERDiagram,
50098
- layoutGraph: () => layoutGraph,
50099
- layoutInfra: () => layoutInfra,
50100
- layoutJourneyMap: () => layoutJourneyMap,
50101
- layoutMindmap: () => layoutMindmap,
50102
- layoutOrg: () => layoutOrg,
50103
- layoutPert: () => layoutPert,
50104
- layoutSitemap: () => layoutSitemap,
50105
- layoutWireframe: () => layoutWireframe,
50106
- looksLikeClassDiagram: () => looksLikeClassDiagram,
50107
- looksLikeERDiagram: () => looksLikeERDiagram,
50108
- looksLikeFlowchart: () => looksLikeFlowchart,
50109
- looksLikePert: () => looksLikePert,
50110
- looksLikeSequence: () => looksLikeSequence,
50111
- looksLikeSitemap: () => looksLikeSitemap,
50112
- looksLikeState: () => looksLikeState,
50113
- makeDgmoError: () => makeDgmoError,
50114
- matchColorParens: () => matchColorParens,
50115
- matchesContiguously: () => matchesContiguously,
50116
- measurePertAnalysisBlock: () => measurePertAnalysisBlock,
50117
- mix: () => mix,
50118
- monokaiPalette: () => monokaiPalette,
50119
- nord: () => nord,
50120
- nordPalette: () => nordPalette,
50121
- normalizeChartTypePrompt: () => normalize,
50122
- normalizeName: () => normalizeName,
50123
- normalizePertSourceForShare: () => normalizePertSourceForShare,
50124
- oneDarkPalette: () => oneDarkPalette,
50125
- orderArcNodes: () => orderArcNodes,
50126
- parseAndLayoutInfra: () => parseAndLayoutInfra,
50127
- parseBoxesAndLines: () => parseBoxesAndLines,
50128
- parseC4: () => parseC4,
50129
- parseChart: () => parseChart,
50130
- parseClassDiagram: () => parseClassDiagram,
50131
- parseCycle: () => parseCycle,
50132
- parseDataRowValues: () => parseDataRowValues,
50133
- parseDgmo: () => parseDgmo,
50134
- parseDgmoChartType: () => parseDgmoChartType,
50135
- parseERDiagram: () => parseERDiagram,
50136
- parseExtendedChart: () => parseExtendedChart,
50137
- parseFirstLine: () => parseFirstLine,
50138
- parseFlowchart: () => parseFlowchart,
50139
- parseGantt: () => parseGantt,
50140
- parseInArrowLabel: () => parseInArrowLabel,
50141
- parseInfra: () => parseInfra,
50142
- parseInlineMarkdown: () => parseInlineMarkdown,
50143
- parseJourneyMap: () => parseJourneyMap,
50144
- parseKanban: () => parseKanban,
50145
- parseMindmap: () => parseMindmap,
50146
- parseOrg: () => parseOrg,
50147
- parsePert: () => parsePert,
50148
- parsePyramid: () => parsePyramid,
50149
- parseRaci: () => parseRaci,
50150
- parseRing: () => parseRing,
50151
- parseSequenceDgmo: () => parseSequenceDgmo,
50152
- parseSequenceDiagram: () => parseSequenceDgmo,
50153
- parseSitemap: () => parseSitemap,
50154
- parseState: () => parseState,
50155
- parseTechRadar: () => parseTechRadar,
50156
- parseTimelineDate: () => parseTimelineDate,
50157
- parseVisualization: () => parseVisualization,
50158
- parseWireframe: () => parseWireframe,
50159
- pertLegendBlockWidth: () => pertLegendBlockWidth,
50160
- pertLegendEntries: () => pertLegendEntries,
50161
- raciCellAppendMarker: () => cellAppendMarker,
50162
- raciCellCycle: () => cellCycle,
50163
- raciCellRemove: () => cellRemove,
50164
- raciCellReplace: () => cellReplace,
50165
- registerExtractor: () => registerExtractor,
50166
- registerPalette: () => registerPalette,
50167
- relayoutPert: () => relayoutPert,
50168
- render: () => render,
50169
- renderArcDiagram: () => renderArcDiagram,
50170
- renderBoxesAndLines: () => renderBoxesAndLines,
50171
- renderBoxesAndLinesForExport: () => renderBoxesAndLinesForExport,
50172
- renderC4ComponentsForExport: () => renderC4ComponentsForExport,
50173
- renderC4Containers: () => renderC4Containers,
50174
- renderC4ContainersForExport: () => renderC4ContainersForExport,
50175
- renderC4Context: () => renderC4Context,
50176
- renderC4ContextForExport: () => renderC4ContextForExport,
50177
- renderC4Deployment: () => renderC4Deployment,
50178
- renderC4DeploymentForExport: () => renderC4DeploymentForExport,
50179
- renderClassDiagram: () => renderClassDiagram,
50180
- renderClassDiagramForExport: () => renderClassDiagramForExport,
50181
- renderCycle: () => renderCycle,
50182
- renderCycleForExport: () => renderCycleForExport,
50183
- renderERDiagram: () => renderERDiagram,
50184
- renderERDiagramForExport: () => renderERDiagramForExport,
50185
- renderExtendedChartForExport: () => renderExtendedChartForExport,
50186
- renderFlowchart: () => renderFlowchart,
50187
- renderFlowchartForExport: () => renderFlowchartForExport,
50188
- renderForExport: () => renderForExport,
50189
- renderGantt: () => renderGantt,
50190
- renderInfra: () => renderInfra,
50191
- renderJourneyMap: () => renderJourneyMap,
50192
- renderJourneyMapForExport: () => renderJourneyMapForExport,
50193
- renderKanban: () => renderKanban,
50194
- renderKanbanForExport: () => renderKanbanForExport,
50195
- renderLegendD3: () => renderLegendD3,
50196
- renderLegendSvg: () => renderLegendSvg,
50197
- renderLegendSvgFromConfig: () => renderLegendSvgFromConfig,
50198
- renderMindmap: () => renderMindmap,
50199
- renderMindmapForExport: () => renderMindmapForExport,
50200
- renderOrg: () => renderOrg,
50201
- renderOrgForExport: () => renderOrgForExport,
50202
- renderPert: () => renderPert,
50203
- renderPertAnalysisBlock: () => renderPertAnalysisBlock,
50204
- renderPertForExport: () => renderPertForExport,
50205
- renderPertLegendBlock: () => renderLegendBlock,
50206
- renderPyramid: () => renderPyramid,
50207
- renderPyramidForExport: () => renderPyramidForExport,
50208
- renderQuadrant: () => renderQuadrant,
50209
- renderQuadrantFocus: () => renderQuadrantFocus,
50210
- renderQuadrantFocusForExport: () => renderQuadrantFocusForExport,
50211
- renderRaci: () => renderRaci,
50212
- renderRaciForExport: () => renderRaciForExport,
50213
- renderRing: () => renderRing,
50214
- renderRingForExport: () => renderRingForExport,
50215
- renderSequenceDiagram: () => renderSequenceDiagram,
50216
- renderSitemap: () => renderSitemap,
50217
- renderSitemapForExport: () => renderSitemapForExport,
50218
- renderSlopeChart: () => renderSlopeChart,
50219
- renderState: () => renderState,
50220
- renderStateForExport: () => renderStateForExport,
50221
- renderTechRadar: () => renderTechRadar,
50222
- renderTechRadarForExport: () => renderTechRadarForExport,
50223
- renderTimeline: () => renderTimeline,
50224
- renderVenn: () => renderVenn,
50225
- renderWireframe: () => renderWireframe,
50226
- renderWordCloud: () => renderWordCloud,
50227
- resetPertCriticalPath: () => resetPertCriticalPath,
50228
- resetPertHighlight: () => resetPertHighlight,
50229
- resolveColor: () => resolveColor,
50230
- resolveColorWithDiagnostic: () => resolveColorWithDiagnostic,
50231
- resolveOrgImports: () => resolveOrgImports,
50232
- resolveTaskName: () => resolveTaskName,
50233
- rollUpContextRelationships: () => rollUpContextRelationships,
50234
- rosePinePalette: () => rosePinePalette,
50235
- scoreChartType: () => scoreChartType,
50236
- seriesColors: () => seriesColors,
50237
- shade: () => shade,
50238
- shapeFill: () => shapeFill,
50239
- solarizedPalette: () => solarizedPalette,
50240
- suggestChartTypes: () => suggestChartTypes,
50241
- tint: () => tint,
50242
- tokyoNightPalette: () => tokyoNightPalette,
50243
- truncateBareUrl: () => truncateBareUrl,
50244
- validateComputed: () => validateComputed,
50245
- validateInfra: () => validateInfra,
50246
- validateLabelCharacters: () => validateLabelCharacters
49629
+ palettes: () => palettes,
49630
+ render: () => render2,
49631
+ themes: () => themes,
49632
+ validate: () => parseDgmo
50247
49633
  });
50248
49634
  module.exports = __toCommonJS(index_exports);
50249
- init_diagnostics();
50250
- init_arrows();
50251
49635
 
50252
49636
  // src/render.ts
50253
49637
  init_d3();
@@ -50256,7 +49640,7 @@ init_dgmo_router();
50256
49640
  init_registry();
50257
49641
  async function ensureDom() {
50258
49642
  if (typeof document !== "undefined") return;
50259
- const { JSDOM } = await import("jsdom");
49643
+ const { JSDOM } = await loadJsdom();
50260
49644
  const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>");
50261
49645
  const win = dom.window;
50262
49646
  Object.defineProperty(globalThis, "document", {
@@ -50280,6 +49664,14 @@ async function ensureDom() {
50280
49664
  configurable: true
50281
49665
  });
50282
49666
  }
49667
+ async function loadJsdom() {
49668
+ const spec = ["js", "dom"].join("");
49669
+ return import(
49670
+ /* @vite-ignore */
49671
+ /* webpackIgnore: true */
49672
+ spec
49673
+ );
49674
+ }
50283
49675
  async function render(content, options) {
50284
49676
  const theme = options?.theme ?? "light";
50285
49677
  const paletteName = options?.palette ?? "nord";
@@ -50308,933 +49700,6 @@ async function render(content, options) {
50308
49700
  return { svg, diagnostics };
50309
49701
  }
50310
49702
 
50311
- // src/index.ts
50312
- init_chart_types();
50313
-
50314
- // src/chart-type-scoring.ts
50315
- init_chart_types();
50316
- var TYPOGRAPHIC_REPLACEMENTS = [
50317
- [/[‘’]/g, "'"],
50318
- // curly single quotes
50319
- [/[“”]/g, '"'],
50320
- // curly double quotes
50321
- [/[–—]/g, "-"],
50322
- // en/em dash
50323
- [/×/g, "x"]
50324
- // unicode multiplication → ASCII (for "2×2" vs "2x2")
50325
- ];
50326
- function normalize(s) {
50327
- let out = s.normalize("NFKD").toLowerCase();
50328
- for (const [re, repl] of TYPOGRAPHIC_REPLACEMENTS)
50329
- out = out.replace(re, repl);
50330
- return out.split(/[^a-z0-9]+/).filter(Boolean);
50331
- }
50332
- function matchesContiguously(promptTokens, triggerTokens) {
50333
- if (triggerTokens.length === 0 || triggerTokens.length > promptTokens.length)
50334
- return false;
50335
- outer: for (let i = 0; i <= promptTokens.length - triggerTokens.length; i++) {
50336
- for (let j = 0; j < triggerTokens.length; j++) {
50337
- if (promptTokens[i + j] !== triggerTokens[j]) continue outer;
50338
- }
50339
- return true;
50340
- }
50341
- return false;
50342
- }
50343
- function scoreChartType(prompt, type) {
50344
- const promptTokens = normalize(prompt);
50345
- const matched = [];
50346
- let score = 0;
50347
- for (const trigger of type.triggers) {
50348
- const triggerTokens = normalize(trigger);
50349
- if (matchesContiguously(promptTokens, triggerTokens)) {
50350
- matched.push(trigger);
50351
- score += triggerTokens.length;
50352
- }
50353
- }
50354
- const descTokens = new Set(normalize(type.description));
50355
- let descHits = 0;
50356
- for (const t of promptTokens) if (descTokens.has(t)) descHits++;
50357
- score += descHits * 0.25;
50358
- return { score, matched };
50359
- }
50360
- var MIN_PRIMARY_SCORE = 1;
50361
- var AMBIGUITY_THRESHOLD = 0.5;
50362
- function confidence(top, second) {
50363
- if (top < MIN_PRIMARY_SCORE) return "ambiguous";
50364
- if (second === 0) return "high";
50365
- if (top >= second * 2) return "high";
50366
- if (top - second < AMBIGUITY_THRESHOLD) return "ambiguous";
50367
- return "medium";
50368
- }
50369
- function suggestChartTypes(prompt) {
50370
- const scored = [];
50371
- for (const type of chartTypes) {
50372
- const { score, matched } = scoreChartType(prompt, type);
50373
- if (score > 0) scored.push({ type, score, matched });
50374
- }
50375
- scored.sort((a, b) => b.score - a.score);
50376
- const fallback = chartTypes.filter((c) => c.fallback);
50377
- const topScore = scored[0]?.score ?? 0;
50378
- const secondScore = scored[1]?.score ?? 0;
50379
- const fellBack = topScore < MIN_PRIMARY_SCORE;
50380
- return {
50381
- ranked: scored,
50382
- fallback,
50383
- confidence: confidence(topScore, secondScore),
50384
- fellBack
50385
- };
50386
- }
50387
-
50388
- // src/index.ts
50389
- init_dgmo_router();
50390
- init_chart();
50391
- init_echarts();
50392
- init_d3();
50393
- init_time_ticks();
50394
- init_parser();
50395
- init_participant_inference();
50396
- init_flowchart_parser();
50397
- init_state_parser();
50398
- init_state_renderer();
50399
-
50400
- // src/graph/state-collapse.ts
50401
- function collapseStateGroups(parsed, collapsedGroups) {
50402
- const originalGroups = parsed.groups ?? [];
50403
- if (collapsedGroups.size === 0 || originalGroups.length === 0) {
50404
- return { parsed, collapsedChildCounts: /* @__PURE__ */ new Map(), originalGroups };
50405
- }
50406
- const groupById = /* @__PURE__ */ new Map();
50407
- for (const group of originalGroups) {
50408
- groupById.set(group.id, group);
50409
- }
50410
- const nodeToGroup = /* @__PURE__ */ new Map();
50411
- const collapsedChildCounts = /* @__PURE__ */ new Map();
50412
- for (const groupId3 of collapsedGroups) {
50413
- const group = groupById.get(groupId3);
50414
- if (!group) continue;
50415
- for (const nodeId3 of group.nodeIds) {
50416
- nodeToGroup.set(nodeId3, groupId3);
50417
- }
50418
- collapsedChildCounts.set(groupId3, group.nodeIds.length);
50419
- }
50420
- const nodes = parsed.nodes.filter((n) => !nodeToGroup.has(n.id));
50421
- const edgeKeys = /* @__PURE__ */ new Set();
50422
- const edges = [];
50423
- for (const edge of parsed.edges) {
50424
- const src = nodeToGroup.get(edge.source) ?? edge.source;
50425
- const tgt = nodeToGroup.get(edge.target) ?? edge.target;
50426
- if (src === tgt && src !== edge.source) continue;
50427
- const key = `${src}|${tgt}|${edge.label ?? ""}`;
50428
- if (edgeKeys.has(key)) continue;
50429
- edgeKeys.add(key);
50430
- edges.push({ ...edge, source: src, target: tgt });
50431
- }
50432
- const groups = originalGroups.filter((g) => !collapsedGroups.has(g.id));
50433
- return {
50434
- parsed: { ...parsed, nodes, edges, groups },
50435
- collapsedChildCounts,
50436
- originalGroups
50437
- };
50438
- }
50439
-
50440
- // src/index.ts
50441
- init_parser2();
50442
- init_layout3();
50443
- init_renderer4();
50444
- init_parser3();
50445
- init_layout4();
50446
- init_renderer5();
50447
- init_inline_markdown();
50448
- init_name_normalize();
50449
- init_parser4();
50450
- init_layout();
50451
- init_renderer();
50452
- init_parser5();
50453
- init_mutations();
50454
- init_renderer3();
50455
- init_parser6();
50456
- init_layout8();
50457
- init_renderer9();
50458
- init_parser11();
50459
- init_layout5();
50460
- init_renderer6();
50461
-
50462
- // src/boxes-and-lines/collapse.ts
50463
- function collapseBoxesAndLines(parsed, collapsedGroups) {
50464
- const originalGroups = parsed.groups;
50465
- if (collapsedGroups.size === 0) {
50466
- return { parsed, collapsedChildCounts: /* @__PURE__ */ new Map(), originalGroups };
50467
- }
50468
- const groupByLabel = /* @__PURE__ */ new Map();
50469
- for (const group of parsed.groups) {
50470
- groupByLabel.set(group.label, group);
50471
- }
50472
- const nodeToGroup = /* @__PURE__ */ new Map();
50473
- const collapsedChildCounts = /* @__PURE__ */ new Map();
50474
- function collectDescendants(groupLabel) {
50475
- const group = groupByLabel.get(groupLabel);
50476
- if (!group) return [];
50477
- const descendants = [];
50478
- for (const child of group.children) {
50479
- descendants.push(child);
50480
- if (groupByLabel.has(child)) {
50481
- descendants.push(...collectDescendants(child));
50482
- }
50483
- }
50484
- return descendants;
50485
- }
50486
- for (const groupLabel of collapsedGroups) {
50487
- const group = groupByLabel.get(groupLabel);
50488
- if (!group) continue;
50489
- const groupId3 = `__group_${groupLabel}`;
50490
- const allDescendants = collectDescendants(groupLabel);
50491
- for (const child of allDescendants) {
50492
- nodeToGroup.set(child, groupId3);
50493
- }
50494
- collapsedChildCounts.set(groupLabel, group.children.length);
50495
- }
50496
- const nodes = parsed.nodes.filter((n) => !nodeToGroup.has(n.label));
50497
- const edgeKeys = /* @__PURE__ */ new Set();
50498
- const edges = [];
50499
- for (const edge of parsed.edges) {
50500
- const src = nodeToGroup.get(edge.source) ?? edge.source;
50501
- const tgt = nodeToGroup.get(edge.target) ?? edge.target;
50502
- if (src === tgt) continue;
50503
- const key = `${src}|${tgt}|${edge.label ?? ""}`;
50504
- if (edgeKeys.has(key)) continue;
50505
- edgeKeys.add(key);
50506
- edges.push({ ...edge, source: src, target: tgt });
50507
- }
50508
- const groups = parsed.groups.filter(
50509
- (g) => !collapsedGroups.has(g.label) && !nodeToGroup.has(g.label)
50510
- );
50511
- return {
50512
- parsed: { ...parsed, nodes, edges, groups },
50513
- collapsedChildCounts,
50514
- originalGroups
50515
- };
50516
- }
50517
-
50518
- // src/index.ts
50519
- init_parser7();
50520
- init_layout2();
50521
- init_renderer2();
50522
- init_collapse2();
50523
- init_parser8();
50524
- init_types();
50525
- init_compute();
50526
-
50527
- // src/infra/validation.ts
50528
- function detectCycles(parsed) {
50529
- const diagnostics = [];
50530
- const adj = /* @__PURE__ */ new Map();
50531
- const edgeLines = /* @__PURE__ */ new Map();
50532
- for (const edge of parsed.edges) {
50533
- const list = adj.get(edge.sourceId) ?? [];
50534
- list.push(edge.targetId);
50535
- adj.set(edge.sourceId, list);
50536
- edgeLines.set(`${edge.sourceId}->${edge.targetId}`, edge.lineNumber);
50537
- }
50538
- const color = /* @__PURE__ */ new Map();
50539
- const parent = /* @__PURE__ */ new Map();
50540
- function dfs(nodeId3) {
50541
- color.set(nodeId3, 1);
50542
- const neighbors = adj.get(nodeId3) ?? [];
50543
- for (const next of neighbors) {
50544
- const c = color.get(next) ?? 0;
50545
- if (c === 1) {
50546
- const lineKey = `${nodeId3}->${next}`;
50547
- diagnostics.push({
50548
- type: "CYCLE",
50549
- line: edgeLines.get(lineKey) ?? 0,
50550
- message: `Cycle detected: ${nodeId3} -> ${next} creates a circular reference.`
50551
- });
50552
- return true;
50553
- }
50554
- if (c === 0) {
50555
- parent.set(next, nodeId3);
50556
- if (dfs(next)) return true;
50557
- }
50558
- }
50559
- color.set(nodeId3, 2);
50560
- return false;
50561
- }
50562
- for (const node of parsed.nodes) {
50563
- if ((color.get(node.id) ?? 0) === 0) {
50564
- dfs(node.id);
50565
- }
50566
- }
50567
- return diagnostics;
50568
- }
50569
- function validateSplits(parsed) {
50570
- const diagnostics = [];
50571
- const outbound = /* @__PURE__ */ new Map();
50572
- for (const edge of parsed.edges) {
50573
- const list = outbound.get(edge.sourceId) ?? [];
50574
- list.push(edge);
50575
- outbound.set(edge.sourceId, list);
50576
- }
50577
- for (const [sourceId, edges] of outbound) {
50578
- if (edges.length <= 1) continue;
50579
- const declared = edges.filter((e) => e.split !== null);
50580
- if (declared.length === edges.length) {
50581
- const sum = declared.reduce((s, e) => s + (e.split ?? 0), 0);
50582
- if (Math.abs(sum - 100) > 0.01) {
50583
- diagnostics.push({
50584
- type: "SPLIT_SUM",
50585
- line: declared[0].lineNumber,
50586
- message: `Splits from '${sourceId}' sum to ${sum}%, expected 100%.`
50587
- });
50588
- }
50589
- } else if (declared.length > 0) {
50590
- const declaredSum = declared.reduce((s, e) => s + (e.split ?? 0), 0);
50591
- if (declaredSum > 100) {
50592
- diagnostics.push({
50593
- type: "SPLIT_SUM",
50594
- line: declared[0].lineNumber,
50595
- message: `Declared splits from '${sourceId}' sum to ${declaredSum}%, exceeding 100%.`
50596
- });
50597
- }
50598
- }
50599
- }
50600
- return diagnostics;
50601
- }
50602
- function detectOrphans(parsed) {
50603
- const diagnostics = [];
50604
- const edgeNode = parsed.nodes.find((n) => n.isEdge);
50605
- if (!edgeNode) return diagnostics;
50606
- const reachable = /* @__PURE__ */ new Set();
50607
- const adj = /* @__PURE__ */ new Map();
50608
- for (const edge of parsed.edges) {
50609
- const list = adj.get(edge.sourceId) ?? [];
50610
- list.push(edge.targetId);
50611
- adj.set(edge.sourceId, list);
50612
- }
50613
- const queue = [edgeNode.id];
50614
- while (queue.length > 0) {
50615
- const id = queue.shift();
50616
- if (reachable.has(id)) continue;
50617
- reachable.add(id);
50618
- for (const next of adj.get(id) ?? []) {
50619
- queue.push(next);
50620
- }
50621
- }
50622
- for (const group of parsed.groups) {
50623
- if (reachable.has(group.id)) {
50624
- for (const node of parsed.nodes) {
50625
- if (node.groupId === group.id) reachable.add(node.id);
50626
- }
50627
- }
50628
- }
50629
- for (const node of parsed.nodes) {
50630
- if (!node.isEdge && !reachable.has(node.id)) {
50631
- diagnostics.push({
50632
- type: "ORPHAN",
50633
- line: node.lineNumber,
50634
- message: `Component '${node.label}' is not reachable from the edge entry point.`
50635
- });
50636
- }
50637
- }
50638
- return diagnostics;
50639
- }
50640
- function validateInfra(parsed) {
50641
- return [
50642
- ...detectCycles(parsed),
50643
- ...validateSplits(parsed),
50644
- ...detectOrphans(parsed)
50645
- ];
50646
- }
50647
- function validateComputed(computed) {
50648
- const diagnostics = [];
50649
- if (computed.systemUptime > 0 && computed.systemUptime < 0.99) {
50650
- const pct = (computed.systemUptime * 100).toFixed(2);
50651
- diagnostics.push({
50652
- type: "UPTIME",
50653
- line: 1,
50654
- message: `System uptime is ${pct}%, below 99% SLA threshold.`
50655
- });
50656
- }
50657
- return diagnostics;
50658
- }
50659
-
50660
- // src/index.ts
50661
- init_roles();
50662
- init_layout10();
50663
- init_renderer10();
50664
- init_parser9();
50665
- init_calculator();
50666
- init_renderer12();
50667
- init_resolver();
50668
- init_parser10();
50669
- init_analyzer();
50670
- init_layout11();
50671
-
50672
- // src/pert/share-normalize.ts
50673
- init_internal();
50674
- var START_DATE_NOW_RE = /^(\s*start-date\s+)now(\s*)$/i;
50675
- function splitTrailingComment(line12) {
50676
- const m = line12.match(/^(.*?)(\s+#.*)$/);
50677
- if (!m) return { code: line12, comment: "" };
50678
- return { code: m[1], comment: m[2] };
50679
- }
50680
- function normalizePertSourceForShare(dsl) {
50681
- const today = formatLocalISODate(/* @__PURE__ */ new Date());
50682
- const lines = dsl.split("\n");
50683
- const out = [];
50684
- for (const line12 of lines) {
50685
- const { code, comment } = splitTrailingComment(line12);
50686
- const m = code.match(START_DATE_NOW_RE);
50687
- if (m) {
50688
- out.push(`${m[1]}${today}${m[2]}${comment}`);
50689
- } else {
50690
- out.push(line12);
50691
- }
50692
- }
50693
- return out.join("\n");
50694
- }
50695
-
50696
- // src/index.ts
50697
- init_renderer11();
50698
- init_collapse();
50699
- init_parser12();
50700
- init_layout6();
50701
- init_renderer7();
50702
- init_collapse3();
50703
- init_parser13();
50704
- init_layout7();
50705
- init_renderer8();
50706
- init_parser14();
50707
- init_layout12();
50708
- init_renderer13();
50709
- init_interactive();
50710
- init_parser15();
50711
- init_layout14();
50712
- init_renderer15();
50713
- init_parser16();
50714
- init_layout13();
50715
- init_renderer14();
50716
- init_parser17();
50717
- init_renderer16();
50718
- init_parser18();
50719
- init_renderer17();
50720
-
50721
- // src/raci/index.ts
50722
- init_parser19();
50723
- init_renderer18();
50724
-
50725
- // src/raci/mutations.ts
50726
- init_parsing();
50727
- init_parser19();
50728
- function cellReplace(content, parsed, taskId, roleId, marker) {
50729
- const task = findTask(parsed, taskId);
50730
- if (!task) return null;
50731
- const lines = content.split("\n");
50732
- const existing = task.roleAssignments.find((a) => a.id === roleId);
50733
- if (existing) {
50734
- if (marker !== null && existing.markers.length === 1 && existing.markers[0] === marker) {
50735
- return null;
50736
- }
50737
- if (marker === null && existing.markers.length === 0) {
50738
- return null;
50739
- }
50740
- if (marker === null) {
50741
- lines.splice(existing.lineNumber - 1, 1);
50742
- return lines.join("\n");
50743
- }
50744
- lines[existing.lineNumber - 1] = rewriteAssignmentLine(
50745
- lines[existing.lineNumber - 1],
50746
- existing.displayName,
50747
- [marker]
50748
- );
50749
- return lines.join("\n");
50750
- }
50751
- if (marker === null) return null;
50752
- const roleDisplay = lookupRoleDisplay(parsed, roleId);
50753
- if (!roleDisplay) return null;
50754
- const indent = inferAssignmentIndent(task, lines);
50755
- const insertAt = insertionLineFor(task, roleId, parsed);
50756
- const newLine = `${" ".repeat(indent)}${roleDisplay}: ${marker}`;
50757
- lines.splice(insertAt, 0, newLine);
50758
- return lines.join("\n");
50759
- }
50760
- function cellAppendMarker(content, parsed, taskId, roleId, marker) {
50761
- const task = findTask(parsed, taskId);
50762
- if (!task) return null;
50763
- const existing = task.roleAssignments.find((a) => a.id === roleId);
50764
- if (!existing) {
50765
- return cellReplace(content, parsed, taskId, roleId, marker);
50766
- }
50767
- if (existing.markers.includes(marker)) return null;
50768
- const lines = content.split("\n");
50769
- lines[existing.lineNumber - 1] = rewriteAssignmentLine(
50770
- lines[existing.lineNumber - 1],
50771
- existing.displayName,
50772
- [...existing.markers, marker]
50773
- );
50774
- return lines.join("\n");
50775
- }
50776
- function cellRemove(content, parsed, taskId, roleId, marker) {
50777
- const task = findTask(parsed, taskId);
50778
- if (!task) return null;
50779
- const existing = task.roleAssignments.find((a) => a.id === roleId);
50780
- if (!existing) return null;
50781
- const lines = content.split("\n");
50782
- let nextMarkers;
50783
- if (marker === void 0) {
50784
- nextMarkers = [];
50785
- } else {
50786
- if (!existing.markers.includes(marker)) return null;
50787
- nextMarkers = existing.markers.filter((m) => m !== marker);
50788
- }
50789
- if (nextMarkers.length === 0) {
50790
- lines.splice(existing.lineNumber - 1, 1);
50791
- return lines.join("\n");
50792
- }
50793
- lines[existing.lineNumber - 1] = rewriteAssignmentLine(
50794
- lines[existing.lineNumber - 1],
50795
- existing.displayName,
50796
- nextMarkers
50797
- );
50798
- return lines.join("\n");
50799
- }
50800
- function cellCycle(content, parsed, taskId, roleId, alphabet) {
50801
- if (alphabet.length === 0) return null;
50802
- const task = findTask(parsed, taskId);
50803
- if (!task) return null;
50804
- const existing = task.roleAssignments.find((a) => a.id === roleId);
50805
- const current = existing?.markers ?? [];
50806
- let next;
50807
- if (current.length === 0) {
50808
- next = alphabet[0];
50809
- } else {
50810
- const dominant = current[0];
50811
- const idx = alphabet.indexOf(dominant);
50812
- if (idx < 0) {
50813
- next = alphabet[0];
50814
- } else if (idx === alphabet.length - 1) {
50815
- next = null;
50816
- } else {
50817
- next = alphabet[idx + 1];
50818
- }
50819
- }
50820
- return cellReplace(content, parsed, taskId, roleId, next);
50821
- }
50822
- function findTask(parsed, taskId) {
50823
- for (const t of allTasks(parsed)) {
50824
- if (t.id === taskId) return t;
50825
- }
50826
- return null;
50827
- }
50828
- function lookupRoleDisplay(parsed, roleId) {
50829
- const idx = parsed.roles.indexOf(roleId);
50830
- if (idx < 0) return null;
50831
- return parsed.roleDisplayNames[idx] ?? null;
50832
- }
50833
- function rewriteAssignmentLine(originalLine, displayName2, markers) {
50834
- const indent = measureIndent(originalLine);
50835
- return `${" ".repeat(indent)}${displayName2}: ${markers.join(" ")}`;
50836
- }
50837
- function inferAssignmentIndent(task, lines) {
50838
- if (task.roleAssignments.length > 0) {
50839
- return measureIndent(lines[task.roleAssignments[0].lineNumber - 1]);
50840
- }
50841
- const taskIndent = measureIndent(lines[task.lineNumber - 1]);
50842
- return taskIndent + 2;
50843
- }
50844
- function insertionLineFor(task, roleId, parsed) {
50845
- if (task.roleAssignments.length === 0) {
50846
- return task.endLineNumber;
50847
- }
50848
- const targetIdx = parsed.roles.indexOf(roleId);
50849
- const lastAssignmentLine = Math.max(
50850
- ...task.roleAssignments.map((a) => a.endLineNumber)
50851
- );
50852
- if (targetIdx < 0) {
50853
- return lastAssignmentLine;
50854
- }
50855
- for (const a of task.roleAssignments) {
50856
- const aIdx = parsed.roles.indexOf(a.id);
50857
- if (aIdx > targetIdx) {
50858
- return a.lineNumber - 1;
50859
- }
50860
- }
50861
- return lastAssignmentLine;
50862
- }
50863
-
50864
- // src/raci/index.ts
50865
- init_variants();
50866
-
50867
- // src/org/resolver.ts
50868
- init_diagnostics();
50869
- init_tag_groups();
50870
- var MAX_DEPTH = 10;
50871
- var IMPORT_RE = /^(\s+)import:?\s+(.+\.dgmo)\s*$/i;
50872
- var TAGS_RE = /^tags:?\s+(.+\.dgmo)\s*$/i;
50873
- var HEADER_RE = /^(org|kanban|title\s*:)/i;
50874
- var KNOWN_HEADER_OPTIONS = /* @__PURE__ */ new Set([
50875
- "direction-tb",
50876
- "sub-node-label",
50877
- "hide",
50878
- "show-sub-node-count",
50879
- "color-off",
50880
- "solid-fill",
50881
- "active-tag"
50882
- ]);
50883
- function dirname(filePath) {
50884
- const last = filePath.lastIndexOf("/");
50885
- return last > 0 ? filePath.substring(0, last) : "/";
50886
- }
50887
- function resolvePath(base, relative) {
50888
- const parts = dirname(base).split("/");
50889
- for (const seg of relative.split("/")) {
50890
- if (seg === "..") {
50891
- if (parts.length > 1) parts.pop();
50892
- } else if (seg !== "." && seg !== "") {
50893
- parts.push(seg);
50894
- }
50895
- }
50896
- return parts.join("/") || "/";
50897
- }
50898
- function extractTagGroups(lines) {
50899
- const blocks = [];
50900
- let current = null;
50901
- for (const line12 of lines) {
50902
- const trimmed = line12.trim();
50903
- const headingMatch = matchTagBlockHeading(trimmed);
50904
- if (headingMatch) {
50905
- const name = headingMatch.name.toLowerCase();
50906
- current = { name, lines: [line12] };
50907
- blocks.push(current);
50908
- } else if (current) {
50909
- if (trimmed === "" || trimmed.startsWith("//")) {
50910
- current = null;
50911
- } else if (line12.match(/^\s+/)) {
50912
- current.lines.push(line12);
50913
- } else {
50914
- current = null;
50915
- }
50916
- }
50917
- }
50918
- return blocks;
50919
- }
50920
- function parseFileHeader(lines) {
50921
- const tagGroups = extractTagGroups(lines);
50922
- const tagGroupLineSet = /* @__PURE__ */ new Set();
50923
- for (const group of tagGroups) {
50924
- for (let i = 0; i < lines.length; i++) {
50925
- if (lines[i] === group.lines[0]) {
50926
- for (let j = 0; j < group.lines.length; j++) {
50927
- tagGroupLineSet.add(i + j);
50928
- }
50929
- break;
50930
- }
50931
- }
50932
- }
50933
- let tagsDirective = null;
50934
- const contentLines = [];
50935
- const contentLineIndices = [];
50936
- let headerDone = false;
50937
- for (let i = 0; i < lines.length; i++) {
50938
- if (tagGroupLineSet.has(i)) continue;
50939
- const trimmed = lines[i].trim();
50940
- if (!headerDone && (trimmed === "" || trimmed.startsWith("//"))) continue;
50941
- if (!headerDone) {
50942
- if (HEADER_RE.test(trimmed)) continue;
50943
- const tagsMatch = trimmed.match(TAGS_RE);
50944
- if (tagsMatch) {
50945
- tagsDirective = tagsMatch[1].trim();
50946
- continue;
50947
- }
50948
- if (!lines[i].match(/^\s/) && !isTagBlockHeading(trimmed) && !trimmed.includes("|")) {
50949
- const firstToken = trimmed.split(/\s/)[0].toLowerCase();
50950
- if (KNOWN_HEADER_OPTIONS.has(firstToken)) {
50951
- continue;
50952
- }
50953
- }
50954
- headerDone = true;
50955
- }
50956
- contentLines.push(lines[i]);
50957
- contentLineIndices.push(i);
50958
- }
50959
- return { contentLines, contentLineIndices, tagGroups, tagsDirective };
50960
- }
50961
- async function resolveOrgImports(content, filePath, readFileFn) {
50962
- const diagnostics = [];
50963
- const result = await resolveFile(
50964
- content,
50965
- filePath,
50966
- readFileFn,
50967
- diagnostics,
50968
- /* @__PURE__ */ new Set([filePath]),
50969
- 0
50970
- );
50971
- return {
50972
- content: result.content,
50973
- diagnostics,
50974
- lineMap: result.lineMap,
50975
- importSourceMap: result.importSourceMap
50976
- };
50977
- }
50978
- async function resolveFile(content, filePath, readFileFn, diagnostics, ancestorChain, depth) {
50979
- const lines = content.split("\n");
50980
- const headerLines = [];
50981
- let tagsDirective = null;
50982
- const inlineTagGroups = extractTagGroups(lines);
50983
- const bodyStartIndex = findBodyStart(lines);
50984
- let tagsLineNumber = 0;
50985
- for (let i = 0; i < bodyStartIndex; i++) {
50986
- const trimmed = lines[i].trim();
50987
- if (trimmed === "" || trimmed.startsWith("//")) {
50988
- headerLines.push({ text: lines[i], originalLine: i + 1 });
50989
- continue;
50990
- }
50991
- if (isTagBlockHeading(trimmed)) continue;
50992
- if (/^\s/.test(lines[i])) continue;
50993
- const tagsMatch = trimmed.match(TAGS_RE);
50994
- if (tagsMatch) {
50995
- tagsDirective = tagsMatch[1].trim();
50996
- tagsLineNumber = i + 1;
50997
- continue;
50998
- }
50999
- headerLines.push({ text: lines[i], originalLine: i + 1 });
51000
- }
51001
- let tagsFileGroups = [];
51002
- if (tagsDirective) {
51003
- const tagsPath = resolvePath(filePath, tagsDirective);
51004
- try {
51005
- const tagsContent = await readFileFn(tagsPath);
51006
- const tagsLines = tagsContent.split("\n");
51007
- tagsFileGroups = extractTagGroups(tagsLines);
51008
- } catch {
51009
- diagnostics.push(
51010
- makeDgmoError(tagsLineNumber, `Tags file not found: ${tagsDirective}`)
51011
- );
51012
- }
51013
- }
51014
- const bodyLines = lines.slice(bodyStartIndex);
51015
- const resolvedBodyLines = [];
51016
- const importedTagGroups = [];
51017
- for (let i = 0; i < bodyLines.length; i++) {
51018
- const line12 = bodyLines[i];
51019
- const lineNumber = bodyStartIndex + i + 1;
51020
- const importMatch = line12.match(IMPORT_RE);
51021
- if (!importMatch) {
51022
- const trimmed = line12.trim();
51023
- if (isTagBlockHeading(trimmed) || inlineTagGroups.length > 0 && isTagGroupEntry(line12, bodyLines, i)) {
51024
- continue;
51025
- }
51026
- resolvedBodyLines.push({
51027
- text: line12,
51028
- originalLine: lineNumber,
51029
- importSource: null
51030
- });
51031
- continue;
51032
- }
51033
- const indent = importMatch[1];
51034
- const importRelPath = importMatch[2].trim();
51035
- const importAbsPath = resolvePath(filePath, importRelPath);
51036
- if (depth >= MAX_DEPTH) {
51037
- diagnostics.push(
51038
- makeDgmoError(
51039
- lineNumber,
51040
- `Import depth limit exceeded (${MAX_DEPTH}): ${importRelPath}`
51041
- )
51042
- );
51043
- continue;
51044
- }
51045
- if (ancestorChain.has(importAbsPath)) {
51046
- const chain = [...ancestorChain, importAbsPath].map((p) => p.split("/").pop()).join(" -> ");
51047
- diagnostics.push(
51048
- makeDgmoError(lineNumber, `Circular import detected: ${chain}`)
51049
- );
51050
- continue;
51051
- }
51052
- let importedContent;
51053
- try {
51054
- importedContent = await readFileFn(importAbsPath);
51055
- } catch {
51056
- diagnostics.push(
51057
- makeDgmoError(lineNumber, `Import file not found: ${importRelPath}`)
51058
- );
51059
- continue;
51060
- }
51061
- const nestedChain = new Set(ancestorChain);
51062
- nestedChain.add(importAbsPath);
51063
- const resolved = await resolveFile(
51064
- importedContent,
51065
- importAbsPath,
51066
- readFileFn,
51067
- diagnostics,
51068
- nestedChain,
51069
- depth + 1
51070
- );
51071
- const resolvedLines = resolved.content.split("\n");
51072
- const parsed = parseFileHeader(resolvedLines);
51073
- for (const group of parsed.tagGroups) {
51074
- importedTagGroups.push(group);
51075
- }
51076
- const importedContentLines = [];
51077
- for (let j = 0; j < parsed.contentLines.length; j++) {
51078
- if (parsed.contentLines[j].trim() !== "") {
51079
- importedContentLines.push({
51080
- text: parsed.contentLines[j],
51081
- index: parsed.contentLineIndices[j]
51082
- });
51083
- }
51084
- }
51085
- let lastNonEmpty = importedContentLines.length - 1;
51086
- while (lastNonEmpty >= 0 && importedContentLines[lastNonEmpty].text.trim() === "") {
51087
- lastNonEmpty--;
51088
- }
51089
- const trimmedImported = importedContentLines.slice(0, lastNonEmpty + 1);
51090
- for (const entry of trimmedImported) {
51091
- const resolvedLineNum = entry.index + 1;
51092
- let importSource = null;
51093
- if (resolved.importSourceMap[resolvedLineNum]) {
51094
- importSource = resolved.importSourceMap[resolvedLineNum];
51095
- } else {
51096
- const origLine = resolved.lineMap[resolvedLineNum];
51097
- if (origLine != null) {
51098
- importSource = { filePath: importAbsPath, sourceLine: origLine };
51099
- }
51100
- }
51101
- if (entry.text.trim() === "") {
51102
- resolvedBodyLines.push({
51103
- text: "",
51104
- originalLine: lineNumber,
51105
- importSource
51106
- });
51107
- } else {
51108
- resolvedBodyLines.push({
51109
- text: indent + entry.text,
51110
- originalLine: lineNumber,
51111
- importSource
51112
- });
51113
- }
51114
- }
51115
- }
51116
- const mergedGroups = mergeTagGroups(
51117
- inlineTagGroups,
51118
- tagsFileGroups,
51119
- importedTagGroups
51120
- );
51121
- const outputLines = [];
51122
- const lineMap = [null];
51123
- const importSourceMap = [null];
51124
- for (const entry of headerLines) {
51125
- outputLines.push(entry.text);
51126
- lineMap.push(entry.originalLine);
51127
- importSourceMap.push(null);
51128
- }
51129
- if (mergedGroups.length > 0) {
51130
- if (outputLines.length > 0 && outputLines[outputLines.length - 1].trim() !== "") {
51131
- outputLines.push("");
51132
- lineMap.push(null);
51133
- importSourceMap.push(null);
51134
- }
51135
- for (const group of mergedGroups) {
51136
- const inlineMatch = inlineTagGroups.find((g) => g.name === group.name);
51137
- for (const line12 of group.lines) {
51138
- outputLines.push(line12);
51139
- if (inlineMatch) {
51140
- const srcIdx = lines.indexOf(line12);
51141
- lineMap.push(srcIdx >= 0 ? srcIdx + 1 : null);
51142
- } else {
51143
- lineMap.push(null);
51144
- }
51145
- importSourceMap.push(null);
51146
- }
51147
- outputLines.push("");
51148
- lineMap.push(null);
51149
- importSourceMap.push(null);
51150
- }
51151
- }
51152
- if (resolvedBodyLines.length > 0 && outputLines.length > 0 && outputLines[outputLines.length - 1].trim() !== "") {
51153
- outputLines.push("");
51154
- lineMap.push(null);
51155
- importSourceMap.push(null);
51156
- }
51157
- for (const entry of resolvedBodyLines) {
51158
- outputLines.push(entry.text);
51159
- lineMap.push(entry.originalLine);
51160
- importSourceMap.push(entry.importSource);
51161
- }
51162
- return { content: outputLines.join("\n"), lineMap, importSourceMap };
51163
- }
51164
- function findBodyStart(lines) {
51165
- let inTagGroup = false;
51166
- for (let i = 0; i < lines.length; i++) {
51167
- const trimmed = lines[i].trim();
51168
- if (trimmed === "" || trimmed.startsWith("//")) {
51169
- if (inTagGroup) inTagGroup = false;
51170
- continue;
51171
- }
51172
- if (isTagBlockHeading(trimmed)) {
51173
- inTagGroup = true;
51174
- continue;
51175
- }
51176
- if (inTagGroup && lines[i].match(/^\s+/)) {
51177
- continue;
51178
- }
51179
- if (inTagGroup) {
51180
- inTagGroup = false;
51181
- }
51182
- if (HEADER_RE.test(trimmed)) continue;
51183
- if (TAGS_RE.test(trimmed)) continue;
51184
- if (!lines[i].match(/^\s/) && !trimmed.includes("|") && !isTagBlockHeading(trimmed)) {
51185
- const firstToken = trimmed.split(/\s/)[0].toLowerCase();
51186
- if (KNOWN_HEADER_OPTIONS.has(firstToken)) {
51187
- continue;
51188
- }
51189
- }
51190
- return i;
51191
- }
51192
- return lines.length;
51193
- }
51194
- function isTagGroupEntry(line12, allLines, index) {
51195
- if (!line12.match(/^\s+/)) return false;
51196
- for (let i = index - 1; i >= 0; i--) {
51197
- const prev = allLines[i].trim();
51198
- if (prev === "" || prev.startsWith("//")) continue;
51199
- if (isTagBlockHeading(prev)) return true;
51200
- if (allLines[i].match(/^\s+/)) continue;
51201
- return false;
51202
- }
51203
- return false;
51204
- }
51205
- function mergeTagGroups(inline, tagsFile, imported) {
51206
- const seen = /* @__PURE__ */ new Map();
51207
- for (const group of inline) {
51208
- seen.set(group.name, group);
51209
- }
51210
- for (const group of tagsFile) {
51211
- if (!seen.has(group.name)) {
51212
- seen.set(group.name, group);
51213
- }
51214
- }
51215
- for (const group of imported) {
51216
- if (!seen.has(group.name)) {
51217
- seen.set(group.name, group);
51218
- }
51219
- }
51220
- return Array.from(seen.values());
51221
- }
51222
-
51223
- // src/index.ts
51224
- init_layout9();
51225
- init_flowchart_renderer();
51226
- init_echarts();
51227
- init_legend_svg();
51228
- init_legend_constants();
51229
- init_legend_d3();
51230
- init_legend_layout();
51231
- init_d3();
51232
- init_renderer19();
51233
- init_collapse4();
51234
- init_colors();
51235
- init_palettes();
51236
- init_color_utils();
51237
-
51238
49703
  // src/sharing.ts
51239
49704
  var import_lz_string = __toESM(require_lz_string(), 1);
51240
49705
  var DEFAULT_BASE_URL = "https://online.diagrammo.app";
@@ -51326,1453 +49791,87 @@ function decodeDiagramUrl(hash) {
51326
49791
  }
51327
49792
  }
51328
49793
 
51329
- // src/completion.ts
51330
- init_parser3();
51331
- init_flowchart_parser();
51332
- init_parser8();
51333
- init_parser2();
51334
- init_parser10();
51335
- init_parsing();
49794
+ // src/index.ts
51336
49795
  init_dgmo_router();
51337
- var extractorRegistry = /* @__PURE__ */ new Map();
51338
- function registerExtractor(kind, fn) {
51339
- extractorRegistry.set(kind, fn);
51340
- }
51341
- function extractDiagramSymbols(docText) {
51342
- let chartType = null;
51343
- for (const line12 of docText.split("\n")) {
51344
- const trimmed = line12.trim();
51345
- if (!trimmed || trimmed.startsWith("//")) continue;
51346
- const result2 = parseFirstLine(trimmed);
51347
- if (result2) {
51348
- chartType = result2.chartType;
51349
- }
51350
- break;
51351
- }
51352
- if (!chartType) return null;
51353
- const fn = extractorRegistry.get(chartType);
51354
- if (!fn) return null;
51355
- const result = fn(docText);
51356
- const aliases = extractAliasDeclarations(docText);
51357
- return Object.keys(aliases).length > 0 ? { ...result, aliases } : result;
51358
- }
51359
- var GLOBAL_DIRECTIVES = {
51360
- palette: {
51361
- description: "Color palette name",
51362
- values: [
51363
- "nord",
51364
- "solarized",
51365
- "catppuccin",
51366
- "rose-pine",
51367
- "gruvbox",
51368
- "tokyo-night",
51369
- "one-dark",
51370
- "bold",
51371
- "dracula",
51372
- "monokai"
51373
- ]
51374
- },
51375
- theme: {
51376
- description: "Color theme",
51377
- values: ["light", "dark", "transparent"]
51378
- },
51379
- "no-title": {
51380
- description: "Hide the diagram title"
51381
- }
49796
+ init_palettes();
49797
+ init_diagnostics();
49798
+ init_palettes();
49799
+
49800
+ // src/themes.ts
49801
+ var themes = {
49802
+ light: "light",
49803
+ dark: "dark",
49804
+ transparent: "transparent"
51382
49805
  };
51383
- function withGlobals(directives = {}) {
51384
- return { directives: { ...GLOBAL_DIRECTIVES, ...directives } };
51385
- }
51386
- var COMPLETION_REGISTRY = /* @__PURE__ */ new Map([
51387
- // ── Data charts ──────────────────────────────────────────
51388
- [
51389
- "bar",
51390
- withGlobals({
51391
- series: { description: "Series name(s)" },
51392
- "x-label": { description: "X-axis label" },
51393
- "y-label": { description: "Y-axis label" },
51394
- "orientation-horizontal": { description: "Switch to horizontal bars" },
51395
- "no-value": { description: "Hide value labels atop each bar" },
51396
- color: { description: "Bar color override" }
51397
- })
51398
- ],
51399
- [
51400
- "line",
51401
- withGlobals({
51402
- series: { description: "Series name(s)" },
51403
- "x-label": { description: "X-axis label" },
51404
- "y-label": { description: "Y-axis label" },
51405
- "no-value": { description: "Hide value labels at each point" }
51406
- })
51407
- ],
51408
- [
51409
- "pie",
51410
- withGlobals({
51411
- "no-name": { description: "Hide name from segment labels" },
51412
- "no-value": { description: "Hide value from segment labels" },
51413
- "no-percent": { description: "Hide percent from segment labels" }
51414
- })
51415
- ],
51416
- [
51417
- "doughnut",
51418
- withGlobals({
51419
- "no-name": { description: "Hide name from segment labels" },
51420
- "no-value": { description: "Hide value from segment labels" },
51421
- "no-percent": { description: "Hide percent from segment labels" }
51422
- })
51423
- ],
51424
- [
51425
- "area",
51426
- withGlobals({
51427
- series: { description: "Series name(s)" },
51428
- "x-label": { description: "X-axis label" },
51429
- "y-label": { description: "Y-axis label" },
51430
- "no-value": { description: "Hide value labels at each point" }
51431
- })
51432
- ],
51433
- [
51434
- "multi-line",
51435
- withGlobals({
51436
- series: { description: "Series name(s)" },
51437
- "x-label": { description: "X-axis label" },
51438
- "y-label": { description: "Y-axis label" },
51439
- "no-value": { description: "Hide value labels at each point" }
51440
- })
51441
- ],
51442
- [
51443
- "polar-area",
51444
- withGlobals({
51445
- "no-name": { description: "Hide name from segment labels" },
51446
- "no-value": { description: "Hide value from segment labels" },
51447
- "no-percent": { description: "Hide percent from segment labels" }
51448
- })
51449
- ],
51450
- [
51451
- "radar",
51452
- withGlobals({
51453
- "no-value": { description: "Hide value labels at each vertex" }
51454
- })
51455
- ],
51456
- [
51457
- "bar-stacked",
51458
- withGlobals({
51459
- series: { description: "Series name(s) (required)" },
51460
- "x-label": { description: "X-axis label" },
51461
- "y-label": { description: "Y-axis label" },
51462
- "orientation-horizontal": { description: "Switch to horizontal bars" },
51463
- "no-value": { description: "Hide per-segment values inside each stack" }
51464
- })
51465
- ],
51466
- // ── Extended charts ──────────────────────────────────────
51467
- [
51468
- "scatter",
51469
- withGlobals({
51470
- "no-name": { description: "Hide point labels" },
51471
- "x-label": { description: "X-axis label" },
51472
- "y-label": { description: "Y-axis label" },
51473
- "size-label": { description: "Size axis label" }
51474
- })
51475
- ],
51476
- [
51477
- "heatmap",
51478
- withGlobals({
51479
- columns: { description: "Column labels (required)" },
51480
- "no-value": { description: "Hide cell value text" }
51481
- })
51482
- ],
51483
- ["sankey", withGlobals()],
51484
- ["chord", withGlobals()],
51485
- [
51486
- "funnel",
51487
- withGlobals({
51488
- "no-name": { description: "Hide left-side name labels" },
51489
- "no-value": { description: "Hide right-side value labels" }
51490
- })
51491
- ],
51492
- [
51493
- "function",
51494
- withGlobals({
51495
- x: { description: "X-axis range (start to end)" },
51496
- "x-label": { description: "X-axis label" },
51497
- "y-label": { description: "Y-axis label" },
51498
- shade: { description: "Fill area below curves with translucent color" }
51499
- })
51500
- ],
51501
- // ── Visualizations ───────────────────────────────────────
51502
- ["slope", withGlobals()],
51503
- [
51504
- "wordcloud",
51505
- withGlobals({
51506
- rotate: {
51507
- description: "Word rotation",
51508
- values: ["none", "mixed", "angled"]
51509
- },
51510
- max: { description: "Maximum word count" },
51511
- size: { description: "Font size range (min, max)" }
51512
- })
51513
- ],
51514
- [
51515
- "arc",
51516
- withGlobals({
51517
- order: {
51518
- description: "Node ordering",
51519
- values: ["appearance", "name", "group", "degree"]
51520
- }
51521
- })
51522
- ],
51523
- ["timeline", withGlobals()],
51524
- ["venn", withGlobals()],
51525
- [
51526
- "quadrant",
51527
- withGlobals({
51528
- "x-label": { description: "X-axis labels (low, high)" },
51529
- "y-label": { description: "Y-axis labels (low, high)" }
51530
- })
51531
- ],
51532
- // ── Diagrams ─────────────────────────────────────────────
51533
- [
51534
- "sequence",
51535
- withGlobals({
51536
- activations: {
51537
- description: "Show activation bars",
51538
- values: ["on", "off"]
51539
- },
51540
- "active-tag": { description: "Active tag group name" }
51541
- })
51542
- ],
51543
- [
51544
- "flowchart",
51545
- // Spec §5 §4.6: direction-lr, orientation-vertical, no-color, solid-fill
51546
- withGlobals({
51547
- "direction-lr": { description: "Switch to left-to-right layout" },
51548
- "orientation-vertical": {
51549
- description: "Use vertical orientation for ranks"
51550
- },
51551
- "no-color": {
51552
- description: "Resolve all nodes to muted neutral fill"
51553
- }
51554
- })
51555
- ],
51556
- [
51557
- "class",
51558
- withGlobals({
51559
- "no-auto-color": {
51560
- description: "Disable automatic modifier-based coloring"
51561
- }
51562
- })
51563
- ],
51564
- [
51565
- "er",
51566
- // Spec §9 §8.5: notation (chen/crow), active-tag.
51567
- withGlobals({
51568
- notation: {
51569
- description: "ER notation style",
51570
- values: ["chen", "crow"]
51571
- },
51572
- "active-tag": { description: "Active tag group name" }
51573
- })
51574
- ],
51575
- [
51576
- "org",
51577
- // Spec §7 §6.5: direction-tb, sub-node-label, show-sub-node-count,
51578
- // hide, active-tag. solid-fill via SOLID_FILL_CAPABLE.
51579
- withGlobals({
51580
- "direction-tb": { description: "Switch to top-to-bottom layout" },
51581
- "sub-node-label": { description: "Label for sub-nodes" },
51582
- "show-sub-node-count": { description: "Show sub-node counts" },
51583
- hide: { description: "Hide tag:value pairs" },
51584
- "active-tag": { description: "Active tag group name" }
51585
- })
51586
- ],
51587
- [
51588
- "kanban",
51589
- // Spec §11 §10.4: no-auto-color, hide, active-tag.
51590
- withGlobals({
51591
- "no-auto-color": { description: "Disable automatic card coloring" },
51592
- hide: { description: "Hide tag:value pairs" },
51593
- "active-tag": { description: "Active tag group name" }
51594
- })
51595
- ],
51596
- // RACI / RASCI / DACI — one chart type (`raci`), variant inferred from
51597
- // markers or locked via `variant-*` bare directive. `rasci`/`daci` are
51598
- // not first-line keywords so they get no separate registry entry.
51599
- [
51600
- "raci",
51601
- withGlobals({
51602
- "variant-raci": {
51603
- description: "Lock chart to RACI variant (R / A / C / I markers)"
51604
- },
51605
- "variant-rasci": {
51606
- description: "Lock chart to RASCI variant (adds Support \u2014 R / A / S / C / I)"
51607
- },
51608
- "variant-daci": {
51609
- description: "Lock chart to DACI variant (Driver / Approver / Contributor / Informed)"
51610
- },
51611
- roles: {
51612
- description: "Declare role column order (inline `roles A, B, C` or indented block with per-role pipe metadata)"
51613
- },
51614
- "active-tag": { description: "Active tag group name" }
51615
- })
51616
- ],
51617
- [
51618
- "c4",
51619
- // Spec §8 §7.7: direction-tb, active-tag.
51620
- withGlobals({
51621
- "direction-tb": { description: "Switch to top-to-bottom layout" },
51622
- "active-tag": { description: "Active tag group name" }
51623
- })
51624
- ],
51625
- [
51626
- "state",
51627
- // Spec §6 §5.5: direction-tb, no-color, solid-fill.
51628
- withGlobals({
51629
- "direction-tb": { description: "Switch to top-to-bottom layout" },
51630
- "no-color": {
51631
- description: "Resolve all states to muted neutral fill"
51632
- }
51633
- })
51634
- ],
51635
- [
51636
- "sitemap",
51637
- withGlobals({
51638
- "direction-tb": { description: "Switch to top-to-bottom layout" },
51639
- "active-tag": { description: "Active tag group name" }
51640
- })
51641
- ],
51642
- [
51643
- "infra",
51644
- withGlobals({
51645
- "direction-tb": { description: "Switch to top-to-bottom layout" },
51646
- animate: { description: "Enable traffic animation" },
51647
- "no-animate": { description: "Disable traffic animation" },
51648
- "default-latency-ms": { description: "Default latency for all nodes" },
51649
- "default-uptime": { description: "Default uptime for all nodes" },
51650
- "default-rps": { description: "Default RPS capacity for all nodes" },
51651
- "slo-availability": { description: "SLO availability target (0-1)" },
51652
- "slo-p90-latency-ms": { description: "SLO p90 latency target in ms" },
51653
- "slo-warning-margin": { description: "SLO warning margin percentage" },
51654
- "active-tag": { description: "Active tag group name" }
51655
- })
51656
- ],
51657
- [
51658
- "pert",
51659
- withGlobals({
51660
- "time-unit": {
51661
- description: "Time unit for activity durations",
51662
- values: ["min", "h", "d", "bd", "w", "m", "q", "y"]
51663
- },
51664
- confidence: {
51665
- description: "Confidence factor for M-only durations",
51666
- values: ["high", "medium", "low"]
51667
- },
51668
- direction: { description: "Layout direction", values: ["LR", "TB"] },
51669
- "node-detail": {
51670
- description: "Node visual density",
51671
- values: ["compact", "full"]
51672
- },
51673
- trials: {
51674
- description: "Monte Carlo trial count (auto-derived from activity count)"
51675
- },
51676
- seed: { description: "Monte Carlo PRNG seed (auto-derived from title)" },
51677
- "scrubber-trials": {
51678
- description: "Fast-MC trials for the duration scrubber (default 300)"
51679
- }
51680
- })
51681
- ],
51682
- [
51683
- "gantt",
51684
- // Spec §13 §12.2 Options.
51685
- withGlobals({
51686
- start: { description: "Project start date (YYYY-MM-DD)" },
51687
- "today-marker": {
51688
- description: "Today marker (bare = on, or YYYY-MM-DD date)"
51689
- },
51690
- sort: { description: "Sort order", values: ["time", "group", "tag"] },
51691
- "critical-path": { description: "Show critical path" },
51692
- "no-dependencies": { description: "Hide dependency arrows" },
51693
- "sprint-length": { description: "Sprint duration (e.g. 2w)" },
51694
- "sprint-number": { description: "Starting sprint number" },
51695
- "sprint-start": { description: "Sprint start date (YYYY-MM-DD)" },
51696
- "active-tag": { description: "Active tag group name" },
51697
- // Legacy positive form `dependencies` — kept for back-compat. Use
51698
- // `no-dependencies` to suppress dependency arrows in new code.
51699
- dependencies: { description: "Show dependencies (legacy form)" }
51700
- })
51701
- ],
51702
- [
51703
- "boxes-and-lines",
51704
- withGlobals({
51705
- direction: { description: "Layout direction", values: ["LR", "TB"] },
51706
- "active-tag": { description: "Active tag group name" },
51707
- hide: { description: "Hide tag:value pairs" }
51708
- })
51709
- ],
51710
- [
51711
- "mindmap",
51712
- withGlobals({
51713
- "no-descriptions": { description: "Hide node descriptions" },
51714
- "active-tag": { description: "Active tag group name" }
51715
- })
51716
- ],
51717
- [
51718
- "wireframe",
51719
- withGlobals({
51720
- mobile: { description: "Use mobile (narrow vertical) layout" },
51721
- "active-tag": { description: "Active tag group name" }
51722
- })
51723
- ],
51724
- [
51725
- "tech-radar",
51726
- // Spec §20 documents one directive: `show-blip-legend`. `rings` is a
51727
- // structural block keyword; quadrant/ring/trend/color are pipe metadata
51728
- // that live in PIPE_METADATA.
51729
- withGlobals({
51730
- "show-blip-legend": {
51731
- description: "Render the four-column blip listing alongside the radar"
51732
- }
51733
- })
51734
- ],
51735
- [
51736
- "cycle",
51737
- withGlobals({
51738
- "direction-counterclockwise": {
51739
- description: "Reverse cycle direction to counterclockwise"
51740
- },
51741
- "no-descriptions": { description: "Hide node and edge descriptions" },
51742
- "circle-nodes": {
51743
- description: "Render nodes as circles instead of rectangles"
51744
- }
51745
- })
51746
- ],
51747
- [
51748
- "journey-map",
51749
- // Spec §22 directives: `no-legend`, `active-tag`. `persona` is a
51750
- // structural keyword (like `tag` / `roles`), not a directive.
51751
- // `solid-fill` is added via SOLID_FILL_CAPABLE below.
51752
- withGlobals({
51753
- "no-legend": { description: "Hide the score legend" },
51754
- "active-tag": { description: "Active tag group name" }
51755
- })
51756
- ],
51757
- [
51758
- "pyramid",
51759
- // Spec §23.5 documents `inverted`; `solid-fill` is added via
51760
- // SOLID_FILL_CAPABLE below (working but not yet in spec §23.5).
51761
- // `color`/`description` are layer pipe-metadata, not directives.
51762
- withGlobals({
51763
- inverted: { description: "Flip apex to the bottom (funnel orientation)" }
51764
- })
51765
- ],
51766
- [
51767
- "ring",
51768
- // Per spec §24.5 the only chart-specific directive is `solid-fill`,
51769
- // applied via SOLID_FILL_CAPABLE below. `color`/`description` are
51770
- // layer pipe-metadata, not directives — they live in PIPE_METADATA.
51771
- withGlobals({})
51772
- ]
51773
- ]);
51774
- {
51775
- const raciSpec = COMPLETION_REGISTRY.get("raci");
51776
- if (raciSpec) {
51777
- COMPLETION_REGISTRY.set("rasci", raciSpec);
51778
- COMPLETION_REGISTRY.set("daci", raciSpec);
51779
- }
51780
- }
51781
- var SOLID_FILL_CAPABLE = /* @__PURE__ */ new Set([
51782
- "flowchart",
51783
- "state",
51784
- "sequence",
51785
- "c4",
51786
- "org",
51787
- "kanban",
51788
- "journey-map",
51789
- "mindmap",
51790
- "cycle",
51791
- "pyramid",
51792
- "ring",
51793
- "funnel",
51794
- "class",
51795
- "er",
51796
- "sitemap",
51797
- "boxes-and-lines",
51798
- "wireframe",
51799
- "bar",
51800
- "bar-stacked",
51801
- "pie",
51802
- "doughnut",
51803
- "polar-area",
51804
- "radar",
51805
- "scatter",
51806
- "chord"
51807
- ]);
51808
- for (const [type, spec] of COMPLETION_REGISTRY) {
51809
- if (SOLID_FILL_CAPABLE.has(type)) {
51810
- spec.directives["solid-fill"] = {
51811
- description: "Render shapes with full intent color instead of the default 25% tint"
51812
- };
51813
- }
51814
- }
51815
- var CHART_TYPES = [...ALL_CHART_TYPES].filter((t) => t !== "multi-line").map((name) => ({
51816
- name,
51817
- description: CHART_TYPE_DESCRIPTIONS[name] ?? name
51818
- }));
51819
- var ENTITY_TYPES = /* @__PURE__ */ new Map([
51820
- [
51821
- "sequence",
51822
- [
51823
- "service",
51824
- "database",
51825
- "actor",
51826
- "queue",
51827
- "cache",
51828
- "gateway",
51829
- "external",
51830
- "networking",
51831
- "frontend"
51832
- ]
51833
- ],
51834
- [
51835
- "c4",
51836
- ["person", "system", "container", "component", "external", "database"]
51837
- ]
51838
- ]);
51839
- var PIPE_METADATA = /* @__PURE__ */ new Map([
51840
- [
51841
- "infra",
51842
- {
51843
- node: {
51844
- description: { description: "Node description text" },
51845
- instances: {
51846
- description: "Instance count or auto-scaling range (N-M)"
51847
- },
51848
- "latency-ms": { description: "Per-request latency in milliseconds" },
51849
- "max-rps": { description: "Max requests per second per instance" },
51850
- "cache-hit": { description: "Cache hit percentage (0-100)" },
51851
- "firewall-block": { description: "Traffic blocked percentage" },
51852
- "ratelimit-rps": { description: "Max RPS allowed through" },
51853
- "cb-error-threshold": {
51854
- description: "Circuit breaker error threshold %"
51855
- },
51856
- "cb-latency-threshold-ms": {
51857
- description: "Circuit breaker latency threshold"
51858
- },
51859
- uptime: { description: "Component availability (0-1)" },
51860
- concurrency: { description: "Concurrent request limit" },
51861
- "duration-ms": { description: "Processing duration" },
51862
- "cold-start-ms": { description: "Function cold-start time" },
51863
- buffer: { description: "Queue/buffer capacity" },
51864
- "drain-rate": { description: "Queue drain rate" },
51865
- "retention-hours": { description: "Data retention period" },
51866
- partitions: { description: "Queue/stream partition count" },
51867
- "slo-availability": { description: "Node availability target (0-1)" },
51868
- "slo-p90-latency-ms": { description: "Node p90 latency target" },
51869
- "slo-warning-margin": { description: "Node SLO warning margin" }
51870
- },
51871
- edge: {
51872
- split: { description: "Traffic split percentage (e.g., 60%)" },
51873
- fanout: { description: "Fanout multiplier (integer >= 1)" }
51874
- }
51875
- }
51876
- ],
51877
- [
51878
- "c4",
51879
- {
51880
- node: {
51881
- description: { description: "Element description" },
51882
- tech: { description: "Technology stack" },
51883
- technology: { description: "Technology stack (alias for tech)" }
51884
- },
51885
- edge: {}
51886
- }
51887
- ],
51888
- [
51889
- "gantt",
51890
- {
51891
- node: {},
51892
- edge: {
51893
- // Gantt "edge" = dependency arrow (TaskA -> TaskB | offset 2bd)
51894
- offset: { description: "Dependency offset (e.g., 2bd, -1w)" }
51895
- }
51896
- }
51897
- ],
51898
- [
51899
- "boxes-and-lines",
51900
- {
51901
- node: {
51902
- description: { description: "Node description text" }
51903
- },
51904
- edge: {}
51905
- }
51906
- ],
51907
- [
51908
- "mindmap",
51909
- {
51910
- node: {
51911
- description: { description: "Node description text" },
51912
- collapsed: { description: "Collapse node subtree by default" }
51913
- },
51914
- edge: {}
51915
- }
51916
- ],
51917
- [
51918
- // Tech-radar pipe metadata (spec §20). Two contexts:
51919
- // - quadrant: top-level quadrant headers (`Tools | quadrant: top-left, color: blue`)
51920
- // - blip: indented blip lines (` Vite | ring: Adopt, trend: up`)
51921
- "tech-radar",
51922
- {
51923
- quadrant: {
51924
- quadrant: {
51925
- description: "Quadrant position",
51926
- values: ["top-left", "top-right", "bottom-left", "bottom-right"]
51927
- },
51928
- color: { description: "Override quadrant color" }
51929
- },
51930
- blip: {
51931
- ring: { description: "Ring assignment (must match a declared ring)" },
51932
- trend: {
51933
- description: "Blip trend indicator",
51934
- values: ["new", "up", "down", "stable"]
51935
- }
51936
- }
51937
- }
51938
- ],
51939
- [
51940
- "cycle",
51941
- {
51942
- node: {
51943
- color: { description: "Node fill color (palette name)" },
51944
- span: { description: "Relative arc distance to next node" },
51945
- description: { description: "Node description text" }
51946
- },
51947
- edge: {
51948
- color: { description: "Edge stroke color (palette name)" },
51949
- width: { description: "Edge stroke width in pixels" }
51950
- }
51951
- }
51952
- ],
51953
- [
51954
- // RACI pipe metadata (spec §24A). Two contexts:
51955
- // - role: declarations inside the `roles` block (`Cap | color: red`)
51956
- // - phase: bracketed phase headers (`[Departure] | color: teal`)
51957
- "raci",
51958
- {
51959
- role: {
51960
- color: { description: "Role column tint (palette name)" }
51961
- },
51962
- phase: {
51963
- color: { description: "Phase bar tint (palette name)" }
51964
- }
51965
- }
51966
- ],
51967
- [
51968
- // Ring layer pipe metadata (spec §24.4). One context: `layer`.
51969
- "ring",
51970
- {
51971
- layer: {
51972
- color: { description: "Ring color (palette name)" },
51973
- description: { description: "Layer description (one-liner shorthand)" }
51974
- }
51975
- }
51976
- ],
51977
- [
51978
- // Pyramid layer pipe metadata (spec §23.4). Identical surface to ring.
51979
- "pyramid",
51980
- {
51981
- layer: {
51982
- color: { description: "Layer color (palette name)" },
51983
- description: { description: "Layer description (one-liner shorthand)" }
51984
- }
51985
- }
51986
- ],
51987
- [
51988
- // Journey-map step pipe metadata (spec §22). One static key: `score`.
51989
- // Tag aliases (e.g. `ch: Web`) are user-defined via the `tag` block
51990
- // and resolved dynamically — not part of the static map.
51991
- "journey-map",
51992
- {
51993
- step: {
51994
- score: { description: "Step score (1\u20135 integer; high = good)" }
51995
- }
51996
- }
51997
- ]
51998
- ]);
51999
- var METADATA_KEY_SET = /* @__PURE__ */ new Set([
52000
- "chart",
52001
- "title",
52002
- // implicit directives recognized as metadata
52003
- ...[...COMPLETION_REGISTRY.values()].flatMap(
52004
- (spec) => Object.keys(spec.directives)
52005
- )
52006
- ]);
52007
- var SEQ_ARROW_RE = /^(?:"([^"]+)"|([^|"]+?))\s+(->|-.*->|~>|~.*~>)\s+(?:"([^"]+)"|([^|"]+?))(?:\s|\|.*)?$/;
52008
- var SEQ_IS_A_RE = /^(?:"([^"]+)"|([^|":]+?))\s+is\s+an?\s+/i;
52009
- var SEQ_SECTION_RE = /^==/;
52010
- var SEQ_STRUCTURAL_RE = /^(if|else|loop|parallel|end)\b/i;
52011
- function extractSequenceSymbols(docText) {
52012
- const lines = docText.split("\n");
52013
- const entities = [];
52014
- let pastFirstLine = false;
52015
- for (const line12 of lines) {
52016
- const trimmed = line12.trim();
52017
- if (!trimmed || trimmed.startsWith("//")) continue;
52018
- if (!pastFirstLine) {
52019
- pastFirstLine = true;
52020
- continue;
52021
- }
52022
- const firstToken = trimmed.split(/\s+/)[0].toLowerCase();
52023
- if (METADATA_KEY_SET.has(firstToken)) continue;
52024
- if (SEQ_SECTION_RE.test(trimmed)) continue;
52025
- if (SEQ_STRUCTURAL_RE.test(trimmed)) continue;
52026
- const arrowMatch = trimmed.match(SEQ_ARROW_RE);
52027
- if (arrowMatch) {
52028
- const src = (arrowMatch[1] ?? arrowMatch[2] ?? "").trim();
52029
- const dst = (arrowMatch[4] ?? arrowMatch[5] ?? "").trim();
52030
- if (src && !entities.includes(src)) entities.push(src);
52031
- if (dst && !entities.includes(dst)) entities.push(dst);
52032
- continue;
52033
- }
52034
- const isAMatch = trimmed.match(SEQ_IS_A_RE);
52035
- if (isAMatch) {
52036
- const name = (isAMatch[1] ?? isAMatch[2] ?? "").trim();
52037
- if (name && !entities.includes(name)) entities.push(name);
52038
- continue;
52039
- }
52040
- }
52041
- return {
52042
- kind: "sequence",
52043
- entities,
52044
- keywords: ["if", "else", "loop", "parallel", "note"]
52045
- };
52046
- }
52047
- var STATE_ARROW_RE = /^(\S+)\s+->\s+(\S+)/;
52048
- function extractStateSymbols(docText) {
52049
- const lines = docText.split("\n");
52050
- const entities = [];
52051
- let pastFirstLine = false;
52052
- for (const line12 of lines) {
52053
- const trimmed = line12.trim();
52054
- if (!trimmed || trimmed.startsWith("//")) continue;
52055
- if (!pastFirstLine) {
52056
- pastFirstLine = true;
52057
- continue;
52058
- }
52059
- const firstToken = trimmed.split(/\s+/)[0].toLowerCase();
52060
- if (METADATA_KEY_SET.has(firstToken)) continue;
52061
- const arrowMatch = trimmed.match(STATE_ARROW_RE);
52062
- if (arrowMatch) {
52063
- const src = arrowMatch[1].split("|")[0].trim();
52064
- const dst = arrowMatch[2].split("|")[0].trim();
52065
- if (src && !entities.includes(src)) entities.push(src);
52066
- if (dst && !entities.includes(dst)) entities.push(dst);
52067
- }
52068
- }
52069
- return { kind: "state", entities, keywords: [] };
52070
- }
52071
- var TAG_DECL_EXPLICIT_RE = /^tag\s+(\S+)\s+alias\s+(\S+)/i;
52072
- var TAG_DECL_SHORT_RE = /^tag\s+(\S+)\s+([a-z]{1,4})(?:\s|$)/;
52073
- function extractTagDeclarations(docText) {
52074
- const result = /* @__PURE__ */ new Map();
52075
- const lines = docText.split("\n");
52076
- let currentAlias = null;
52077
- let currentValues = [];
52078
- for (let i = 0; i < lines.length; i++) {
52079
- const raw = lines[i];
52080
- const trimmed = raw.trim();
52081
- const tagMatch = trimmed.match(TAG_DECL_EXPLICIT_RE) ?? trimmed.match(TAG_DECL_SHORT_RE);
52082
- if (tagMatch) {
52083
- if (currentAlias !== null) {
52084
- result.set(currentAlias, currentValues);
52085
- }
52086
- const name = tagMatch[1];
52087
- const alias = tagMatch[2] ?? name;
52088
- currentAlias = alias;
52089
- currentValues = [];
52090
- continue;
52091
- }
52092
- if (/^tag\s+(\S+)\s*$/i.test(trimmed)) {
52093
- if (currentAlias !== null) {
52094
- result.set(currentAlias, currentValues);
52095
- }
52096
- currentAlias = trimmed.match(/^tag\s+(\S+)/i)[1];
52097
- currentValues = [];
52098
- continue;
52099
- }
52100
- if (currentAlias !== null && raw.length > 0 && (raw[0] === " " || raw[0] === " ")) {
52101
- if (trimmed && !trimmed.startsWith("//")) {
52102
- const colorIdx = trimmed.indexOf("(");
52103
- const value = colorIdx > 0 ? trimmed.substring(0, colorIdx).trim() : trimmed;
52104
- if (value) currentValues.push(value);
52105
- }
52106
- continue;
52107
- }
52108
- if (currentAlias !== null && trimmed) {
52109
- result.set(currentAlias, currentValues);
52110
- currentAlias = null;
52111
- currentValues = [];
52112
- }
52113
- }
52114
- if (currentAlias !== null) {
52115
- result.set(currentAlias, currentValues);
52116
- }
52117
- return result;
52118
- }
52119
- var ALIAS_POSTFIX_DECL_RE = /(?:^|[^|/])\s*(.+?)\s+as\s+([A-Za-z][A-Za-z0-9_]{0,11})\s*(?:\|.*)?$/;
52120
- function extractAliasDeclarations(docText) {
52121
- const aliases = {};
52122
- for (const raw of docText.split("\n")) {
52123
- const trimmed = raw.trim();
52124
- if (!trimmed || trimmed.startsWith("//")) continue;
52125
- const match = trimmed.match(ALIAS_POSTFIX_DECL_RE);
52126
- if (!match) continue;
52127
- const canonical = match[1].trim();
52128
- const alias = match[2];
52129
- if (!canonical || canonical === "[" || canonical === "]") continue;
52130
- if (!(alias in aliases)) {
52131
- aliases[alias] = canonical;
52132
- }
52133
- }
52134
- return aliases;
52135
- }
52136
- var SITEMAP_CONTAINER_RE = /^\[([^\]]+)\]/;
52137
- var SITEMAP_ARROW_RE = /^-.*->\s*(.+)$/;
52138
- var SITEMAP_BARE_ARROW_RE = /^->\s*(.+)$/;
52139
- var SITEMAP_METADATA_RE = /^([^:]+):\s*(.+)$/;
52140
- function extractSitemapSymbols(docText) {
52141
- const lines = docText.split("\n");
52142
- const entities = [];
52143
- let pastFirstLine = false;
52144
- let inTagBlock = false;
52145
- let lastNodeIndent = -1;
52146
- for (const line12 of lines) {
52147
- const trimmed = line12.trim();
52148
- if (!trimmed || trimmed.startsWith("//")) continue;
52149
- if (!pastFirstLine) {
52150
- pastFirstLine = true;
52151
- continue;
52152
- }
52153
- const firstToken = trimmed.split(/\s+/)[0].toLowerCase();
52154
- if (METADATA_KEY_SET.has(firstToken)) continue;
52155
- if (/^tag\s+/i.test(trimmed)) {
52156
- inTagBlock = true;
52157
- continue;
52158
- }
52159
- const indent = line12.search(/\S/);
52160
- if (inTagBlock) {
52161
- if (indent > 0) continue;
52162
- inTagBlock = false;
52163
- }
52164
- const containerMatch = trimmed.match(SITEMAP_CONTAINER_RE);
52165
- if (containerMatch) {
52166
- const name = containerMatch[1].split("|")[0].trim();
52167
- if (name && !entities.includes(name)) entities.push(name);
52168
- lastNodeIndent = indent;
52169
- continue;
52170
- }
52171
- const bareArrow = trimmed.match(SITEMAP_BARE_ARROW_RE);
52172
- const labeledArrow = !bareArrow ? trimmed.match(SITEMAP_ARROW_RE) : null;
52173
- if (bareArrow || labeledArrow) {
52174
- const target = (bareArrow?.[1] ?? labeledArrow?.[1] ?? "").split("|")[0].trim();
52175
- if (target && !entities.includes(target)) entities.push(target);
52176
- continue;
52177
- }
52178
- if (indent > 0 && lastNodeIndent >= 0 && indent > lastNodeIndent && SITEMAP_METADATA_RE.test(trimmed)) {
52179
- continue;
52180
- }
52181
- const label = trimmed.split("|")[0].trim();
52182
- if (label) {
52183
- if (!entities.includes(label)) entities.push(label);
52184
- lastNodeIndent = indent;
52185
- }
52186
- }
52187
- return { kind: "sitemap", entities, keywords: [] };
52188
- }
52189
- var C4_ELEMENT_RE = /^(person|system|container|component)\s+(.+)$/i;
52190
- var C4_IS_A_RE2 = /^(.+?)\s+is\s+an?\s+(person|system|container|component|external|database)\b/i;
52191
- var C4_ARROW_RE = /^(\S+)\s+(?:->|-.*->|~>|~.*~>|<->|<-.*->|<~>|<~.*~>)\s+(\S+)/;
52192
- var C4_SECTION_RE = /^(containers|components|deployment)\s*$/i;
52193
- function extractC4Symbols(docText) {
52194
- const lines = docText.split("\n");
52195
- const entities = [];
52196
- let pastFirstLine = false;
52197
- let inTagBlock = false;
52198
- for (const line12 of lines) {
52199
- const trimmed = line12.trim();
52200
- if (!trimmed || trimmed.startsWith("//")) continue;
52201
- if (!pastFirstLine) {
52202
- pastFirstLine = true;
52203
- continue;
52204
- }
52205
- const firstToken = trimmed.split(/\s+/)[0].toLowerCase();
52206
- if (METADATA_KEY_SET.has(firstToken)) continue;
52207
- if (/^tag\s+/i.test(trimmed)) {
52208
- inTagBlock = true;
52209
- continue;
52210
- }
52211
- const indent = line12.search(/\S/);
52212
- if (inTagBlock) {
52213
- if (indent > 0) continue;
52214
- inTagBlock = false;
52215
- }
52216
- if (C4_SECTION_RE.test(trimmed)) continue;
52217
- const elemMatch = trimmed.match(C4_ELEMENT_RE);
52218
- if (elemMatch) {
52219
- const name = elemMatch[2].split("|")[0].trim();
52220
- if (name && !entities.includes(name)) entities.push(name);
52221
- continue;
52222
- }
52223
- const isAMatch = trimmed.match(C4_IS_A_RE2);
52224
- if (isAMatch) {
52225
- const name = isAMatch[1].split("|")[0].trim();
52226
- if (name && !entities.includes(name)) entities.push(name);
52227
- continue;
52228
- }
52229
- const arrowMatch = trimmed.match(C4_ARROW_RE);
52230
- if (arrowMatch) {
52231
- const src = arrowMatch[1].split("|")[0].trim();
52232
- const dst = arrowMatch[2].split("|")[0].trim();
52233
- if (src && !entities.includes(src)) entities.push(src);
52234
- if (dst && !entities.includes(dst)) entities.push(dst);
52235
- continue;
52236
- }
52237
- }
52238
- return {
52239
- kind: "c4",
52240
- entities,
52241
- keywords: ["containers", "components", "deployment"]
52242
- };
52243
- }
52244
- var GANTT_DURATION_RE2 = /^(\d+(?:\.\d+)?)(min|bd|d|w|m|q|y|h)\??\s+(.+)$/;
52245
- var GANTT_DATE_RE2 = /^(\d{4}-\d{2}-\d{2}(?:\s\d{2}:\d{2})?)\s+(.+)$/;
52246
- var GANTT_GROUP_RE = /^\[(.+?)\]/;
52247
- var GANTT_STRUCTURAL_RE = /^(era|marker|holiday|workweek|parallel)\b/i;
52248
- function extractGanttSymbols(docText) {
52249
- const lines = docText.split("\n");
52250
- const entities = [];
52251
- let pastFirstLine = false;
52252
- let inTagBlock = false;
52253
- for (const line12 of lines) {
52254
- const trimmed = line12.trim();
52255
- if (!trimmed || trimmed.startsWith("//")) continue;
52256
- if (!pastFirstLine) {
52257
- pastFirstLine = true;
52258
- continue;
52259
- }
52260
- const firstToken = trimmed.split(/\s+/)[0].toLowerCase();
52261
- if (METADATA_KEY_SET.has(firstToken)) continue;
52262
- if (/^tag\s+/i.test(trimmed)) {
52263
- inTagBlock = true;
52264
- continue;
52265
- }
52266
- const indent = line12.search(/\S/);
52267
- if (inTagBlock) {
52268
- if (indent > 0) continue;
52269
- inTagBlock = false;
52270
- }
52271
- if (GANTT_STRUCTURAL_RE.test(trimmed)) continue;
52272
- const groupMatch = trimmed.match(GANTT_GROUP_RE);
52273
- if (groupMatch) {
52274
- const name = groupMatch[1].trim();
52275
- if (name && !entities.includes(name)) entities.push(name);
52276
- continue;
52277
- }
52278
- const durMatch = trimmed.match(GANTT_DURATION_RE2);
52279
- if (durMatch) {
52280
- let taskName = durMatch[3].split("|")[0].trim();
52281
- const arrowIdx = taskName.indexOf("->");
52282
- if (arrowIdx > 0)
52283
- taskName = taskName.substring(0, arrowIdx).replace(/-[^>]*$/, "").trim();
52284
- if (taskName && !entities.includes(taskName)) entities.push(taskName);
52285
- continue;
52286
- }
52287
- const dateMatch = trimmed.match(GANTT_DATE_RE2);
52288
- if (dateMatch) {
52289
- let taskName = dateMatch[2].split("|")[0].trim();
52290
- const arrowIdx = taskName.indexOf("->");
52291
- if (arrowIdx > 0)
52292
- taskName = taskName.substring(0, arrowIdx).replace(/-[^>]*$/, "").trim();
52293
- if (taskName && !entities.includes(taskName)) entities.push(taskName);
52294
- continue;
52295
- }
52296
- }
52297
- return { kind: "gantt", entities, keywords: [] };
52298
- }
52299
- var BL_ARROW_RE = /^(\S+)\s+(?:-.*)?(?:->|<->)\s+(\S+)/;
52300
- function extractBoxesAndLinesSymbols(docText) {
52301
- const lines = docText.split("\n");
52302
- const entities = [];
52303
- let pastFirstLine = false;
52304
- let inTagBlock = false;
52305
- for (const line12 of lines) {
52306
- const trimmed = line12.trim();
52307
- if (!trimmed || trimmed.startsWith("//")) continue;
52308
- if (!pastFirstLine) {
52309
- pastFirstLine = true;
52310
- continue;
52311
- }
52312
- const firstToken = trimmed.split(/\s+/)[0].toLowerCase();
52313
- if (METADATA_KEY_SET.has(firstToken)) continue;
52314
- if (/^tag\s+/i.test(trimmed)) {
52315
- inTagBlock = true;
52316
- continue;
52317
- }
52318
- const indent = line12.search(/\S/);
52319
- if (inTagBlock) {
52320
- if (indent > 0) continue;
52321
- inTagBlock = false;
52322
- }
52323
- if (/^\[.+?\]/.test(trimmed)) continue;
52324
- const arrowMatch = trimmed.match(BL_ARROW_RE);
52325
- if (arrowMatch) {
52326
- const src = arrowMatch[1].split("|")[0].trim();
52327
- const dst = arrowMatch[2].split("|")[0].trim();
52328
- if (src && !entities.includes(src)) entities.push(src);
52329
- if (dst && !entities.includes(dst)) entities.push(dst);
52330
- continue;
52331
- }
52332
- const label = trimmed.split("|")[0].split("[")[0].trim();
52333
- if (label && !entities.includes(label)) entities.push(label);
52334
- }
52335
- return { kind: "boxes-and-lines", entities, keywords: [] };
52336
- }
52337
- registerExtractor("er", extractSymbols3);
52338
- registerExtractor("flowchart", extractSymbols);
52339
- registerExtractor("infra", extractSymbols4);
52340
- registerExtractor("class", extractSymbols2);
52341
- registerExtractor("sequence", extractSequenceSymbols);
52342
- registerExtractor("state", extractStateSymbols);
52343
- registerExtractor("sitemap", extractSitemapSymbols);
52344
- registerExtractor("c4", extractC4Symbols);
52345
- registerExtractor("gantt", extractGanttSymbols);
52346
- registerExtractor("pert", extractPertSymbols);
52347
- registerExtractor("boxes-and-lines", extractBoxesAndLinesSymbols);
52348
- registerExtractor("tech-radar", extractTechRadarSymbols);
52349
- registerExtractor("cycle", extractCycleSymbols);
52350
- registerExtractor("journey-map", extractJourneyMapSymbols);
52351
- registerExtractor("raci", extractRaciSymbols);
52352
- registerExtractor("rasci", extractRaciSymbols);
52353
- registerExtractor("daci", extractRaciSymbols);
52354
- function extractTechRadarSymbols(docText) {
52355
- const entities = [];
52356
- const keywords = [
52357
- "rings",
52358
- "quadrant",
52359
- "ring",
52360
- "trend",
52361
- "new",
52362
- "up",
52363
- "down",
52364
- "stable",
52365
- "top-left",
52366
- "top-right",
52367
- "bottom-left",
52368
- "bottom-right",
52369
- "alias",
52370
- "aka",
52371
- "color"
52372
- ];
52373
- const lines = docText.split("\n");
52374
- let inRings = false;
52375
- for (const line12 of lines) {
52376
- const trimmed = line12.trim();
52377
- if (trimmed.toLowerCase() === "rings") {
52378
- inRings = true;
52379
- continue;
52380
- }
52381
- if (inRings) {
52382
- if (!trimmed || line12[0] !== " " && line12[0] !== " ") {
52383
- inRings = false;
52384
- continue;
52385
- }
52386
- const aliasMatch = trimmed.match(/^(.+?)\s+(?:alias|aka)\s+(\S+)\s*$/i);
52387
- if (aliasMatch) {
52388
- entities.push(aliasMatch[1].trim());
52389
- entities.push(aliasMatch[2].trim());
52390
- } else {
52391
- entities.push(trimmed);
52392
- }
52393
- }
49806
+
49807
+ // src/index.ts
49808
+ async function render2(text, options) {
49809
+ const palette = options?.palette ?? palettes.nord;
49810
+ const onError = options?.onError ?? "svg";
49811
+ const result = await render(text, {
49812
+ theme: options?.theme,
49813
+ palette: palette.id
49814
+ });
49815
+ const errors = result.diagnostics.filter((d) => d.severity === "error");
49816
+ if (errors.length === 0) {
49817
+ return result;
52394
49818
  }
52395
- return { kind: "tech-radar", entities, keywords };
52396
- }
52397
- function extractCycleSymbols(docText) {
52398
- const lines = docText.split("\n");
52399
- const entities = [];
52400
- let pastFirstLine = false;
52401
- for (const line12 of lines) {
52402
- const trimmed = line12.trim();
52403
- if (!trimmed || trimmed.startsWith("//")) continue;
52404
- if (!pastFirstLine) {
52405
- pastFirstLine = true;
52406
- continue;
52407
- }
52408
- const firstToken = trimmed.split(/\s+/)[0].toLowerCase();
52409
- if (METADATA_KEY_SET.has(firstToken)) continue;
52410
- if (firstToken === "direction-counterclockwise" || firstToken === "circle-nodes" || firstToken === "no-descriptions")
52411
- continue;
52412
- if (line12[0] === " " || line12[0] === " ") continue;
52413
- const label = trimmed.split("|")[0].trim();
52414
- if (label && !entities.includes(label)) entities.push(label);
49819
+ if (onError === "throw") {
49820
+ throw new Error(
49821
+ `DGMO parse error: ${errors.map(formatDgmoError).join("; ")}`
49822
+ );
52415
49823
  }
52416
- return {
52417
- kind: "cycle",
52418
- entities,
52419
- keywords: ["direction-counterclockwise", "no-descriptions", "circle-nodes"]
52420
- };
52421
- }
52422
- var RACI_PHASE_RE = /^\[(.+)\]\s*$/;
52423
- var RACI_ROLES_DIRECTIVE_RE = /^roles\s+(.+)$/i;
52424
- var RACI_VARIANT_DIRECTIVE_RE = /^variant\s+(.+)$/i;
52425
- var RACI_ROLE_ASSIGNMENT_RE = /^([^:]+):\s*(.*)$/;
52426
- function extractRaciSymbols(docText) {
52427
- const lines = docText.split("\n");
52428
- const entities = [];
52429
- let chartType = "raci";
52430
- let pastFirstLine = false;
52431
- let underTask = false;
52432
- const push = (s) => {
52433
- const trimmed = s.trim();
52434
- if (trimmed && !entities.includes(trimmed)) entities.push(trimmed);
52435
- };
52436
- for (const line12 of lines) {
52437
- const trimmed = line12.trim();
52438
- if (!trimmed || trimmed.startsWith("//")) continue;
52439
- if (!pastFirstLine) {
52440
- pastFirstLine = true;
52441
- const firstToken = trimmed.split(/\s+/)[0].toLowerCase();
52442
- if (firstToken === "raci" || firstToken === "rasci" || firstToken === "daci") {
52443
- chartType = firstToken;
52444
- }
52445
- continue;
52446
- }
52447
- const indent = line12.length - line12.trimStart().length;
52448
- if (indent === 0) {
52449
- const rolesMatch = trimmed.match(RACI_ROLES_DIRECTIVE_RE);
52450
- if (rolesMatch) {
52451
- for (const r of rolesMatch[1].split(",")) push(r);
52452
- continue;
52453
- }
52454
- if (RACI_VARIANT_DIRECTIVE_RE.test(trimmed)) continue;
52455
- if (METADATA_KEY_SET.has(trimmed.split(/\s+/)[0].toLowerCase())) continue;
52456
- if (trimmed.toLowerCase() === "draft" || trimmed.toLowerCase() === "solid-fill")
52457
- continue;
52458
- }
52459
- const phaseMatch = trimmed.match(RACI_PHASE_RE);
52460
- if (phaseMatch && indent === 0) {
52461
- push(phaseMatch[1]);
52462
- underTask = false;
52463
- continue;
52464
- }
52465
- const roleMatch = trimmed.match(RACI_ROLE_ASSIGNMENT_RE);
52466
- if (underTask && roleMatch) {
52467
- const rolePart = roleMatch[1].trim();
52468
- push(rolePart);
52469
- continue;
52470
- }
52471
- push(trimmed);
52472
- underTask = true;
49824
+ if (onError === "silent") {
49825
+ return result;
52473
49826
  }
52474
49827
  return {
52475
- kind: chartType,
52476
- entities,
52477
- keywords: ["variant", "roles", "no-rule-enforcement"]
52478
- };
49828
+ svg: result.svg || renderErrorSvg(errors, palette, options?.theme),
49829
+ diagnostics: result.diagnostics
49830
+ };
49831
+ }
49832
+ function renderErrorSvg(errors, palette, theme) {
49833
+ const colors = palette[theme === "dark" ? "dark" : "light"];
49834
+ const bg = theme === "transparent" ? "transparent" : colors.bg;
49835
+ const fg = colors.destructive ?? colors.text;
49836
+ const muted = colors.textMuted ?? colors.text;
49837
+ const lines = errors.slice(0, 5).map((e) => formatDgmoError(e));
49838
+ const height = 60 + lines.length * 20;
49839
+ const body = lines.map(
49840
+ (line12, i) => `<text x="20" y="${60 + i * 20}" fill="${fg}" font-family="ui-monospace, monospace" font-size="12">${escapeXml(line12)}</text>`
49841
+ ).join("");
49842
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="640" height="${height}" viewBox="0 0 640 ${height}"><rect width="100%" height="100%" fill="${bg}"/><text x="20" y="34" fill="${muted}" font-family="system-ui, sans-serif" font-size="13" font-weight="600">DGMO parse error</text>${body}</svg>`;
49843
+ }
49844
+ function escapeXml(s) {
49845
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
52479
49846
  }
52480
- function extractJourneyMapSymbols(docText) {
52481
- const lines = docText.split("\n");
52482
- const entities = [];
52483
- let pastFirstLine = false;
52484
- for (const line12 of lines) {
52485
- const trimmed = line12.trim();
52486
- if (!trimmed || trimmed.startsWith("//")) continue;
52487
- if (!pastFirstLine) {
52488
- pastFirstLine = true;
52489
- continue;
52490
- }
52491
- const firstToken = trimmed.split(/\s+/)[0].toLowerCase();
52492
- if (METADATA_KEY_SET.has(firstToken)) continue;
52493
- if (firstToken === "persona" || firstToken === "tag" || firstToken === "no-legend")
52494
- continue;
52495
- const isIndented = line12[0] === " " || line12[0] === " ";
52496
- if (isIndented) {
52497
- if (/^(pain|opportunity|thought|description)\s*:/i.test(trimmed))
52498
- continue;
52499
- if (/^\S+\([^)]+\)/.test(trimmed)) continue;
52500
- }
52501
- const phaseMatch = trimmed.match(/^\[(.+?)\]$/);
52502
- if (phaseMatch) {
52503
- entities.push(phaseMatch[1].trim());
52504
- continue;
52505
- }
52506
- const label = trimmed.split("|")[0].trim();
52507
- if (label && !entities.includes(label)) entities.push(label);
52508
- }
52509
- return {
52510
- kind: "journey-map",
52511
- entities,
52512
- keywords: [
52513
- "persona",
52514
- "no-legend",
52515
- "pain",
52516
- "opportunity",
52517
- "thought",
52518
- "description"
52519
- ]
52520
- };
49847
+ function encodeDiagramUrl2(text, options) {
49848
+ const internalTheme = options?.theme === "light" || options?.theme === "dark" ? options.theme : void 0;
49849
+ const result = encodeDiagramUrl(text, {
49850
+ baseUrl: options?.baseUrl,
49851
+ palette: options?.palette?.id,
49852
+ theme: internalTheme,
49853
+ filename: options?.filename
49854
+ });
49855
+ return "error" in result && result.error ? null : result.url ?? null;
49856
+ }
49857
+ function decodeDiagramUrl2(url) {
49858
+ const decoded = decodeDiagramUrl(url);
49859
+ if (!decoded.dsl) return null;
49860
+ const palette = decoded.palette ? getPalette(decoded.palette) : void 0;
49861
+ const out = { text: decoded.dsl };
49862
+ if (palette) out.palette = palette;
49863
+ if (decoded.theme) out.theme = decoded.theme;
49864
+ if (decoded.filename) out.filename = decoded.filename;
49865
+ return out;
52521
49866
  }
52522
-
52523
- // src/index.ts
52524
- init_parsing();
52525
49867
  // Annotate the CommonJS export names for ESM import in node:
52526
49868
  0 && (module.exports = {
52527
- ALL_CHART_TYPES,
52528
- AMBIGUITY_THRESHOLD,
52529
- ARROW_DIAGNOSTIC_CODES,
52530
- BETA_CHART_IDS,
52531
- CHART_TYPES,
52532
- CHART_TYPE_DESCRIPTIONS,
52533
- COMPLETION_REGISTRY,
52534
- ENTITY_TYPES,
52535
- INFRA_BEHAVIOR_KEYS,
52536
- LEGEND_GEAR_PILL_W,
52537
- LEGEND_HEIGHT,
52538
- METADATA_KEY_SET,
52539
- MIN_PRIMARY_SCORE,
52540
- PERT_LEGEND_PILL_HEIGHT,
52541
- PIPE_METADATA,
52542
- RACI_ERROR_CODES,
52543
- RACI_VARIANTS,
52544
- RACI_WARNING_CODES,
52545
- RECOGNIZED_COLOR_NAMES,
52546
- RULE_COUNT,
52547
- addDurationToDate,
52548
- analyzePert,
52549
- applyCollapseProjection,
52550
- applyGroupOrdering,
52551
- applyPositionOverrides,
52552
- boldPalette,
52553
- buildExtendedChartOption,
52554
- buildNoteMessageMap,
52555
- buildRenderSequence,
52556
- buildSimpleChartOption,
52557
- buildTagLaneRowList,
52558
- calculateSchedule,
52559
- catppuccinPalette,
52560
- chartTypeConfidence,
52561
- chartTypeParsers,
52562
- chartTypes,
52563
- collapseBoxesAndLines,
52564
- collapseMindmapTree,
52565
- collapseOrgTree,
52566
- collapseSitemapTree,
52567
- collapseStateGroups,
52568
- collectDiagramRoles,
52569
- collectTasks,
52570
- colorNames,
52571
- computeActivations,
52572
- computeCardArchive,
52573
- computeCardMove,
52574
- computeCycleLayout,
52575
- computeInfra,
52576
- computeInfraLegendGroups,
52577
- computeLegendLayout,
52578
- computeRadarLayout,
52579
- computeScatterLabelGraphics,
52580
- computeTimeTicks,
52581
- contrastText,
52582
- controlsGroupCapsuleWidth,
52583
49869
  decodeDiagramUrl,
52584
- decodeViewState,
52585
- displayName,
52586
- draculaPalette,
52587
49870
  encodeDiagramUrl,
52588
- encodeViewState,
52589
- extractDiagramSymbols,
52590
- extractPertSymbols,
52591
- extractTagDeclarations,
52592
- focusOrgTree,
52593
- formatDateLabel,
52594
49871
  formatDgmoError,
52595
- getAllChartTypes,
52596
- getAvailablePalettes,
52597
- getExtendedChartLegendGroups,
52598
- getLegendReservedHeight,
52599
- getOrCreateName,
52600
- getPalette,
52601
- getRadarGeometry,
52602
- getRenderCategory,
52603
- getSeriesColors,
52604
- getSimpleChartLegendGroups,
52605
- groupMessagesBySection,
52606
- gruvboxPalette,
52607
- hexToHSL,
52608
- hexToHSLString,
52609
- highlightPertCriticalPath,
52610
- highlightPertSet,
52611
- hslToHex,
52612
- inferParticipantType,
52613
- inferRoles,
52614
- isArchiveColumn,
52615
- isExtendedChartType,
52616
- isRecognizedColorName,
52617
- isSequenceBlock,
52618
- isSequenceNote,
52619
- isValidHex,
52620
- knownChartTypeIds,
52621
- layoutBoxesAndLines,
52622
- layoutC4Components,
52623
- layoutC4Containers,
52624
- layoutC4Context,
52625
- layoutC4Deployment,
52626
- layoutClassDiagram,
52627
- layoutERDiagram,
52628
- layoutGraph,
52629
- layoutInfra,
52630
- layoutJourneyMap,
52631
- layoutMindmap,
52632
- layoutOrg,
52633
- layoutPert,
52634
- layoutSitemap,
52635
- layoutWireframe,
52636
- looksLikeClassDiagram,
52637
- looksLikeERDiagram,
52638
- looksLikeFlowchart,
52639
- looksLikePert,
52640
- looksLikeSequence,
52641
- looksLikeSitemap,
52642
- looksLikeState,
52643
- makeDgmoError,
52644
- matchColorParens,
52645
- matchesContiguously,
52646
- measurePertAnalysisBlock,
52647
- mix,
52648
- monokaiPalette,
52649
- nord,
52650
- nordPalette,
52651
- normalizeChartTypePrompt,
52652
- normalizeName,
52653
- normalizePertSourceForShare,
52654
- oneDarkPalette,
52655
- orderArcNodes,
52656
- parseAndLayoutInfra,
52657
- parseBoxesAndLines,
52658
- parseC4,
52659
- parseChart,
52660
- parseClassDiagram,
52661
- parseCycle,
52662
- parseDataRowValues,
52663
- parseDgmo,
52664
- parseDgmoChartType,
52665
- parseERDiagram,
52666
- parseExtendedChart,
52667
- parseFirstLine,
52668
- parseFlowchart,
52669
- parseGantt,
52670
- parseInArrowLabel,
52671
- parseInfra,
52672
- parseInlineMarkdown,
52673
- parseJourneyMap,
52674
- parseKanban,
52675
- parseMindmap,
52676
- parseOrg,
52677
- parsePert,
52678
- parsePyramid,
52679
- parseRaci,
52680
- parseRing,
52681
- parseSequenceDgmo,
52682
- parseSequenceDiagram,
52683
- parseSitemap,
52684
- parseState,
52685
- parseTechRadar,
52686
- parseTimelineDate,
52687
- parseVisualization,
52688
- parseWireframe,
52689
- pertLegendBlockWidth,
52690
- pertLegendEntries,
52691
- raciCellAppendMarker,
52692
- raciCellCycle,
52693
- raciCellRemove,
52694
- raciCellReplace,
52695
- registerExtractor,
52696
- registerPalette,
52697
- relayoutPert,
49872
+ palettes,
52698
49873
  render,
52699
- renderArcDiagram,
52700
- renderBoxesAndLines,
52701
- renderBoxesAndLinesForExport,
52702
- renderC4ComponentsForExport,
52703
- renderC4Containers,
52704
- renderC4ContainersForExport,
52705
- renderC4Context,
52706
- renderC4ContextForExport,
52707
- renderC4Deployment,
52708
- renderC4DeploymentForExport,
52709
- renderClassDiagram,
52710
- renderClassDiagramForExport,
52711
- renderCycle,
52712
- renderCycleForExport,
52713
- renderERDiagram,
52714
- renderERDiagramForExport,
52715
- renderExtendedChartForExport,
52716
- renderFlowchart,
52717
- renderFlowchartForExport,
52718
- renderForExport,
52719
- renderGantt,
52720
- renderInfra,
52721
- renderJourneyMap,
52722
- renderJourneyMapForExport,
52723
- renderKanban,
52724
- renderKanbanForExport,
52725
- renderLegendD3,
52726
- renderLegendSvg,
52727
- renderLegendSvgFromConfig,
52728
- renderMindmap,
52729
- renderMindmapForExport,
52730
- renderOrg,
52731
- renderOrgForExport,
52732
- renderPert,
52733
- renderPertAnalysisBlock,
52734
- renderPertForExport,
52735
- renderPertLegendBlock,
52736
- renderPyramid,
52737
- renderPyramidForExport,
52738
- renderQuadrant,
52739
- renderQuadrantFocus,
52740
- renderQuadrantFocusForExport,
52741
- renderRaci,
52742
- renderRaciForExport,
52743
- renderRing,
52744
- renderRingForExport,
52745
- renderSequenceDiagram,
52746
- renderSitemap,
52747
- renderSitemapForExport,
52748
- renderSlopeChart,
52749
- renderState,
52750
- renderStateForExport,
52751
- renderTechRadar,
52752
- renderTechRadarForExport,
52753
- renderTimeline,
52754
- renderVenn,
52755
- renderWireframe,
52756
- renderWordCloud,
52757
- resetPertCriticalPath,
52758
- resetPertHighlight,
52759
- resolveColor,
52760
- resolveColorWithDiagnostic,
52761
- resolveOrgImports,
52762
- resolveTaskName,
52763
- rollUpContextRelationships,
52764
- rosePinePalette,
52765
- scoreChartType,
52766
- seriesColors,
52767
- shade,
52768
- shapeFill,
52769
- solarizedPalette,
52770
- suggestChartTypes,
52771
- tint,
52772
- tokyoNightPalette,
52773
- truncateBareUrl,
52774
- validateComputed,
52775
- validateInfra,
52776
- validateLabelCharacters
49874
+ themes,
49875
+ validate
52777
49876
  });
52778
49877
  //# sourceMappingURL=index.cjs.map