@diagrammo/dgmo 0.34.0 → 0.36.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/.claude/commands/dgmo.md +41 -43
- package/.github/copilot-instructions.md +1 -1
- package/README.md +7 -1
- package/SKILL.md +12 -7
- package/dist/advanced.cjs +460 -463
- package/dist/advanced.d.cts +2 -51
- package/dist/advanced.d.ts +2 -51
- package/dist/advanced.js +460 -464
- package/dist/auto.cjs +461 -140
- package/dist/auto.js +91 -91
- package/dist/auto.mjs +461 -140
- package/dist/cli.cjs +143 -326
- package/dist/index.cjs +460 -139
- package/dist/index.js +460 -139
- package/docs/ai-integration.md +47 -25
- package/docs/language-reference.md +2 -2
- package/package.json +2 -2
- package/src/advanced.ts +0 -12
- package/src/c4/parser.ts +15 -6
- package/src/chart.ts +1 -1
- package/src/class/parser.ts +6 -2
- package/src/cli-banner.ts +2 -3
- package/src/cli.ts +539 -1223
- package/src/cycle/parser.ts +4 -1
- package/src/dgmo-router.ts +16 -2
- package/src/diagnostics.ts +0 -0
- package/src/echarts.ts +5 -1
- package/src/er/parser.ts +5 -1
- package/src/gantt/parser.ts +13 -4
- package/src/graph/flowchart-parser.ts +5 -1
- package/src/graph/state-parser.ts +5 -1
- package/src/infra/parser.ts +10 -6
- package/src/journey-map/parser.ts +5 -2
- package/src/kanban/parser.ts +6 -2
- package/src/map/context-labels.ts +29 -19
- package/src/map/layout.ts +403 -108
- package/src/map/legend-band.ts +28 -0
- package/src/map/parser.ts +13 -4
- package/src/map/renderer.ts +74 -23
- package/src/map/resolver.ts +2 -2
- package/src/org/parser.ts +8 -2
- package/src/pyramid/parser.ts +4 -1
- package/src/raci/parser.ts +4 -1
- package/src/ring/parser.ts +4 -1
- package/src/sequence/parser.ts +6 -3
- package/src/sitemap/parser.ts +12 -3
- package/src/tech-radar/parser.ts +6 -3
- package/src/utils/parsing.ts +2 -2
- package/src/utils/tag-groups.ts +3 -3
- package/src/visualizations/parse.ts +9 -3
- package/src/migrate/data-comma.ts +0 -117
- package/src/migrate/embedded.ts +0 -238
- package/src/migrate/index.ts +0 -295
- package/src/migrate/line-classifier.ts +0 -128
- package/src/migrate/line-transformer.ts +0 -218
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
// Single-line transformer for the `dgmo migrate` tool.
|
|
2
|
-
//
|
|
3
|
-
// Given a legacy line with a `|` metadata delimiter, emit the new
|
|
4
|
-
// §1.4 same-line form (`Foo k: v, k: v` — no pipe). Chart-type-specific
|
|
5
|
-
// bare-positional shapes (gantt `| 80%`, journey-map `| 4 Delighted`,
|
|
6
|
-
// pyramid/ring `| description text`) are promoted to keyed metadata
|
|
7
|
-
// per spec §13.8 / §22 / §23 / §24.
|
|
8
|
-
//
|
|
9
|
-
// Lines that the classifier flags as legacy but contain only invalid
|
|
10
|
-
// content (e.g. `|` with nothing after) are returned verbatim with
|
|
11
|
-
// `changed: false` — the legacy parser would have rejected them, the
|
|
12
|
-
// new parser will too, and the migration tool's contract is "don't
|
|
13
|
-
// repair pre-existing parse errors" (spec §"Migration Tool Contract").
|
|
14
|
-
|
|
15
|
-
import { findUnsafePipePositions } from './line-classifier';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Rewrite every "unsafe" `|` (outside quotes / brace dropdowns /
|
|
19
|
-
* arrow-label regions) inside `s` to a comma. Quoted, brace-nested,
|
|
20
|
-
* and arrow-label pipes are left intact — this is the same scan the
|
|
21
|
-
* classifier uses, applied as a substitution.
|
|
22
|
-
*/
|
|
23
|
-
function replaceUnsafePipesWithCommas(s: string): string {
|
|
24
|
-
const positions = findUnsafePipePositions(s);
|
|
25
|
-
if (positions.length === 0) return s;
|
|
26
|
-
const chars = s.split('');
|
|
27
|
-
for (const pos of positions) {
|
|
28
|
-
chars[pos] = ',';
|
|
29
|
-
}
|
|
30
|
-
return chars.join('');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface TransformResult {
|
|
34
|
-
/** New line content (indent preserved); equal to input when `changed: false`. */
|
|
35
|
-
readonly line: string;
|
|
36
|
-
/** Whether the transformer mutated the line. */
|
|
37
|
-
readonly changed: boolean;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// ============================================================
|
|
41
|
-
// Chart-type-specific bare-positional promotions
|
|
42
|
-
// ============================================================
|
|
43
|
-
|
|
44
|
-
interface Promotion {
|
|
45
|
-
/** Matches a single comma-tokenized bare meta segment. */
|
|
46
|
-
readonly match: (token: string) => boolean;
|
|
47
|
-
/** Returns a `key: value[, key: value]` string. */
|
|
48
|
-
readonly promote: (token: string) => string;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Gantt §13.8 — bare `<N>%` promotes to `progress: <N>`.
|
|
52
|
-
const GANTT_PERCENT: Promotion = {
|
|
53
|
-
match: (t) => /^\d+(?:\.\d+)?\s*%$/.test(t.trim()),
|
|
54
|
-
promote: (t) => `progress: ${t.trim().replace(/\s*%$/, '')}`,
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// Journey-map §22 — bare `<N>` or `<N> <Word>` promotes to
|
|
58
|
-
// `score: <N>[, emotion: <Word>]`.
|
|
59
|
-
const JOURNEY_SCORE: Promotion = {
|
|
60
|
-
match: (t) => /^\d+(?:\s+[A-Za-z][A-Za-z0-9_-]*)?$/.test(t.trim()),
|
|
61
|
-
promote: (t) => {
|
|
62
|
-
const m = t.trim().match(/^(\d+)(?:\s+([A-Za-z][A-Za-z0-9_-]*))?$/);
|
|
63
|
-
if (!m) return t;
|
|
64
|
-
return m[2] ? `score: ${m[1]}, emotion: ${m[2]}` : `score: ${m[1]}`;
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
const PROMOTIONS_BY_CHART: Record<string, readonly Promotion[]> = {
|
|
69
|
-
gantt: [GANTT_PERCENT],
|
|
70
|
-
'journey-map': [JOURNEY_SCORE],
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Chart types whose meta region accepts a bare-text shorthand (`| Some
|
|
75
|
-
* description text` with no `key:`) — promoted to `description: <text>`.
|
|
76
|
-
* Only fires when the ENTIRE meta region contains no `:` at all.
|
|
77
|
-
*/
|
|
78
|
-
const BARE_DESCRIPTION_CHARTS = new Set(['pyramid', 'ring']);
|
|
79
|
-
|
|
80
|
-
// ============================================================
|
|
81
|
-
// Meta region tokenization
|
|
82
|
-
// ============================================================
|
|
83
|
-
//
|
|
84
|
-
// Split the meta region on commas, but respect quoted values so a
|
|
85
|
-
// `description: "with, commas"` segment stays whole.
|
|
86
|
-
|
|
87
|
-
function tokenizeMetaRegion(region: string): string[] {
|
|
88
|
-
const tokens: string[] = [];
|
|
89
|
-
let i = 0;
|
|
90
|
-
let buf = '';
|
|
91
|
-
let inQuote: '"' | "'" | null = null;
|
|
92
|
-
while (i < region.length) {
|
|
93
|
-
const ch = region[i]!;
|
|
94
|
-
if (inQuote) {
|
|
95
|
-
buf += ch;
|
|
96
|
-
if (ch === inQuote) inQuote = null;
|
|
97
|
-
i++;
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
if (ch === '"' || ch === "'") {
|
|
101
|
-
inQuote = ch as '"' | "'";
|
|
102
|
-
buf += ch;
|
|
103
|
-
i++;
|
|
104
|
-
continue;
|
|
105
|
-
}
|
|
106
|
-
if (ch === ',') {
|
|
107
|
-
const t = buf.trim();
|
|
108
|
-
if (t) tokens.push(t);
|
|
109
|
-
buf = '';
|
|
110
|
-
i++;
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
buf += ch;
|
|
114
|
-
i++;
|
|
115
|
-
}
|
|
116
|
-
const tail = buf.trim();
|
|
117
|
-
if (tail) tokens.push(tail);
|
|
118
|
-
return tokens;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// ============================================================
|
|
122
|
-
// Main transformer
|
|
123
|
-
// ============================================================
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Transform `line` from legacy `Foo | k: v, k: v` into the new §1.4
|
|
127
|
-
* same-line form. `chartType` enables chart-type-specific bare-positional
|
|
128
|
-
* promotions; pass `null` for the conservative generic transform.
|
|
129
|
-
*/
|
|
130
|
-
export function transformLine(
|
|
131
|
-
line: string,
|
|
132
|
-
chartType: string | null
|
|
133
|
-
): TransformResult {
|
|
134
|
-
// Preserve the exact leading indent (mix of tabs/spaces).
|
|
135
|
-
const indentMatch = line.match(/^[ \t]*/);
|
|
136
|
-
const indent = indentMatch ? indentMatch[0] : '';
|
|
137
|
-
const body = line.substring(indent.length);
|
|
138
|
-
|
|
139
|
-
const pipePositions = findUnsafePipePositions(body);
|
|
140
|
-
if (pipePositions.length === 0) {
|
|
141
|
-
return { line, changed: false };
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// First unsafe `|` is the cut point. Legacy grammar nominally
|
|
145
|
-
// disallowed multiple metadata pipes on a line (E_MULTIPLE_PIPES),
|
|
146
|
-
// but the pattern `Foo | k: v | k: v` is common in user content —
|
|
147
|
-
// authors treated `|` as an inter-key delimiter. Convert any
|
|
148
|
-
// additional unsafe pipes in the meta region into commas so the
|
|
149
|
-
// tokenizer sees one flat comma-separated key list.
|
|
150
|
-
const cut = pipePositions[0]!;
|
|
151
|
-
const nameRegion = body.substring(0, cut).trimEnd();
|
|
152
|
-
let metaRegion = body.substring(cut + 1).trimStart();
|
|
153
|
-
if (pipePositions.length > 1) {
|
|
154
|
-
metaRegion = replaceUnsafePipesWithCommas(metaRegion);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Pyramid/ring "bare description" — entire meta region carries no
|
|
158
|
-
// `:` AND no unsafe-pipe (i.e. no further metadata segments). The
|
|
159
|
-
// whole text becomes `description: <text>`. Commas in the source
|
|
160
|
-
// text are preserved by wrapping in quotes when needed.
|
|
161
|
-
if (
|
|
162
|
-
chartType !== null &&
|
|
163
|
-
BARE_DESCRIPTION_CHARTS.has(chartType) &&
|
|
164
|
-
!metaRegion.includes(':')
|
|
165
|
-
) {
|
|
166
|
-
const text = metaRegion.trim();
|
|
167
|
-
if (!text) {
|
|
168
|
-
// `Foo |` with nothing after — let the new parser surface
|
|
169
|
-
// the issue (empty-meta or pipe-removed); strip the pipe but
|
|
170
|
-
// emit no metadata.
|
|
171
|
-
return {
|
|
172
|
-
line: indent + nameRegion,
|
|
173
|
-
changed: true,
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
const value = text.includes(',') ? `"${text}"` : text;
|
|
177
|
-
return {
|
|
178
|
-
line: `${indent}${nameRegion} description: ${value}`,
|
|
179
|
-
changed: true,
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
const tokens = tokenizeMetaRegion(metaRegion);
|
|
184
|
-
const promotions = chartType ? (PROMOTIONS_BY_CHART[chartType] ?? []) : [];
|
|
185
|
-
|
|
186
|
-
const emitted: string[] = [];
|
|
187
|
-
for (const raw of tokens) {
|
|
188
|
-
if (raw.includes(':')) {
|
|
189
|
-
// Already a `key: value` pair — emit verbatim. Whitespace
|
|
190
|
-
// around the `:` is preserved as authored; the new parser
|
|
191
|
-
// tolerates either form (`k:v`, `k: v`).
|
|
192
|
-
emitted.push(raw);
|
|
193
|
-
continue;
|
|
194
|
-
}
|
|
195
|
-
// Bare token — try chart-type-specific promotions.
|
|
196
|
-
const promo = promotions.find((p) => p.match(raw));
|
|
197
|
-
if (promo) {
|
|
198
|
-
emitted.push(promo.promote(raw));
|
|
199
|
-
continue;
|
|
200
|
-
}
|
|
201
|
-
// Unrecognized bare token. Carry through verbatim — the new
|
|
202
|
-
// parser will surface a diagnostic. Don't drop silently; the
|
|
203
|
-
// user needs to see what's left over.
|
|
204
|
-
emitted.push(raw);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if (emitted.length === 0) {
|
|
208
|
-
return {
|
|
209
|
-
line: indent + nameRegion,
|
|
210
|
-
changed: true,
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
return {
|
|
215
|
-
line: `${indent}${nameRegion} ${emitted.join(', ')}`,
|
|
216
|
-
changed: true,
|
|
217
|
-
};
|
|
218
|
-
}
|