@diagrammo/dgmo 0.6.2 → 0.6.3

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 (44) hide show
  1. package/.claude/commands/dgmo.md +231 -13
  2. package/AGENTS.md +148 -0
  3. package/dist/cli.cjs +327 -153
  4. package/dist/index.cjs +305 -177
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.d.cts +24 -3
  7. package/dist/index.d.ts +24 -3
  8. package/dist/index.js +303 -177
  9. package/dist/index.js.map +1 -1
  10. package/package.json +5 -3
  11. package/src/c4/layout.ts +0 -5
  12. package/src/c4/parser.ts +0 -16
  13. package/src/c4/renderer.ts +1 -5
  14. package/src/class/layout.ts +0 -1
  15. package/src/class/parser.ts +28 -0
  16. package/src/class/renderer.ts +5 -26
  17. package/src/cli.ts +563 -14
  18. package/src/completion.ts +58 -0
  19. package/src/d3.ts +58 -106
  20. package/src/dgmo-router.ts +0 -57
  21. package/src/echarts.ts +96 -55
  22. package/src/er/parser.ts +30 -1
  23. package/src/er/renderer.ts +1 -2
  24. package/src/graph/flowchart-parser.ts +27 -4
  25. package/src/graph/flowchart-renderer.ts +1 -2
  26. package/src/graph/state-parser.ts +0 -1
  27. package/src/graph/state-renderer.ts +1 -3
  28. package/src/index.ts +10 -0
  29. package/src/infra/compute.ts +0 -7
  30. package/src/infra/layout.ts +0 -2
  31. package/src/infra/parser.ts +46 -4
  32. package/src/infra/renderer.ts +1 -15
  33. package/src/initiative-status/renderer.ts +5 -25
  34. package/src/kanban/parser.ts +0 -2
  35. package/src/org/layout.ts +0 -4
  36. package/src/org/renderer.ts +7 -28
  37. package/src/sequence/parser.ts +14 -11
  38. package/src/sequence/renderer.ts +0 -2
  39. package/src/sequence/tag-resolution.ts +0 -1
  40. package/src/sitemap/layout.ts +1 -14
  41. package/src/sitemap/parser.ts +1 -2
  42. package/src/sitemap/renderer.ts +0 -3
  43. package/src/utils/arrows.ts +7 -7
  44. package/src/utils/export-container.ts +40 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diagrammo/dgmo",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "description": "DGMO diagram markup language — parser, renderer, and color system",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -29,7 +29,8 @@
29
29
  ".claude/commands",
30
30
  ".github/copilot-instructions.md",
31
31
  ".cursorrules",
32
- ".windsurfrules"
32
+ ".windsurfrules",
33
+ "AGENTS.md"
33
34
  ],
34
35
  "sideEffects": false,
35
36
  "scripts": {
@@ -40,6 +41,7 @@
40
41
  "test:watch": "vitest",
41
42
  "gallery": "pnpm build && node scripts/generate-gallery.mjs",
42
43
  "check:duplication": "jscpd ./src",
44
+ "check:deadcode": "knip",
43
45
  "postinstall": "node -e \"console.log('\\nšŸ’” Claude Code user? Run: dgmo --install-claude-skill\\n')\""
44
46
  },
45
47
  "dependencies": {
@@ -64,9 +66,9 @@
64
66
  "@types/d3-scale": "^4.0.8",
65
67
  "@types/d3-selection": "^3.0.11",
66
68
  "@types/d3-shape": "^3.1.7",
67
- "@types/dagre": "^0.7.54",
68
69
  "@types/jsdom": "^28.0.0",
69
70
  "jscpd": "^4.0.8",
71
+ "knip": "^6.0.1",
70
72
  "tsup": "^8.5.1",
71
73
  "typescript": "^5.7.3",
72
74
  "vitest": "^4.0.18"
package/src/c4/layout.ts CHANGED
@@ -86,7 +86,6 @@ const DESC_LINE_HEIGHT = 16;
86
86
  const DESC_CHAR_WIDTH = 6.5;
87
87
  const CARD_V_PAD = 14;
88
88
  const CARD_H_PAD = 20;
89
- const TECH_LINE_HEIGHT = 16;
90
89
  const META_LINE_HEIGHT = 16;
91
90
  const META_CHAR_WIDTH = 6.5;
92
91
  const MARGIN = 40;
@@ -478,10 +477,6 @@ export function rollUpContextRelationships(parsed: ParsedC4): ContextRelationshi
478
477
  const allRels = collectAllRelationships(parsed.elements, ownerMap);
479
478
 
480
479
  // Also include orphan relationships
481
- for (const rel of parsed.relationships) {
482
- // Orphan rels have no source element name — skip them for context roll-up
483
- }
484
-
485
480
  // Separate system-level (explicit) from nested (rolled-up)
486
481
  const topLevelNames = new Set(parsed.elements.map((e) => e.name));
487
482
  const explicitKeys = new Set<string>();
package/src/c4/parser.ts CHANGED
@@ -3,7 +3,6 @@
3
3
  // ============================================================
4
4
 
5
5
  import type { PaletteColors } from '../palettes';
6
- import type { DgmoError } from '../diagnostics';
7
6
  import { makeDgmoError, formatDgmoError, suggest } from '../diagnostics';
8
7
  import type { TagGroup } from '../utils/tag-groups';
9
8
  import { matchTagBlockHeading } from '../utils/tag-groups';
@@ -751,21 +750,6 @@ function attachElement(
751
750
  // Post-parse validation
752
751
  // ============================================================
753
752
 
754
- function collectAllNames(result: ParsedC4): Map<string, number> {
755
- const names = new Map<string, number>();
756
- function walk(elements: C4Element[]) {
757
- for (const el of elements) {
758
- names.set(el.name.toLowerCase(), el.lineNumber);
759
- walk(el.children);
760
- for (const g of el.groups) {
761
- walk(g.children);
762
- }
763
- }
764
- }
765
- walk(result.elements);
766
- return names;
767
- }
768
-
769
753
  function validateRelationshipTargets(
770
754
  result: ParsedC4,
771
755
  knownNames: Map<string, number>,
@@ -9,8 +9,7 @@ import type { PaletteColors } from '../palettes';
9
9
  import { mix } from '../palettes/color-utils';
10
10
  import { renderInlineText } from '../utils/inline-markdown';
11
11
  import type { ParsedC4 } from './types';
12
- import type { C4Shape } from './types';
13
- import type { C4LayoutResult, C4LayoutNode, C4LayoutEdge, C4LayoutBoundary, C4LegendGroup } from './layout';
12
+ import type { C4LayoutResult, C4LayoutEdge, C4LegendGroup } from './layout';
14
13
  import { parseC4 } from './parser';
15
14
  import { layoutC4Context, layoutC4Containers, layoutC4Components, layoutC4Deployment, collectCardMetadata } from './layout';
16
15
  import {
@@ -50,7 +49,6 @@ const CARD_V_PAD = 14;
50
49
  const TYPE_LABEL_HEIGHT = 18;
51
50
  const DIVIDER_GAP = 6;
52
51
  const NAME_HEIGHT = 20;
53
- const TECH_LINE_HEIGHT = 16;
54
52
  const META_FONT_SIZE = 11;
55
53
  const META_CHAR_WIDTH = 6.5;
56
54
  const META_LINE_HEIGHT = 16;
@@ -257,7 +255,6 @@ export function renderC4Context(
257
255
  const scale = Math.min(MAX_SCALE, scaleX, scaleY);
258
256
 
259
257
  const scaledW = diagramW * scale;
260
- const scaledH = diagramH * scale;
261
258
  const offsetX = (width - scaledW) / 2;
262
259
  const offsetY = titleHeight + DIAGRAM_PADDING;
263
260
 
@@ -1300,7 +1297,6 @@ export function renderC4Containers(
1300
1297
  const scale = Math.min(MAX_SCALE, scaleX, scaleY);
1301
1298
 
1302
1299
  const scaledW = diagramW * scale;
1303
- const scaledH = diagramH * scale;
1304
1300
  const offsetX = (width - scaledW) / 2;
1305
1301
  const offsetY = titleHeight + DIAGRAM_PADDING;
1306
1302
 
@@ -2,7 +2,6 @@ import dagre from '@dagrejs/dagre';
2
2
  import type {
3
3
  ParsedClassDiagram,
4
4
  ClassNode,
5
- ClassRelationship,
6
5
  RelationshipType,
7
6
  } from './types';
8
7
 
@@ -383,3 +383,31 @@ export function looksLikeClassDiagram(content: string): boolean {
383
383
 
384
384
  return false;
385
385
  }
386
+
387
+ // ============================================================
388
+ // Symbol extraction (for completion API)
389
+ // ============================================================
390
+
391
+ import type { DiagramSymbols } from '../completion';
392
+
393
+ /**
394
+ * Extract class names (entities) from class diagram document text.
395
+ * Used by the dgmo completion API for ghost hints and popup completions.
396
+ */
397
+ export function extractSymbols(docText: string): DiagramSymbols {
398
+ const entities: string[] = [];
399
+ let inMetadata = true;
400
+ for (const rawLine of docText.split('\n')) {
401
+ const line = rawLine.trim();
402
+ if (inMetadata && /^[a-z-]+\s*:/i.test(line)) continue;
403
+ inMetadata = false;
404
+ if (line.length === 0 || /^\s/.test(rawLine)) continue;
405
+ const m = CLASS_DECL_RE.exec(line);
406
+ if (m && !entities.includes(m[1]!)) entities.push(m[1]!);
407
+ }
408
+ return {
409
+ kind: 'class',
410
+ entities,
411
+ keywords: ['extends', 'implements', 'abstract', 'interface', 'enum'],
412
+ };
413
+ }
@@ -5,10 +5,11 @@
5
5
  import * as d3Selection from 'd3-selection';
6
6
  import * as d3Shape from 'd3-shape';
7
7
  import { FONT_FAMILY } from '../fonts';
8
+ import { runInExportContainer, extractExportSvg } from '../utils/export-container';
8
9
  import type { PaletteColors } from '../palettes';
9
10
  import { mix } from '../palettes/color-utils';
10
11
  import type { ParsedClassDiagram, ClassModifier, RelationshipType } from './types';
11
- import type { ClassLayoutResult, ClassLayoutNode, ClassLayoutEdge } from './layout';
12
+ import type { ClassLayoutResult } from './layout';
12
13
  import { parseClassDiagram } from './parser';
13
14
  import { layoutClassDiagram } from './layout';
14
15
 
@@ -99,8 +100,6 @@ function isSourceMarker(type: RelationshipType): boolean {
99
100
  // Main renderer
100
101
  // ============================================================
101
102
 
102
- type GSelection = d3Selection.Selection<SVGGElement, unknown, null, undefined>;
103
-
104
103
  export function renderClassDiagram(
105
104
  container: HTMLDivElement,
106
105
  parsed: ParsedClassDiagram,
@@ -125,7 +124,6 @@ export function renderClassDiagram(
125
124
  const scale = Math.min(MAX_SCALE, scaleX, scaleY);
126
125
 
127
126
  const scaledW = diagramW * scale;
128
- const scaledH = diagramH * scale;
129
127
  const offsetX = (width - scaledW) / 2;
130
128
  const offsetY = titleHeight + DIAGRAM_PADDING;
131
129
 
@@ -506,16 +504,10 @@ export function renderClassDiagramForExport(
506
504
  const layout = layoutClassDiagram(parsed);
507
505
  const isDark = theme === 'dark';
508
506
 
509
- const container = document.createElement('div');
510
507
  const exportWidth = layout.width + DIAGRAM_PADDING * 2;
511
508
  const exportHeight = layout.height + DIAGRAM_PADDING * 2 + (parsed.title ? 40 : 0);
512
- container.style.width = `${exportWidth}px`;
513
- container.style.height = `${exportHeight}px`;
514
- container.style.position = 'absolute';
515
- container.style.left = '-9999px';
516
- document.body.appendChild(container);
517
509
 
518
- try {
510
+ return runInExportContainer(exportWidth, exportHeight, (container) => {
519
511
  renderClassDiagram(
520
512
  container,
521
513
  parsed,
@@ -525,19 +517,6 @@ export function renderClassDiagramForExport(
525
517
  undefined,
526
518
  { width: exportWidth, height: exportHeight }
527
519
  );
528
-
529
- const svgEl = container.querySelector('svg');
530
- if (!svgEl) return '';
531
-
532
- if (theme === 'transparent') {
533
- svgEl.style.background = 'none';
534
- }
535
-
536
- svgEl.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
537
- svgEl.style.fontFamily = FONT_FAMILY;
538
-
539
- return svgEl.outerHTML;
540
- } finally {
541
- document.body.removeChild(container);
542
- }
520
+ return extractExportSvg(container, theme);
521
+ });
543
522
  }