@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.
Files changed (122) hide show
  1. package/.claude/commands/dgmo-diagram-this.md +60 -0
  2. package/.claude/commands/dgmo-document-project.md +128 -0
  3. package/.claude/commands/dgmo.md +452 -50
  4. package/.cursorrules +32 -37
  5. package/.github/copilot-instructions.md +35 -44
  6. package/.windsurfrules +32 -37
  7. package/README.md +4 -4
  8. package/dist/cli.cjs +188 -185
  9. package/dist/editor.cjs +338 -0
  10. package/dist/editor.cjs.map +1 -0
  11. package/dist/editor.d.cts +27 -0
  12. package/dist/editor.d.ts +27 -0
  13. package/dist/editor.js +307 -0
  14. package/dist/editor.js.map +1 -0
  15. package/dist/highlight.cjs +560 -0
  16. package/dist/highlight.cjs.map +1 -0
  17. package/dist/highlight.d.cts +32 -0
  18. package/dist/highlight.d.ts +32 -0
  19. package/dist/highlight.js +530 -0
  20. package/dist/highlight.js.map +1 -0
  21. package/dist/index.cjs +3467 -1078
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +22 -1
  24. package/dist/index.d.ts +22 -1
  25. package/dist/index.js +3466 -1078
  26. package/dist/index.js.map +1 -1
  27. package/docs/language-reference.md +46 -37
  28. package/gallery/fixtures/arc.dgmo +18 -0
  29. package/gallery/fixtures/area.dgmo +19 -0
  30. package/gallery/fixtures/bar-stacked.dgmo +10 -0
  31. package/gallery/fixtures/bar.dgmo +10 -0
  32. package/gallery/fixtures/c4-full.dgmo +52 -0
  33. package/gallery/fixtures/c4.dgmo +17 -0
  34. package/gallery/fixtures/chord.dgmo +12 -0
  35. package/gallery/fixtures/class-basic.dgmo +14 -0
  36. package/gallery/fixtures/class-full.dgmo +43 -0
  37. package/gallery/fixtures/doughnut.dgmo +8 -0
  38. package/gallery/fixtures/flowchart-basic.dgmo +3 -0
  39. package/gallery/fixtures/flowchart-colors.dgmo +5 -0
  40. package/gallery/fixtures/flowchart-complex.dgmo +17 -0
  41. package/gallery/fixtures/flowchart-decision.dgmo +5 -0
  42. package/gallery/fixtures/flowchart-full.dgmo +13 -0
  43. package/gallery/fixtures/flowchart-groups.dgmo +10 -0
  44. package/gallery/fixtures/flowchart-loop.dgmo +7 -0
  45. package/gallery/fixtures/flowchart-nested.dgmo +7 -0
  46. package/gallery/fixtures/flowchart-shapes.dgmo +5 -0
  47. package/gallery/fixtures/function.dgmo +8 -0
  48. package/gallery/fixtures/funnel.dgmo +7 -0
  49. package/gallery/fixtures/gantt-full.dgmo +49 -0
  50. package/gallery/fixtures/gantt.dgmo +42 -0
  51. package/gallery/fixtures/heatmap.dgmo +8 -0
  52. package/gallery/fixtures/infra-full.dgmo +78 -0
  53. package/gallery/fixtures/infra-overload.dgmo +25 -0
  54. package/gallery/fixtures/infra.dgmo +47 -0
  55. package/gallery/fixtures/initiative-status-full.dgmo +46 -0
  56. package/gallery/fixtures/initiative-status-phases.dgmo +29 -0
  57. package/gallery/fixtures/initiative-status.dgmo +9 -0
  58. package/gallery/fixtures/line.dgmo +19 -0
  59. package/gallery/fixtures/multi-line.dgmo +11 -0
  60. package/gallery/fixtures/org-basic.dgmo +16 -0
  61. package/gallery/fixtures/org-full.dgmo +69 -0
  62. package/gallery/fixtures/org-teams.dgmo +25 -0
  63. package/gallery/fixtures/pie.dgmo +9 -0
  64. package/gallery/fixtures/polar-area.dgmo +8 -0
  65. package/gallery/fixtures/quadrant.dgmo +18 -0
  66. package/gallery/fixtures/radar.dgmo +8 -0
  67. package/gallery/fixtures/sankey.dgmo +31 -0
  68. package/gallery/fixtures/scatter.dgmo +21 -0
  69. package/gallery/fixtures/sequence-tags-protocols.dgmo +45 -0
  70. package/gallery/fixtures/sequence-tags.dgmo +41 -0
  71. package/gallery/fixtures/sequence.dgmo +35 -0
  72. package/gallery/fixtures/sitemap-basic.dgmo +12 -0
  73. package/gallery/fixtures/sitemap-full.dgmo +156 -0
  74. package/gallery/fixtures/slope.dgmo +9 -0
  75. package/gallery/fixtures/spr-eras.dgmo +62 -0
  76. package/gallery/fixtures/state.dgmo +30 -0
  77. package/gallery/fixtures/timeline-intraday.dgmo +14 -0
  78. package/gallery/fixtures/timeline.dgmo +32 -0
  79. package/gallery/fixtures/venn.dgmo +10 -0
  80. package/gallery/fixtures/wordcloud.dgmo +24 -0
  81. package/package.json +71 -2
  82. package/src/c4/layout.ts +372 -90
  83. package/src/c4/parser.ts +100 -55
  84. package/src/chart.ts +91 -28
  85. package/src/class/parser.ts +41 -12
  86. package/src/cli.ts +211 -62
  87. package/src/completion.ts +378 -183
  88. package/src/d3.ts +1044 -303
  89. package/src/dgmo-mermaid.ts +16 -13
  90. package/src/dgmo-router.ts +69 -23
  91. package/src/echarts.ts +646 -153
  92. package/src/editor/dgmo.grammar +69 -0
  93. package/src/editor/dgmo.grammar.d.ts +2 -0
  94. package/src/editor/dgmo.grammar.js +18 -0
  95. package/src/editor/dgmo.grammar.terms.d.ts +5 -0
  96. package/src/editor/dgmo.grammar.terms.js +35 -0
  97. package/src/editor/highlight-api.ts +444 -0
  98. package/src/editor/highlight.ts +36 -0
  99. package/src/editor/index.ts +28 -0
  100. package/src/editor/keywords.ts +222 -0
  101. package/src/editor/tokens.ts +30 -0
  102. package/src/er/parser.ts +48 -14
  103. package/src/er/renderer.ts +112 -53
  104. package/src/gantt/calculator.ts +91 -29
  105. package/src/gantt/parser.ts +197 -71
  106. package/src/gantt/renderer.ts +1120 -350
  107. package/src/graph/flowchart-parser.ts +46 -25
  108. package/src/graph/state-parser.ts +47 -17
  109. package/src/index.ts +96 -31
  110. package/src/infra/parser.ts +157 -53
  111. package/src/infra/renderer.ts +723 -271
  112. package/src/initiative-status/parser.ts +138 -44
  113. package/src/kanban/parser.ts +25 -14
  114. package/src/org/layout.ts +111 -44
  115. package/src/org/parser.ts +69 -22
  116. package/src/palettes/index.ts +3 -2
  117. package/src/sequence/parser.ts +193 -61
  118. package/src/sitemap/parser.ts +65 -29
  119. package/src/utils/arrows.ts +2 -22
  120. package/src/utils/duration.ts +39 -21
  121. package/src/utils/legend-constants.ts +0 -2
  122. package/src/utils/parsing.ts +75 -31
@@ -0,0 +1,222 @@
1
+ /** All supported DGMO chart types. */
2
+ export const CHART_TYPES = new Set([
3
+ // Diagram types
4
+ 'sequence',
5
+ 'flowchart',
6
+ 'class',
7
+ 'er',
8
+ 'org',
9
+ 'kanban',
10
+ 'c4',
11
+ 'initiative-status',
12
+ 'state',
13
+ 'sitemap',
14
+ 'infra',
15
+ 'gantt',
16
+ // Data chart types
17
+ 'bar',
18
+ 'line',
19
+ 'pie',
20
+ 'doughnut',
21
+ 'area',
22
+ 'polar-area',
23
+ 'radar',
24
+ 'bar-stacked',
25
+ 'multi-line',
26
+ 'scatter',
27
+ 'sankey',
28
+ 'chord',
29
+ 'function',
30
+ 'heatmap',
31
+ 'funnel',
32
+ // Visualization types
33
+ 'slope',
34
+ 'wordcloud',
35
+ 'arc',
36
+ 'timeline',
37
+ 'venn',
38
+ 'quadrant',
39
+ ]);
40
+
41
+ /** Metadata keys recognized across chart types. */
42
+ export const METADATA_KEYS = new Set([
43
+ 'title',
44
+ 'series',
45
+ 'orientation',
46
+ 'x-label',
47
+ 'y-label',
48
+ 'size-label',
49
+ 'x',
50
+ 'columns',
51
+ 'rows',
52
+ 'labels',
53
+ 'rotate',
54
+ 'max',
55
+ 'size',
56
+ 'order',
57
+ 'sort',
58
+ 'scale',
59
+ 'values',
60
+ 'notation',
61
+ 'x-axis',
62
+ 'y-axis',
63
+ 'top-right',
64
+ 'top-left',
65
+ 'bottom-right',
66
+ 'bottom-left',
67
+ ]);
68
+
69
+ /** Tag declaration keyword. */
70
+ export const TAG_KEYWORD = 'tag';
71
+
72
+ /** Directive keywords — commands that configure chart behavior. */
73
+ export const DIRECTIVE_KEYWORDS = new Set([
74
+ // Gantt
75
+ 'start',
76
+ 'era',
77
+ 'marker',
78
+ 'holiday',
79
+ 'workweek',
80
+ 'today-marker',
81
+ 'critical-path',
82
+ 'no-dependencies',
83
+ 'sort',
84
+ // Tags
85
+ 'tags',
86
+ 'import',
87
+ 'active-tag',
88
+ 'hide',
89
+ // ER
90
+ 'notation',
91
+ // Class
92
+ 'extends',
93
+ 'implements',
94
+ 'abstract',
95
+ 'interface',
96
+ 'enum',
97
+ // C4
98
+ 'containers',
99
+ 'components',
100
+ 'deployment',
101
+ // Infra directives
102
+ 'sub-node-label',
103
+ 'show-sub-node-count',
104
+ 'no-auto-color',
105
+ // Infra node properties
106
+ 'description',
107
+ 'instances',
108
+ 'max-rps',
109
+ 'latency-ms',
110
+ 'uptime',
111
+ 'firewall-block',
112
+ 'ratelimit-rps',
113
+ 'cb-error-threshold',
114
+ 'cb-latency-threshold-ms',
115
+ 'buffer',
116
+ 'drain-rate',
117
+ 'retention-hours',
118
+ 'partitions',
119
+ 'split',
120
+ 'slo-p90-latency-ms',
121
+ 'slo-availability',
122
+ 'cache-hit',
123
+ 'concurrency',
124
+ 'duration-ms',
125
+ 'cold-start-ms',
126
+ 'rps',
127
+ // Sequence
128
+ 'activations',
129
+ 'no-activations',
130
+ 'collapse-notes',
131
+ 'no-collapse-notes',
132
+ // Data charts
133
+ 'stacked',
134
+ 'no-label-name',
135
+ 'no-label-value',
136
+ 'no-label-percent',
137
+ // Slope
138
+ 'period',
139
+ // Quadrant
140
+ 'x-axis',
141
+ 'y-axis',
142
+ 'top-right',
143
+ 'top-left',
144
+ 'bottom-right',
145
+ 'bottom-left',
146
+ // Layout
147
+ 'direction-tb',
148
+ 'direction-lr',
149
+ // Initiative-status
150
+ 'contains',
151
+ // Data chart metadata
152
+ 'title',
153
+ 'series',
154
+ 'orientation',
155
+ 'x-label',
156
+ 'y-label',
157
+ 'size-label',
158
+ 'columns',
159
+ 'rows',
160
+ 'labels',
161
+ 'rotate',
162
+ 'scale',
163
+ 'values',
164
+ ]);
165
+
166
+ /** Control flow keywords — structural blocks. */
167
+ export const CONTROL_KEYWORDS = new Set([
168
+ 'if',
169
+ 'else',
170
+ 'loop',
171
+ 'parallel',
172
+ 'note',
173
+ ]);
174
+
175
+ /** Status keywords — initiative-status, kanban. */
176
+ export const STATUS_KEYWORDS = new Set([
177
+ 'na',
178
+ 'todo',
179
+ 'wip',
180
+ 'done',
181
+ 'blocked',
182
+ 'in-progress',
183
+ 'backlog',
184
+ 'ready',
185
+ ]);
186
+
187
+ /** Modifier keywords — adjust declarations. */
188
+ export const MODIFIER_KEYWORDS = new Set([
189
+ 'alias',
190
+ 'aka',
191
+ 'position',
192
+ 'default',
193
+ // Sequence participant types
194
+ 'actor',
195
+ 'service',
196
+ 'database',
197
+ 'queue',
198
+ 'cache',
199
+ 'gateway',
200
+ 'external',
201
+ 'networking',
202
+ 'frontend',
203
+ // C4 element types
204
+ 'system',
205
+ 'person',
206
+ 'container',
207
+ 'component',
208
+ // ER column modifiers
209
+ 'pk',
210
+ 'fk',
211
+ 'nullable',
212
+ 'unique',
213
+ // ER data types
214
+ 'int',
215
+ 'varchar',
216
+ 'text',
217
+ 'boolean',
218
+ 'date',
219
+ 'timestamp',
220
+ 'float',
221
+ 'decimal',
222
+ ]);
@@ -0,0 +1,30 @@
1
+ import {
2
+ ChartType,
3
+ TagKeyword,
4
+ DirectiveKeyword,
5
+ ControlKeyword,
6
+ ModifierKeyword,
7
+ } from './dgmo.grammar.terms.js';
8
+ import {
9
+ CHART_TYPES,
10
+ TAG_KEYWORD,
11
+ DIRECTIVE_KEYWORDS,
12
+ CONTROL_KEYWORDS,
13
+ STATUS_KEYWORDS,
14
+ MODIFIER_KEYWORDS,
15
+ } from './keywords';
16
+
17
+ /**
18
+ * Keyword specializer for the Lezer grammar.
19
+ * Called on every Identifier token — returns a specialized term ID
20
+ * or -1 to keep it as a plain Identifier.
21
+ */
22
+ export function specializeKeyword(value: string): number {
23
+ if (CHART_TYPES.has(value)) return ChartType;
24
+ if (value === TAG_KEYWORD) return TagKeyword;
25
+ if (DIRECTIVE_KEYWORDS.has(value)) return DirectiveKeyword;
26
+ if (CONTROL_KEYWORDS.has(value)) return ControlKeyword;
27
+ if (STATUS_KEYWORDS.has(value)) return ModifierKeyword;
28
+ if (MODIFIER_KEYWORDS.has(value)) return ModifierKeyword;
29
+ return -1;
30
+ }
package/src/er/parser.ts CHANGED
@@ -1,7 +1,13 @@
1
1
  import { resolveColor } from '../colors';
2
2
  import type { PaletteColors } from '../palettes';
3
3
  import { makeDgmoError, formatDgmoError, suggest } from '../diagnostics';
4
- import { measureIndent, extractColor, parsePipeMetadata, parseFirstLine, OPTION_NOCOLON_RE } from '../utils/parsing';
4
+ import {
5
+ measureIndent,
6
+ extractColor,
7
+ parsePipeMetadata,
8
+ parseFirstLine,
9
+ OPTION_NOCOLON_RE,
10
+ } from '../utils/parsing';
5
11
  import { matchTagBlockHeading, validateTagValues } from '../utils/tag-groups';
6
12
  import type { TagGroup } from '../utils/tag-groups';
7
13
  import type {
@@ -82,7 +88,7 @@ const KEYWORD_TO_SYMBOL: Record<string, string> = {
82
88
  function parseRelationship(
83
89
  trimmed: string,
84
90
  lineNumber: number,
85
- pushError: (line: number, message: string) => void,
91
+ pushError: (line: number, message: string) => void
86
92
  ): {
87
93
  source: string;
88
94
  target: string;
@@ -113,7 +119,7 @@ function parseRelationship(
113
119
  const toSym = KEYWORD_TO_SYMBOL[kw[3].toLowerCase()] ?? kw[3];
114
120
  pushError(
115
121
  lineNumber,
116
- `Use symbolic cardinality (1--*, ?--1, *--*) instead of "${kw[2]}-to-${kw[3]}". Example: ${kw[1]} ${fromSym}--${toSym} ${kw[4]}`,
122
+ `Use symbolic cardinality (1--*, ?--1, *--*) instead of "${kw[2]}-to-${kw[3]}". Example: ${kw[1]} ${fromSym}--${toSym} ${kw[4]}`
117
123
  );
118
124
  return null;
119
125
  }
@@ -176,7 +182,8 @@ export function parseERDiagram(
176
182
  error: null,
177
183
  };
178
184
 
179
- const fail = (line: number, message: string): ParsedERDiagram => {
185
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
186
+ const _fail = (line: number, message: string): ParsedERDiagram => {
180
187
  const diag = makeDgmoError(line, message);
181
188
  result.diagnostics.push(diag);
182
189
  result.error = formatDgmoError(diag);
@@ -254,7 +261,10 @@ export function parseERDiagram(
254
261
  lineNumber,
255
262
  };
256
263
  if (tagBlockMatch.alias) {
257
- aliasMap.set(tagBlockMatch.alias.toLowerCase(), tagBlockMatch.name.toLowerCase());
264
+ aliasMap.set(
265
+ tagBlockMatch.alias.toLowerCase(),
266
+ tagBlockMatch.name.toLowerCase()
267
+ );
258
268
  }
259
269
  result.tagGroups.push(currentTagGroup);
260
270
  continue;
@@ -265,8 +275,13 @@ export function parseERDiagram(
265
275
  if (currentTagGroup && !contentStarted && indent > 0) {
266
276
  const { label, color } = extractColor(trimmed, palette);
267
277
  if (!color) {
268
- result.diagnostics.push(makeDgmoError(lineNumber,
269
- `Expected 'Value(color)' in tag group '${currentTagGroup.name}'`, 'warning'));
278
+ result.diagnostics.push(
279
+ makeDgmoError(
280
+ lineNumber,
281
+ `Expected 'Value(color)' in tag group '${currentTagGroup.name}'`,
282
+ 'warning'
283
+ )
284
+ );
270
285
  continue;
271
286
  }
272
287
  // First entry becomes the default
@@ -339,8 +354,8 @@ export function parseERDiagram(
339
354
  makeDgmoError(
340
355
  lineNumber,
341
356
  `Relationship "${rel.source} → ${rel.target}" must be indented under the source table "${rel.source}"`,
342
- 'warning',
343
- ),
357
+ 'warning'
358
+ )
344
359
  );
345
360
  continue;
346
361
  }
@@ -367,11 +382,19 @@ export function parseERDiagram(
367
382
  currentTable = table;
368
383
  continue;
369
384
  }
385
+
386
+ // Catch-all: nothing matched this line
387
+ result.diagnostics.push(
388
+ makeDgmoError(lineNumber, `Unexpected line: '${trimmed}'.`, 'warning')
389
+ );
370
390
  }
371
391
 
372
392
  // Validation
373
393
  if (result.tables.length === 0 && !result.error) {
374
- const diag = makeDgmoError(1, 'No tables found. Add table declarations like "users" or "orders (blue)".');
394
+ const diag = makeDgmoError(
395
+ 1,
396
+ 'No tables found. Add table declarations like "users" or "orders (blue)".'
397
+ );
375
398
  result.diagnostics.push(diag);
376
399
  result.error = formatDgmoError(diag);
377
400
  }
@@ -385,8 +408,9 @@ export function parseERDiagram(
385
408
  validateTagValues(
386
409
  tagEntities,
387
410
  result.tagGroups,
388
- (line, msg) => result.diagnostics.push(makeDgmoError(line, msg, 'warning')),
389
- suggest,
411
+ (line, msg) =>
412
+ result.diagnostics.push(makeDgmoError(line, msg, 'warning')),
413
+ suggest
390
414
  );
391
415
 
392
416
  // Inject defaults for tables without explicit tags
@@ -402,7 +426,11 @@ export function parseERDiagram(
402
426
  }
403
427
 
404
428
  // Warn about isolated tables (not in any relationship)
405
- if (result.tables.length >= 2 && result.relationships.length >= 1 && !result.error) {
429
+ if (
430
+ result.tables.length >= 2 &&
431
+ result.relationships.length >= 1 &&
432
+ !result.error
433
+ ) {
406
434
  const connectedIds = new Set<string>();
407
435
  for (const rel of result.relationships) {
408
436
  connectedIds.add(rel.source);
@@ -410,7 +438,13 @@ export function parseERDiagram(
410
438
  }
411
439
  for (const table of result.tables) {
412
440
  if (!connectedIds.has(table.id)) {
413
- result.diagnostics.push(makeDgmoError(table.lineNumber, `Table "${table.name}" is not connected to any other table`, 'warning'));
441
+ result.diagnostics.push(
442
+ makeDgmoError(
443
+ table.lineNumber,
444
+ `Table "${table.name}" is not connected to any other table`,
445
+ 'warning'
446
+ )
447
+ );
414
448
  }
415
449
  }
416
450
  }