@diagrammo/dgmo 0.47.0 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auto.js +1 -1
- package/dist/auto.mjs +1 -1
- package/dist/element.js +1 -1
- package/dist/element.mjs +1 -1
- package/package.json +19 -70
- package/dist/advanced.cjs +0 -71648
- package/dist/advanced.d.cts +0 -5719
- package/dist/auto.cjs +0 -70648
- package/dist/auto.d.cts +0 -54
- package/dist/block.cjs +0 -70208
- package/dist/block.d.cts +0 -115
- package/dist/editor.cjs +0 -526
- package/dist/editor.d.cts +0 -26
- package/dist/element.cjs +0 -70530
- package/dist/element.d.cts +0 -62
- package/dist/highlight.cjs +0 -852
- package/dist/highlight.d.cts +0 -49
- package/dist/index.cjs +0 -70491
- package/dist/index.d.cts +0 -160
- package/dist/pert.cjs +0 -325
- package/dist/pert.d.cts +0 -559
- package/dist/themes-1-CuKpeH.d.cts +0 -908
- package/src/advanced.ts +0 -873
- package/src/arc/parser.ts +0 -15
- package/src/arc/renderer.ts +0 -633
- package/src/auto/index.ts +0 -621
- package/src/auto/shared.ts +0 -370
- package/src/auto/styles.ts +0 -73
- package/src/block/layout.ts +0 -198
- package/src/block/parser.ts +0 -427
- package/src/block/renderer.ts +0 -484
- package/src/block/types.ts +0 -67
- package/src/boxes-and-lines/collapse.ts +0 -96
- package/src/boxes-and-lines/focus.ts +0 -257
- package/src/boxes-and-lines/label-placement.ts +0 -339
- package/src/boxes-and-lines/layout-grouped.ts +0 -912
- package/src/boxes-and-lines/layout-layered.ts +0 -722
- package/src/boxes-and-lines/layout-search.ts +0 -1678
- package/src/boxes-and-lines/layout.ts +0 -398
- package/src/boxes-and-lines/parser.ts +0 -1181
- package/src/boxes-and-lines/renderer.ts +0 -1465
- package/src/boxes-and-lines/types.ts +0 -66
- package/src/c4/layout.ts +0 -2441
- package/src/c4/parser.ts +0 -1158
- package/src/c4/renderer.ts +0 -2008
- package/src/c4/types.ts +0 -89
- package/src/chart-type-registry.ts +0 -529
- package/src/chart-types.ts +0 -225
- package/src/chart.ts +0 -685
- package/src/charts-d3/bar.ts +0 -338
- package/src/charts-d3/chord.ts +0 -140
- package/src/charts-d3/function.ts +0 -147
- package/src/charts-d3/funnel.ts +0 -104
- package/src/charts-d3/heatmap.ts +0 -145
- package/src/charts-d3/index.ts +0 -337
- package/src/charts-d3/interactions.ts +0 -477
- package/src/charts-d3/line.ts +0 -344
- package/src/charts-d3/mount.ts +0 -151
- package/src/charts-d3/pie.ts +0 -117
- package/src/charts-d3/polar.ts +0 -89
- package/src/charts-d3/radar.ts +0 -0
- package/src/charts-d3/sankey.ts +0 -0
- package/src/charts-d3/scatter.ts +0 -185
- package/src/charts-d3/shared.ts +0 -208
- package/src/class/layout.ts +0 -326
- package/src/class/parser.ts +0 -635
- package/src/class/renderer.ts +0 -793
- package/src/class/types.ts +0 -58
- package/src/cli-banner.ts +0 -106
- package/src/cli.ts +0 -1080
- package/src/colors-diagnostics.ts +0 -35
- package/src/colors.ts +0 -379
- package/src/completion-types.ts +0 -27
- package/src/completion.ts +0 -2668
- package/src/cycle/layout.ts +0 -1026
- package/src/cycle/parser.ts +0 -387
- package/src/cycle/renderer.ts +0 -653
- package/src/cycle/types.ts +0 -101
- package/src/d3.ts +0 -1434
- package/src/data-chart-parser.ts +0 -1007
- package/src/dgmo-router.ts +0 -296
- package/src/diagnostics-registry.ts +0 -108
- package/src/diagnostics.ts +0 -0
- package/src/dimensions.ts +0 -20
- package/src/directives-registry.ts +0 -396
- package/src/editor/dgmo.grammar +0 -76
- package/src/editor/dgmo.grammar.d.ts +0 -2
- package/src/editor/dgmo.grammar.js +0 -18
- package/src/editor/dgmo.grammar.terms.d.ts +0 -5
- package/src/editor/dgmo.grammar.terms.js +0 -35
- package/src/editor/highlight-api.ts +0 -596
- package/src/editor/highlight.ts +0 -36
- package/src/editor/index.ts +0 -27
- package/src/editor/keywords.ts +0 -128
- package/src/editor/tokens.ts +0 -30
- package/src/element/index.ts +0 -432
- package/src/embed/css.ts +0 -312
- package/src/embed/escape.ts +0 -15
- package/src/embed/index.ts +0 -280
- package/src/er/classify.ts +0 -228
- package/src/er/layout.ts +0 -530
- package/src/er/parser.ts +0 -750
- package/src/er/renderer.ts +0 -725
- package/src/er/types.ts +0 -52
- package/src/error-card.ts +0 -269
- package/src/event-line/diagnostics.ts +0 -117
- package/src/event-line/parser.ts +0 -643
- package/src/event-line/renderer.ts +0 -1742
- package/src/event-line/types.ts +0 -74
- package/src/fonts.ts +0 -3
- package/src/gantt/calculator.ts +0 -979
- package/src/gantt/parser.ts +0 -1641
- package/src/gantt/renderer.ts +0 -3787
- package/src/gantt/resolver.ts +0 -172
- package/src/gantt/types.ts +0 -206
- package/src/graph/diagnostics.ts +0 -64
- package/src/graph/edge-spline.ts +0 -29
- package/src/graph/flowchart-parser.ts +0 -759
- package/src/graph/flowchart-renderer.ts +0 -817
- package/src/graph/layout.ts +0 -472
- package/src/graph/notes.ts +0 -21
- package/src/graph/state-collapse.ts +0 -78
- package/src/graph/state-parser.ts +0 -574
- package/src/graph/state-renderer.ts +0 -653
- package/src/graph/types.ts +0 -65
- package/src/index.ts +0 -261
- package/src/infra/compute.ts +0 -1385
- package/src/infra/layout.ts +0 -888
- package/src/infra/parser.ts +0 -1234
- package/src/infra/renderer.ts +0 -2534
- package/src/infra/roles.ts +0 -75
- package/src/infra/types.ts +0 -216
- package/src/infra/validation.ts +0 -201
- package/src/journey-map/layout.ts +0 -490
- package/src/journey-map/parser.ts +0 -557
- package/src/journey-map/renderer.ts +0 -1580
- package/src/journey-map/types.ts +0 -47
- package/src/kanban/mutations.ts +0 -175
- package/src/kanban/parser.ts +0 -509
- package/src/kanban/renderer.ts +0 -1449
- package/src/kanban/types.ts +0 -39
- package/src/label-layout.ts +0 -368
- package/src/map/colorize.ts +0 -54
- package/src/map/completion.ts +0 -316
- package/src/map/context-labels.ts +0 -609
- package/src/map/data/PROVENANCE.json +0 -1
- package/src/map/data/README.md +0 -40
- package/src/map/data/airport-collisions.json +0 -1
- package/src/map/data/airports.json +0 -1
- package/src/map/data/gazetteer.json +0 -1
- package/src/map/data/lakes.json +0 -1
- package/src/map/data/mountain-ranges.json +0 -1
- package/src/map/data/na-lakes.json +0 -1
- package/src/map/data/na-land.json +0 -1
- package/src/map/data/region-names.json +0 -1
- package/src/map/data/rivers.json +0 -1
- package/src/map/data/types.ts +0 -121
- package/src/map/data/us-states.json +0 -1
- package/src/map/data/water-bodies.json +0 -1
- package/src/map/data/world-coarse.json +0 -1
- package/src/map/data/world-detail.json +0 -1
- package/src/map/diagnostics.ts +0 -134
- package/src/map/dimensions.ts +0 -150
- package/src/map/geo-query.ts +0 -295
- package/src/map/geo.ts +0 -438
- package/src/map/invert.ts +0 -111
- package/src/map/layout.ts +0 -5069
- package/src/map/legend-band.ts +0 -127
- package/src/map/load-data.ts +0 -186
- package/src/map/parser.ts +0 -783
- package/src/map/renderer.ts +0 -1445
- package/src/map/resolved-types.ts +0 -160
- package/src/map/resolver.ts +0 -1146
- package/src/map/types.ts +0 -194
- package/src/mindmap/collapse.ts +0 -67
- package/src/mindmap/layout.ts +0 -649
- package/src/mindmap/parser.ts +0 -430
- package/src/mindmap/renderer.ts +0 -637
- package/src/mindmap/text-wrap.ts +0 -218
- package/src/mindmap/types.ts +0 -56
- package/src/org/collapse.ts +0 -151
- package/src/org/layout.ts +0 -1262
- package/src/org/parser.ts +0 -519
- package/src/org/renderer.ts +0 -866
- package/src/org/resolver.ts +0 -636
- package/src/palettes/atlas.ts +0 -77
- package/src/palettes/blueprint.ts +0 -73
- package/src/palettes/catppuccin.ts +0 -84
- package/src/palettes/color-utils.ts +0 -443
- package/src/palettes/index.ts +0 -67
- package/src/palettes/nord.ts +0 -67
- package/src/palettes/registry.ts +0 -114
- package/src/palettes/slate.ts +0 -73
- package/src/palettes/tidewater.ts +0 -73
- package/src/palettes/tokyo-night.ts +0 -86
- package/src/palettes/types.ts +0 -88
- package/src/pert/analyzer.ts +0 -1183
- package/src/pert/diagnostics.ts +0 -110
- package/src/pert/index.ts +0 -43
- package/src/pert/internal.ts +0 -252
- package/src/pert/layout.ts +0 -971
- package/src/pert/monte-carlo.ts +0 -446
- package/src/pert/parser.ts +0 -1606
- package/src/pert/renderer.ts +0 -4009
- package/src/pert/share-normalize.ts +0 -62
- package/src/pert/types.ts +0 -604
- package/src/pyramid/parser.ts +0 -185
- package/src/pyramid/renderer.ts +0 -768
- package/src/pyramid/types.ts +0 -28
- package/src/quadrant/parser.ts +0 -18
- package/src/quadrant/renderer.ts +0 -638
- package/src/raci/diagnostics.ts +0 -213
- package/src/raci/index.ts +0 -23
- package/src/raci/mutations.ts +0 -321
- package/src/raci/parser.ts +0 -699
- package/src/raci/renderer.ts +0 -1627
- package/src/raci/types.ts +0 -82
- package/src/raci/variants.ts +0 -320
- package/src/render.ts +0 -268
- package/src/ring/parser.ts +0 -212
- package/src/ring/renderer.ts +0 -490
- package/src/ring/types.ts +0 -27
- package/src/sequence/collapse.ts +0 -174
- package/src/sequence/parser.ts +0 -1596
- package/src/sequence/participant-inference.ts +0 -152
- package/src/sequence/renderer.ts +0 -3168
- package/src/sequence/tag-resolution.ts +0 -164
- package/src/sharing.ts +0 -211
- package/src/sitemap/collapse.ts +0 -100
- package/src/sitemap/layout.ts +0 -925
- package/src/sitemap/parser.ts +0 -755
- package/src/sitemap/renderer.ts +0 -828
- package/src/sitemap/types.ts +0 -42
- package/src/slope/parser.ts +0 -18
- package/src/slope/renderer.ts +0 -378
- package/src/swimlane/diagnostics.ts +0 -94
- package/src/swimlane/layout.ts +0 -597
- package/src/swimlane/parser.ts +0 -613
- package/src/swimlane/renderer.ts +0 -681
- package/src/swimlane/types.ts +0 -151
- package/src/tech-radar/interactive.ts +0 -1129
- package/src/tech-radar/layout.ts +0 -197
- package/src/tech-radar/parser.ts +0 -436
- package/src/tech-radar/renderer.ts +0 -1239
- package/src/tech-radar/shared.ts +0 -151
- package/src/tech-radar/types.ts +0 -86
- package/src/themes.ts +0 -22
- package/src/timeline/parser.ts +0 -472
- package/src/timeline/renderer.ts +0 -3024
- package/src/timeline/types.ts +0 -33
- package/src/timeline/viz-parser.ts +0 -21
- package/src/treemap/diagnostics.ts +0 -62
- package/src/treemap/layout-radial.ts +0 -233
- package/src/treemap/layout.ts +0 -189
- package/src/treemap/parser.ts +0 -463
- package/src/treemap/renderer-radial.ts +0 -438
- package/src/treemap/renderer.ts +0 -572
- package/src/treemap/treemap-shared.ts +0 -309
- package/src/treemap/types.ts +0 -60
- package/src/utils/arrow-markers.ts +0 -51
- package/src/utils/arrows-diagnostics.ts +0 -62
- package/src/utils/arrows.ts +0 -227
- package/src/utils/brand.ts +0 -61
- package/src/utils/card.ts +0 -183
- package/src/utils/collapse-engine/tree-edges.ts +0 -115
- package/src/utils/collapse-engine/tree.ts +0 -117
- package/src/utils/d3-helpers.ts +0 -219
- package/src/utils/d3-types.ts +0 -9
- package/src/utils/description-helpers.ts +0 -38
- package/src/utils/duration.ts +0 -312
- package/src/utils/export-container.ts +0 -41
- package/src/utils/expr-eval.ts +0 -27
- package/src/utils/fit-canvas.ts +0 -64
- package/src/utils/hover-styles.ts +0 -673
- package/src/utils/inline-markdown.ts +0 -96
- package/src/utils/legend-constants.ts +0 -48
- package/src/utils/legend-d3.ts +0 -618
- package/src/utils/legend-integration.ts +0 -107
- package/src/utils/legend-layout.ts +0 -776
- package/src/utils/legend-svg.ts +0 -214
- package/src/utils/legend-types.ts +0 -272
- package/src/utils/name-normalize.ts +0 -163
- package/src/utils/note-box/constants.ts +0 -25
- package/src/utils/note-box/index.ts +0 -11
- package/src/utils/note-box/metrics.ts +0 -90
- package/src/utils/note-box/svg.ts +0 -331
- package/src/utils/notes/bounds.ts +0 -30
- package/src/utils/notes/build.ts +0 -131
- package/src/utils/notes/index.ts +0 -18
- package/src/utils/notes/model.ts +0 -19
- package/src/utils/notes/parse.ts +0 -131
- package/src/utils/notes/place.ts +0 -177
- package/src/utils/notes/resolve.ts +0 -88
- package/src/utils/number-format.ts +0 -36
- package/src/utils/parsing.ts +0 -953
- package/src/utils/reserved-key-registry.ts +0 -239
- package/src/utils/safe-href.ts +0 -38
- package/src/utils/scaling.ts +0 -97
- package/src/utils/svg-embed.ts +0 -251
- package/src/utils/tag-groups.ts +0 -607
- package/src/utils/text-measure.ts +0 -122
- package/src/utils/time-ticks.ts +0 -253
- package/src/utils/title-constants.ts +0 -24
- package/src/utils/visual-conventions.ts +0 -61
- package/src/utils/wrapped-desc.ts +0 -87
- package/src/venn/parser.ts +0 -18
- package/src/venn/renderer.ts +0 -1047
- package/src/version-control/diagnostics.ts +0 -67
- package/src/version-control/parser.ts +0 -544
- package/src/version-control/renderer.ts +0 -724
- package/src/version-control/types.ts +0 -100
- package/src/visualizations/parse.ts +0 -1560
- package/src/visualizations/types.ts +0 -262
- package/src/wireframe/layout.ts +0 -479
- package/src/wireframe/parser.ts +0 -1114
- package/src/wireframe/renderer.ts +0 -1318
- package/src/wireframe/types.ts +0 -110
- package/src/wordcloud/parser.ts +0 -18
- package/src/wordcloud/renderer.ts +0 -357
package/src/mindmap/parser.ts
DELETED
|
@@ -1,430 +0,0 @@
|
|
|
1
|
-
import type { PaletteColors } from '../palettes';
|
|
2
|
-
import {
|
|
3
|
-
formatDgmoError,
|
|
4
|
-
makeDgmoError,
|
|
5
|
-
makeFail,
|
|
6
|
-
suggest,
|
|
7
|
-
} from '../diagnostics';
|
|
8
|
-
import type { TagGroup } from '../utils/tag-groups';
|
|
9
|
-
import type { Writable } from '../utils/brand';
|
|
10
|
-
import {
|
|
11
|
-
matchTagBlockHeading,
|
|
12
|
-
validateTagValues,
|
|
13
|
-
validateTagGroupNames,
|
|
14
|
-
stripDefaultModifier,
|
|
15
|
-
finalizeAutoTagColors,
|
|
16
|
-
cascadeTagMetadata,
|
|
17
|
-
AUTO_TAG_COLOR_SENTINEL,
|
|
18
|
-
tagAttrKey,
|
|
19
|
-
} from '../utils/tag-groups';
|
|
20
|
-
import {
|
|
21
|
-
measureIndent,
|
|
22
|
-
extractColor,
|
|
23
|
-
parseFirstLine,
|
|
24
|
-
OPTION_NOCOLON_RE,
|
|
25
|
-
splitNameAndMeta,
|
|
26
|
-
tryParseSharedOption,
|
|
27
|
-
warnUnknownMetaKeys,
|
|
28
|
-
} from '../utils/parsing';
|
|
29
|
-
import {
|
|
30
|
-
MINDMAP_REGISTRY,
|
|
31
|
-
withTagAliases,
|
|
32
|
-
} from '../utils/reserved-key-registry';
|
|
33
|
-
import type { MindmapNode, ParsedMindmap } from './types';
|
|
34
|
-
import { tryStripDescriptionKeyword } from '../utils/description-helpers';
|
|
35
|
-
|
|
36
|
-
// ============================================================
|
|
37
|
-
// Constants
|
|
38
|
-
// ============================================================
|
|
39
|
-
|
|
40
|
-
/** Known mindmap options (key-value). */
|
|
41
|
-
const KNOWN_OPTIONS = new Set(['active-tag']);
|
|
42
|
-
|
|
43
|
-
// ============================================================
|
|
44
|
-
// Parser
|
|
45
|
-
// ============================================================
|
|
46
|
-
|
|
47
|
-
export function parseMindmap(
|
|
48
|
-
content: string,
|
|
49
|
-
palette?: PaletteColors
|
|
50
|
-
): ParsedMindmap {
|
|
51
|
-
const options: Record<string, string> = {};
|
|
52
|
-
const result: Writable<ParsedMindmap> = {
|
|
53
|
-
title: null,
|
|
54
|
-
titleLineNumber: null,
|
|
55
|
-
roots: [],
|
|
56
|
-
tagGroups: [],
|
|
57
|
-
options,
|
|
58
|
-
diagnostics: [],
|
|
59
|
-
error: null,
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const fail = makeFail(result);
|
|
63
|
-
|
|
64
|
-
const pushError = (line: number, message: string): void => {
|
|
65
|
-
const diag = makeDgmoError(line, message);
|
|
66
|
-
result.diagnostics.push(diag);
|
|
67
|
-
if (!result.error) result.error = formatDgmoError(diag);
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const pushWarning = (line: number, message: string): void => {
|
|
71
|
-
result.diagnostics.push(makeDgmoError(line, message, 'warning'));
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
if (!content?.trim()) {
|
|
75
|
-
return fail(0, 'No content provided');
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const lines = content.split('\n');
|
|
79
|
-
let contentStarted = false;
|
|
80
|
-
let nodeCounter = 0;
|
|
81
|
-
|
|
82
|
-
// Tag group parsing state
|
|
83
|
-
let currentTagGroup: Writable<TagGroup> | null = null;
|
|
84
|
-
const aliasMap = new Map<string, string>();
|
|
85
|
-
|
|
86
|
-
// Indent stack for hierarchy tracking
|
|
87
|
-
const indentStack: { node: Writable<MindmapNode>; indent: number }[] = [];
|
|
88
|
-
|
|
89
|
-
// Track which nodes have had a child added (for late-description warnings)
|
|
90
|
-
const nodesWithChildren = new Set<string>();
|
|
91
|
-
|
|
92
|
-
// Title-derived root node (if title exists on first line)
|
|
93
|
-
let titleRoot: Writable<MindmapNode> | null = null;
|
|
94
|
-
|
|
95
|
-
for (let i = 0; i < lines.length; i++) {
|
|
96
|
-
// In-bounds by loop guard (i < lines.length).
|
|
97
|
-
const line = lines[i]!;
|
|
98
|
-
const lineNumber = i + 1;
|
|
99
|
-
const trimmed = line.trim();
|
|
100
|
-
|
|
101
|
-
// Skip empty lines
|
|
102
|
-
if (!trimmed) {
|
|
103
|
-
if (currentTagGroup) {
|
|
104
|
-
currentTagGroup = null;
|
|
105
|
-
}
|
|
106
|
-
continue;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Skip comments
|
|
110
|
-
if (trimmed.startsWith('//')) continue;
|
|
111
|
-
|
|
112
|
-
// --- Header phase ---
|
|
113
|
-
|
|
114
|
-
if (!contentStarted) {
|
|
115
|
-
// Extract chart type + title from first line
|
|
116
|
-
const firstLine = parseFirstLine(trimmed);
|
|
117
|
-
if (firstLine) {
|
|
118
|
-
if (firstLine.chartType !== 'mindmap') {
|
|
119
|
-
let msg = `Expected chart type "mindmap", got "${firstLine.chartType}"`;
|
|
120
|
-
const hint = suggest(firstLine.chartType, ['mindmap']);
|
|
121
|
-
if (hint) msg += `. ${hint}`;
|
|
122
|
-
return fail(lineNumber, msg);
|
|
123
|
-
}
|
|
124
|
-
if (firstLine.title) {
|
|
125
|
-
// Title IS the root
|
|
126
|
-
const label = firstLine.title;
|
|
127
|
-
result.title = label;
|
|
128
|
-
result.titleLineNumber = lineNumber;
|
|
129
|
-
|
|
130
|
-
nodeCounter++;
|
|
131
|
-
const titleMetadata: Record<string, string> = {};
|
|
132
|
-
titleRoot = {
|
|
133
|
-
id: `node-${nodeCounter}`,
|
|
134
|
-
label,
|
|
135
|
-
metadata: titleMetadata,
|
|
136
|
-
children: [],
|
|
137
|
-
parentId: null,
|
|
138
|
-
lineNumber,
|
|
139
|
-
};
|
|
140
|
-
result.roots.push(titleRoot);
|
|
141
|
-
// Push title root onto indent stack at indent -1 so all indent-0 lines become children
|
|
142
|
-
indentStack.push({ node: titleRoot, indent: -1 });
|
|
143
|
-
}
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Tag group heading
|
|
149
|
-
const tagBlockMatch = matchTagBlockHeading(trimmed);
|
|
150
|
-
if (tagBlockMatch) {
|
|
151
|
-
if (contentStarted) {
|
|
152
|
-
pushError(lineNumber, 'Tag groups must appear before mindmap content');
|
|
153
|
-
continue;
|
|
154
|
-
}
|
|
155
|
-
currentTagGroup = {
|
|
156
|
-
name: tagBlockMatch.name,
|
|
157
|
-
...(tagBlockMatch.alias !== undefined && {
|
|
158
|
-
alias: tagBlockMatch.alias,
|
|
159
|
-
}),
|
|
160
|
-
entries: [],
|
|
161
|
-
lineNumber,
|
|
162
|
-
};
|
|
163
|
-
if (tagBlockMatch.alias) {
|
|
164
|
-
aliasMap.set(
|
|
165
|
-
tagBlockMatch.alias.toLowerCase(),
|
|
166
|
-
tagAttrKey(tagBlockMatch.name)
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
aliasMap.set(
|
|
170
|
-
tagAttrKey(tagBlockMatch.name),
|
|
171
|
-
tagAttrKey(tagBlockMatch.name)
|
|
172
|
-
);
|
|
173
|
-
result.tagGroups.push(currentTagGroup);
|
|
174
|
-
continue;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Options: key-value (e.g., `active-tag Priority`)
|
|
178
|
-
if (!contentStarted && !currentTagGroup && measureIndent(line) === 0) {
|
|
179
|
-
const optMatch = trimmed.match(OPTION_NOCOLON_RE);
|
|
180
|
-
if (optMatch) {
|
|
181
|
-
// Capture groups [1] and [2] are guaranteed by OPTION_NOCOLON_RE shape.
|
|
182
|
-
const key = optMatch[1]!.trim().toLowerCase();
|
|
183
|
-
if (KNOWN_OPTIONS.has(key)) {
|
|
184
|
-
options[key] = optMatch[2]!.trim();
|
|
185
|
-
continue;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
const lower = trimmed.toLowerCase();
|
|
189
|
-
if (lower === 'no-descriptions') {
|
|
190
|
-
pushWarning(
|
|
191
|
-
lineNumber,
|
|
192
|
-
'"no-descriptions" has been removed — delete description lines from your source instead.'
|
|
193
|
-
);
|
|
194
|
-
continue;
|
|
195
|
-
}
|
|
196
|
-
// Bare flag: colour nodes by depth instead of by tag (off by default).
|
|
197
|
-
// View-state directive written by the app's Color-by-depth toggle.
|
|
198
|
-
if (lower === 'color-by-depth') {
|
|
199
|
-
options['color-by-depth'] = 'on';
|
|
200
|
-
continue;
|
|
201
|
-
}
|
|
202
|
-
if (tryParseSharedOption(trimmed, options)) {
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// Tag group entries (indented Value color under tag heading)
|
|
208
|
-
if (currentTagGroup && !contentStarted) {
|
|
209
|
-
const indent = measureIndent(line);
|
|
210
|
-
if (indent > 0) {
|
|
211
|
-
const { text: cleanEntry, isDefault } = stripDefaultModifier(trimmed);
|
|
212
|
-
const { label, color } = extractColor(
|
|
213
|
-
cleanEntry,
|
|
214
|
-
palette,
|
|
215
|
-
result.diagnostics,
|
|
216
|
-
lineNumber
|
|
217
|
-
);
|
|
218
|
-
// Bare value (no explicit color) → keep it; finalized below.
|
|
219
|
-
if (isDefault) {
|
|
220
|
-
currentTagGroup.defaultValue = label;
|
|
221
|
-
} else if (currentTagGroup.entries.length === 0) {
|
|
222
|
-
currentTagGroup.defaultValue = label;
|
|
223
|
-
}
|
|
224
|
-
currentTagGroup.entries.push({
|
|
225
|
-
value: label,
|
|
226
|
-
color: color ?? AUTO_TAG_COLOR_SENTINEL,
|
|
227
|
-
lineNumber,
|
|
228
|
-
});
|
|
229
|
-
continue;
|
|
230
|
-
}
|
|
231
|
-
currentTagGroup = null; // eslint-disable-line no-useless-assignment
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// --- Content phase ---
|
|
235
|
-
contentStarted = true;
|
|
236
|
-
currentTagGroup = null;
|
|
237
|
-
|
|
238
|
-
const indent = measureIndent(line);
|
|
239
|
-
|
|
240
|
-
// Check for indented `description: text` metadata
|
|
241
|
-
if (indent > 0) {
|
|
242
|
-
const descResult = tryStripDescriptionKeyword(trimmed);
|
|
243
|
-
if (descResult.isKeyword && !descResult.needsColon) {
|
|
244
|
-
// Find parent node from indent stack
|
|
245
|
-
const parent = findMetadataParent(indent, indentStack);
|
|
246
|
-
if (parent) {
|
|
247
|
-
const descValue = descResult.text.trim();
|
|
248
|
-
if (!descValue) {
|
|
249
|
-
// Empty description: silently skip
|
|
250
|
-
continue;
|
|
251
|
-
}
|
|
252
|
-
// Check if parent already has children at this indent level
|
|
253
|
-
if (nodesWithChildren.has(parent.id)) {
|
|
254
|
-
pushWarning(
|
|
255
|
-
lineNumber,
|
|
256
|
-
`description after child nodes under "${parent.label}" — should precede children`
|
|
257
|
-
);
|
|
258
|
-
continue;
|
|
259
|
-
}
|
|
260
|
-
const existing: string[] = parent.description
|
|
261
|
-
? [...parent.description]
|
|
262
|
-
: [];
|
|
263
|
-
existing.push(descValue);
|
|
264
|
-
parent.description = existing;
|
|
265
|
-
continue;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// It's a node line — possibly with same-line metadata
|
|
271
|
-
const node = parseNodeLine(
|
|
272
|
-
trimmed,
|
|
273
|
-
lineNumber,
|
|
274
|
-
palette,
|
|
275
|
-
++nodeCounter,
|
|
276
|
-
aliasMap,
|
|
277
|
-
result.diagnostics
|
|
278
|
-
);
|
|
279
|
-
attachNode(node, indent, indentStack, result, nodesWithChildren);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// If no title and roots exist, infer title from first root
|
|
283
|
-
if (result.title === null && result.roots.length > 0) {
|
|
284
|
-
// In-bounds: roots.length > 0 from the condition above.
|
|
285
|
-
result.title = result.roots[0]!.label;
|
|
286
|
-
result.titleLineNumber = result.roots[0]!.lineNumber;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// Validate tag group values
|
|
290
|
-
// Assign palette colors to bare (colorless) tag values.
|
|
291
|
-
finalizeAutoTagColors(result.tagGroups as Writable<TagGroup>[], palette);
|
|
292
|
-
|
|
293
|
-
if (result.tagGroups.length > 0) {
|
|
294
|
-
const allNodes: MindmapNode[] = [];
|
|
295
|
-
const collectAll = (nodes: readonly MindmapNode[]) => {
|
|
296
|
-
for (const node of nodes) {
|
|
297
|
-
allNodes.push(node);
|
|
298
|
-
collectAll(node.children);
|
|
299
|
-
}
|
|
300
|
-
};
|
|
301
|
-
collectAll(result.roots);
|
|
302
|
-
validateTagValues(allNodes, result.tagGroups, pushWarning, suggest);
|
|
303
|
-
validateTagGroupNames(result.tagGroups, pushWarning);
|
|
304
|
-
|
|
305
|
-
// Cascade explicit tag values down the tree so sub-nodes inherit a tagged
|
|
306
|
-
// ancestor's value (overridable per-node). Runs after validation (so we
|
|
307
|
-
// don't double-warn on inherited values) and before the layout's
|
|
308
|
-
// global-default injection (so an inherited value wins over the default).
|
|
309
|
-
cascadeTagMetadata(result.roots, result.tagGroups);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// Check for empty mindmap
|
|
313
|
-
if (result.roots.length === 0 && !result.error) {
|
|
314
|
-
const diag = makeDgmoError(1, 'No nodes found in mindmap');
|
|
315
|
-
result.diagnostics.push(diag);
|
|
316
|
-
result.error = formatDgmoError(diag);
|
|
317
|
-
} else if (
|
|
318
|
-
titleRoot?.children.length === 0 &&
|
|
319
|
-
result.roots.length === 1 &&
|
|
320
|
-
!result.error
|
|
321
|
-
) {
|
|
322
|
-
// Title-only mindmap with no children is valid (single node)
|
|
323
|
-
// No error needed
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
return result;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
// ============================================================
|
|
330
|
-
// Internal helpers
|
|
331
|
-
// ============================================================
|
|
332
|
-
|
|
333
|
-
function parseNodeLine(
|
|
334
|
-
trimmed: string,
|
|
335
|
-
lineNumber: number,
|
|
336
|
-
_palette: PaletteColors | undefined,
|
|
337
|
-
counter: number,
|
|
338
|
-
aliasMap: Map<string, string>,
|
|
339
|
-
diagnostics: ReturnType<typeof makeDgmoError>[]
|
|
340
|
-
): Writable<MindmapNode> {
|
|
341
|
-
// §1.4 unified metadata grammar — build registry with active tag aliases.
|
|
342
|
-
const registry = withTagAliases(MINDMAP_REGISTRY, new Set(aliasMap.keys()));
|
|
343
|
-
const split = splitNameAndMeta(
|
|
344
|
-
trimmed,
|
|
345
|
-
registry,
|
|
346
|
-
aliasMap,
|
|
347
|
-
undefined,
|
|
348
|
-
diagnostics,
|
|
349
|
-
lineNumber
|
|
350
|
-
);
|
|
351
|
-
warnUnknownMetaKeys(
|
|
352
|
-
split.meta,
|
|
353
|
-
registry,
|
|
354
|
-
(msg) => diagnostics.push(makeDgmoError(lineNumber, msg, 'warning')),
|
|
355
|
-
split.name
|
|
356
|
-
);
|
|
357
|
-
const label = split.name;
|
|
358
|
-
const metadata: Record<string, string> = { ...split.meta };
|
|
359
|
-
if (split.color !== undefined) metadata['color'] = split.color;
|
|
360
|
-
|
|
361
|
-
let description: string[] | undefined;
|
|
362
|
-
if ('description' in metadata) {
|
|
363
|
-
const descVal = metadata['description'].trim();
|
|
364
|
-
if (descVal) description = [descVal];
|
|
365
|
-
delete metadata['description'];
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
let collapsed: boolean | undefined;
|
|
369
|
-
if ('collapsed' in metadata) {
|
|
370
|
-
collapsed = metadata['collapsed'].toLowerCase() === 'true';
|
|
371
|
-
delete metadata['collapsed'];
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
return {
|
|
375
|
-
id: `node-${counter}`,
|
|
376
|
-
label,
|
|
377
|
-
...(description !== undefined && { description }),
|
|
378
|
-
metadata,
|
|
379
|
-
children: [],
|
|
380
|
-
parentId: null,
|
|
381
|
-
lineNumber,
|
|
382
|
-
...(collapsed !== undefined && { collapsed }),
|
|
383
|
-
};
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
function attachNode(
|
|
387
|
-
node: Writable<MindmapNode>,
|
|
388
|
-
indent: number,
|
|
389
|
-
indentStack: { node: Writable<MindmapNode>; indent: number }[],
|
|
390
|
-
result: Writable<ParsedMindmap>,
|
|
391
|
-
nodesWithChildren: Set<string>
|
|
392
|
-
): void {
|
|
393
|
-
// Pop stack entries with indent >= current indent
|
|
394
|
-
while (indentStack.length > 0) {
|
|
395
|
-
// In-bounds: indentStack.length > 0 from loop guard.
|
|
396
|
-
const top = indentStack[indentStack.length - 1]!;
|
|
397
|
-
if (top.indent < indent) break;
|
|
398
|
-
indentStack.pop();
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
if (indentStack.length > 0) {
|
|
402
|
-
// In-bounds: indentStack.length > 0 from condition above.
|
|
403
|
-
const parent = indentStack[indentStack.length - 1]!.node;
|
|
404
|
-
node.parentId = parent.id;
|
|
405
|
-
parent.children.push(node);
|
|
406
|
-
nodesWithChildren.add(parent.id);
|
|
407
|
-
} else {
|
|
408
|
-
result.roots.push(node);
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
indentStack.push({ node, indent });
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
function findMetadataParent(
|
|
415
|
-
indent: number,
|
|
416
|
-
indentStack: { node: Writable<MindmapNode>; indent: number }[]
|
|
417
|
-
): Writable<MindmapNode> | null {
|
|
418
|
-
for (let i = indentStack.length - 1; i >= 0; i--) {
|
|
419
|
-
// In-bounds by loop guard (i in [0, indentStack.length)).
|
|
420
|
-
const entry = indentStack[i]!;
|
|
421
|
-
if (entry.indent < indent) {
|
|
422
|
-
return entry.node;
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
if (indentStack.length > 0) {
|
|
426
|
-
// In-bounds: indentStack.length > 0 from condition above.
|
|
427
|
-
return indentStack[indentStack.length - 1]!.node;
|
|
428
|
-
}
|
|
429
|
-
return null;
|
|
430
|
-
}
|