@diagrammo/dgmo 0.8.11 → 0.8.13
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 +115 -719
- package/dist/index.cjs +196 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +194 -54
- package/dist/index.js.map +1 -1
- package/docs/guide/chart-arc.md +71 -0
- package/docs/guide/chart-area.md +73 -0
- package/docs/guide/chart-bar-stacked.md +61 -0
- package/docs/guide/chart-bar.md +62 -0
- package/docs/guide/chart-boxes-and-lines.md +243 -0
- package/docs/guide/chart-c4.md +300 -0
- package/docs/guide/chart-chord.md +43 -0
- package/docs/guide/chart-class.md +204 -0
- package/docs/guide/chart-doughnut.md +38 -0
- package/docs/guide/chart-er.md +218 -0
- package/docs/guide/chart-flowchart.md +102 -0
- package/docs/guide/chart-function.md +56 -0
- package/docs/guide/chart-funnel.md +38 -0
- package/docs/guide/chart-gantt.md +368 -0
- package/docs/guide/chart-heatmap.md +41 -0
- package/docs/guide/chart-infra.md +694 -0
- package/docs/guide/chart-kanban.md +156 -0
- package/docs/guide/chart-line.md +79 -0
- package/docs/guide/chart-multi-line.md +84 -0
- package/docs/guide/chart-org.md +209 -0
- package/docs/guide/chart-pie.md +39 -0
- package/docs/guide/chart-polar-area.md +38 -0
- package/docs/guide/chart-quadrant.md +69 -0
- package/docs/guide/chart-radar.md +38 -0
- package/docs/guide/chart-sankey.md +103 -0
- package/docs/guide/chart-scatter.md +94 -0
- package/docs/guide/chart-sequence.md +332 -0
- package/docs/guide/chart-sitemap.md +248 -0
- package/docs/guide/chart-slope.md +56 -0
- package/docs/guide/chart-state.md +171 -0
- package/docs/guide/chart-timeline.md +229 -0
- package/docs/guide/chart-venn.md +81 -0
- package/docs/guide/chart-wordcloud.md +66 -0
- package/docs/guide/colors.md +283 -0
- package/docs/guide/index.md +55 -0
- package/docs/guide/keyboard-shortcuts.md +49 -0
- package/docs/guide/registry.json +51 -0
- package/gallery/fixtures/boxes-and-lines.dgmo +4 -6
- package/gallery/fixtures/er.dgmo +36 -0
- package/gallery/fixtures/kanban.dgmo +27 -0
- package/package.json +1 -1
- package/src/boxes-and-lines/parser.ts +2 -0
- package/src/boxes-and-lines/renderer.ts +12 -4
- package/src/c4/parser.ts +5 -1
- package/src/completion.ts +17 -2
- package/src/d3.ts +140 -71
- package/src/echarts.ts +1 -1
- package/src/er/parser.ts +5 -1
- package/src/gantt/parser.ts +8 -0
- package/src/gantt/renderer.ts +6 -7
- package/src/gantt/types.ts +1 -0
- package/src/infra/parser.ts +4 -0
- package/src/kanban/parser.ts +4 -1
- package/src/kanban/renderer.ts +1 -1
- package/src/org/parser.ts +3 -0
- package/src/sequence/parser.ts +2 -0
- package/src/sequence/renderer.ts +8 -6
- package/src/sharing.ts +18 -9
- package/src/sitemap/parser.ts +2 -0
- package/src/utils/legend-layout.ts +7 -3
- package/src/utils/tag-groups.ts +64 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
er Pirate Fleet
|
|
2
|
+
|
|
3
|
+
ships
|
|
4
|
+
id int pk
|
|
5
|
+
name varchar
|
|
6
|
+
ship_type varchar
|
|
7
|
+
cannons int
|
|
8
|
+
1-aboard-* crew_members
|
|
9
|
+
1-1 captains
|
|
10
|
+
1-carries-* treasure
|
|
11
|
+
|
|
12
|
+
captains
|
|
13
|
+
id int pk
|
|
14
|
+
name varchar
|
|
15
|
+
ship_id int fk
|
|
16
|
+
bounty int
|
|
17
|
+
?-frequents-1 ports
|
|
18
|
+
*-has-1 crew_members
|
|
19
|
+
|
|
20
|
+
crew_members
|
|
21
|
+
id int pk
|
|
22
|
+
name varchar
|
|
23
|
+
ship_id int fk
|
|
24
|
+
role varchar nullable
|
|
25
|
+
|
|
26
|
+
treasure
|
|
27
|
+
id int pk
|
|
28
|
+
name varchar
|
|
29
|
+
value int
|
|
30
|
+
ship_id int fk, nullable
|
|
31
|
+
|
|
32
|
+
ports
|
|
33
|
+
id int pk
|
|
34
|
+
name varchar
|
|
35
|
+
region varchar unique
|
|
36
|
+
1-docks-* ships
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
kanban Plunder Sprint 7
|
|
2
|
+
|
|
3
|
+
tag Priority
|
|
4
|
+
Low(green)
|
|
5
|
+
Urgent(red)
|
|
6
|
+
High(orange)
|
|
7
|
+
|
|
8
|
+
tag Crew c
|
|
9
|
+
Blackbeard(red)
|
|
10
|
+
Anne Bonny(purple)
|
|
11
|
+
Calico Jack(teal)
|
|
12
|
+
|
|
13
|
+
[Awaiting Orders](red)
|
|
14
|
+
Recruit gunners at Tortuga | priority: High, c: Calico Jack
|
|
15
|
+
Chart new trade route | priority: Urgent, c: Anne Bonny
|
|
16
|
+
Scout the Windward Passage
|
|
17
|
+
Avoid Royal Navy patrols
|
|
18
|
+
Resupply rum and powder | priority: Low, c: Calico Jack
|
|
19
|
+
|
|
20
|
+
[Underway](orange) | wip: 2
|
|
21
|
+
Forge letters of marque | priority: High, c: Anne Bonny
|
|
22
|
+
Raid merchant convoy | priority: Urgent, c: Blackbeard
|
|
23
|
+
Three ships spotted off Nassau
|
|
24
|
+
|
|
25
|
+
[Done](green)
|
|
26
|
+
Bribe the harbour master | priority: High, c: Anne Bonny
|
|
27
|
+
Repair hull damage | priority: Low, c: Blackbeard
|
package/package.json
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
matchTagBlockHeading,
|
|
10
10
|
injectDefaultTagMetadata,
|
|
11
11
|
validateTagValues,
|
|
12
|
+
validateTagGroupNames,
|
|
12
13
|
stripDefaultModifier,
|
|
13
14
|
} from '../utils/tag-groups';
|
|
14
15
|
import type { TagGroup } from '../utils/tag-groups';
|
|
@@ -531,6 +532,7 @@ export function parseBoxesAndLines(content: string): ParsedBoxesAndLines {
|
|
|
531
532
|
if (result.tagGroups.length > 0) {
|
|
532
533
|
injectDefaultTagMetadata(result.nodes, result.tagGroups);
|
|
533
534
|
validateTagValues(result.nodes, result.tagGroups, pushWarning, suggest);
|
|
535
|
+
validateTagGroupNames(result.tagGroups, pushWarning);
|
|
534
536
|
}
|
|
535
537
|
|
|
536
538
|
return result;
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
TITLE_Y,
|
|
15
15
|
} from '../utils/title-constants';
|
|
16
16
|
import { contrastText, mix } from '../palettes/color-utils';
|
|
17
|
-
import { resolveTagColor } from '../utils/tag-groups';
|
|
17
|
+
import { resolveTagColor, resolveActiveTagGroup } from '../utils/tag-groups';
|
|
18
18
|
import type { TagGroup } from '../utils/tag-groups';
|
|
19
19
|
import type { PaletteColors } from '../palettes';
|
|
20
20
|
import type { ParsedBoxesAndLines, BLNode } from './types';
|
|
@@ -315,8 +315,12 @@ export function renderBoxesAndLines(
|
|
|
315
315
|
const height = exportDims?.height ?? container.clientHeight;
|
|
316
316
|
if (width <= 0 || height <= 0) return;
|
|
317
317
|
|
|
318
|
-
// Determine active tag group
|
|
319
|
-
const activeGroup =
|
|
318
|
+
// Determine active tag group — shared utility handles priority chain
|
|
319
|
+
const activeGroup = resolveActiveTagGroup(
|
|
320
|
+
parsed.tagGroups,
|
|
321
|
+
parsed.options['active-tag'],
|
|
322
|
+
activeTagGroup
|
|
323
|
+
);
|
|
320
324
|
|
|
321
325
|
// Build hidden set
|
|
322
326
|
const hidden = hiddenTagValues ?? parsed.initialHiddenTagValues;
|
|
@@ -736,9 +740,13 @@ export function renderBoxesAndLinesForExport(
|
|
|
736
740
|
layout: BLLayoutResult,
|
|
737
741
|
palette: PaletteColors,
|
|
738
742
|
isDark: boolean,
|
|
739
|
-
options?: {
|
|
743
|
+
options?: {
|
|
744
|
+
exportDims?: { width: number; height: number };
|
|
745
|
+
activeTagGroup?: string | null;
|
|
746
|
+
}
|
|
740
747
|
): void {
|
|
741
748
|
renderBoxesAndLines(container, parsed, layout, palette, isDark, {
|
|
742
749
|
exportDims: options?.exportDims,
|
|
750
|
+
activeTagGroup: options?.activeTagGroup,
|
|
743
751
|
});
|
|
744
752
|
}
|
package/src/c4/parser.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type { TagGroup } from '../utils/tag-groups';
|
|
|
8
8
|
import {
|
|
9
9
|
matchTagBlockHeading,
|
|
10
10
|
stripDefaultModifier,
|
|
11
|
+
validateTagGroupNames,
|
|
11
12
|
} from '../utils/tag-groups';
|
|
12
13
|
import { inferParticipantType } from '../sequence/participant-inference';
|
|
13
14
|
import {
|
|
@@ -84,7 +85,7 @@ const VALID_SHAPES = new Set<string>([
|
|
|
84
85
|
]);
|
|
85
86
|
|
|
86
87
|
/** Known top-level option keys for C4 diagrams. */
|
|
87
|
-
const KNOWN_C4_OPTIONS = new Set<string>(['layout']);
|
|
88
|
+
const KNOWN_C4_OPTIONS = new Set<string>(['layout', 'active-tag']);
|
|
88
89
|
|
|
89
90
|
/** Known C4 boolean options (bare keyword = on). */
|
|
90
91
|
const KNOWN_C4_BOOLEANS = new Set<string>(['direction-tb']);
|
|
@@ -829,6 +830,9 @@ export function parseC4(content: string, palette?: PaletteColors): ParsedC4 {
|
|
|
829
830
|
// ── Post-parse validation ───────────────────────────────
|
|
830
831
|
validateRelationshipTargets(result, knownNames, pushError);
|
|
831
832
|
validateDeploymentRefs(result, knownNames, pushError);
|
|
833
|
+
validateTagGroupNames(result.tagGroups, (line, msg) =>
|
|
834
|
+
pushError(line, msg, 'warning')
|
|
835
|
+
);
|
|
832
836
|
|
|
833
837
|
return result;
|
|
834
838
|
}
|
package/src/completion.ts
CHANGED
|
@@ -258,21 +258,33 @@ export const COMPLETION_REGISTRY = new Map<string, DirectiveSpec>([
|
|
|
258
258
|
},
|
|
259
259
|
}),
|
|
260
260
|
],
|
|
261
|
-
[
|
|
261
|
+
[
|
|
262
|
+
'er',
|
|
263
|
+
withGlobals({
|
|
264
|
+
'active-tag': { description: 'Active tag group name' },
|
|
265
|
+
}),
|
|
266
|
+
],
|
|
262
267
|
[
|
|
263
268
|
'org',
|
|
264
269
|
withGlobals({
|
|
265
270
|
'sub-node-label': { description: 'Label for sub-nodes' },
|
|
266
271
|
'show-sub-node-count': { description: 'Show sub-node counts' },
|
|
272
|
+
'active-tag': { description: 'Active tag group name' },
|
|
267
273
|
}),
|
|
268
274
|
],
|
|
269
275
|
[
|
|
270
276
|
'kanban',
|
|
271
277
|
withGlobals({
|
|
272
278
|
'no-auto-color': { description: 'Disable automatic card coloring' },
|
|
279
|
+
'active-tag': { description: 'Active tag group name' },
|
|
280
|
+
}),
|
|
281
|
+
],
|
|
282
|
+
[
|
|
283
|
+
'c4',
|
|
284
|
+
withGlobals({
|
|
285
|
+
'active-tag': { description: 'Active tag group name' },
|
|
273
286
|
}),
|
|
274
287
|
],
|
|
275
|
-
['c4', withGlobals()],
|
|
276
288
|
[
|
|
277
289
|
'state',
|
|
278
290
|
withGlobals({
|
|
@@ -284,6 +296,7 @@ export const COMPLETION_REGISTRY = new Map<string, DirectiveSpec>([
|
|
|
284
296
|
'sitemap',
|
|
285
297
|
withGlobals({
|
|
286
298
|
'direction-tb': { description: 'Switch to top-to-bottom layout' },
|
|
299
|
+
'active-tag': { description: 'Active tag group name' },
|
|
287
300
|
}),
|
|
288
301
|
],
|
|
289
302
|
[
|
|
@@ -298,6 +311,7 @@ export const COMPLETION_REGISTRY = new Map<string, DirectiveSpec>([
|
|
|
298
311
|
'slo-availability': { description: 'SLO availability target (0-1)' },
|
|
299
312
|
'slo-p90-latency-ms': { description: 'SLO p90 latency target in ms' },
|
|
300
313
|
'slo-warning-margin': { description: 'SLO warning margin percentage' },
|
|
314
|
+
'active-tag': { description: 'Active tag group name' },
|
|
301
315
|
}),
|
|
302
316
|
],
|
|
303
317
|
[
|
|
@@ -310,6 +324,7 @@ export const COMPLETION_REGISTRY = new Map<string, DirectiveSpec>([
|
|
|
310
324
|
sort: { description: 'Sort order', values: ['time', 'group', 'tag'] },
|
|
311
325
|
'critical-path': { description: 'Show critical path' },
|
|
312
326
|
dependencies: { description: 'Show dependencies' },
|
|
327
|
+
'active-tag': { description: 'Active tag group name' },
|
|
313
328
|
}),
|
|
314
329
|
],
|
|
315
330
|
[
|
package/src/d3.ts
CHANGED
|
@@ -193,7 +193,9 @@ import {
|
|
|
193
193
|
import {
|
|
194
194
|
matchTagBlockHeading,
|
|
195
195
|
validateTagValues,
|
|
196
|
+
validateTagGroupNames,
|
|
196
197
|
resolveTagColor,
|
|
198
|
+
resolveActiveTagGroup,
|
|
197
199
|
stripDefaultModifier,
|
|
198
200
|
} from './utils/tag-groups';
|
|
199
201
|
import type { TagGroup } from './utils/tag-groups';
|
|
@@ -1477,6 +1479,9 @@ export function parseVisualization(
|
|
|
1477
1479
|
result.diagnostics.push(makeDgmoError(line, msg, 'warning')),
|
|
1478
1480
|
suggest
|
|
1479
1481
|
);
|
|
1482
|
+
validateTagGroupNames(result.timelineTagGroups, (line, msg) =>
|
|
1483
|
+
result.diagnostics.push(makeDgmoError(line, msg, 'warning'))
|
|
1484
|
+
);
|
|
1480
1485
|
for (const group of result.timelineTagGroups) {
|
|
1481
1486
|
if (!group.defaultValue) continue;
|
|
1482
1487
|
const key = group.name.toLowerCase();
|
|
@@ -3405,6 +3410,78 @@ function buildEraTooltipHtml(era: TimelineEra): string {
|
|
|
3405
3410
|
// Timeline Renderer
|
|
3406
3411
|
// ============================================================
|
|
3407
3412
|
|
|
3413
|
+
/**
|
|
3414
|
+
* Renders timeline group legend as pills (colored dot + text in rounded rect),
|
|
3415
|
+
* matching the centralized legend pill style.
|
|
3416
|
+
*/
|
|
3417
|
+
function renderTimelineGroupLegend(
|
|
3418
|
+
g: d3Selection.Selection<SVGGElement, unknown, null, undefined>,
|
|
3419
|
+
groups: TimelineGroup[],
|
|
3420
|
+
groupColorMap: Map<string, string>,
|
|
3421
|
+
textColor: string,
|
|
3422
|
+
palette: PaletteColors,
|
|
3423
|
+
isDark: boolean,
|
|
3424
|
+
legendY: number,
|
|
3425
|
+
onHover: (name: string) => void,
|
|
3426
|
+
onLeave: () => void
|
|
3427
|
+
): void {
|
|
3428
|
+
const PILL_H = 22;
|
|
3429
|
+
const DOT_R = 4;
|
|
3430
|
+
const DOT_GAP = 4;
|
|
3431
|
+
const PAD_X = 10;
|
|
3432
|
+
const FONT_SIZE = 11;
|
|
3433
|
+
const GAP = 8;
|
|
3434
|
+
const pillBg = isDark
|
|
3435
|
+
? mix(palette.surface, palette.bg, 50)
|
|
3436
|
+
: mix(palette.surface, palette.bg, 30);
|
|
3437
|
+
|
|
3438
|
+
let legendX = 0;
|
|
3439
|
+
for (const grp of groups) {
|
|
3440
|
+
const color = groupColorMap.get(grp.name) ?? textColor;
|
|
3441
|
+
const textW = measureLegendText(grp.name, FONT_SIZE);
|
|
3442
|
+
const pillW = PAD_X + DOT_R * 2 + DOT_GAP + textW + PAD_X;
|
|
3443
|
+
|
|
3444
|
+
const itemG = g
|
|
3445
|
+
.append('g')
|
|
3446
|
+
.attr('class', 'tl-legend-item')
|
|
3447
|
+
.attr('data-group', grp.name)
|
|
3448
|
+
.style('cursor', 'pointer')
|
|
3449
|
+
.on('mouseenter', () => onHover(grp.name))
|
|
3450
|
+
.on('mouseleave', () => onLeave());
|
|
3451
|
+
|
|
3452
|
+
// Pill background
|
|
3453
|
+
itemG
|
|
3454
|
+
.append('rect')
|
|
3455
|
+
.attr('x', legendX)
|
|
3456
|
+
.attr('y', legendY - PILL_H / 2)
|
|
3457
|
+
.attr('width', pillW)
|
|
3458
|
+
.attr('height', PILL_H)
|
|
3459
|
+
.attr('rx', PILL_H / 2)
|
|
3460
|
+
.attr('fill', pillBg);
|
|
3461
|
+
|
|
3462
|
+
// Colored dot
|
|
3463
|
+
itemG
|
|
3464
|
+
.append('circle')
|
|
3465
|
+
.attr('cx', legendX + PAD_X + DOT_R)
|
|
3466
|
+
.attr('cy', legendY)
|
|
3467
|
+
.attr('r', DOT_R)
|
|
3468
|
+
.attr('fill', color);
|
|
3469
|
+
|
|
3470
|
+
// Label text
|
|
3471
|
+
itemG
|
|
3472
|
+
.append('text')
|
|
3473
|
+
.attr('x', legendX + PAD_X + DOT_R * 2 + DOT_GAP)
|
|
3474
|
+
.attr('y', legendY)
|
|
3475
|
+
.attr('dy', '0.35em')
|
|
3476
|
+
.attr('fill', textColor)
|
|
3477
|
+
.attr('font-size', `${FONT_SIZE}px`)
|
|
3478
|
+
.attr('font-family', FONT_FAMILY)
|
|
3479
|
+
.text(grp.name);
|
|
3480
|
+
|
|
3481
|
+
legendX += pillW + GAP;
|
|
3482
|
+
}
|
|
3483
|
+
}
|
|
3484
|
+
|
|
3408
3485
|
/**
|
|
3409
3486
|
* Renders a timeline chart into the given container using D3.
|
|
3410
3487
|
* Supports horizontal (default) and vertical orientation.
|
|
@@ -4038,38 +4115,19 @@ export function renderTimeline(
|
|
|
4038
4115
|
);
|
|
4039
4116
|
}
|
|
4040
4117
|
|
|
4041
|
-
// Group legend
|
|
4118
|
+
// Group legend (pill style)
|
|
4042
4119
|
if (timelineGroups.length > 0) {
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
itemG
|
|
4056
|
-
.append('circle')
|
|
4057
|
-
.attr('cx', legendX)
|
|
4058
|
-
.attr('cy', legendY)
|
|
4059
|
-
.attr('r', 5)
|
|
4060
|
-
.attr('fill', color);
|
|
4061
|
-
|
|
4062
|
-
itemG
|
|
4063
|
-
.append('text')
|
|
4064
|
-
.attr('x', legendX + 10)
|
|
4065
|
-
.attr('y', legendY)
|
|
4066
|
-
.attr('dy', '0.35em')
|
|
4067
|
-
.attr('fill', textColor)
|
|
4068
|
-
.attr('font-size', '11px')
|
|
4069
|
-
.text(grp.name);
|
|
4070
|
-
|
|
4071
|
-
legendX += grp.name.length * 7 + 30;
|
|
4072
|
-
}
|
|
4120
|
+
renderTimelineGroupLegend(
|
|
4121
|
+
g,
|
|
4122
|
+
timelineGroups,
|
|
4123
|
+
groupColorMap,
|
|
4124
|
+
textColor,
|
|
4125
|
+
palette,
|
|
4126
|
+
isDark,
|
|
4127
|
+
-55,
|
|
4128
|
+
(name) => fadeToGroup(g, name),
|
|
4129
|
+
() => fadeReset(g)
|
|
4130
|
+
);
|
|
4073
4131
|
}
|
|
4074
4132
|
|
|
4075
4133
|
g.append('line')
|
|
@@ -4656,38 +4714,20 @@ export function renderTimeline(
|
|
|
4656
4714
|
);
|
|
4657
4715
|
}
|
|
4658
4716
|
|
|
4659
|
-
// Group legend at top-left
|
|
4717
|
+
// Group legend at top-left (pill style)
|
|
4660
4718
|
if (timelineGroups.length > 0) {
|
|
4661
|
-
let legendX = 0;
|
|
4662
4719
|
const legendY = timelineScale ? -75 : -55;
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
.append('circle')
|
|
4675
|
-
.attr('cx', legendX)
|
|
4676
|
-
.attr('cy', legendY)
|
|
4677
|
-
.attr('r', 5)
|
|
4678
|
-
.attr('fill', color);
|
|
4679
|
-
|
|
4680
|
-
itemG
|
|
4681
|
-
.append('text')
|
|
4682
|
-
.attr('x', legendX + 10)
|
|
4683
|
-
.attr('y', legendY)
|
|
4684
|
-
.attr('dy', '0.35em')
|
|
4685
|
-
.attr('fill', textColor)
|
|
4686
|
-
.attr('font-size', '11px')
|
|
4687
|
-
.text(grp.name);
|
|
4688
|
-
|
|
4689
|
-
legendX += grp.name.length * 7 + 30;
|
|
4690
|
-
}
|
|
4720
|
+
renderTimelineGroupLegend(
|
|
4721
|
+
g,
|
|
4722
|
+
timelineGroups,
|
|
4723
|
+
groupColorMap,
|
|
4724
|
+
textColor,
|
|
4725
|
+
palette,
|
|
4726
|
+
isDark,
|
|
4727
|
+
legendY,
|
|
4728
|
+
(name) => fadeToGroup(g, name),
|
|
4729
|
+
() => fadeReset(g)
|
|
4730
|
+
);
|
|
4691
4731
|
}
|
|
4692
4732
|
|
|
4693
4733
|
sorted.forEach((ev, i) => {
|
|
@@ -6658,8 +6698,11 @@ export async function renderForExport(
|
|
|
6658
6698
|
|
|
6659
6699
|
// Apply interactive collapse state when provided
|
|
6660
6700
|
const collapsedNodes = orgExportState?.collapsedNodes;
|
|
6661
|
-
const activeTagGroup =
|
|
6662
|
-
|
|
6701
|
+
const activeTagGroup = resolveActiveTagGroup(
|
|
6702
|
+
orgParsed.tagGroups,
|
|
6703
|
+
orgParsed.options['active-tag'],
|
|
6704
|
+
orgExportState?.activeTagGroup ?? options?.tagGroup
|
|
6705
|
+
);
|
|
6663
6706
|
const hiddenAttributes = orgExportState?.hiddenAttributes;
|
|
6664
6707
|
|
|
6665
6708
|
const { parsed: effectiveParsed, hiddenCounts } =
|
|
@@ -6709,8 +6752,11 @@ export async function renderForExport(
|
|
|
6709
6752
|
|
|
6710
6753
|
// Apply interactive collapse state when provided
|
|
6711
6754
|
const collapsedNodes = orgExportState?.collapsedNodes;
|
|
6712
|
-
const activeTagGroup =
|
|
6713
|
-
|
|
6755
|
+
const activeTagGroup = resolveActiveTagGroup(
|
|
6756
|
+
sitemapParsed.tagGroups,
|
|
6757
|
+
sitemapParsed.options['active-tag'],
|
|
6758
|
+
orgExportState?.activeTagGroup ?? options?.tagGroup
|
|
6759
|
+
);
|
|
6714
6760
|
const hiddenAttributes = orgExportState?.hiddenAttributes;
|
|
6715
6761
|
|
|
6716
6762
|
const { parsed: effectiveParsed, hiddenCounts } =
|
|
@@ -6767,7 +6813,11 @@ export async function renderForExport(
|
|
|
6767
6813
|
theme === 'dark',
|
|
6768
6814
|
undefined,
|
|
6769
6815
|
undefined,
|
|
6770
|
-
|
|
6816
|
+
resolveActiveTagGroup(
|
|
6817
|
+
kanbanParsed.tagGroups,
|
|
6818
|
+
kanbanParsed.options['active-tag'],
|
|
6819
|
+
options?.tagGroup
|
|
6820
|
+
)
|
|
6771
6821
|
);
|
|
6772
6822
|
return finalizeSvgExport(container, theme, effectivePalette, options);
|
|
6773
6823
|
}
|
|
@@ -6824,7 +6874,11 @@ export async function renderForExport(
|
|
|
6824
6874
|
theme === 'dark',
|
|
6825
6875
|
undefined,
|
|
6826
6876
|
{ width: exportWidth, height: exportHeight },
|
|
6827
|
-
|
|
6877
|
+
resolveActiveTagGroup(
|
|
6878
|
+
erParsed.tagGroups,
|
|
6879
|
+
erParsed.options['active-tag'],
|
|
6880
|
+
options?.tagGroup
|
|
6881
|
+
)
|
|
6828
6882
|
);
|
|
6829
6883
|
return finalizeSvgExport(container, theme, effectivePalette, options);
|
|
6830
6884
|
}
|
|
@@ -6852,7 +6906,10 @@ export async function renderForExport(
|
|
|
6852
6906
|
blLayout,
|
|
6853
6907
|
effectivePalette,
|
|
6854
6908
|
theme === 'dark',
|
|
6855
|
-
{
|
|
6909
|
+
{
|
|
6910
|
+
exportDims: { width: exportWidth, height: exportHeight },
|
|
6911
|
+
activeTagGroup: options?.tagGroup,
|
|
6912
|
+
}
|
|
6856
6913
|
);
|
|
6857
6914
|
return finalizeSvgExport(container, theme, effectivePalette, options);
|
|
6858
6915
|
}
|
|
@@ -6909,7 +6966,11 @@ export async function renderForExport(
|
|
|
6909
6966
|
theme === 'dark',
|
|
6910
6967
|
undefined,
|
|
6911
6968
|
{ width: exportWidth, height: exportHeight },
|
|
6912
|
-
|
|
6969
|
+
resolveActiveTagGroup(
|
|
6970
|
+
c4Parsed.tagGroups,
|
|
6971
|
+
c4Parsed.options['active-tag'],
|
|
6972
|
+
options?.tagGroup
|
|
6973
|
+
)
|
|
6913
6974
|
);
|
|
6914
6975
|
return finalizeSvgExport(container, theme, effectivePalette, options);
|
|
6915
6976
|
}
|
|
@@ -6951,7 +7012,11 @@ export async function renderForExport(
|
|
|
6951
7012
|
|
|
6952
7013
|
const infraComputed = computeInfra(infraParsed);
|
|
6953
7014
|
const infraLayout = layoutInfra(infraComputed);
|
|
6954
|
-
const activeTagGroup =
|
|
7015
|
+
const activeTagGroup = resolveActiveTagGroup(
|
|
7016
|
+
infraParsed.tagGroups,
|
|
7017
|
+
infraParsed.options['active-tag'],
|
|
7018
|
+
options?.tagGroup
|
|
7019
|
+
);
|
|
6955
7020
|
|
|
6956
7021
|
const titleOffset = infraParsed.title ? 40 : 0;
|
|
6957
7022
|
const legendGroups = computeInfraLegendGroups(
|
|
@@ -7104,7 +7169,11 @@ export async function renderForExport(
|
|
|
7104
7169
|
isDark,
|
|
7105
7170
|
undefined,
|
|
7106
7171
|
dims,
|
|
7107
|
-
|
|
7172
|
+
resolveActiveTagGroup(
|
|
7173
|
+
parsed.timelineTagGroups,
|
|
7174
|
+
undefined,
|
|
7175
|
+
orgExportState?.activeTagGroup ?? options?.tagGroup
|
|
7176
|
+
),
|
|
7108
7177
|
orgExportState?.swimlaneTagGroup
|
|
7109
7178
|
);
|
|
7110
7179
|
} else if (parsed.type === 'venn') {
|
package/src/echarts.ts
CHANGED
package/src/er/parser.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
matchTagBlockHeading,
|
|
13
13
|
validateTagValues,
|
|
14
|
+
validateTagGroupNames,
|
|
14
15
|
stripDefaultModifier,
|
|
15
16
|
} from '../utils/tag-groups';
|
|
16
17
|
import type { TagGroup } from '../utils/tag-groups';
|
|
@@ -54,7 +55,7 @@ const CONSTRAINT_MAP: Record<string, ERConstraint> = {
|
|
|
54
55
|
};
|
|
55
56
|
|
|
56
57
|
// Known options (space-separated, no colon)
|
|
57
|
-
const KNOWN_OPTIONS = new Set(['notation']);
|
|
58
|
+
const KNOWN_OPTIONS = new Set(['notation', 'active-tag']);
|
|
58
59
|
|
|
59
60
|
// ============================================================
|
|
60
61
|
// Cardinality parsing
|
|
@@ -418,6 +419,9 @@ export function parseERDiagram(
|
|
|
418
419
|
result.diagnostics.push(makeDgmoError(line, msg, 'warning')),
|
|
419
420
|
suggest
|
|
420
421
|
);
|
|
422
|
+
validateTagGroupNames(result.tagGroups, (line, msg) =>
|
|
423
|
+
result.diagnostics.push(makeDgmoError(line, msg, 'warning'))
|
|
424
|
+
);
|
|
421
425
|
|
|
422
426
|
// Inject defaults for tables without explicit tags
|
|
423
427
|
for (const group of result.tagGroups) {
|
package/src/gantt/parser.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type { TagGroup } from '../utils/tag-groups';
|
|
|
8
8
|
import {
|
|
9
9
|
matchTagBlockHeading,
|
|
10
10
|
stripDefaultModifier,
|
|
11
|
+
validateTagGroupNames,
|
|
11
12
|
} from '../utils/tag-groups';
|
|
12
13
|
import {
|
|
13
14
|
measureIndent,
|
|
@@ -134,6 +135,7 @@ export function parseGantt(
|
|
|
134
135
|
dependencies: true,
|
|
135
136
|
sort: 'default',
|
|
136
137
|
defaultSwimlaneGroup: null,
|
|
138
|
+
activeTag: null,
|
|
137
139
|
optionLineNumbers: {},
|
|
138
140
|
holidaysLineNumber: null,
|
|
139
141
|
},
|
|
@@ -645,6 +647,9 @@ export function parseGantt(
|
|
|
645
647
|
);
|
|
646
648
|
}
|
|
647
649
|
break;
|
|
650
|
+
case 'active-tag':
|
|
651
|
+
result.options.activeTag = value;
|
|
652
|
+
break;
|
|
648
653
|
}
|
|
649
654
|
continue;
|
|
650
655
|
}
|
|
@@ -872,6 +877,8 @@ export function parseGantt(
|
|
|
872
877
|
result.options.sort = 'default';
|
|
873
878
|
}
|
|
874
879
|
|
|
880
|
+
validateTagGroupNames(result.tagGroups, warn);
|
|
881
|
+
|
|
875
882
|
return result;
|
|
876
883
|
|
|
877
884
|
// ── Helper: create a task ───────────────────────────────
|
|
@@ -1033,6 +1040,7 @@ const KNOWN_OPTIONS = new Set([
|
|
|
1033
1040
|
'dependencies',
|
|
1034
1041
|
'chart',
|
|
1035
1042
|
'sort',
|
|
1043
|
+
'active-tag',
|
|
1036
1044
|
]);
|
|
1037
1045
|
|
|
1038
1046
|
/** Boolean options that can appear as bare keywords or with `no-` prefix. */
|
package/src/gantt/renderer.ts
CHANGED
|
@@ -7,7 +7,7 @@ import * as d3Selection from 'd3-selection';
|
|
|
7
7
|
import { FONT_FAMILY } from '../fonts';
|
|
8
8
|
import { getSeriesColors } from '../palettes';
|
|
9
9
|
import { mix } from '../palettes/color-utils';
|
|
10
|
-
import { resolveTagColor } from '../utils/tag-groups';
|
|
10
|
+
import { resolveTagColor, resolveActiveTagGroup } from '../utils/tag-groups';
|
|
11
11
|
import { computeTimeTicks } from '../d3';
|
|
12
12
|
import {
|
|
13
13
|
LEGEND_HEIGHT,
|
|
@@ -227,12 +227,11 @@ export function renderGantt(
|
|
|
227
227
|
// ── Compute layout dimensions ───────────────────────────
|
|
228
228
|
|
|
229
229
|
const seriesColors = getSeriesColors(palette);
|
|
230
|
-
let currentActiveGroup: string | null =
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
: null;
|
|
230
|
+
let currentActiveGroup: string | null = resolveActiveTagGroup(
|
|
231
|
+
resolved.tagGroups,
|
|
232
|
+
resolved.options.activeTag ?? undefined,
|
|
233
|
+
options?.currentActiveGroup
|
|
234
|
+
);
|
|
236
235
|
let criticalPathActive = false;
|
|
237
236
|
|
|
238
237
|
// ── Build row list (structural vs tag mode) ─────────────
|
package/src/gantt/types.ts
CHANGED
|
@@ -115,6 +115,7 @@ export interface GanttOptions {
|
|
|
115
115
|
dependencies: boolean;
|
|
116
116
|
sort: 'default' | 'tag';
|
|
117
117
|
defaultSwimlaneGroup: string | null; // tag group name from `sort: tag:Team`
|
|
118
|
+
activeTag: string | null; // from `active-tag GroupName` or `active-tag none`
|
|
118
119
|
/** Line numbers for option/block keywords — maps key to source line */
|
|
119
120
|
optionLineNumbers: Record<string, number>;
|
|
120
121
|
holidaysLineNumber: number | null;
|
package/src/infra/parser.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
import {
|
|
16
16
|
matchTagBlockHeading,
|
|
17
17
|
stripDefaultModifier,
|
|
18
|
+
validateTagGroupNames,
|
|
18
19
|
} from '../utils/tag-groups';
|
|
19
20
|
import type {
|
|
20
21
|
ParsedInfra,
|
|
@@ -77,6 +78,7 @@ const TOP_LEVEL_OPTIONS = new Set([
|
|
|
77
78
|
'default-latency-ms',
|
|
78
79
|
'default-uptime',
|
|
79
80
|
'default-rps',
|
|
81
|
+
'active-tag',
|
|
80
82
|
]);
|
|
81
83
|
|
|
82
84
|
// ============================================================
|
|
@@ -726,6 +728,8 @@ export function parseInfra(content: string): ParsedInfra {
|
|
|
726
728
|
}
|
|
727
729
|
}
|
|
728
730
|
|
|
731
|
+
validateTagGroupNames(result.tagGroups, warn);
|
|
732
|
+
|
|
729
733
|
return result;
|
|
730
734
|
}
|
|
731
735
|
|
package/src/kanban/parser.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { resolveColor } from '../colors';
|
|
|
4
4
|
import {
|
|
5
5
|
matchTagBlockHeading,
|
|
6
6
|
stripDefaultModifier,
|
|
7
|
+
validateTagGroupNames,
|
|
7
8
|
} from '../utils/tag-groups';
|
|
8
9
|
import {
|
|
9
10
|
measureIndent,
|
|
@@ -29,7 +30,7 @@ const COLUMN_RE = /^\[(.+?)\](?:\s*\(([^)]+)\))?\s*(?:\|\s*(.+))?$/;
|
|
|
29
30
|
const LEGACY_COLUMN_RE = /^==\s+(.+?)\s*(?:\[wip:\s*(\d+)\])?\s*==$/;
|
|
30
31
|
|
|
31
32
|
/** Known kanban options (key-value). */
|
|
32
|
-
const KNOWN_OPTIONS = new Set(['hide']);
|
|
33
|
+
const KNOWN_OPTIONS = new Set(['hide', 'active-tag']);
|
|
33
34
|
/** Known kanban boolean options (bare keyword = on). */
|
|
34
35
|
const KNOWN_BOOLEANS = new Set<string>(['no-auto-color']);
|
|
35
36
|
|
|
@@ -366,6 +367,8 @@ export function parseKanban(
|
|
|
366
367
|
return fail(1, 'No columns found. Use [Column Name] to define columns');
|
|
367
368
|
}
|
|
368
369
|
|
|
370
|
+
validateTagGroupNames(result.tagGroups, warn);
|
|
371
|
+
|
|
369
372
|
return result;
|
|
370
373
|
}
|
|
371
374
|
|