@diagrammo/dgmo 0.2.21 → 0.2.23
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/cli.cjs +119 -113
- package/dist/index.cjs +6317 -2337
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +264 -1
- package/dist/index.d.ts +264 -1
- package/dist/index.js +6299 -2337
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/c4/layout.ts +2137 -0
- package/src/c4/parser.ts +809 -0
- package/src/c4/renderer.ts +1916 -0
- package/src/c4/types.ts +86 -0
- package/src/class/renderer.ts +2 -2
- package/src/cli.ts +54 -10
- package/src/d3.ts +148 -10
- package/src/dgmo-router.ts +13 -0
- package/src/echarts.ts +7 -8
- package/src/er/renderer.ts +2 -2
- package/src/graph/flowchart-renderer.ts +1 -1
- package/src/index.ts +54 -0
- package/src/initiative-status/layout.ts +217 -0
- package/src/initiative-status/parser.ts +246 -0
- package/src/initiative-status/renderer.ts +834 -0
- package/src/initiative-status/types.ts +43 -0
- package/src/kanban/renderer.ts +23 -3
- package/src/org/layout.ts +64 -26
- package/src/org/renderer.ts +47 -18
- package/src/org/resolver.ts +3 -1
- package/src/render.ts +9 -1
- package/src/sequence/participant-inference.ts +1 -0
- package/src/sequence/renderer.ts +12 -6
package/src/c4/types.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// C4 Architecture Diagram — Types
|
|
3
|
+
// ============================================================
|
|
4
|
+
|
|
5
|
+
import type { OrgTagGroup, OrgTagEntry } from '../org/parser';
|
|
6
|
+
import type { DgmoError } from '../diagnostics';
|
|
7
|
+
|
|
8
|
+
// Re-export tag types for convenience
|
|
9
|
+
export type { OrgTagGroup as C4TagGroup, OrgTagEntry as C4TagEntry };
|
|
10
|
+
|
|
11
|
+
// ── String unions ────────────────────────────────────────────
|
|
12
|
+
|
|
13
|
+
export type C4ElementType = 'person' | 'system' | 'container' | 'component';
|
|
14
|
+
|
|
15
|
+
export type C4Shape =
|
|
16
|
+
| 'default'
|
|
17
|
+
| 'database'
|
|
18
|
+
| 'cache'
|
|
19
|
+
| 'queue'
|
|
20
|
+
| 'cloud'
|
|
21
|
+
| 'external';
|
|
22
|
+
|
|
23
|
+
export type C4ArrowType =
|
|
24
|
+
| 'sync'
|
|
25
|
+
| 'async'
|
|
26
|
+
| 'bidirectional'
|
|
27
|
+
| 'bidirectional-async';
|
|
28
|
+
|
|
29
|
+
// ── Relationships ────────────────────────────────────────────
|
|
30
|
+
|
|
31
|
+
export interface C4Relationship {
|
|
32
|
+
target: string;
|
|
33
|
+
label?: string;
|
|
34
|
+
technology?: string;
|
|
35
|
+
arrowType: C4ArrowType;
|
|
36
|
+
lineNumber: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// ── Groups ───────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
export interface C4Group {
|
|
42
|
+
name: string;
|
|
43
|
+
children: C4Element[];
|
|
44
|
+
lineNumber: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ── Elements ─────────────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
export interface C4Element {
|
|
50
|
+
name: string;
|
|
51
|
+
type: C4ElementType;
|
|
52
|
+
shape: C4Shape;
|
|
53
|
+
metadata: Record<string, string>;
|
|
54
|
+
children: C4Element[];
|
|
55
|
+
groups: C4Group[];
|
|
56
|
+
relationships: C4Relationship[];
|
|
57
|
+
importPath?: string;
|
|
58
|
+
lineNumber: number;
|
|
59
|
+
sectionHeader?: 'containers' | 'components';
|
|
60
|
+
sectionHeaderLineNumber?: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ── Deployment ───────────────────────────────────────────────
|
|
64
|
+
|
|
65
|
+
export interface C4DeploymentNode {
|
|
66
|
+
name: string;
|
|
67
|
+
metadata: Record<string, string>;
|
|
68
|
+
shape: C4Shape;
|
|
69
|
+
children: C4DeploymentNode[];
|
|
70
|
+
containerRefs: string[];
|
|
71
|
+
lineNumber: number;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ── Parsed result ────────────────────────────────────────────
|
|
75
|
+
|
|
76
|
+
export interface ParsedC4 {
|
|
77
|
+
title: string | null;
|
|
78
|
+
titleLineNumber: number | null;
|
|
79
|
+
options: Record<string, string>;
|
|
80
|
+
tagGroups: OrgTagGroup[];
|
|
81
|
+
elements: C4Element[];
|
|
82
|
+
relationships: C4Relationship[];
|
|
83
|
+
deployment: C4DeploymentNode[];
|
|
84
|
+
diagnostics: DgmoError[];
|
|
85
|
+
error: string | null;
|
|
86
|
+
}
|
package/src/class/renderer.ts
CHANGED
|
@@ -53,7 +53,7 @@ function modifierColor(modifier: ClassModifier | undefined, palette: PaletteColo
|
|
|
53
53
|
|
|
54
54
|
function nodeFill(palette: PaletteColors, isDark: boolean, modifier: ClassModifier | undefined, nodeColor?: string, colorOff?: boolean): string {
|
|
55
55
|
const color = nodeColor ?? modifierColor(modifier, palette, colorOff);
|
|
56
|
-
return mix(color, isDark ? palette.surface : palette.bg,
|
|
56
|
+
return mix(color, isDark ? palette.surface : palette.bg, 25);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
function nodeStroke(palette: PaletteColors, modifier: ClassModifier | undefined, nodeColor?: string, colorOff?: boolean): string {
|
|
@@ -137,7 +137,7 @@ export function renderClassDiagram(
|
|
|
137
137
|
const scaledW = diagramW * scale;
|
|
138
138
|
const scaledH = diagramH * scale;
|
|
139
139
|
const offsetX = (width - scaledW) / 2;
|
|
140
|
-
const offsetY = titleHeight +
|
|
140
|
+
const offsetY = titleHeight + DIAGRAM_PADDING;
|
|
141
141
|
|
|
142
142
|
const svg = d3Selection
|
|
143
143
|
.select(container)
|
package/src/cli.ts
CHANGED
|
@@ -31,16 +31,19 @@ function printHelp(): void {
|
|
|
31
31
|
Render a .dgmo file to PNG (default) or SVG.
|
|
32
32
|
|
|
33
33
|
Options:
|
|
34
|
-
-o <file>
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
--theme <theme>
|
|
39
|
-
--palette <name>
|
|
40
|
-
--
|
|
41
|
-
--
|
|
42
|
-
--
|
|
43
|
-
--
|
|
34
|
+
-o <file> Output file (default: <input>.png in cwd)
|
|
35
|
+
Format inferred from extension: .svg → SVG, else PNG
|
|
36
|
+
Use -o url to output a shareable diagrammo.app URL
|
|
37
|
+
With stdin and no -o, PNG is written to stdout
|
|
38
|
+
--theme <theme> Theme: ${THEMES.join(', ')} (default: light)
|
|
39
|
+
--palette <name> Palette: ${PALETTES.join(', ')} (default: nord)
|
|
40
|
+
--c4-level <level> C4 render level: context (default), containers, components, deployment
|
|
41
|
+
--c4-system <name> System to drill into (with --c4-level containers or components)
|
|
42
|
+
--c4-container <name> Container to drill into (with --c4-level components)
|
|
43
|
+
--no-branding Omit diagrammo.app branding from exports
|
|
44
|
+
--copy Copy URL to clipboard (only with -o url)
|
|
45
|
+
--help Show this help
|
|
46
|
+
--version Show version`);
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
function printVersion(): void {
|
|
@@ -59,6 +62,9 @@ function parseArgs(argv: string[]): {
|
|
|
59
62
|
version: boolean;
|
|
60
63
|
noBranding: boolean;
|
|
61
64
|
copy: boolean;
|
|
65
|
+
c4Level: 'context' | 'containers' | 'components' | 'deployment';
|
|
66
|
+
c4System: string | undefined;
|
|
67
|
+
c4Container: string | undefined;
|
|
62
68
|
} {
|
|
63
69
|
const result = {
|
|
64
70
|
input: undefined as string | undefined,
|
|
@@ -69,6 +75,9 @@ function parseArgs(argv: string[]): {
|
|
|
69
75
|
version: false,
|
|
70
76
|
noBranding: false,
|
|
71
77
|
copy: false,
|
|
78
|
+
c4Level: 'context' as 'context' | 'containers' | 'components' | 'deployment',
|
|
79
|
+
c4System: undefined as string | undefined,
|
|
80
|
+
c4Container: undefined as string | undefined,
|
|
72
81
|
};
|
|
73
82
|
|
|
74
83
|
const args = argv.slice(2); // skip node + script
|
|
@@ -106,6 +115,22 @@ function parseArgs(argv: string[]): {
|
|
|
106
115
|
}
|
|
107
116
|
result.palette = val;
|
|
108
117
|
i++;
|
|
118
|
+
} else if (arg === '--c4-level') {
|
|
119
|
+
const val = args[++i];
|
|
120
|
+
if (val !== 'context' && val !== 'containers' && val !== 'components' && val !== 'deployment') {
|
|
121
|
+
console.error(
|
|
122
|
+
`Error: Invalid C4 level "${val}". Valid levels: context, containers, components, deployment`
|
|
123
|
+
);
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
result.c4Level = val;
|
|
127
|
+
i++;
|
|
128
|
+
} else if (arg === '--c4-system') {
|
|
129
|
+
result.c4System = args[++i];
|
|
130
|
+
i++;
|
|
131
|
+
} else if (arg === '--c4-container') {
|
|
132
|
+
result.c4Container = args[++i];
|
|
133
|
+
i++;
|
|
109
134
|
} else if (arg === '--no-branding') {
|
|
110
135
|
result.noBranding = true;
|
|
111
136
|
i++;
|
|
@@ -304,10 +329,29 @@ async function main(): Promise<void> {
|
|
|
304
329
|
console.error(`\u2716 ${formatDgmoError(e)}`);
|
|
305
330
|
}
|
|
306
331
|
|
|
332
|
+
// Validate C4 options
|
|
333
|
+
if (opts.c4Level === 'containers' && !opts.c4System) {
|
|
334
|
+
console.error('Error: --c4-system is required when --c4-level is containers');
|
|
335
|
+
process.exit(1);
|
|
336
|
+
}
|
|
337
|
+
if (opts.c4Level === 'components') {
|
|
338
|
+
if (!opts.c4System) {
|
|
339
|
+
console.error('Error: --c4-system is required when --c4-level is components');
|
|
340
|
+
process.exit(1);
|
|
341
|
+
}
|
|
342
|
+
if (!opts.c4Container) {
|
|
343
|
+
console.error('Error: --c4-container is required when --c4-level is components');
|
|
344
|
+
process.exit(1);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
307
348
|
const svg = await render(content, {
|
|
308
349
|
theme: opts.theme,
|
|
309
350
|
palette: opts.palette,
|
|
310
351
|
branding: !opts.noBranding,
|
|
352
|
+
c4Level: opts.c4Level,
|
|
353
|
+
c4System: opts.c4System,
|
|
354
|
+
c4Container: opts.c4Container,
|
|
311
355
|
});
|
|
312
356
|
|
|
313
357
|
if (!svg) {
|
package/src/d3.ts
CHANGED
|
@@ -429,15 +429,15 @@ export function parseD3(content: string, palette?: PaletteColors): ParsedD3 {
|
|
|
429
429
|
if (result.type === 'timeline') {
|
|
430
430
|
// Duration event: 2026-07-15->30d: description (d=days, w=weeks, m=months, y=years)
|
|
431
431
|
// Supports decimals up to 2 places (e.g., 1.25y = 1 year 3 months)
|
|
432
|
-
// Supports uncertain end with ?
|
|
432
|
+
// Supports uncertain end with ? suffix (e.g., ->3m?: fades out the last 20%)
|
|
433
433
|
const durationMatch = line.match(
|
|
434
|
-
/^(\d{4}(?:-\d{2})?(?:-\d{2})?)\s*->\s*(
|
|
434
|
+
/^(\d{4}(?:-\d{2})?(?:-\d{2})?)\s*->\s*(\d+(?:\.\d{1,2})?)([dwmy])(\?)?\s*:\s*(.+)$/
|
|
435
435
|
);
|
|
436
436
|
if (durationMatch) {
|
|
437
437
|
const startDate = durationMatch[1];
|
|
438
|
-
const uncertain = durationMatch[
|
|
439
|
-
const amount = parseFloat(durationMatch[
|
|
440
|
-
const unit = durationMatch[
|
|
438
|
+
const uncertain = durationMatch[4] === '?';
|
|
439
|
+
const amount = parseFloat(durationMatch[2]);
|
|
440
|
+
const unit = durationMatch[3] as 'd' | 'w' | 'm' | 'y';
|
|
441
441
|
const endDate = addDurationToDate(startDate, amount, unit);
|
|
442
442
|
result.timelineEvents.push({
|
|
443
443
|
date: startDate,
|
|
@@ -450,18 +450,18 @@ export function parseD3(content: string, palette?: PaletteColors): ParsedD3 {
|
|
|
450
450
|
continue;
|
|
451
451
|
}
|
|
452
452
|
|
|
453
|
-
// Range event: 1655->1667: description (supports uncertain end: 1655
|
|
453
|
+
// Range event: 1655->1667: description (supports uncertain end: 1655->1667?)
|
|
454
454
|
const rangeMatch = line.match(
|
|
455
|
-
/^(\d{4}(?:-\d{2})?(?:-\d{2})?)\s*->\s*(
|
|
455
|
+
/^(\d{4}(?:-\d{2})?(?:-\d{2})?)\s*->\s*(\d{4}(?:-\d{2})?(?:-\d{2})?)(\?)?\s*:\s*(.+)$/
|
|
456
456
|
);
|
|
457
457
|
if (rangeMatch) {
|
|
458
458
|
result.timelineEvents.push({
|
|
459
459
|
date: rangeMatch[1],
|
|
460
|
-
endDate: rangeMatch[
|
|
460
|
+
endDate: rangeMatch[2],
|
|
461
461
|
label: rangeMatch[4].trim(),
|
|
462
462
|
group: currentTimelineGroup,
|
|
463
463
|
lineNumber,
|
|
464
|
-
uncertain: rangeMatch[
|
|
464
|
+
uncertain: rangeMatch[3] === '?',
|
|
465
465
|
});
|
|
466
466
|
continue;
|
|
467
467
|
}
|
|
@@ -5263,7 +5263,7 @@ export async function renderD3ForExport(
|
|
|
5263
5263
|
activeTagGroup?: string | null;
|
|
5264
5264
|
hiddenAttributes?: Set<string>;
|
|
5265
5265
|
},
|
|
5266
|
-
options?: { branding?: boolean }
|
|
5266
|
+
options?: { branding?: boolean; c4Level?: 'context' | 'containers' | 'components' | 'deployment'; c4System?: string; c4Container?: string }
|
|
5267
5267
|
): Promise<string> {
|
|
5268
5268
|
// Flowchart and org chart use their own parser pipelines — intercept before parseD3()
|
|
5269
5269
|
const { parseDgmoChartType } = await import('./dgmo-router');
|
|
@@ -5512,6 +5512,144 @@ export async function renderD3ForExport(
|
|
|
5512
5512
|
}
|
|
5513
5513
|
}
|
|
5514
5514
|
|
|
5515
|
+
if (detectedType === 'initiative-status') {
|
|
5516
|
+
const { parseInitiativeStatus } = await import('./initiative-status/parser');
|
|
5517
|
+
const { layoutInitiativeStatus } = await import('./initiative-status/layout');
|
|
5518
|
+
const { renderInitiativeStatus } = await import('./initiative-status/renderer');
|
|
5519
|
+
|
|
5520
|
+
const isDark = theme === 'dark';
|
|
5521
|
+
const { getPalette } = await import('./palettes');
|
|
5522
|
+
const effectivePalette =
|
|
5523
|
+
palette ?? (isDark ? getPalette('nord').dark : getPalette('nord').light);
|
|
5524
|
+
|
|
5525
|
+
const isParsed = parseInitiativeStatus(content);
|
|
5526
|
+
if (isParsed.error || isParsed.nodes.length === 0) return '';
|
|
5527
|
+
|
|
5528
|
+
const isLayout = layoutInitiativeStatus(isParsed);
|
|
5529
|
+
const PADDING = 20;
|
|
5530
|
+
const titleOffset = isParsed.title ? 40 : 0;
|
|
5531
|
+
const exportWidth = isLayout.width + PADDING * 2;
|
|
5532
|
+
const exportHeight = isLayout.height + PADDING * 2 + titleOffset;
|
|
5533
|
+
|
|
5534
|
+
const container = document.createElement('div');
|
|
5535
|
+
container.style.width = `${exportWidth}px`;
|
|
5536
|
+
container.style.height = `${exportHeight}px`;
|
|
5537
|
+
container.style.position = 'absolute';
|
|
5538
|
+
container.style.left = '-9999px';
|
|
5539
|
+
document.body.appendChild(container);
|
|
5540
|
+
|
|
5541
|
+
try {
|
|
5542
|
+
renderInitiativeStatus(
|
|
5543
|
+
container,
|
|
5544
|
+
isParsed,
|
|
5545
|
+
isLayout,
|
|
5546
|
+
effectivePalette,
|
|
5547
|
+
isDark,
|
|
5548
|
+
undefined,
|
|
5549
|
+
{ width: exportWidth, height: exportHeight }
|
|
5550
|
+
);
|
|
5551
|
+
|
|
5552
|
+
const svgEl = container.querySelector('svg');
|
|
5553
|
+
if (!svgEl) return '';
|
|
5554
|
+
|
|
5555
|
+
if (theme === 'transparent') {
|
|
5556
|
+
svgEl.style.background = 'none';
|
|
5557
|
+
} else if (!svgEl.style.background) {
|
|
5558
|
+
svgEl.style.background = effectivePalette.bg;
|
|
5559
|
+
}
|
|
5560
|
+
|
|
5561
|
+
svgEl.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
|
5562
|
+
svgEl.style.fontFamily = FONT_FAMILY;
|
|
5563
|
+
|
|
5564
|
+
const svgHtml = svgEl.outerHTML;
|
|
5565
|
+
if (options?.branding !== false) {
|
|
5566
|
+
const brandColor = theme === 'transparent' ? '#888' : effectivePalette.textMuted;
|
|
5567
|
+
return injectBranding(svgHtml, brandColor);
|
|
5568
|
+
}
|
|
5569
|
+
return svgHtml;
|
|
5570
|
+
} finally {
|
|
5571
|
+
document.body.removeChild(container);
|
|
5572
|
+
}
|
|
5573
|
+
}
|
|
5574
|
+
|
|
5575
|
+
if (detectedType === 'c4') {
|
|
5576
|
+
const { parseC4 } = await import('./c4/parser');
|
|
5577
|
+
const { layoutC4Context, layoutC4Containers, layoutC4Components, layoutC4Deployment } = await import('./c4/layout');
|
|
5578
|
+
const { renderC4Context, renderC4Containers } = await import('./c4/renderer');
|
|
5579
|
+
|
|
5580
|
+
const isDark = theme === 'dark';
|
|
5581
|
+
const { getPalette } = await import('./palettes');
|
|
5582
|
+
const effectivePalette =
|
|
5583
|
+
palette ?? (isDark ? getPalette('nord').dark : getPalette('nord').light);
|
|
5584
|
+
|
|
5585
|
+
const c4Parsed = parseC4(content, effectivePalette);
|
|
5586
|
+
if (c4Parsed.error || c4Parsed.elements.length === 0) return '';
|
|
5587
|
+
|
|
5588
|
+
// Container/component-level rendering
|
|
5589
|
+
const c4Level = options?.c4Level ?? 'context';
|
|
5590
|
+
const c4System = options?.c4System;
|
|
5591
|
+
const c4Container = options?.c4Container;
|
|
5592
|
+
|
|
5593
|
+
const c4Layout = c4Level === 'deployment'
|
|
5594
|
+
? layoutC4Deployment(c4Parsed)
|
|
5595
|
+
: c4Level === 'components' && c4System && c4Container
|
|
5596
|
+
? layoutC4Components(c4Parsed, c4System, c4Container)
|
|
5597
|
+
: c4Level === 'containers' && c4System
|
|
5598
|
+
? layoutC4Containers(c4Parsed, c4System)
|
|
5599
|
+
: layoutC4Context(c4Parsed);
|
|
5600
|
+
|
|
5601
|
+
if (c4Layout.nodes.length === 0) return '';
|
|
5602
|
+
|
|
5603
|
+
const PADDING = 20;
|
|
5604
|
+
const titleOffset = c4Parsed.title ? 40 : 0;
|
|
5605
|
+
const exportWidth = c4Layout.width + PADDING * 2;
|
|
5606
|
+
const exportHeight = c4Layout.height + PADDING * 2 + titleOffset;
|
|
5607
|
+
|
|
5608
|
+
const container = document.createElement('div');
|
|
5609
|
+
container.style.width = `${exportWidth}px`;
|
|
5610
|
+
container.style.height = `${exportHeight}px`;
|
|
5611
|
+
container.style.position = 'absolute';
|
|
5612
|
+
container.style.left = '-9999px';
|
|
5613
|
+
document.body.appendChild(container);
|
|
5614
|
+
|
|
5615
|
+
try {
|
|
5616
|
+
const renderFn = c4Level === 'deployment' || (c4Level === 'components' && c4System && c4Container) || (c4Level === 'containers' && c4System)
|
|
5617
|
+
? renderC4Containers
|
|
5618
|
+
: renderC4Context;
|
|
5619
|
+
|
|
5620
|
+
renderFn(
|
|
5621
|
+
container,
|
|
5622
|
+
c4Parsed,
|
|
5623
|
+
c4Layout,
|
|
5624
|
+
effectivePalette,
|
|
5625
|
+
isDark,
|
|
5626
|
+
undefined,
|
|
5627
|
+
{ width: exportWidth, height: exportHeight }
|
|
5628
|
+
);
|
|
5629
|
+
|
|
5630
|
+
const svgEl = container.querySelector('svg');
|
|
5631
|
+
if (!svgEl) return '';
|
|
5632
|
+
|
|
5633
|
+
if (theme === 'transparent') {
|
|
5634
|
+
svgEl.style.background = 'none';
|
|
5635
|
+
} else if (!svgEl.style.background) {
|
|
5636
|
+
svgEl.style.background = effectivePalette.bg;
|
|
5637
|
+
}
|
|
5638
|
+
|
|
5639
|
+
svgEl.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
|
5640
|
+
svgEl.style.fontFamily = FONT_FAMILY;
|
|
5641
|
+
|
|
5642
|
+
const svgHtml = svgEl.outerHTML;
|
|
5643
|
+
if (options?.branding !== false) {
|
|
5644
|
+
const brandColor = theme === 'transparent' ? '#888' : effectivePalette.textMuted;
|
|
5645
|
+
return injectBranding(svgHtml, brandColor);
|
|
5646
|
+
}
|
|
5647
|
+
return svgHtml;
|
|
5648
|
+
} finally {
|
|
5649
|
+
document.body.removeChild(container);
|
|
5650
|
+
}
|
|
5651
|
+
}
|
|
5652
|
+
|
|
5515
5653
|
if (detectedType === 'flowchart') {
|
|
5516
5654
|
const { parseFlowchart } = await import('./graph/flowchart-parser');
|
|
5517
5655
|
const { layoutGraph } = await import('./graph/layout');
|
package/src/dgmo-router.ts
CHANGED
|
@@ -11,6 +11,8 @@ import { parseEChart } from './echarts';
|
|
|
11
11
|
import { parseD3 } from './d3';
|
|
12
12
|
import { parseOrg, looksLikeOrg } from './org/parser';
|
|
13
13
|
import { parseKanban } from './kanban/parser';
|
|
14
|
+
import { parseC4 } from './c4/parser';
|
|
15
|
+
import { looksLikeInitiativeStatus, parseInitiativeStatus } from './initiative-status/parser';
|
|
14
16
|
import type { DgmoError } from './diagnostics';
|
|
15
17
|
|
|
16
18
|
/**
|
|
@@ -58,6 +60,8 @@ export const DGMO_CHART_TYPE_MAP: Record<string, DgmoFramework> = {
|
|
|
58
60
|
er: 'd3',
|
|
59
61
|
org: 'd3',
|
|
60
62
|
kanban: 'd3',
|
|
63
|
+
c4: 'd3',
|
|
64
|
+
'initiative-status': 'd3',
|
|
61
65
|
};
|
|
62
66
|
|
|
63
67
|
/**
|
|
@@ -89,6 +93,7 @@ export function parseDgmoChartType(content: string): string | null {
|
|
|
89
93
|
if (looksLikeFlowchart(content)) return 'flowchart';
|
|
90
94
|
if (looksLikeClassDiagram(content)) return 'class';
|
|
91
95
|
if (looksLikeERDiagram(content)) return 'er';
|
|
96
|
+
if (looksLikeInitiativeStatus(content)) return 'initiative-status';
|
|
92
97
|
if (looksLikeOrg(content)) return 'org';
|
|
93
98
|
|
|
94
99
|
return null;
|
|
@@ -142,6 +147,14 @@ export function parseDgmo(content: string): { diagnostics: DgmoError[] } {
|
|
|
142
147
|
const parsed = parseKanban(content);
|
|
143
148
|
return { diagnostics: parsed.diagnostics };
|
|
144
149
|
}
|
|
150
|
+
if (chartType === 'c4') {
|
|
151
|
+
const parsed = parseC4(content);
|
|
152
|
+
return { diagnostics: parsed.diagnostics };
|
|
153
|
+
}
|
|
154
|
+
if (chartType === 'initiative-status') {
|
|
155
|
+
const parsed = parseInitiativeStatus(content);
|
|
156
|
+
return { diagnostics: parsed.diagnostics };
|
|
157
|
+
}
|
|
145
158
|
if (STANDARD_CHART_TYPES.has(chartType)) {
|
|
146
159
|
const parsed = parseChart(content);
|
|
147
160
|
return { diagnostics: parsed.diagnostics };
|
package/src/echarts.ts
CHANGED
|
@@ -1198,16 +1198,15 @@ function buildFunnelOption(
|
|
|
1198
1198
|
const val = p.value;
|
|
1199
1199
|
const prev = prevValueMap.get(p.name) ?? val;
|
|
1200
1200
|
const isFirst = p.dataIndex === 0;
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
if (!isFirst && topValue > 0) {
|
|
1201
|
+
if (isFirst) return '';
|
|
1202
|
+
const parts: string[] = [];
|
|
1203
|
+
const stepDrop = ((1 - val / prev) * 100).toFixed(1);
|
|
1204
|
+
parts.push(`Step drop-off: ${stepDrop}%`);
|
|
1205
|
+
if (topValue > 0) {
|
|
1207
1206
|
const totalDrop = ((1 - val / topValue) * 100).toFixed(1);
|
|
1208
|
-
|
|
1207
|
+
parts.push(`Overall drop-off: ${totalDrop}%`);
|
|
1209
1208
|
}
|
|
1210
|
-
return
|
|
1209
|
+
return parts.join('<br/>');
|
|
1211
1210
|
},
|
|
1212
1211
|
},
|
|
1213
1212
|
series: [
|
package/src/er/renderer.ts
CHANGED
|
@@ -233,7 +233,7 @@ export function renderERDiagram(
|
|
|
233
233
|
const scaledW = diagramW * scale;
|
|
234
234
|
const scaledH = diagramH * scale;
|
|
235
235
|
const offsetX = (width - scaledW) / 2;
|
|
236
|
-
const offsetY = titleHeight +
|
|
236
|
+
const offsetY = titleHeight + DIAGRAM_PADDING;
|
|
237
237
|
|
|
238
238
|
const svg = d3Selection
|
|
239
239
|
.select(container)
|
|
@@ -369,7 +369,7 @@ export function renderERDiagram(
|
|
|
369
369
|
|
|
370
370
|
const w = node.width;
|
|
371
371
|
const h = node.height;
|
|
372
|
-
const fill = mix(nodeColor, isDark ? palette.surface : palette.bg,
|
|
372
|
+
const fill = mix(nodeColor, isDark ? palette.surface : palette.bg, 25);
|
|
373
373
|
const stroke = nodeColor;
|
|
374
374
|
|
|
375
375
|
// Outer rectangle
|
|
@@ -259,7 +259,7 @@ export function renderFlowchart(
|
|
|
259
259
|
const scaledW = diagramW * scale;
|
|
260
260
|
const scaledH = diagramH * scale;
|
|
261
261
|
const offsetX = (width - scaledW) / 2;
|
|
262
|
-
const offsetY = titleHeight +
|
|
262
|
+
const offsetY = titleHeight + DIAGRAM_PADDING;
|
|
263
263
|
|
|
264
264
|
// Create SVG
|
|
265
265
|
const svg = d3Selection
|
package/src/index.ts
CHANGED
|
@@ -155,6 +155,60 @@ export type {
|
|
|
155
155
|
export { computeCardMove, computeCardArchive, isArchiveColumn } from './kanban/mutations';
|
|
156
156
|
export { renderKanban, renderKanbanForExport } from './kanban/renderer';
|
|
157
157
|
|
|
158
|
+
export { parseC4 } from './c4/parser';
|
|
159
|
+
export type {
|
|
160
|
+
ParsedC4,
|
|
161
|
+
C4Element,
|
|
162
|
+
C4ElementType,
|
|
163
|
+
C4Shape,
|
|
164
|
+
C4ArrowType,
|
|
165
|
+
C4Relationship,
|
|
166
|
+
C4Group,
|
|
167
|
+
C4DeploymentNode,
|
|
168
|
+
C4TagGroup,
|
|
169
|
+
C4TagEntry,
|
|
170
|
+
} from './c4/types';
|
|
171
|
+
|
|
172
|
+
export { layoutC4Context, layoutC4Containers, layoutC4Components, layoutC4Deployment, rollUpContextRelationships } from './c4/layout';
|
|
173
|
+
export type {
|
|
174
|
+
C4LayoutResult,
|
|
175
|
+
C4LayoutNode,
|
|
176
|
+
C4LayoutEdge,
|
|
177
|
+
C4LayoutBoundary,
|
|
178
|
+
C4LegendGroup,
|
|
179
|
+
C4LegendEntry,
|
|
180
|
+
ContextRelationship,
|
|
181
|
+
} from './c4/layout';
|
|
182
|
+
|
|
183
|
+
export {
|
|
184
|
+
renderC4Context,
|
|
185
|
+
renderC4ContextForExport,
|
|
186
|
+
renderC4Containers,
|
|
187
|
+
renderC4ContainersForExport,
|
|
188
|
+
renderC4ComponentsForExport,
|
|
189
|
+
renderC4Deployment,
|
|
190
|
+
renderC4DeploymentForExport,
|
|
191
|
+
} from './c4/renderer';
|
|
192
|
+
|
|
193
|
+
export { parseInitiativeStatus, looksLikeInitiativeStatus } from './initiative-status/parser';
|
|
194
|
+
export type {
|
|
195
|
+
ParsedInitiativeStatus,
|
|
196
|
+
ISNode,
|
|
197
|
+
ISEdge,
|
|
198
|
+
ISGroup,
|
|
199
|
+
InitiativeStatus,
|
|
200
|
+
} from './initiative-status/types';
|
|
201
|
+
|
|
202
|
+
export { layoutInitiativeStatus } from './initiative-status/layout';
|
|
203
|
+
export type {
|
|
204
|
+
ISLayoutResult,
|
|
205
|
+
ISLayoutNode,
|
|
206
|
+
ISLayoutEdge,
|
|
207
|
+
ISLayoutGroup,
|
|
208
|
+
} from './initiative-status/layout';
|
|
209
|
+
|
|
210
|
+
export { renderInitiativeStatus, renderInitiativeStatusForExport } from './initiative-status/renderer';
|
|
211
|
+
|
|
158
212
|
export { collapseOrgTree } from './org/collapse';
|
|
159
213
|
export type { CollapsedOrgResult } from './org/collapse';
|
|
160
214
|
|