@diagrammo/dgmo 0.8.3 → 0.8.5
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-diagram-this.md +60 -0
- package/.claude/commands/dgmo-document-project.md +128 -0
- package/.claude/commands/dgmo.md +452 -50
- package/.cursorrules +32 -37
- package/.github/copilot-instructions.md +35 -44
- package/.windsurfrules +32 -37
- package/README.md +4 -4
- package/dist/cli.cjs +188 -185
- package/dist/editor.cjs +338 -0
- package/dist/editor.cjs.map +1 -0
- package/dist/editor.d.cts +27 -0
- package/dist/editor.d.ts +27 -0
- package/dist/editor.js +307 -0
- package/dist/editor.js.map +1 -0
- package/dist/highlight.cjs +560 -0
- package/dist/highlight.cjs.map +1 -0
- package/dist/highlight.d.cts +32 -0
- package/dist/highlight.d.ts +32 -0
- package/dist/highlight.js +530 -0
- package/dist/highlight.js.map +1 -0
- package/dist/index.cjs +3467 -1078
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -1
- package/dist/index.d.ts +22 -1
- package/dist/index.js +3466 -1078
- package/dist/index.js.map +1 -1
- package/docs/language-reference.md +46 -37
- package/gallery/fixtures/arc.dgmo +18 -0
- package/gallery/fixtures/area.dgmo +19 -0
- package/gallery/fixtures/bar-stacked.dgmo +10 -0
- package/gallery/fixtures/bar.dgmo +10 -0
- package/gallery/fixtures/c4-full.dgmo +52 -0
- package/gallery/fixtures/c4.dgmo +17 -0
- package/gallery/fixtures/chord.dgmo +12 -0
- package/gallery/fixtures/class-basic.dgmo +14 -0
- package/gallery/fixtures/class-full.dgmo +43 -0
- package/gallery/fixtures/doughnut.dgmo +8 -0
- package/gallery/fixtures/flowchart-basic.dgmo +3 -0
- package/gallery/fixtures/flowchart-colors.dgmo +5 -0
- package/gallery/fixtures/flowchart-complex.dgmo +17 -0
- package/gallery/fixtures/flowchart-decision.dgmo +5 -0
- package/gallery/fixtures/flowchart-full.dgmo +13 -0
- package/gallery/fixtures/flowchart-groups.dgmo +10 -0
- package/gallery/fixtures/flowchart-loop.dgmo +7 -0
- package/gallery/fixtures/flowchart-nested.dgmo +7 -0
- package/gallery/fixtures/flowchart-shapes.dgmo +5 -0
- package/gallery/fixtures/function.dgmo +8 -0
- package/gallery/fixtures/funnel.dgmo +7 -0
- package/gallery/fixtures/gantt-full.dgmo +49 -0
- package/gallery/fixtures/gantt.dgmo +42 -0
- package/gallery/fixtures/heatmap.dgmo +8 -0
- package/gallery/fixtures/infra-full.dgmo +78 -0
- package/gallery/fixtures/infra-overload.dgmo +25 -0
- package/gallery/fixtures/infra.dgmo +47 -0
- package/gallery/fixtures/initiative-status-full.dgmo +46 -0
- package/gallery/fixtures/initiative-status-phases.dgmo +29 -0
- package/gallery/fixtures/initiative-status.dgmo +9 -0
- package/gallery/fixtures/line.dgmo +19 -0
- package/gallery/fixtures/multi-line.dgmo +11 -0
- package/gallery/fixtures/org-basic.dgmo +16 -0
- package/gallery/fixtures/org-full.dgmo +69 -0
- package/gallery/fixtures/org-teams.dgmo +25 -0
- package/gallery/fixtures/pie.dgmo +9 -0
- package/gallery/fixtures/polar-area.dgmo +8 -0
- package/gallery/fixtures/quadrant.dgmo +18 -0
- package/gallery/fixtures/radar.dgmo +8 -0
- package/gallery/fixtures/sankey.dgmo +31 -0
- package/gallery/fixtures/scatter.dgmo +21 -0
- package/gallery/fixtures/sequence-tags-protocols.dgmo +45 -0
- package/gallery/fixtures/sequence-tags.dgmo +41 -0
- package/gallery/fixtures/sequence.dgmo +35 -0
- package/gallery/fixtures/sitemap-basic.dgmo +12 -0
- package/gallery/fixtures/sitemap-full.dgmo +156 -0
- package/gallery/fixtures/slope.dgmo +9 -0
- package/gallery/fixtures/spr-eras.dgmo +62 -0
- package/gallery/fixtures/state.dgmo +30 -0
- package/gallery/fixtures/timeline-intraday.dgmo +14 -0
- package/gallery/fixtures/timeline.dgmo +32 -0
- package/gallery/fixtures/venn.dgmo +10 -0
- package/gallery/fixtures/wordcloud.dgmo +24 -0
- package/package.json +71 -2
- package/src/c4/layout.ts +372 -90
- package/src/c4/parser.ts +100 -55
- package/src/chart.ts +91 -28
- package/src/class/parser.ts +41 -12
- package/src/cli.ts +211 -62
- package/src/completion.ts +378 -183
- package/src/d3.ts +1044 -303
- package/src/dgmo-mermaid.ts +16 -13
- package/src/dgmo-router.ts +69 -23
- package/src/echarts.ts +646 -153
- package/src/editor/dgmo.grammar +69 -0
- package/src/editor/dgmo.grammar.d.ts +2 -0
- package/src/editor/dgmo.grammar.js +18 -0
- package/src/editor/dgmo.grammar.terms.d.ts +5 -0
- package/src/editor/dgmo.grammar.terms.js +35 -0
- package/src/editor/highlight-api.ts +444 -0
- package/src/editor/highlight.ts +36 -0
- package/src/editor/index.ts +28 -0
- package/src/editor/keywords.ts +222 -0
- package/src/editor/tokens.ts +30 -0
- package/src/er/parser.ts +48 -14
- package/src/er/renderer.ts +112 -53
- package/src/gantt/calculator.ts +91 -29
- package/src/gantt/parser.ts +197 -71
- package/src/gantt/renderer.ts +1120 -350
- package/src/graph/flowchart-parser.ts +46 -25
- package/src/graph/state-parser.ts +47 -17
- package/src/index.ts +96 -31
- package/src/infra/parser.ts +157 -53
- package/src/infra/renderer.ts +723 -271
- package/src/initiative-status/parser.ts +138 -44
- package/src/kanban/parser.ts +25 -14
- package/src/org/layout.ts +111 -44
- package/src/org/parser.ts +69 -22
- package/src/palettes/index.ts +3 -2
- package/src/sequence/parser.ts +193 -61
- package/src/sitemap/parser.ts +65 -29
- package/src/utils/arrows.ts +2 -22
- package/src/utils/duration.ts +39 -21
- package/src/utils/legend-constants.ts +0 -2
- package/src/utils/parsing.ts +75 -31
package/src/completion.ts
CHANGED
|
@@ -79,7 +79,18 @@ export interface DirectiveSpec {
|
|
|
79
79
|
const GLOBAL_DIRECTIVES: Record<string, DirectiveValueSpec> = {
|
|
80
80
|
palette: {
|
|
81
81
|
description: 'Color palette name',
|
|
82
|
-
values: [
|
|
82
|
+
values: [
|
|
83
|
+
'nord',
|
|
84
|
+
'solarized',
|
|
85
|
+
'catppuccin',
|
|
86
|
+
'rose-pine',
|
|
87
|
+
'gruvbox',
|
|
88
|
+
'tokyo-night',
|
|
89
|
+
'one-dark',
|
|
90
|
+
'bold',
|
|
91
|
+
'dracula',
|
|
92
|
+
'monokai',
|
|
93
|
+
],
|
|
83
94
|
},
|
|
84
95
|
theme: {
|
|
85
96
|
description: 'Color theme',
|
|
@@ -87,139 +98,221 @@ const GLOBAL_DIRECTIVES: Record<string, DirectiveValueSpec> = {
|
|
|
87
98
|
},
|
|
88
99
|
};
|
|
89
100
|
|
|
90
|
-
function withGlobals(
|
|
101
|
+
function withGlobals(
|
|
102
|
+
directives: Record<string, DirectiveValueSpec> = {}
|
|
103
|
+
): DirectiveSpec {
|
|
91
104
|
return { directives: { ...GLOBAL_DIRECTIVES, ...directives } };
|
|
92
105
|
}
|
|
93
106
|
|
|
94
107
|
/** Chart-type → directive specifications. Every chart type has at least palette + theme. */
|
|
95
108
|
export const COMPLETION_REGISTRY = new Map<string, DirectiveSpec>([
|
|
96
109
|
// ── Data charts ──────────────────────────────────────────
|
|
97
|
-
[
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
'
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
110
|
+
[
|
|
111
|
+
'bar',
|
|
112
|
+
withGlobals({
|
|
113
|
+
series: { description: 'Series name(s)' },
|
|
114
|
+
'x-label': { description: 'X-axis label' },
|
|
115
|
+
'y-label': { description: 'Y-axis label' },
|
|
116
|
+
'orientation-horizontal': { description: 'Switch to horizontal bars' },
|
|
117
|
+
color: { description: 'Bar color override' },
|
|
118
|
+
}),
|
|
119
|
+
],
|
|
120
|
+
[
|
|
121
|
+
'line',
|
|
122
|
+
withGlobals({
|
|
123
|
+
series: { description: 'Series name(s)' },
|
|
124
|
+
'x-label': { description: 'X-axis label' },
|
|
125
|
+
'y-label': { description: 'Y-axis label' },
|
|
126
|
+
}),
|
|
127
|
+
],
|
|
128
|
+
[
|
|
129
|
+
'pie',
|
|
130
|
+
withGlobals({
|
|
131
|
+
'no-label-name': { description: 'Hide name from segment labels' },
|
|
132
|
+
'no-label-value': { description: 'Hide value from segment labels' },
|
|
133
|
+
'no-label-percent': { description: 'Hide percent from segment labels' },
|
|
134
|
+
}),
|
|
135
|
+
],
|
|
136
|
+
[
|
|
137
|
+
'doughnut',
|
|
138
|
+
withGlobals({
|
|
139
|
+
'no-label-name': { description: 'Hide name from segment labels' },
|
|
140
|
+
'no-label-value': { description: 'Hide value from segment labels' },
|
|
141
|
+
'no-label-percent': { description: 'Hide percent from segment labels' },
|
|
142
|
+
}),
|
|
143
|
+
],
|
|
144
|
+
[
|
|
145
|
+
'area',
|
|
146
|
+
withGlobals({
|
|
147
|
+
series: { description: 'Series name(s)' },
|
|
148
|
+
'x-label': { description: 'X-axis label' },
|
|
149
|
+
'y-label': { description: 'Y-axis label' },
|
|
150
|
+
}),
|
|
151
|
+
],
|
|
152
|
+
[
|
|
153
|
+
'polar-area',
|
|
154
|
+
withGlobals({
|
|
155
|
+
'no-label-name': { description: 'Hide name from segment labels' },
|
|
156
|
+
'no-label-value': { description: 'Hide value from segment labels' },
|
|
157
|
+
'no-label-percent': { description: 'Hide percent from segment labels' },
|
|
158
|
+
}),
|
|
159
|
+
],
|
|
129
160
|
['radar', withGlobals()],
|
|
130
|
-
[
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
161
|
+
[
|
|
162
|
+
'bar-stacked',
|
|
163
|
+
withGlobals({
|
|
164
|
+
series: { description: 'Series name(s) (required)' },
|
|
165
|
+
'x-label': { description: 'X-axis label' },
|
|
166
|
+
'y-label': { description: 'Y-axis label' },
|
|
167
|
+
'orientation-horizontal': { description: 'Switch to horizontal bars' },
|
|
168
|
+
}),
|
|
169
|
+
],
|
|
136
170
|
|
|
137
171
|
// ── Extended charts ──────────────────────────────────────
|
|
138
|
-
[
|
|
139
|
-
'
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
172
|
+
[
|
|
173
|
+
'scatter',
|
|
174
|
+
withGlobals({
|
|
175
|
+
'no-labels': { description: 'Hide point labels' },
|
|
176
|
+
'x-label': { description: 'X-axis label' },
|
|
177
|
+
'y-label': { description: 'Y-axis label' },
|
|
178
|
+
'size-label': { description: 'Size axis label' },
|
|
179
|
+
}),
|
|
180
|
+
],
|
|
181
|
+
[
|
|
182
|
+
'heatmap',
|
|
183
|
+
withGlobals({
|
|
184
|
+
columns: { description: 'Column labels (required)' },
|
|
185
|
+
}),
|
|
186
|
+
],
|
|
147
187
|
['sankey', withGlobals()],
|
|
148
188
|
['chord', withGlobals()],
|
|
149
189
|
['funnel', withGlobals()],
|
|
150
|
-
[
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
190
|
+
[
|
|
191
|
+
'function',
|
|
192
|
+
withGlobals({
|
|
193
|
+
x: { description: 'X-axis range (start to end)' },
|
|
194
|
+
'x-label': { description: 'X-axis label' },
|
|
195
|
+
'y-label': { description: 'Y-axis label' },
|
|
196
|
+
shade: { description: 'Fill area below curves with translucent color' },
|
|
197
|
+
}),
|
|
198
|
+
],
|
|
156
199
|
|
|
157
200
|
// ── Visualizations ───────────────────────────────────────
|
|
158
|
-
['slope', withGlobals(
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
201
|
+
['slope', withGlobals()],
|
|
202
|
+
[
|
|
203
|
+
'wordcloud',
|
|
204
|
+
withGlobals({
|
|
205
|
+
rotate: {
|
|
206
|
+
description: 'Word rotation',
|
|
207
|
+
values: ['none', 'mixed', 'angled'],
|
|
208
|
+
},
|
|
209
|
+
max: { description: 'Maximum word count' },
|
|
210
|
+
size: { description: 'Font size range (min, max)' },
|
|
211
|
+
}),
|
|
212
|
+
],
|
|
213
|
+
[
|
|
214
|
+
'arc',
|
|
215
|
+
withGlobals({
|
|
216
|
+
order: {
|
|
217
|
+
description: 'Node ordering',
|
|
218
|
+
values: ['appearance', 'name', 'group', 'degree'],
|
|
219
|
+
},
|
|
220
|
+
}),
|
|
221
|
+
],
|
|
169
222
|
['timeline', withGlobals()],
|
|
170
|
-
['venn', withGlobals(
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
223
|
+
['venn', withGlobals()],
|
|
224
|
+
[
|
|
225
|
+
'quadrant',
|
|
226
|
+
withGlobals({
|
|
227
|
+
'x-label': { description: 'X-axis labels (low, high)' },
|
|
228
|
+
'y-label': { description: 'Y-axis labels (low, high)' },
|
|
229
|
+
}),
|
|
230
|
+
],
|
|
177
231
|
|
|
178
232
|
// ── Diagrams ─────────────────────────────────────────────
|
|
179
|
-
[
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
233
|
+
[
|
|
234
|
+
'sequence',
|
|
235
|
+
withGlobals({
|
|
236
|
+
activations: {
|
|
237
|
+
description: 'Show activation bars',
|
|
238
|
+
values: ['on', 'off'],
|
|
239
|
+
},
|
|
240
|
+
'collapse-notes': {
|
|
241
|
+
description: 'Collapse note blocks',
|
|
242
|
+
values: ['yes', 'no'],
|
|
243
|
+
},
|
|
244
|
+
'active-tag': { description: 'Active tag group name' },
|
|
245
|
+
}),
|
|
246
|
+
],
|
|
247
|
+
[
|
|
248
|
+
'flowchart',
|
|
249
|
+
withGlobals({
|
|
250
|
+
'direction-lr': { description: 'Switch to left-to-right layout' },
|
|
251
|
+
}),
|
|
252
|
+
],
|
|
253
|
+
[
|
|
254
|
+
'class',
|
|
255
|
+
withGlobals({
|
|
256
|
+
'no-auto-color': {
|
|
257
|
+
description: 'Disable automatic modifier-based coloring',
|
|
258
|
+
},
|
|
259
|
+
}),
|
|
260
|
+
],
|
|
190
261
|
['er', withGlobals()],
|
|
191
|
-
[
|
|
192
|
-
'
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
262
|
+
[
|
|
263
|
+
'org',
|
|
264
|
+
withGlobals({
|
|
265
|
+
'sub-node-label': { description: 'Label for sub-nodes' },
|
|
266
|
+
'show-sub-node-count': { description: 'Show sub-node counts' },
|
|
267
|
+
}),
|
|
268
|
+
],
|
|
269
|
+
[
|
|
270
|
+
'kanban',
|
|
271
|
+
withGlobals({
|
|
272
|
+
'no-auto-color': { description: 'Disable automatic card coloring' },
|
|
273
|
+
}),
|
|
274
|
+
],
|
|
198
275
|
['c4', withGlobals()],
|
|
199
276
|
['initiative-status', withGlobals()],
|
|
200
|
-
[
|
|
201
|
-
'
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
[
|
|
208
|
-
'
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
'
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
277
|
+
[
|
|
278
|
+
'state',
|
|
279
|
+
withGlobals({
|
|
280
|
+
'direction-tb': { description: 'Switch to top-to-bottom layout' },
|
|
281
|
+
color: { description: 'Color mode', values: ['off'] },
|
|
282
|
+
}),
|
|
283
|
+
],
|
|
284
|
+
[
|
|
285
|
+
'sitemap',
|
|
286
|
+
withGlobals({
|
|
287
|
+
'direction-tb': { description: 'Switch to top-to-bottom layout' },
|
|
288
|
+
}),
|
|
289
|
+
],
|
|
290
|
+
[
|
|
291
|
+
'infra',
|
|
292
|
+
withGlobals({
|
|
293
|
+
'direction-tb': { description: 'Switch to top-to-bottom layout' },
|
|
294
|
+
animate: { description: 'Enable traffic animation' },
|
|
295
|
+
'no-animate': { description: 'Disable traffic animation' },
|
|
296
|
+
'default-latency-ms': { description: 'Default latency for all nodes' },
|
|
297
|
+
'default-uptime': { description: 'Default uptime for all nodes' },
|
|
298
|
+
'default-rps': { description: 'Default RPS capacity for all nodes' },
|
|
299
|
+
'slo-availability': { description: 'SLO availability target (0-1)' },
|
|
300
|
+
'slo-p90-latency-ms': { description: 'SLO p90 latency target in ms' },
|
|
301
|
+
'slo-warning-margin': { description: 'SLO warning margin percentage' },
|
|
302
|
+
}),
|
|
303
|
+
],
|
|
304
|
+
[
|
|
305
|
+
'gantt',
|
|
306
|
+
withGlobals({
|
|
307
|
+
start: { description: 'Project start date (YYYY-MM-DD)' },
|
|
308
|
+
'today-marker': {
|
|
309
|
+
description: 'Today marker (bare = on, or YYYY-MM-DD date)',
|
|
310
|
+
},
|
|
311
|
+
sort: { description: 'Sort order', values: ['time', 'group', 'tag'] },
|
|
312
|
+
'critical-path': { description: 'Show critical path' },
|
|
313
|
+
dependencies: { description: 'Show dependencies' },
|
|
314
|
+
}),
|
|
315
|
+
],
|
|
223
316
|
]);
|
|
224
317
|
|
|
225
318
|
// ============================================================
|
|
@@ -266,12 +359,13 @@ const CHART_TYPE_DESCRIPTIONS: Record<string, string> = {
|
|
|
266
359
|
};
|
|
267
360
|
|
|
268
361
|
/** All chart types with descriptions, for chart type autocomplete. Excludes `multi-line` alias. */
|
|
269
|
-
export const CHART_TYPES: ReadonlyArray<{ name: string; description: string }> =
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
name
|
|
273
|
-
|
|
274
|
-
|
|
362
|
+
export const CHART_TYPES: ReadonlyArray<{ name: string; description: string }> =
|
|
363
|
+
[...ALL_CHART_TYPES]
|
|
364
|
+
.filter((t) => t !== 'multi-line')
|
|
365
|
+
.map((name) => ({
|
|
366
|
+
name,
|
|
367
|
+
description: CHART_TYPE_DESCRIPTIONS[name] ?? name,
|
|
368
|
+
}));
|
|
275
369
|
|
|
276
370
|
// ============================================================
|
|
277
371
|
// Entity types for `is a` declarations
|
|
@@ -283,8 +377,24 @@ export const CHART_TYPES: ReadonlyArray<{ name: string; description: string }> =
|
|
|
283
377
|
* C4_IS_A_RE).
|
|
284
378
|
*/
|
|
285
379
|
export const ENTITY_TYPES = new Map<string, string[]>([
|
|
286
|
-
[
|
|
287
|
-
|
|
380
|
+
[
|
|
381
|
+
'sequence',
|
|
382
|
+
[
|
|
383
|
+
'service',
|
|
384
|
+
'database',
|
|
385
|
+
'actor',
|
|
386
|
+
'queue',
|
|
387
|
+
'cache',
|
|
388
|
+
'gateway',
|
|
389
|
+
'external',
|
|
390
|
+
'networking',
|
|
391
|
+
'frontend',
|
|
392
|
+
],
|
|
393
|
+
],
|
|
394
|
+
[
|
|
395
|
+
'c4',
|
|
396
|
+
['person', 'system', 'container', 'component', 'external', 'database'],
|
|
397
|
+
],
|
|
288
398
|
]);
|
|
289
399
|
|
|
290
400
|
// ============================================================
|
|
@@ -305,53 +415,96 @@ export interface PipeKeySpec {
|
|
|
305
415
|
* diagrams separates display names from identifiers and tag metadata.
|
|
306
416
|
* Adding sequence would trigger false pipe-metadata completions on every `|`.
|
|
307
417
|
*/
|
|
308
|
-
export const PIPE_METADATA = new Map<
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
418
|
+
export const PIPE_METADATA = new Map<
|
|
419
|
+
string,
|
|
420
|
+
{
|
|
421
|
+
node: Record<string, PipeKeySpec>;
|
|
422
|
+
edge: Record<string, PipeKeySpec>;
|
|
423
|
+
}
|
|
424
|
+
>([
|
|
425
|
+
[
|
|
426
|
+
'infra',
|
|
427
|
+
{
|
|
428
|
+
node: {
|
|
429
|
+
description: { description: 'Node description text' },
|
|
430
|
+
instances: {
|
|
431
|
+
description: 'Instance count or auto-scaling range (N-M)',
|
|
432
|
+
},
|
|
433
|
+
'latency-ms': { description: 'Per-request latency in milliseconds' },
|
|
434
|
+
'max-rps': { description: 'Max requests per second per instance' },
|
|
435
|
+
'cache-hit': { description: 'Cache hit percentage (0-100)' },
|
|
436
|
+
'firewall-block': { description: 'Traffic blocked percentage' },
|
|
437
|
+
'ratelimit-rps': { description: 'Max RPS allowed through' },
|
|
438
|
+
'cb-error-threshold': {
|
|
439
|
+
description: 'Circuit breaker error threshold %',
|
|
440
|
+
},
|
|
441
|
+
'cb-latency-threshold-ms': {
|
|
442
|
+
description: 'Circuit breaker latency threshold',
|
|
443
|
+
},
|
|
444
|
+
uptime: { description: 'Component availability (0-1)' },
|
|
445
|
+
concurrency: { description: 'Concurrent request limit' },
|
|
446
|
+
'duration-ms': { description: 'Processing duration' },
|
|
447
|
+
'cold-start-ms': { description: 'Function cold-start time' },
|
|
448
|
+
buffer: { description: 'Queue/buffer capacity' },
|
|
449
|
+
'drain-rate': { description: 'Queue drain rate' },
|
|
450
|
+
'retention-hours': { description: 'Data retention period' },
|
|
451
|
+
partitions: { description: 'Queue/stream partition count' },
|
|
452
|
+
'slo-availability': { description: 'Node availability target (0-1)' },
|
|
453
|
+
'slo-p90-latency-ms': { description: 'Node p90 latency target' },
|
|
454
|
+
'slo-warning-margin': { description: 'Node SLO warning margin' },
|
|
455
|
+
},
|
|
456
|
+
edge: {
|
|
457
|
+
split: { description: 'Traffic split percentage (e.g., 60%)' },
|
|
458
|
+
fanout: { description: 'Fanout multiplier (integer >= 1)' },
|
|
459
|
+
},
|
|
334
460
|
},
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
461
|
+
],
|
|
462
|
+
[
|
|
463
|
+
'c4',
|
|
464
|
+
{
|
|
465
|
+
node: {
|
|
466
|
+
description: { description: 'Element description' },
|
|
467
|
+
tech: { description: 'Technology stack' },
|
|
468
|
+
technology: { description: 'Technology stack (alias for tech)' },
|
|
469
|
+
},
|
|
470
|
+
edge: {},
|
|
338
471
|
},
|
|
339
|
-
|
|
340
|
-
[
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
472
|
+
],
|
|
473
|
+
[
|
|
474
|
+
'gantt',
|
|
475
|
+
{
|
|
476
|
+
node: {},
|
|
477
|
+
edge: {
|
|
478
|
+
// Gantt "edge" = dependency arrow (TaskA -> TaskB | offset 2bd)
|
|
479
|
+
offset: { description: 'Dependency offset (e.g., 2bd, -1w)' },
|
|
480
|
+
},
|
|
345
481
|
},
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
482
|
+
],
|
|
483
|
+
[
|
|
484
|
+
'initiative-status',
|
|
485
|
+
{
|
|
486
|
+
node: {
|
|
487
|
+
done: { description: 'Completed' },
|
|
488
|
+
doing: { description: 'In progress' },
|
|
489
|
+
todo: { description: 'Not started' },
|
|
490
|
+
blocked: { description: 'Blocked' },
|
|
491
|
+
na: { description: 'Not applicable' },
|
|
492
|
+
wip: { description: 'Work in progress (alias for doing)' },
|
|
493
|
+
paused: { description: 'Paused (alias for blocked)' },
|
|
494
|
+
waiting: { description: 'Waiting (alias for blocked)' },
|
|
495
|
+
},
|
|
496
|
+
edge: {
|
|
497
|
+
done: { description: 'Completed' },
|
|
498
|
+
doing: { description: 'In progress' },
|
|
499
|
+
todo: { description: 'Not started' },
|
|
500
|
+
blocked: { description: 'Blocked' },
|
|
501
|
+
na: { description: 'Not applicable' },
|
|
502
|
+
wip: { description: 'Work in progress (alias for doing)' },
|
|
503
|
+
paused: { description: 'Paused (alias for blocked)' },
|
|
504
|
+
waiting: { description: 'Waiting (alias for blocked)' },
|
|
505
|
+
},
|
|
353
506
|
},
|
|
354
|
-
|
|
507
|
+
],
|
|
355
508
|
]);
|
|
356
509
|
|
|
357
510
|
// ============================================================
|
|
@@ -360,15 +513,18 @@ export const PIPE_METADATA = new Map<string, {
|
|
|
360
513
|
|
|
361
514
|
/** All known directive keys, derived from COMPLETION_REGISTRY. Includes implicit keys. */
|
|
362
515
|
export const METADATA_KEY_SET: ReadonlySet<string> = new Set([
|
|
363
|
-
'chart',
|
|
364
|
-
|
|
516
|
+
'chart',
|
|
517
|
+
'title', // implicit directives recognized as metadata
|
|
518
|
+
...[...COMPLETION_REGISTRY.values()].flatMap((spec) =>
|
|
519
|
+
Object.keys(spec.directives)
|
|
520
|
+
),
|
|
365
521
|
]);
|
|
366
522
|
|
|
367
523
|
// ============================================================
|
|
368
524
|
// Sequence extractor
|
|
369
525
|
// ============================================================
|
|
370
526
|
|
|
371
|
-
const SEQ_ARROW_RE = /^(\S+)\s+(
|
|
527
|
+
const SEQ_ARROW_RE = /^(\S+)\s+(->|-.*->|~>|~.*~>)\s+(\S+)/;
|
|
372
528
|
const SEQ_IS_A_RE = /^(\S+)\s+is\s+an?\s+/i;
|
|
373
529
|
const SEQ_SECTION_RE = /^==/;
|
|
374
530
|
const SEQ_STRUCTURAL_RE = /^(if|else|loop|parallel|end)\b/i;
|
|
@@ -484,7 +640,8 @@ export function extractTagDeclarations(docText: string): Map<string, string[]> {
|
|
|
484
640
|
const trimmed = raw.trim();
|
|
485
641
|
|
|
486
642
|
// Check for tag declaration — try explicit `alias` keyword first, then shorthand
|
|
487
|
-
const tagMatch =
|
|
643
|
+
const tagMatch =
|
|
644
|
+
trimmed.match(TAG_DECL_EXPLICIT_RE) ?? trimmed.match(TAG_DECL_SHORT_RE);
|
|
488
645
|
if (tagMatch) {
|
|
489
646
|
// Save previous tag group
|
|
490
647
|
if (currentAlias !== null) {
|
|
@@ -507,11 +664,16 @@ export function extractTagDeclarations(docText: string): Map<string, string[]> {
|
|
|
507
664
|
}
|
|
508
665
|
|
|
509
666
|
// Collect indented tag values
|
|
510
|
-
if (
|
|
667
|
+
if (
|
|
668
|
+
currentAlias !== null &&
|
|
669
|
+
raw.length > 0 &&
|
|
670
|
+
(raw[0] === ' ' || raw[0] === '\t')
|
|
671
|
+
) {
|
|
511
672
|
if (trimmed && !trimmed.startsWith('//')) {
|
|
512
673
|
// Strip color annotation: Frontend(blue) → Frontend
|
|
513
674
|
const colorIdx = trimmed.indexOf('(');
|
|
514
|
-
const value =
|
|
675
|
+
const value =
|
|
676
|
+
colorIdx > 0 ? trimmed.substring(0, colorIdx).trim() : trimmed;
|
|
515
677
|
if (value) currentValues.push(value);
|
|
516
678
|
}
|
|
517
679
|
continue;
|
|
@@ -563,7 +725,10 @@ function extractSitemapSymbols(docText: string): DiagramSymbols {
|
|
|
563
725
|
if (METADATA_KEY_SET.has(firstToken)) continue;
|
|
564
726
|
|
|
565
727
|
// Track tag blocks
|
|
566
|
-
if (/^tag\s+/i.test(trimmed)) {
|
|
728
|
+
if (/^tag\s+/i.test(trimmed)) {
|
|
729
|
+
inTagBlock = true;
|
|
730
|
+
continue;
|
|
731
|
+
}
|
|
567
732
|
const indent = line.search(/\S/);
|
|
568
733
|
if (inTagBlock) {
|
|
569
734
|
if (indent > 0) continue;
|
|
@@ -583,13 +748,20 @@ function extractSitemapSymbols(docText: string): DiagramSymbols {
|
|
|
583
748
|
const bareArrow = trimmed.match(SITEMAP_BARE_ARROW_RE);
|
|
584
749
|
const labeledArrow = !bareArrow ? trimmed.match(SITEMAP_ARROW_RE) : null;
|
|
585
750
|
if (bareArrow || labeledArrow) {
|
|
586
|
-
const target = (bareArrow?.[1] ?? labeledArrow?.[1] ?? '')
|
|
751
|
+
const target = (bareArrow?.[1] ?? labeledArrow?.[1] ?? '')
|
|
752
|
+
.split('|')[0]
|
|
753
|
+
.trim();
|
|
587
754
|
if (target && !entities.includes(target)) entities.push(target);
|
|
588
755
|
continue;
|
|
589
756
|
}
|
|
590
757
|
|
|
591
758
|
// Indented metadata under a node (key: value) — skip
|
|
592
|
-
if (
|
|
759
|
+
if (
|
|
760
|
+
indent > 0 &&
|
|
761
|
+
lastNodeIndent >= 0 &&
|
|
762
|
+
indent > lastNodeIndent &&
|
|
763
|
+
SITEMAP_METADATA_RE.test(trimmed)
|
|
764
|
+
) {
|
|
593
765
|
continue;
|
|
594
766
|
}
|
|
595
767
|
|
|
@@ -609,8 +781,10 @@ function extractSitemapSymbols(docText: string): DiagramSymbols {
|
|
|
609
781
|
// ============================================================
|
|
610
782
|
|
|
611
783
|
const C4_ELEMENT_RE = /^(person|system|container|component)\s+(.+)$/i;
|
|
612
|
-
const C4_IS_A_RE =
|
|
613
|
-
|
|
784
|
+
const C4_IS_A_RE =
|
|
785
|
+
/^(.+?)\s+is\s+an?\s+(person|system|container|component|external|database)\b/i;
|
|
786
|
+
const C4_ARROW_RE =
|
|
787
|
+
/^(\S+)\s+(?:->|-.*->|~>|~.*~>|<->|<-.*->|<~>|<~.*~>)\s+(\S+)/;
|
|
614
788
|
const C4_SECTION_RE = /^(containers|components|deployment)\s*$/i;
|
|
615
789
|
|
|
616
790
|
function extractC4Symbols(docText: string): DiagramSymbols {
|
|
@@ -631,7 +805,10 @@ function extractC4Symbols(docText: string): DiagramSymbols {
|
|
|
631
805
|
const firstToken = trimmed.split(/\s+/)[0].toLowerCase();
|
|
632
806
|
if (METADATA_KEY_SET.has(firstToken)) continue;
|
|
633
807
|
|
|
634
|
-
if (/^tag\s+/i.test(trimmed)) {
|
|
808
|
+
if (/^tag\s+/i.test(trimmed)) {
|
|
809
|
+
inTagBlock = true;
|
|
810
|
+
continue;
|
|
811
|
+
}
|
|
635
812
|
const indent = line.search(/\S/);
|
|
636
813
|
if (inTagBlock) {
|
|
637
814
|
if (indent > 0) continue;
|
|
@@ -668,7 +845,11 @@ function extractC4Symbols(docText: string): DiagramSymbols {
|
|
|
668
845
|
}
|
|
669
846
|
}
|
|
670
847
|
|
|
671
|
-
return {
|
|
848
|
+
return {
|
|
849
|
+
kind: 'c4',
|
|
850
|
+
entities,
|
|
851
|
+
keywords: ['containers', 'components', 'deployment'],
|
|
852
|
+
};
|
|
672
853
|
}
|
|
673
854
|
|
|
674
855
|
// ============================================================
|
|
@@ -678,7 +859,7 @@ function extractC4Symbols(docText: string): DiagramSymbols {
|
|
|
678
859
|
const GANTT_DURATION_RE = /^(\d+(?:\.\d+)?)(min|bd|d|w|m|q|y|h)\??\s+(.+)$/;
|
|
679
860
|
const GANTT_DATE_RE = /^(\d{4}-\d{2}-\d{2}(?:\s\d{2}:\d{2})?)\s+(.+)$/;
|
|
680
861
|
const GANTT_GROUP_RE = /^\[(.+?)\]/;
|
|
681
|
-
const GANTT_STRUCTURAL_RE = /^(era|marker|
|
|
862
|
+
const GANTT_STRUCTURAL_RE = /^(era|marker|holiday|workweek|parallel)\b/i;
|
|
682
863
|
|
|
683
864
|
function extractGanttSymbols(docText: string): DiagramSymbols {
|
|
684
865
|
const lines = docText.split('\n');
|
|
@@ -698,7 +879,10 @@ function extractGanttSymbols(docText: string): DiagramSymbols {
|
|
|
698
879
|
const firstToken = trimmed.split(/\s+/)[0].toLowerCase();
|
|
699
880
|
if (METADATA_KEY_SET.has(firstToken)) continue;
|
|
700
881
|
|
|
701
|
-
if (/^tag\s+/i.test(trimmed)) {
|
|
882
|
+
if (/^tag\s+/i.test(trimmed)) {
|
|
883
|
+
inTagBlock = true;
|
|
884
|
+
continue;
|
|
885
|
+
}
|
|
702
886
|
const indent = line.search(/\S/);
|
|
703
887
|
if (inTagBlock) {
|
|
704
888
|
if (indent > 0) continue;
|
|
@@ -723,7 +907,11 @@ function extractGanttSymbols(docText: string): DiagramSymbols {
|
|
|
723
907
|
let taskName = durMatch[3].split('|')[0].trim();
|
|
724
908
|
// Remove trailing dependency: "Task Name -> Other" → "Task Name"
|
|
725
909
|
const arrowIdx = taskName.indexOf('->');
|
|
726
|
-
if (arrowIdx > 0)
|
|
910
|
+
if (arrowIdx > 0)
|
|
911
|
+
taskName = taskName
|
|
912
|
+
.substring(0, arrowIdx)
|
|
913
|
+
.replace(/-[^>]*$/, '')
|
|
914
|
+
.trim();
|
|
727
915
|
if (taskName && !entities.includes(taskName)) entities.push(taskName);
|
|
728
916
|
continue;
|
|
729
917
|
}
|
|
@@ -733,7 +921,11 @@ function extractGanttSymbols(docText: string): DiagramSymbols {
|
|
|
733
921
|
if (dateMatch) {
|
|
734
922
|
let taskName = dateMatch[2].split('|')[0].trim();
|
|
735
923
|
const arrowIdx = taskName.indexOf('->');
|
|
736
|
-
if (arrowIdx > 0)
|
|
924
|
+
if (arrowIdx > 0)
|
|
925
|
+
taskName = taskName
|
|
926
|
+
.substring(0, arrowIdx)
|
|
927
|
+
.replace(/-[^>]*$/, '')
|
|
928
|
+
.trim();
|
|
737
929
|
if (taskName && !entities.includes(taskName)) entities.push(taskName);
|
|
738
930
|
continue;
|
|
739
931
|
}
|
|
@@ -766,7 +958,10 @@ function extractInitiativeStatusSymbols(docText: string): DiagramSymbols {
|
|
|
766
958
|
const firstToken = trimmed.split(/\s+/)[0].toLowerCase();
|
|
767
959
|
if (METADATA_KEY_SET.has(firstToken)) continue;
|
|
768
960
|
|
|
769
|
-
if (/^tag\s+/i.test(trimmed)) {
|
|
961
|
+
if (/^tag\s+/i.test(trimmed)) {
|
|
962
|
+
inTagBlock = true;
|
|
963
|
+
continue;
|
|
964
|
+
}
|
|
770
965
|
const indent = line.search(/\S/);
|
|
771
966
|
if (inTagBlock) {
|
|
772
967
|
if (indent > 0) continue;
|