@diagrammo/dgmo 0.25.0 → 0.25.1
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/advanced.cjs +189 -333
- package/dist/advanced.d.cts +17 -80
- package/dist/advanced.d.ts +17 -80
- package/dist/advanced.js +189 -325
- package/dist/auto.cjs +187 -318
- package/dist/auto.js +118 -118
- package/dist/auto.mjs +187 -318
- package/dist/cli.cjs +154 -154
- package/dist/editor.cjs +1 -0
- package/dist/editor.js +1 -0
- package/dist/highlight.cjs +1 -0
- package/dist/highlight.js +1 -0
- package/dist/index.cjs +204 -319
- package/dist/index.js +204 -319
- package/dist/internal.cjs +189 -333
- package/dist/internal.d.cts +17 -80
- package/dist/internal.d.ts +17 -80
- package/dist/internal.js +189 -325
- package/package.json +1 -1
- package/src/advanced.ts +0 -8
- package/src/completion.ts +5 -0
- package/src/d3.ts +12 -2
- package/src/editor/keywords.ts +1 -0
- package/src/map/layout.ts +18 -11
- package/src/map/parser.ts +12 -2
- package/src/map/renderer.ts +25 -2
- package/src/map/types.ts +9 -0
- package/src/pert/renderer.ts +21 -358
- package/src/sequence/renderer.ts +36 -1
- package/src/utils/svg-embed.ts +36 -2
package/package.json
CHANGED
package/src/advanced.ts
CHANGED
|
@@ -402,14 +402,6 @@ export {
|
|
|
402
402
|
renderPertForExport,
|
|
403
403
|
renderPertAnalysisBlock,
|
|
404
404
|
measurePertAnalysisBlock,
|
|
405
|
-
highlightPertCriticalPath,
|
|
406
|
-
highlightPertSet,
|
|
407
|
-
pertLegendEntries,
|
|
408
|
-
pertLegendBlockWidth,
|
|
409
|
-
PERT_LEGEND_PILL_HEIGHT,
|
|
410
|
-
renderLegendBlock as renderPertLegendBlock,
|
|
411
|
-
resetPertCriticalPath,
|
|
412
|
-
resetPertHighlight,
|
|
413
405
|
} from './pert/renderer';
|
|
414
406
|
export type { PertRenderOptions } from './pert/renderer';
|
|
415
407
|
export type {
|
package/src/completion.ts
CHANGED
|
@@ -534,6 +534,7 @@ export const COMPLETION_REGISTRY = new Map<string, DirectiveSpec>([
|
|
|
534
534
|
description: 'Which tag group leads when several are present',
|
|
535
535
|
},
|
|
536
536
|
caption: { description: 'Caption line (data-source attribution)' },
|
|
537
|
+
'no-title': { description: 'Suppress the title banner' },
|
|
537
538
|
'no-legend': { description: 'Suppress the legend' },
|
|
538
539
|
'no-coastline': {
|
|
539
540
|
description: 'Turn off coastal water-lines (on by default)',
|
|
@@ -552,6 +553,10 @@ export const COMPLETION_REGISTRY = new Map<string, DirectiveSpec>([
|
|
|
552
553
|
description:
|
|
553
554
|
'Force plain green-land reference dress (regions are auto-coloured by default)',
|
|
554
555
|
},
|
|
556
|
+
'no-cluster-pois': {
|
|
557
|
+
description:
|
|
558
|
+
'Always fan out coincident POI markers instead of collapsing them into a count badge',
|
|
559
|
+
},
|
|
555
560
|
}),
|
|
556
561
|
],
|
|
557
562
|
]);
|
package/src/d3.ts
CHANGED
|
@@ -8609,6 +8609,14 @@ export async function renderForExport(
|
|
|
8609
8609
|
const { renderSequenceDiagram } = await import('./sequence/renderer');
|
|
8610
8610
|
const seqParsed = parseSequenceDgmo(content);
|
|
8611
8611
|
if (seqParsed.error || seqParsed.participants.length === 0) return '';
|
|
8612
|
+
// Apply interactive view state from share links (read from unified viewState).
|
|
8613
|
+
// Sequences key both sections and groups by source line number; `cg` is the
|
|
8614
|
+
// shared string[] field, so coerce its entries back to numbers.
|
|
8615
|
+
const collapsedSections = viewState?.cs ? new Set(viewState.cs) : undefined;
|
|
8616
|
+
const collapsedGroups = viewState?.cg
|
|
8617
|
+
? new Set(viewState.cg.map(Number).filter((n) => Number.isFinite(n)))
|
|
8618
|
+
: undefined;
|
|
8619
|
+
const seqActiveTagGroup = viewState?.tag ?? options?.tagGroup;
|
|
8612
8620
|
renderSequenceDiagram(
|
|
8613
8621
|
container,
|
|
8614
8622
|
seqParsed,
|
|
@@ -8617,9 +8625,11 @@ export async function renderForExport(
|
|
|
8617
8625
|
undefined,
|
|
8618
8626
|
{
|
|
8619
8627
|
exportWidth: EXPORT_WIDTH,
|
|
8620
|
-
...(
|
|
8621
|
-
activeTagGroup:
|
|
8628
|
+
...(seqActiveTagGroup !== undefined && {
|
|
8629
|
+
activeTagGroup: seqActiveTagGroup,
|
|
8622
8630
|
}),
|
|
8631
|
+
...(collapsedSections !== undefined && { collapsedSections }),
|
|
8632
|
+
...(collapsedGroups !== undefined && { collapsedGroups }),
|
|
8623
8633
|
}
|
|
8624
8634
|
);
|
|
8625
8635
|
} else if (parsed.type === 'wordcloud') {
|
package/src/editor/keywords.ts
CHANGED
package/src/map/layout.ts
CHANGED
|
@@ -1027,18 +1027,22 @@ export function layoutMap(
|
|
|
1027
1027
|
|
|
1028
1028
|
// -- Colorize: content-inferred distinct political fills (§24B) --
|
|
1029
1029
|
// Colorize is the DEFAULT dress for any map that is NOT colouring regions by
|
|
1030
|
-
// data. The
|
|
1030
|
+
// data. The things that turn it off: (1) a data dimension exists on a
|
|
1031
1031
|
// region (any `value:` or tag group) — data owns the saturation, so the basemap
|
|
1032
|
-
// recedes to the gray choropleth/categorical dress;
|
|
1033
|
-
//
|
|
1034
|
-
//
|
|
1035
|
-
//
|
|
1036
|
-
//
|
|
1037
|
-
//
|
|
1038
|
-
//
|
|
1032
|
+
// recedes to the gray choropleth/categorical dress; (2) any region carries a
|
|
1033
|
+
// direct trailing color (`Japan red`) — that's explicit authoring intent, so
|
|
1034
|
+
// auto-political-tinting would only fight the hand-picked colours; or (3) the
|
|
1035
|
+
// `no-colorize` opt-out. Everything else — bare `map`, POI/route-only maps,
|
|
1036
|
+
// named regions without data or direct colours — gets distinct political
|
|
1037
|
+
// pastels (markers/routes draw on top). Data EXISTENCE (not which dimension is
|
|
1038
|
+
// *active*) is the discriminator, so a tag map viewed with `active-tag none`
|
|
1039
|
+
// still keeps its neutral data dress; and the live-preview `California` →
|
|
1040
|
+
// `California value: 92` edit transitions colorized → choropleth cleanly.
|
|
1041
|
+
const hasDirectColor = resolved.regions.some((r) => r.color !== undefined);
|
|
1039
1042
|
const colorizeActive =
|
|
1040
1043
|
resolved.directives.noColorize !== true &&
|
|
1041
1044
|
!hasRamp &&
|
|
1045
|
+
!hasDirectColor &&
|
|
1042
1046
|
resolved.tagGroups.length === 0;
|
|
1043
1047
|
// Hue per ISO over ONE UNIFIED graph spanning every drawn topology, so no two
|
|
1044
1048
|
// bordering regions share a hue — INCLUDING across the international seam. The
|
|
@@ -1201,9 +1205,12 @@ export function layoutMap(
|
|
|
1201
1205
|
// the foreground). A POI-less choropleth needs no reserve — the land fills to
|
|
1202
1206
|
// the top and the title simply overlays it, so neighbour land (e.g. Canada)
|
|
1203
1207
|
// isn't cut short by a band of empty water above it.
|
|
1208
|
+
// `no-title` suppresses the banner entirely — drop it from layout so the title
|
|
1209
|
+
// reserves no top band and the renderer's `if (layout.title)` skips it.
|
|
1210
|
+
const shownTitle = resolved.directives.noTitle ? null : resolved.title;
|
|
1204
1211
|
const TITLE_GAP = 16;
|
|
1205
1212
|
let topPad = FIT_PAD;
|
|
1206
|
-
if (
|
|
1213
|
+
if (shownTitle && resolved.pois.length > 0) {
|
|
1207
1214
|
const bannerBottom =
|
|
1208
1215
|
(resolved.subtitle ? TITLE_Y + TITLE_FONT_SIZE : TITLE_Y) +
|
|
1209
1216
|
TITLE_FONT_SIZE / 2;
|
|
@@ -1217,7 +1224,7 @@ export function layoutMap(
|
|
|
1217
1224
|
const legendBand = mapLegendBand(legend, {
|
|
1218
1225
|
width,
|
|
1219
1226
|
mode: opts.legendMode ?? 'preview',
|
|
1220
|
-
hasTitle: Boolean(
|
|
1227
|
+
hasTitle: Boolean(shownTitle),
|
|
1221
1228
|
hasSubtitle: Boolean(resolved.subtitle),
|
|
1222
1229
|
});
|
|
1223
1230
|
if (legendBand > topPad) topPad = legendBand;
|
|
@@ -2932,7 +2939,7 @@ export function layoutMap(
|
|
|
2932
2939
|
width,
|
|
2933
2940
|
height,
|
|
2934
2941
|
background: water,
|
|
2935
|
-
title:
|
|
2942
|
+
title: shownTitle,
|
|
2936
2943
|
...(resolved.subtitle !== undefined && { subtitle: resolved.subtitle }),
|
|
2937
2944
|
...(resolved.caption !== undefined && { caption: resolved.caption }),
|
|
2938
2945
|
regions,
|
package/src/map/parser.ts
CHANGED
|
@@ -46,8 +46,10 @@ const HUB_RE = /^(->|~>)\s+(.+)$/;
|
|
|
46
46
|
const LEG_ARROW_RE = /^(-[^>]*?->|->|~[^>]*?~>|~>|--)\s+(.+)$/;
|
|
47
47
|
const AT_RE = /(^|[\s,])at\s*:/i; // the removed `at:` coord form (§24B.9)
|
|
48
48
|
|
|
49
|
-
//
|
|
50
|
-
// opt-outs
|
|
49
|
+
// The 14 map-specific directives (§24B.2): 6 irreducible-intent + 8 `no-*`
|
|
50
|
+
// cosmetic opt-outs (every cosmetic on by default; its `no-*` flag is the only
|
|
51
|
+
// switch). Plus `no-title` — the universal banner-suppression flag (§1), wired
|
|
52
|
+
// in here so the map parser recognizes it rather than mis-parsing it as a region.
|
|
51
53
|
const DIRECTIVE_SET: ReadonlySet<string> = new Set([
|
|
52
54
|
'region-metric',
|
|
53
55
|
'poi-metric',
|
|
@@ -55,6 +57,7 @@ const DIRECTIVE_SET: ReadonlySet<string> = new Set([
|
|
|
55
57
|
'locale',
|
|
56
58
|
'active-tag',
|
|
57
59
|
'caption',
|
|
60
|
+
'no-title',
|
|
58
61
|
'no-legend',
|
|
59
62
|
'no-coastline',
|
|
60
63
|
'no-relief',
|
|
@@ -62,6 +65,7 @@ const DIRECTIVE_SET: ReadonlySet<string> = new Set([
|
|
|
62
65
|
'no-region-labels',
|
|
63
66
|
'no-poi-labels',
|
|
64
67
|
'no-colorize',
|
|
68
|
+
'no-cluster-pois',
|
|
65
69
|
]);
|
|
66
70
|
|
|
67
71
|
/** True when the first non-blank/non-comment line declares `map`. */
|
|
@@ -313,6 +317,9 @@ export function parseMap(content: string): ParsedMap {
|
|
|
313
317
|
break;
|
|
314
318
|
// ── Cosmetic `no-*` opt-outs: bare flags, idempotent (mirror `no-legend`,
|
|
315
319
|
// no dup warning); each defaults the feature ON when absent. ──
|
|
320
|
+
case 'no-title':
|
|
321
|
+
d.noTitle = true;
|
|
322
|
+
break;
|
|
316
323
|
case 'no-legend':
|
|
317
324
|
d.noLegend = true;
|
|
318
325
|
break;
|
|
@@ -334,6 +341,9 @@ export function parseMap(content: string): ParsedMap {
|
|
|
334
341
|
case 'no-colorize':
|
|
335
342
|
d.noColorize = true;
|
|
336
343
|
break;
|
|
344
|
+
case 'no-cluster-pois':
|
|
345
|
+
d.noClusterPois = true;
|
|
346
|
+
break;
|
|
337
347
|
}
|
|
338
348
|
}
|
|
339
349
|
|
package/src/map/renderer.ts
CHANGED
|
@@ -694,11 +694,16 @@ export function renderMap(
|
|
|
694
694
|
// toggles only their opacity. Drawn VISIBLE so export + the no-JS default show
|
|
695
695
|
// the expanded fan. An invisible hit-area circle (interactive only) owns all
|
|
696
696
|
// pointer interaction so hover/click drives the spiderfy controller robustly.
|
|
697
|
+
// `no-cluster-pois` (or any export) keeps the fan permanently expanded: draw
|
|
698
|
+
// the legs/hub/members visible but emit NO hit-area + NO badge, so there is
|
|
699
|
+
// nothing for the app's spiderfy controller to collapse — the map reads the
|
|
700
|
+
// same on screen as on paper.
|
|
701
|
+
const clusterUi = !exportDims && !resolved.directives.noClusterPois;
|
|
697
702
|
const gSpider = svg.append('g').attr('class', 'dgmo-map-spider');
|
|
698
703
|
for (const cl of layout.clusters) {
|
|
699
704
|
// Pointer hit-area — bottom of the stack so member dots still take their own
|
|
700
705
|
// clicks (line-jump); clicks on the empty centre fall through to here.
|
|
701
|
-
if (
|
|
706
|
+
if (clusterUi) {
|
|
702
707
|
gSpider
|
|
703
708
|
.append('circle')
|
|
704
709
|
.attr('cx', cl.cx)
|
|
@@ -863,7 +868,7 @@ export function renderMap(
|
|
|
863
868
|
// export keeps the expanded fan (every label visible), so no badge there. A
|
|
864
869
|
// neutral dot ringed with the bare member count, emitted hidden; the app shows
|
|
865
870
|
// it at rest and hides it (revealing the spider) on click. ──
|
|
866
|
-
if (
|
|
871
|
+
if (clusterUi && layout.clusters.length) {
|
|
867
872
|
const gBadge = svg.append('g').attr('class', 'dgmo-map-cluster-badges');
|
|
868
873
|
for (const cl of layout.clusters) {
|
|
869
874
|
// Decorative: the hit-area (drawn under the dots) owns hover + click; the
|
|
@@ -889,6 +894,24 @@ export function renderMap(
|
|
|
889
894
|
.attr('fill', 'none')
|
|
890
895
|
.attr('stroke', palette.textMuted)
|
|
891
896
|
.attr('stroke-width', 1);
|
|
897
|
+
// Directional colour beads: one small dot threaded on the outer ring per
|
|
898
|
+
// member, placed at the ANGLE of that member's spider leg (centroid → its
|
|
899
|
+
// expanded position) and filled with the member's own marker colour. So the
|
|
900
|
+
// collapsed badge previews WHAT is stacked here and roughly WHERE each item
|
|
901
|
+
// will fan out, before the spider opens. A bg-coloured halo keeps adjacent
|
|
902
|
+
// beads + the ring line legible.
|
|
903
|
+
const beadR = R + 2.5;
|
|
904
|
+
for (const leg of cl.legs) {
|
|
905
|
+
const a = Math.atan2(leg.y2 - cl.cy, leg.x2 - cl.cx);
|
|
906
|
+
g.append('circle')
|
|
907
|
+
.attr('class', 'dgmo-map-cluster-bead')
|
|
908
|
+
.attr('cx', cl.cx + beadR * Math.cos(a))
|
|
909
|
+
.attr('cy', cl.cy + beadR * Math.sin(a))
|
|
910
|
+
.attr('r', 1.8)
|
|
911
|
+
.attr('fill', leg.color)
|
|
912
|
+
.attr('stroke', palette.bg)
|
|
913
|
+
.attr('stroke-width', 0.5);
|
|
914
|
+
}
|
|
892
915
|
// Bare count (RQ1).
|
|
893
916
|
emitText(
|
|
894
917
|
g,
|
package/src/map/types.ts
CHANGED
|
@@ -33,6 +33,9 @@ export interface MapDirectives {
|
|
|
33
33
|
locale?: string;
|
|
34
34
|
activeTag?: string;
|
|
35
35
|
caption?: string;
|
|
36
|
+
/** `no-title` — suppress the title banner (the subtitle/caption, if any, still
|
|
37
|
+
* render). Mirrors the `no-title` directive across the other chart types. */
|
|
38
|
+
noTitle?: boolean;
|
|
36
39
|
/** `no-legend` — suppress the legend (default-on). */
|
|
37
40
|
noLegend?: boolean;
|
|
38
41
|
/** `no-coastline` — suppress the faint nautical-chart water-lines along
|
|
@@ -52,6 +55,12 @@ export interface MapDirectives {
|
|
|
52
55
|
* are referenced (regions are auto-coloured by default; §24B colorize). A
|
|
53
56
|
* no-op under data — the basemap is already gray there. */
|
|
54
57
|
noColorize?: boolean;
|
|
58
|
+
/** `no-cluster-pois` — never collapse coincident POI markers into a count badge
|
|
59
|
+
* (clustering/spiderfy is default-on in the interactive preview). With this set
|
|
60
|
+
* the markers always render fanned out with their legs — the same as a static
|
|
61
|
+
* export — so a dense map reads the same on screen as on paper. No-op for
|
|
62
|
+
* export (already always expanded). */
|
|
63
|
+
noClusterPois?: boolean;
|
|
55
64
|
}
|
|
56
65
|
|
|
57
66
|
/** A region-fill: a subdivision name with an optional score and/or tag values
|