@diagrammo/dgmo 0.39.0 → 0.41.0
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 +372 -162
- package/dist/advanced.js +372 -162
- package/dist/auto.cjs +373 -163
- package/dist/auto.js +92 -92
- package/dist/auto.mjs +373 -163
- package/dist/cli.cjs +115 -115
- package/dist/index.cjs +550 -217
- package/dist/index.js +550 -217
- package/docs/language-reference.md +17 -0
- package/gallery/fixtures/block.dgmo +16 -0
- package/gallery/fixtures/event-line.dgmo +26 -0
- package/package.json +1 -1
- package/src/diagnostics.ts +0 -0
- package/src/echarts.ts +5 -0
- package/src/error-card.ts +200 -0
- package/src/event-line/parser.ts +155 -55
- package/src/event-line/renderer.ts +350 -139
- package/src/index.ts +7 -30
- package/src/journey-map/renderer.ts +50 -18
package/dist/index.cjs
CHANGED
|
@@ -105,7 +105,7 @@ function vennAliasKeywordRemovedMessage(args) {
|
|
|
105
105
|
return `Venn 'alias' keyword was removed. Use 'as' instead \u2014 '${args.name} as ${args.alias}'.`;
|
|
106
106
|
}
|
|
107
107
|
function pipeOperatorRemovedMessage() {
|
|
108
|
-
return `'|'
|
|
108
|
+
return `'|' is no longer metadata syntax \u2014 write metadata inline as 'key: value' (e.g. "Name color: red"), or remove the '|'.`;
|
|
109
109
|
}
|
|
110
110
|
function ganttBarePercentRemovedMessage(percent) {
|
|
111
111
|
return `Bare-percent progress shorthand '| ${percent}' was removed. Use 'progress: ${percent.replace(/%$/, "")}' (integer 0\u2013100, no '%').`;
|
|
@@ -13609,7 +13609,8 @@ function buildScatterOption(parsed, palette, isDark, textColor, axisLineColor, g
|
|
|
13609
13609
|
solid: parsed.solidFill === true
|
|
13610
13610
|
}),
|
|
13611
13611
|
borderColor: catColor,
|
|
13612
|
-
borderWidth: CHART_BORDER_WIDTH
|
|
13612
|
+
borderWidth: CHART_BORDER_WIDTH,
|
|
13613
|
+
opacity: SCATTER_FILL_OPACITY
|
|
13613
13614
|
},
|
|
13614
13615
|
label: labelConfig,
|
|
13615
13616
|
emphasis: emphasisConfig,
|
|
@@ -13636,6 +13637,7 @@ function buildScatterOption(parsed, palette, isDark, textColor, axisLineColor, g
|
|
|
13636
13637
|
{
|
|
13637
13638
|
type: "scatter",
|
|
13638
13639
|
data,
|
|
13640
|
+
itemStyle: { opacity: SCATTER_FILL_OPACITY },
|
|
13639
13641
|
label: labelConfig,
|
|
13640
13642
|
emphasis: emphasisConfig,
|
|
13641
13643
|
blur: blurConfig
|
|
@@ -14941,7 +14943,7 @@ async function renderExtendedChartForExport(content, theme, palette) {
|
|
|
14941
14943
|
chart.dispose();
|
|
14942
14944
|
}
|
|
14943
14945
|
}
|
|
14944
|
-
var echarts, import_charts, import_components, import_renderers, EMPHASIS_SELF, EMPHASIS_SERIES, BLUR_DIM, EMPHASIS_LINE, CHART_BASE, CHART_BORDER_WIDTH, VALID_EXTENDED_TYPES, KNOWN_EXTENDED_OPTIONS, EXTENDED_CHART_DOORS, FIT_PADDING, OFFSCREEN, fitStackedLabelToSegment, ECHART_EXPORT_WIDTH, ECHART_EXPORT_HEIGHT, STANDARD_CHART_TYPES;
|
|
14946
|
+
var echarts, import_charts, import_components, import_renderers, EMPHASIS_SELF, EMPHASIS_SERIES, BLUR_DIM, EMPHASIS_LINE, CHART_BASE, CHART_BORDER_WIDTH, SCATTER_FILL_OPACITY, VALID_EXTENDED_TYPES, KNOWN_EXTENDED_OPTIONS, EXTENDED_CHART_DOORS, FIT_PADDING, OFFSCREEN, fitStackedLabelToSegment, ECHART_EXPORT_WIDTH, ECHART_EXPORT_HEIGHT, STANDARD_CHART_TYPES;
|
|
14945
14947
|
var init_echarts = __esm({
|
|
14946
14948
|
"src/echarts.ts"() {
|
|
14947
14949
|
"use strict";
|
|
@@ -14999,6 +15001,7 @@ var init_echarts = __esm({
|
|
|
14999
15001
|
tooltip: { show: false }
|
|
15000
15002
|
};
|
|
15001
15003
|
CHART_BORDER_WIDTH = 2;
|
|
15004
|
+
SCATTER_FILL_OPACITY = 0.65;
|
|
15002
15005
|
VALID_EXTENDED_TYPES = /* @__PURE__ */ new Set([
|
|
15003
15006
|
"sankey",
|
|
15004
15007
|
"chord",
|
|
@@ -15096,6 +15099,8 @@ function parseEventLine(content, palette) {
|
|
|
15096
15099
|
let currentTagGroup = null;
|
|
15097
15100
|
let currentEvent = null;
|
|
15098
15101
|
let currentEra = null;
|
|
15102
|
+
let eraIndent = -1;
|
|
15103
|
+
let currentEventIndent = 0;
|
|
15099
15104
|
const aliasMap = /* @__PURE__ */ new Map();
|
|
15100
15105
|
for (let i = 0; i < lines.length; i++) {
|
|
15101
15106
|
const line11 = lines[i];
|
|
@@ -15170,52 +15175,15 @@ function parseEventLine(content, palette) {
|
|
|
15170
15175
|
});
|
|
15171
15176
|
continue;
|
|
15172
15177
|
}
|
|
15173
|
-
if (indent >
|
|
15174
|
-
if (!currentEvent) {
|
|
15175
|
-
pushWarning(
|
|
15176
|
-
lineNumber,
|
|
15177
|
-
`Indented description "${trimmed}" has no event above it \u2014 add an event line first. (\xA728)`
|
|
15178
|
-
);
|
|
15179
|
-
continue;
|
|
15180
|
-
}
|
|
15178
|
+
if (currentEvent && indent > currentEventIndent) {
|
|
15181
15179
|
const descLine = trimmed.startsWith("- ") ? `\u2022 ${trimmed.substring(2)}` : trimmed;
|
|
15182
15180
|
currentEvent.description.push(descLine);
|
|
15183
15181
|
continue;
|
|
15184
15182
|
}
|
|
15185
|
-
currentTagGroup = null;
|
|
15186
|
-
if (trimmed.toLowerCase() === "no-scale") {
|
|
15187
|
-
options.scale = false;
|
|
15188
|
-
continue;
|
|
15189
|
-
}
|
|
15190
|
-
const sideMatch = trimmed.match(SIDE_RE);
|
|
15191
|
-
if (sideMatch) {
|
|
15192
|
-
options.side = sideMatch[1].toLowerCase();
|
|
15193
|
-
continue;
|
|
15194
|
-
}
|
|
15195
|
-
if (trimmed.toLowerCase() === "no-box") {
|
|
15196
|
-
options.noBox = true;
|
|
15197
|
-
continue;
|
|
15198
|
-
}
|
|
15199
|
-
if (trimmed.toLowerCase() === "no-legend") {
|
|
15200
|
-
options.noLegend = true;
|
|
15201
|
-
continue;
|
|
15202
|
-
}
|
|
15203
|
-
const dirMatch = trimmed.match(DIRECTION_RE);
|
|
15204
|
-
if (dirMatch) {
|
|
15205
|
-
const dir = dirMatch[1].toUpperCase();
|
|
15206
|
-
if (dir !== "LR") {
|
|
15207
|
-
pushWarning(
|
|
15208
|
-
lineNumber,
|
|
15209
|
-
`event-line is horizontal-only in v1; \`direction ${dir}\` (vertical orientation) is a fast-follow.`,
|
|
15210
|
-
EVENT_LINE_DIAGNOSTIC_CODES.UNSUPPORTED
|
|
15211
|
-
);
|
|
15212
|
-
}
|
|
15213
|
-
continue;
|
|
15214
|
-
}
|
|
15215
|
-
if (tryParseSharedOption(trimmed, sharedOptions)) continue;
|
|
15216
15183
|
const eraMatch = trimmed.match(ERA_RE);
|
|
15217
15184
|
if (eraMatch) {
|
|
15218
15185
|
contentStarted = true;
|
|
15186
|
+
currentTagGroup = null;
|
|
15219
15187
|
currentEvent = null;
|
|
15220
15188
|
const name = eraMatch[1].trim();
|
|
15221
15189
|
let rest = (eraMatch[2] ?? "").trim();
|
|
@@ -15239,16 +15207,52 @@ function parseEventLine(content, palette) {
|
|
|
15239
15207
|
const era = { name, color, collapsed, lineNumber };
|
|
15240
15208
|
result.eras.push(era);
|
|
15241
15209
|
currentEra = name;
|
|
15210
|
+
eraIndent = indent;
|
|
15242
15211
|
continue;
|
|
15243
15212
|
}
|
|
15244
|
-
if (
|
|
15245
|
-
|
|
15246
|
-
|
|
15247
|
-
|
|
15248
|
-
|
|
15249
|
-
|
|
15250
|
-
|
|
15213
|
+
if (indent === 0) {
|
|
15214
|
+
currentTagGroup = null;
|
|
15215
|
+
if (trimmed.toLowerCase() === "no-scale") {
|
|
15216
|
+
options.scale = false;
|
|
15217
|
+
continue;
|
|
15218
|
+
}
|
|
15219
|
+
const sideMatch = trimmed.match(SIDE_RE);
|
|
15220
|
+
if (sideMatch) {
|
|
15221
|
+
options.side = sideMatch[1].toLowerCase();
|
|
15222
|
+
continue;
|
|
15223
|
+
}
|
|
15224
|
+
if (trimmed.toLowerCase() === "no-box") {
|
|
15225
|
+
options.noBox = true;
|
|
15226
|
+
continue;
|
|
15227
|
+
}
|
|
15228
|
+
if (trimmed.toLowerCase() === "no-legend") {
|
|
15229
|
+
options.noLegend = true;
|
|
15230
|
+
continue;
|
|
15231
|
+
}
|
|
15232
|
+
const dirMatch = trimmed.match(DIRECTION_RE);
|
|
15233
|
+
if (dirMatch) {
|
|
15234
|
+
const dir = dirMatch[1].toUpperCase();
|
|
15235
|
+
if (dir !== "LR") {
|
|
15236
|
+
pushWarning(
|
|
15237
|
+
lineNumber,
|
|
15238
|
+
`event-line is horizontal-only in v1; \`direction ${dir}\` (vertical orientation) is a fast-follow.`,
|
|
15239
|
+
EVENT_LINE_DIAGNOSTIC_CODES.UNSUPPORTED
|
|
15240
|
+
);
|
|
15241
|
+
}
|
|
15242
|
+
continue;
|
|
15243
|
+
}
|
|
15244
|
+
if (tryParseSharedOption(trimmed, sharedOptions)) continue;
|
|
15245
|
+
if (SECTION_SEAM_RE.test(trimmed)) {
|
|
15246
|
+
pushWarning(
|
|
15247
|
+
lineNumber,
|
|
15248
|
+
"Group events with `[Name]` era brackets (\xA728.6a), not `section`.",
|
|
15249
|
+
EVENT_LINE_DIAGNOSTIC_CODES.UNSUPPORTED
|
|
15250
|
+
);
|
|
15251
|
+
continue;
|
|
15252
|
+
}
|
|
15251
15253
|
}
|
|
15254
|
+
const inEra = currentEra !== null && indent > eraIndent;
|
|
15255
|
+
if (!inEra) currentEra = null;
|
|
15252
15256
|
contentStarted = true;
|
|
15253
15257
|
const event = parseEventHeader(
|
|
15254
15258
|
trimmed,
|
|
@@ -15260,6 +15264,7 @@ function parseEventLine(content, palette) {
|
|
|
15260
15264
|
);
|
|
15261
15265
|
result.events.push(event);
|
|
15262
15266
|
currentEvent = event;
|
|
15267
|
+
currentEventIndent = indent;
|
|
15263
15268
|
}
|
|
15264
15269
|
options.noTitle = sharedOptions["no-title"] === "on";
|
|
15265
15270
|
finalizeAutoTagColors(result.tagGroups, palette);
|
|
@@ -15274,8 +15279,61 @@ function parseEventLine(content, palette) {
|
|
|
15274
15279
|
EVENT_LINE_DIAGNOSTIC_CODES.NO_EVENTS
|
|
15275
15280
|
);
|
|
15276
15281
|
}
|
|
15282
|
+
if (options.scale) {
|
|
15283
|
+
validateEraDateOrder(result.events, result.eras, pushWarning);
|
|
15284
|
+
}
|
|
15277
15285
|
return result;
|
|
15278
15286
|
}
|
|
15287
|
+
function validateEraDateOrder(events, eras, pushWarning) {
|
|
15288
|
+
if (eras.length < 2) return;
|
|
15289
|
+
const order = new Map(eras.map((e, i) => [e.name, i]));
|
|
15290
|
+
const dated = events.filter(
|
|
15291
|
+
(e) => e.dateValue !== null && e.era !== null && order.has(e.era)
|
|
15292
|
+
);
|
|
15293
|
+
if (dated.length === 0) return;
|
|
15294
|
+
const perEra = /* @__PURE__ */ new Map();
|
|
15295
|
+
for (const ev of dated) {
|
|
15296
|
+
const idx = order.get(ev.era);
|
|
15297
|
+
const cur = perEra.get(idx);
|
|
15298
|
+
if (!cur) {
|
|
15299
|
+
perEra.set(idx, { min: ev, max: ev });
|
|
15300
|
+
} else {
|
|
15301
|
+
if (ev.dateValue < cur.min.dateValue) cur.min = ev;
|
|
15302
|
+
if (ev.dateValue > cur.max.dateValue) cur.max = ev;
|
|
15303
|
+
}
|
|
15304
|
+
}
|
|
15305
|
+
const n = eras.length;
|
|
15306
|
+
const prefixMax = new Array(n).fill(null);
|
|
15307
|
+
const suffixMin = new Array(n).fill(null);
|
|
15308
|
+
for (let k = 1; k < n; k++) {
|
|
15309
|
+
const prev = perEra.get(k - 1)?.max ?? null;
|
|
15310
|
+
const carried = prefixMax[k - 1] ?? null;
|
|
15311
|
+
prefixMax[k] = prev && (!carried || prev.dateValue > carried.dateValue) ? prev : carried;
|
|
15312
|
+
}
|
|
15313
|
+
for (let k = n - 2; k >= 0; k--) {
|
|
15314
|
+
const next = perEra.get(k + 1)?.min ?? null;
|
|
15315
|
+
const carried = suffixMin[k + 1] ?? null;
|
|
15316
|
+
suffixMin[k] = next && (!carried || next.dateValue < carried.dateValue) ? next : carried;
|
|
15317
|
+
}
|
|
15318
|
+
for (const ev of dated) {
|
|
15319
|
+
const k = order.get(ev.era);
|
|
15320
|
+
const ahead = suffixMin[k];
|
|
15321
|
+
const behind = prefixMax[k];
|
|
15322
|
+
if (ahead && ev.dateValue > ahead.dateValue) {
|
|
15323
|
+
pushWarning(
|
|
15324
|
+
ev.lineNumber,
|
|
15325
|
+
`"${ev.label}" (${ev.date}) is in era "${ev.era}" but dated after era "${ahead.era}" begins (${ahead.date}). event-line eras run left-to-right by date \u2014 fix the date or move it to the right era, or their brackets will overlap.`,
|
|
15326
|
+
EVENT_LINE_DIAGNOSTIC_CODES.ERA_DATE_ORDER
|
|
15327
|
+
);
|
|
15328
|
+
} else if (behind && ev.dateValue < behind.dateValue) {
|
|
15329
|
+
pushWarning(
|
|
15330
|
+
ev.lineNumber,
|
|
15331
|
+
`"${ev.label}" (${ev.date}) is in era "${ev.era}" but dated before era "${behind.era}" ends (${behind.date}). event-line eras run left-to-right by date \u2014 fix the date or move it to the right era, or their brackets will overlap.`,
|
|
15332
|
+
EVENT_LINE_DIAGNOSTIC_CODES.ERA_DATE_ORDER
|
|
15333
|
+
);
|
|
15334
|
+
}
|
|
15335
|
+
}
|
|
15336
|
+
}
|
|
15279
15337
|
function parseEventHeader(trimmed, lineNumber, era, aliasMap, diagnostics, pushWarning) {
|
|
15280
15338
|
let date = null;
|
|
15281
15339
|
let dateValue = null;
|
|
@@ -15342,7 +15400,8 @@ var init_parser13 = __esm({
|
|
|
15342
15400
|
EVENT_LINE_DIAGNOSTIC_CODES = {
|
|
15343
15401
|
NO_EVENTS: "E_EVENT_LINE_NO_EVENTS",
|
|
15344
15402
|
BAD_DATE: "E_EVENT_LINE_BAD_DATE",
|
|
15345
|
-
UNSUPPORTED: "E_EVENT_LINE_UNSUPPORTED"
|
|
15403
|
+
UNSUPPORTED: "E_EVENT_LINE_UNSUPPORTED",
|
|
15404
|
+
ERA_DATE_ORDER: "E_EVENT_LINE_ERA_DATE_ORDER"
|
|
15346
15405
|
};
|
|
15347
15406
|
NON_ISO_DATE_RE = /^\d{1,4}[/.]\d/;
|
|
15348
15407
|
SIDE_RE = /^side\s+(above|below|alternate)\b/i;
|
|
@@ -26278,9 +26337,6 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
|
|
|
26278
26337
|
const hasExpandedEra = parsed.events.some(
|
|
26279
26338
|
(e) => e.era && eraByName.has(e.era) && !collapsedSet.has(e.era)
|
|
26280
26339
|
);
|
|
26281
|
-
const anyCollapsed = parsed.events.some(
|
|
26282
|
-
(e) => e.era && collapsedSet.has(e.era)
|
|
26283
|
-
);
|
|
26284
26340
|
const sideOpt = parsed.options.side;
|
|
26285
26341
|
const alternate = sideOpt === "alternate";
|
|
26286
26342
|
const eraSide = alternate ? "below" : sideOpt === "above" ? "below" : "above";
|
|
@@ -26347,7 +26403,8 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
|
|
|
26347
26403
|
x: 0,
|
|
26348
26404
|
side,
|
|
26349
26405
|
lane: 0,
|
|
26350
|
-
left: 0
|
|
26406
|
+
left: 0,
|
|
26407
|
+
spanHalf: 0
|
|
26351
26408
|
};
|
|
26352
26409
|
}
|
|
26353
26410
|
const era = slot.era;
|
|
@@ -26360,19 +26417,19 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
|
|
|
26360
26417
|
palette.textOnFillLight,
|
|
26361
26418
|
palette.textOnFillDark
|
|
26362
26419
|
);
|
|
26363
|
-
|
|
26364
|
-
|
|
26365
|
-
const
|
|
26420
|
+
let spanLo = null;
|
|
26421
|
+
let spanHi = null;
|
|
26422
|
+
for (const m of slot.members) {
|
|
26423
|
+
if (m.dateValue === null) continue;
|
|
26424
|
+
if (spanLo === null || m.dateValue < spanLo) spanLo = m.dateValue;
|
|
26425
|
+
if (spanHi === null || m.dateValue > spanHi) spanHi = m.dateValue;
|
|
26426
|
+
}
|
|
26427
|
+
const repDateValue = spanLo !== null && spanHi !== null ? (spanLo + spanHi) / 2 : null;
|
|
26428
|
+
const memberStrs = slot.members.map(
|
|
26366
26429
|
(m) => `\u2022 ${m.date ? `${m.date} ` : ""}${m.label}`
|
|
26367
26430
|
);
|
|
26368
|
-
const bulletColors =
|
|
26431
|
+
const bulletColors = slot.members.map(eventColor);
|
|
26369
26432
|
const lines = wrapDescription(memberStrs, charsPerLine);
|
|
26370
|
-
if (overflow) {
|
|
26371
|
-
lines.push({
|
|
26372
|
-
text: `+${slot.members.length - (ERA_MEMBER_MAX - 1)} more`,
|
|
26373
|
-
kind: "plain"
|
|
26374
|
-
});
|
|
26375
|
-
}
|
|
26376
26433
|
return {
|
|
26377
26434
|
kind: "era",
|
|
26378
26435
|
event: null,
|
|
@@ -26380,7 +26437,7 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
|
|
|
26380
26437
|
members: slot.members,
|
|
26381
26438
|
label: era.name,
|
|
26382
26439
|
date: null,
|
|
26383
|
-
dateValue:
|
|
26440
|
+
dateValue: repDateValue,
|
|
26384
26441
|
lineNumber: era.lineNumber,
|
|
26385
26442
|
eraName: era.name,
|
|
26386
26443
|
color: solid,
|
|
@@ -26392,87 +26449,189 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
|
|
|
26392
26449
|
x: 0,
|
|
26393
26450
|
side,
|
|
26394
26451
|
lane: 0,
|
|
26395
|
-
left: 0
|
|
26452
|
+
left: 0,
|
|
26453
|
+
spanHalf: 0
|
|
26396
26454
|
};
|
|
26397
26455
|
});
|
|
26398
|
-
const scaled = parsed.options.scale &&
|
|
26456
|
+
const scaled = parsed.options.scale && placed.every((p) => p.dateValue !== null);
|
|
26399
26457
|
const innerW = width - H_MARGIN * 2;
|
|
26400
|
-
|
|
26401
|
-
|
|
26402
|
-
|
|
26403
|
-
|
|
26404
|
-
|
|
26405
|
-
|
|
26458
|
+
const MIN_DOT_GAP = 16;
|
|
26459
|
+
const STRETCH_CAP = 8;
|
|
26460
|
+
const COLLAPSE_W = 64;
|
|
26461
|
+
const SEG_GAP = 16;
|
|
26462
|
+
const segments = [];
|
|
26463
|
+
let run = [];
|
|
26464
|
+
const flushRun = () => {
|
|
26465
|
+
if (!run.length) return;
|
|
26466
|
+
const ds = run.map((e) => e.dateValue);
|
|
26467
|
+
segments.push({
|
|
26468
|
+
kind: "run",
|
|
26469
|
+
events: run,
|
|
26470
|
+
lo: Math.min(...ds),
|
|
26471
|
+
hi: Math.max(...ds)
|
|
26406
26472
|
});
|
|
26407
|
-
|
|
26408
|
-
|
|
26409
|
-
|
|
26410
|
-
|
|
26411
|
-
|
|
26412
|
-
|
|
26413
|
-
|
|
26473
|
+
run = [];
|
|
26474
|
+
};
|
|
26475
|
+
for (const p of placed) {
|
|
26476
|
+
if (p.kind === "era") {
|
|
26477
|
+
flushRun();
|
|
26478
|
+
segments.push({ kind: "capsule", p });
|
|
26479
|
+
} else {
|
|
26480
|
+
run.push(p);
|
|
26481
|
+
}
|
|
26482
|
+
}
|
|
26483
|
+
flushRun();
|
|
26484
|
+
const totalRunTime = segments.reduce(
|
|
26485
|
+
(s, seg) => s + (seg.kind === "run" ? seg.hi - seg.lo : 0),
|
|
26486
|
+
0
|
|
26487
|
+
);
|
|
26488
|
+
const place = (stretch) => {
|
|
26489
|
+
if (scaled) {
|
|
26490
|
+
const pxPerUnit = totalRunTime > 0 ? innerW * stretch / totalRunTime : 0;
|
|
26491
|
+
let cursor = H_MARGIN;
|
|
26492
|
+
for (const seg of segments) {
|
|
26493
|
+
if (seg.kind === "capsule") {
|
|
26494
|
+
seg.p.x = cursor + COLLAPSE_W / 2;
|
|
26495
|
+
seg.p.spanHalf = COLLAPSE_W / 2;
|
|
26496
|
+
cursor += COLLAPSE_W + SEG_GAP;
|
|
26497
|
+
} else {
|
|
26498
|
+
for (const e of seg.events) {
|
|
26499
|
+
e.x = cursor + (e.dateValue - seg.lo) * pxPerUnit;
|
|
26500
|
+
e.spanHalf = 0;
|
|
26501
|
+
}
|
|
26502
|
+
cursor += (seg.hi - seg.lo) * pxPerUnit + SEG_GAP;
|
|
26503
|
+
}
|
|
26504
|
+
}
|
|
26505
|
+
let prevX = -Infinity;
|
|
26506
|
+
let prevVal = null;
|
|
26507
|
+
for (const p of [...placed].sort((a, b) => a.x - b.x)) {
|
|
26508
|
+
if (p.kind === "era") {
|
|
26509
|
+
prevX = p.x + p.spanHalf;
|
|
26510
|
+
prevVal = null;
|
|
26511
|
+
continue;
|
|
26512
|
+
}
|
|
26513
|
+
if (p.dateValue === prevVal) {
|
|
26514
|
+
p.x = prevX;
|
|
26515
|
+
continue;
|
|
26516
|
+
}
|
|
26517
|
+
if (p.x < prevX + MIN_DOT_GAP) p.x = prevX + MIN_DOT_GAP;
|
|
26518
|
+
prevX = p.x;
|
|
26519
|
+
prevVal = p.dateValue;
|
|
26414
26520
|
}
|
|
26415
|
-
|
|
26416
|
-
|
|
26417
|
-
|
|
26521
|
+
} else {
|
|
26522
|
+
placed.forEach((p) => {
|
|
26523
|
+
p.spanHalf = 0;
|
|
26524
|
+
});
|
|
26525
|
+
const n = placed.length;
|
|
26526
|
+
const spacing = n > 1 ? Math.max(MIN_SPACING, innerW / (n - 1)) : 0;
|
|
26527
|
+
placed.forEach((p, i) => {
|
|
26528
|
+
p.x = H_MARGIN + i * spacing;
|
|
26529
|
+
});
|
|
26418
26530
|
}
|
|
26531
|
+
for (const side of ["above", "below"]) {
|
|
26532
|
+
const arr = placed.filter((p) => p.side === side).sort((a, b) => a.x - b.x);
|
|
26533
|
+
const laneRight = [];
|
|
26534
|
+
for (let i = 0; i < arr.length; i++) {
|
|
26535
|
+
const p = arr[i];
|
|
26536
|
+
const next = arr[i + 1];
|
|
26537
|
+
const crowdedRight = !!next && next.x - p.x < CARD_W + FAN_GAP;
|
|
26538
|
+
const preferred = crowdedRight ? p.x - CARD_W + CARD_INSET : p.x - CARD_W / 2;
|
|
26539
|
+
const maxLeft = p.x - CARD_INSET;
|
|
26540
|
+
const minLeft = p.x - CARD_W + CARD_INSET;
|
|
26541
|
+
let lane = laneRight.length;
|
|
26542
|
+
let left = Math.max(preferred, minLeft);
|
|
26543
|
+
for (let l = 0; l < laneRight.length; l++) {
|
|
26544
|
+
const want = Math.max(preferred, laneRight[l] + FAN_GAP, minLeft);
|
|
26545
|
+
if (want <= maxLeft) {
|
|
26546
|
+
lane = l;
|
|
26547
|
+
left = want;
|
|
26548
|
+
break;
|
|
26549
|
+
}
|
|
26550
|
+
}
|
|
26551
|
+
p.lane = lane;
|
|
26552
|
+
p.left = Math.max(6, left);
|
|
26553
|
+
laneRight[lane] = p.left + CARD_W;
|
|
26554
|
+
}
|
|
26555
|
+
}
|
|
26556
|
+
};
|
|
26557
|
+
const derive = () => {
|
|
26558
|
+
const contentW2 = Math.max(
|
|
26559
|
+
width,
|
|
26560
|
+
Math.max(...placed.map((p) => p.x + p.spanHalf)) + H_MARGIN,
|
|
26561
|
+
Math.max(...placed.map((p) => p.left + CARD_W)) + 6
|
|
26562
|
+
);
|
|
26563
|
+
const laneOffset = { above: [], below: [] };
|
|
26564
|
+
for (const side of ["above", "below"]) {
|
|
26565
|
+
const laneH = [];
|
|
26566
|
+
for (const p of placed) {
|
|
26567
|
+
if (p.side !== side) continue;
|
|
26568
|
+
laneH[p.lane] = Math.max(laneH[p.lane] ?? 0, p.cardH);
|
|
26569
|
+
}
|
|
26570
|
+
const off = [];
|
|
26571
|
+
let acc = 0;
|
|
26572
|
+
for (let l = 0; l < laneH.length; l++) {
|
|
26573
|
+
off[l] = acc;
|
|
26574
|
+
acc += (laneH[l] ?? 0) + LANE_GAP;
|
|
26575
|
+
}
|
|
26576
|
+
laneOffset[side] = off;
|
|
26577
|
+
}
|
|
26578
|
+
const laneNear2 = (p) => (p.side === "above" ? LEADER_ABOVE : LEADER_BELOW) + (laneOffset[p.side][p.lane] ?? 0);
|
|
26579
|
+
const ext = (side) => Math.max(
|
|
26580
|
+
0,
|
|
26581
|
+
...placed.filter((p) => p.side === side).map((p) => laneNear2(p) + p.cardH)
|
|
26582
|
+
);
|
|
26583
|
+
const dateAbove = placed.some((p) => p.side === "below" && p.date);
|
|
26584
|
+
const dateBelow = placed.some((p) => p.side === "above" && p.date);
|
|
26585
|
+
const contentAbove = Math.max(
|
|
26586
|
+
ext("above"),
|
|
26587
|
+
dateAbove ? DATE_OFFSET + 10 : 0
|
|
26588
|
+
);
|
|
26589
|
+
const contentBelow = Math.max(
|
|
26590
|
+
ext("below"),
|
|
26591
|
+
dateBelow ? DATE_OFFSET + 10 : 0
|
|
26592
|
+
);
|
|
26593
|
+
const aboveExt = contentAbove + (hasExpandedEra && eraSide === "above" ? ERA_BLOCK : 0);
|
|
26594
|
+
const belowExt = contentBelow + (hasExpandedEra && eraSide === "below" ? ERA_BLOCK : 0);
|
|
26595
|
+
const TOP_PAD = 14;
|
|
26596
|
+
const BOT_PAD = 14;
|
|
26597
|
+
const spineY2 = topUsed + TOP_PAD + aboveExt;
|
|
26598
|
+
const eraBaseY2 = eraSide === "above" ? spineY2 - (contentAbove + 14) : spineY2 + (contentBelow + 14);
|
|
26599
|
+
const contentH = spineY2 + belowExt + BOT_PAD;
|
|
26600
|
+
const totalH2 = Math.max(heightHint, contentH);
|
|
26601
|
+
return { contentW: contentW2, contentH, totalH: totalH2, spineY: spineY2, eraBaseY: eraBaseY2, laneNear: laneNear2 };
|
|
26602
|
+
};
|
|
26603
|
+
const envStretch = Number(
|
|
26604
|
+
globalThis.process?.env?.["DGMO_EVT_STRETCH"]
|
|
26605
|
+
);
|
|
26606
|
+
let layout;
|
|
26607
|
+
if (Number.isFinite(envStretch) && envStretch > 0) {
|
|
26608
|
+
place(envStretch);
|
|
26609
|
+
layout = derive();
|
|
26419
26610
|
} else {
|
|
26420
|
-
|
|
26421
|
-
|
|
26422
|
-
|
|
26423
|
-
|
|
26424
|
-
|
|
26425
|
-
|
|
26426
|
-
|
|
26427
|
-
|
|
26428
|
-
|
|
26429
|
-
|
|
26430
|
-
|
|
26431
|
-
|
|
26432
|
-
|
|
26433
|
-
|
|
26434
|
-
|
|
26435
|
-
|
|
26436
|
-
|
|
26437
|
-
let left = Math.max(preferred, minLeft);
|
|
26438
|
-
for (let l = 0; l < laneRight.length; l++) {
|
|
26439
|
-
const want = Math.max(preferred, laneRight[l] + FAN_GAP, minLeft);
|
|
26440
|
-
if (want <= maxLeft) {
|
|
26441
|
-
lane = l;
|
|
26442
|
-
left = want;
|
|
26443
|
-
break;
|
|
26611
|
+
place(1);
|
|
26612
|
+
layout = derive();
|
|
26613
|
+
const panelAspect = width / heightHint;
|
|
26614
|
+
const aspectOf = (l) => l.contentW / l.contentH;
|
|
26615
|
+
if (scaled && layout.contentH > heightHint && aspectOf(layout) < panelAspect) {
|
|
26616
|
+
place(STRETCH_CAP);
|
|
26617
|
+
const capped = derive();
|
|
26618
|
+
if (aspectOf(capped) <= panelAspect) {
|
|
26619
|
+
layout = capped;
|
|
26620
|
+
} else {
|
|
26621
|
+
let loF = 1;
|
|
26622
|
+
let hiF = STRETCH_CAP;
|
|
26623
|
+
for (let it = 0; it < 8; it++) {
|
|
26624
|
+
const mid = (loF + hiF) / 2;
|
|
26625
|
+
place(mid);
|
|
26626
|
+
if (aspectOf(derive()) >= panelAspect) hiF = mid;
|
|
26627
|
+
else loF = mid;
|
|
26444
26628
|
}
|
|
26629
|
+
place(hiF);
|
|
26630
|
+
layout = derive();
|
|
26445
26631
|
}
|
|
26446
|
-
p.lane = lane;
|
|
26447
|
-
p.left = Math.max(6, left);
|
|
26448
|
-
laneRight[lane] = p.left + CARD_W;
|
|
26449
26632
|
}
|
|
26450
26633
|
}
|
|
26451
|
-
const contentW =
|
|
26452
|
-
width,
|
|
26453
|
-
Math.max(...placed.map((p) => p.x)) + H_MARGIN,
|
|
26454
|
-
Math.max(...placed.map((p) => p.left + CARD_W)) + 6
|
|
26455
|
-
);
|
|
26456
|
-
const rowGap = (side) => Math.max(0, ...placed.filter((p) => p.side === side).map((p) => p.cardH)) + LANE_GAP;
|
|
26457
|
-
const rowGapA = rowGap("above");
|
|
26458
|
-
const rowGapB = rowGap("below");
|
|
26459
|
-
const ext = (side) => Math.max(
|
|
26460
|
-
0,
|
|
26461
|
-
...placed.filter((p) => p.side === side).map(
|
|
26462
|
-
(p) => (side === "above" ? LEADER_ABOVE : LEADER_BELOW) + p.lane * (side === "above" ? rowGapA : rowGapB) + p.cardH
|
|
26463
|
-
)
|
|
26464
|
-
);
|
|
26465
|
-
const dateAbove = placed.some((p) => p.side === "below" && p.date);
|
|
26466
|
-
const dateBelow = placed.some((p) => p.side === "above" && p.date);
|
|
26467
|
-
const contentAbove = Math.max(ext("above"), dateAbove ? DATE_OFFSET + 10 : 0);
|
|
26468
|
-
const contentBelow = Math.max(ext("below"), dateBelow ? DATE_OFFSET + 10 : 0);
|
|
26469
|
-
const aboveExt = contentAbove + (hasExpandedEra && eraSide === "above" ? ERA_BLOCK : 0);
|
|
26470
|
-
const belowExt = contentBelow + (hasExpandedEra && eraSide === "below" ? ERA_BLOCK : 0);
|
|
26471
|
-
const TOP_PAD = 14;
|
|
26472
|
-
const BOT_PAD = 14;
|
|
26473
|
-
const spineY = topUsed + TOP_PAD + aboveExt;
|
|
26474
|
-
const eraBaseY = eraSide === "above" ? spineY - (contentAbove + 14) : spineY + (contentBelow + 14);
|
|
26475
|
-
const totalH = Math.max(heightHint, spineY + belowExt + BOT_PAD);
|
|
26634
|
+
const { contentW, totalH, spineY, eraBaseY, laneNear } = layout;
|
|
26476
26635
|
const svg = d3Selection6.select(container).append("svg").attr("width", contentW).attr("height", totalH).attr("viewBox", `0 0 ${contentW} ${totalH}`).attr("preserveAspectRatio", "xMidYMin meet").attr("xmlns", "http://www.w3.org/2000/svg").style("font-family", FONT_FAMILY);
|
|
26477
26636
|
svg.append("rect").attr("width", contentW).attr("height", totalH).attr("fill", palette.bg);
|
|
26478
26637
|
if (showTitle) {
|
|
@@ -26500,12 +26659,11 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
|
|
|
26500
26659
|
activeGroup
|
|
26501
26660
|
});
|
|
26502
26661
|
}
|
|
26503
|
-
const
|
|
26504
|
-
const
|
|
26505
|
-
const x1 = Math.max(...xs);
|
|
26662
|
+
const x0 = Math.min(...placed.map((p) => p.x - p.spanHalf));
|
|
26663
|
+
const x1 = Math.max(...placed.map((p) => p.x + p.spanHalf));
|
|
26506
26664
|
svg.append("line").attr("x1", x0 - 20).attr("y1", spineY).attr("x2", x1 + 20).attr("y2", spineY).attr("stroke", palette.text).attr("stroke-width", 2.5).attr("stroke-linecap", "round");
|
|
26507
26665
|
const geo = placed.map((p) => {
|
|
26508
|
-
const near = p.side === "above" ? spineY -
|
|
26666
|
+
const near = p.side === "above" ? spineY - laneNear(p) : spineY + laneNear(p);
|
|
26509
26667
|
const top = p.side === "above" ? near - p.cardH : near;
|
|
26510
26668
|
return { p, near, top };
|
|
26511
26669
|
});
|
|
@@ -26617,7 +26775,7 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
|
|
|
26617
26775
|
for (const p of placed) {
|
|
26618
26776
|
if (p.kind === "era") {
|
|
26619
26777
|
const col = p.color;
|
|
26620
|
-
const half = Math.
|
|
26778
|
+
const half = Math.max(16, p.spanHalf);
|
|
26621
26779
|
const spineLeft = x0 - 20;
|
|
26622
26780
|
const spineRight = x1 + 20;
|
|
26623
26781
|
const bx0 = Math.max(spineLeft, p.x - half);
|
|
@@ -26628,6 +26786,11 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
|
|
|
26628
26786
|
"d",
|
|
26629
26787
|
`M${bx0},${spineY} L${bx0},${barY} L${bx1},${barY} L${bx1},${spineY}`
|
|
26630
26788
|
).attr("fill", "none").attr("stroke", col).attr("stroke-width", 1.5).attr("stroke-linecap", "round").attr("stroke-linejoin", "round");
|
|
26789
|
+
const breakCx = (bx0 + bx1) / 2;
|
|
26790
|
+
eg.append("line").attr("x1", breakCx - BREAK_GAP / 2).attr("y1", spineY).attr("x2", breakCx + BREAK_GAP / 2).attr("y2", spineY).attr("stroke", palette.bg).attr("stroke-width", 4).attr("stroke-linecap", "butt");
|
|
26791
|
+
for (const d of axisBreakPaths(breakCx, spineY)) {
|
|
26792
|
+
eg.append("path").attr("d", d).attr("fill", "none").attr("stroke", col).attr("stroke-width", 1.25).attr("stroke-linecap", "round").attr("stroke-linejoin", "round").attr("stroke-opacity", 0.85);
|
|
26793
|
+
}
|
|
26631
26794
|
if (onClickItem) {
|
|
26632
26795
|
const ln = p.lineNumber;
|
|
26633
26796
|
eg.style("cursor", "pointer").on("click", () => onClickItem(ln));
|
|
@@ -26661,13 +26824,23 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
|
|
|
26661
26824
|
}
|
|
26662
26825
|
const clampX = (v) => Math.max(4, Math.min(contentW - 4, v));
|
|
26663
26826
|
const cap = eraSide === "above" ? 1 : -1;
|
|
26664
|
-
|
|
26665
|
-
|
|
26827
|
+
const drawn = runs.filter((r) => !r.collapsed).map((r) => ({
|
|
26828
|
+
run: r,
|
|
26829
|
+
x0: clampX(r.firstX - ERA_BRACKET_PAD),
|
|
26830
|
+
x1: clampX(r.lastX + ERA_BRACKET_PAD)
|
|
26831
|
+
})).sort((a, b) => a.run.firstX - b.run.firstX);
|
|
26832
|
+
for (let i = 1; i < drawn.length; i++) {
|
|
26833
|
+
const prev = drawn[i - 1];
|
|
26834
|
+
const cur = drawn[i];
|
|
26835
|
+
if (prev.x1 <= cur.x0) continue;
|
|
26836
|
+
const mid = (prev.run.lastX + cur.run.firstX) / 2;
|
|
26837
|
+
prev.x1 = Math.max(prev.run.lastX, Math.min(prev.x1, mid - ERA_SEAM_GAP));
|
|
26838
|
+
cur.x0 = Math.min(cur.run.firstX, Math.max(cur.x0, mid + ERA_SEAM_GAP));
|
|
26839
|
+
}
|
|
26840
|
+
for (const { run: r, x0: x02, x1: x12 } of drawn) {
|
|
26666
26841
|
const neutral = !r.era.color;
|
|
26667
26842
|
const col = neutral ? palette.text : resolveColor(r.era.color, palette) ?? palette.text;
|
|
26668
26843
|
const op = neutral ? 0.5 : 0.85;
|
|
26669
|
-
const x02 = clampX(r.firstX - 14);
|
|
26670
|
-
const x12 = clampX(r.lastX + 14);
|
|
26671
26844
|
const y = eraBaseY;
|
|
26672
26845
|
const eg = svg.append("g").attr("data-era", r.era.name).attr("data-era-collapsed", String(r.collapsed)).attr("data-line-number", r.era.lineNumber);
|
|
26673
26846
|
eg.append("path").attr(
|
|
@@ -26693,6 +26866,22 @@ function renderEventLineForExport(container, parsed, palette, isDark, exportDims
|
|
|
26693
26866
|
tagOverride
|
|
26694
26867
|
);
|
|
26695
26868
|
}
|
|
26869
|
+
function axisBreakPaths(cx, cy) {
|
|
26870
|
+
const HUMPS = 2;
|
|
26871
|
+
const STEPS = 14;
|
|
26872
|
+
const wave = (x0) => {
|
|
26873
|
+
let d = "";
|
|
26874
|
+
for (let i = 0; i <= STEPS; i++) {
|
|
26875
|
+
const t = i / STEPS;
|
|
26876
|
+
const y = cy - BREAK_HALF_H + t * 2 * BREAK_HALF_H;
|
|
26877
|
+
const x = x0 + BREAK_AMP * Math.sin(t * Math.PI * HUMPS);
|
|
26878
|
+
d += `${i === 0 ? "M" : "L"}${x.toFixed(2)},${y.toFixed(2)}`;
|
|
26879
|
+
if (i < STEPS) d += " ";
|
|
26880
|
+
}
|
|
26881
|
+
return d;
|
|
26882
|
+
};
|
|
26883
|
+
return [wave(cx - BREAK_GAP / 2), wave(cx + BREAK_GAP / 2)];
|
|
26884
|
+
}
|
|
26696
26885
|
function wrapDescription(lines, charsPerLine) {
|
|
26697
26886
|
const out = [];
|
|
26698
26887
|
for (const line11 of lines) {
|
|
@@ -26722,7 +26911,7 @@ function renderBody(cardG, lines, bodyColor, palette, startBaseline = CARD_BODY_
|
|
|
26722
26911
|
y += DESC_LINE_H;
|
|
26723
26912
|
}
|
|
26724
26913
|
}
|
|
26725
|
-
var d3Selection6, CARD_W, H_MARGIN, TITLE_AREA, LEGEND_BAND, LEADER_ABOVE, LEADER_BELOW, DESC_FONT, DESC_LINE_H, CARD_PAD, CARD_BODY_TOP, DOT_R, MIN_SPACING, LANE_GAP, NEUTRAL_TAG, CARD_INSET, FAN_GAP, DATE_OFFSET, ERA_BLOCK, ERA_BRACKET_CAP, ERA_LEG, ERA_LABEL_FONT
|
|
26914
|
+
var d3Selection6, CARD_W, H_MARGIN, TITLE_AREA, LEGEND_BAND, LEADER_ABOVE, LEADER_BELOW, DESC_FONT, DESC_LINE_H, CARD_PAD, CARD_BODY_TOP, DOT_R, MIN_SPACING, LANE_GAP, NEUTRAL_TAG, CARD_INSET, FAN_GAP, DATE_OFFSET, ERA_BLOCK, ERA_BRACKET_CAP, ERA_BRACKET_PAD, ERA_SEAM_GAP, BREAK_HALF_H, BREAK_AMP, BREAK_GAP, ERA_LEG, ERA_LABEL_FONT;
|
|
26726
26915
|
var init_renderer = __esm({
|
|
26727
26916
|
"src/event-line/renderer.ts"() {
|
|
26728
26917
|
"use strict";
|
|
@@ -26757,9 +26946,13 @@ var init_renderer = __esm({
|
|
|
26757
26946
|
DATE_OFFSET = 28;
|
|
26758
26947
|
ERA_BLOCK = 30;
|
|
26759
26948
|
ERA_BRACKET_CAP = 8;
|
|
26949
|
+
ERA_BRACKET_PAD = 14;
|
|
26950
|
+
ERA_SEAM_GAP = 3;
|
|
26951
|
+
BREAK_HALF_H = 6;
|
|
26952
|
+
BREAK_AMP = 2.2;
|
|
26953
|
+
BREAK_GAP = 5;
|
|
26760
26954
|
ERA_LEG = 13;
|
|
26761
26955
|
ERA_LABEL_FONT = 11.5;
|
|
26762
|
-
ERA_MEMBER_MAX = 6;
|
|
26763
26956
|
}
|
|
26764
26957
|
});
|
|
26765
26958
|
|
|
@@ -26901,13 +27094,13 @@ function renderVersionControl(container, parsed, palette, isDark, onClickItem, e
|
|
|
26901
27094
|
}
|
|
26902
27095
|
const showTitle = !!parsed.title;
|
|
26903
27096
|
const titleH = showTitle ? TITLE_AREA2 : 0;
|
|
26904
|
-
const
|
|
27097
|
+
const W3 = Math.round(contentW);
|
|
26905
27098
|
const H2 = Math.round(contentH + titleH);
|
|
26906
27099
|
const exportMode = !!exportDims;
|
|
26907
|
-
const svg = d3Selection7.select(container).append("svg").attr("width",
|
|
26908
|
-
svg.append("rect").attr("width",
|
|
27100
|
+
const svg = d3Selection7.select(container).append("svg").attr("width", W3).attr("height", H2).attr("viewBox", `0 0 ${W3} ${H2}`).attr("preserveAspectRatio", "xMidYMin meet").attr("xmlns", "http://www.w3.org/2000/svg").style("font-family", FONT_FAMILY);
|
|
27101
|
+
svg.append("rect").attr("width", W3).attr("height", H2).attr("fill", palette.bg);
|
|
26909
27102
|
if (showTitle) {
|
|
26910
|
-
const t = svg.append("text").attr("class", "chart-title").attr("x",
|
|
27103
|
+
const t = svg.append("text").attr("class", "chart-title").attr("x", W3 / 2).attr("y", TITLE_Y).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-family", FONT_FAMILY).attr("font-size", TITLE_FONT_SIZE).attr("font-weight", TITLE_FONT_WEIGHT).attr("data-line-number", parsed.titleLineNumber ?? 1).text(parsed.title);
|
|
26911
27104
|
if (onClickItem && parsed.titleLineNumber && !exportMode) {
|
|
26912
27105
|
const ln = parsed.titleLineNumber;
|
|
26913
27106
|
t.style("cursor", "pointer").on("click", () => onClickItem(ln));
|
|
@@ -32689,7 +32882,7 @@ function findClearPosition(w, h, points, obstacles) {
|
|
|
32689
32882
|
}
|
|
32690
32883
|
function resolveLabelOverlaps(boxes) {
|
|
32691
32884
|
const MAX_PASSES = 8;
|
|
32692
|
-
const
|
|
32885
|
+
const PAD2 = 4;
|
|
32693
32886
|
for (let pass = 0; pass < MAX_PASSES; pass++) {
|
|
32694
32887
|
let moved = false;
|
|
32695
32888
|
for (let i = 0; i < boxes.length; i++) {
|
|
@@ -32698,8 +32891,8 @@ function resolveLabelOverlaps(boxes) {
|
|
|
32698
32891
|
const b = boxes[j];
|
|
32699
32892
|
const dx = Math.abs(a.cx - b.cx);
|
|
32700
32893
|
const dy = Math.abs(a.cy - b.cy);
|
|
32701
|
-
const overlapX = (a.w + b.w) / 2 +
|
|
32702
|
-
const overlapY = (a.h + b.h) / 2 +
|
|
32894
|
+
const overlapX = (a.w + b.w) / 2 + PAD2 - dx;
|
|
32895
|
+
const overlapY = (a.h + b.h) / 2 + PAD2 - dy;
|
|
32703
32896
|
if (overlapX > 0 && overlapY > 0) {
|
|
32704
32897
|
const shift = overlapY / 2 + 1;
|
|
32705
32898
|
if (a.cy < b.cy) {
|
|
@@ -43078,7 +43271,7 @@ function buildPathD(pts, direction) {
|
|
|
43078
43271
|
function computePortPts(edges, nodeMap, direction) {
|
|
43079
43272
|
const srcPts = /* @__PURE__ */ new Map();
|
|
43080
43273
|
const tgtPts = /* @__PURE__ */ new Map();
|
|
43081
|
-
const
|
|
43274
|
+
const PAD2 = 0.1;
|
|
43082
43275
|
const activeEdges = edges.filter((e) => e.points.length > 0);
|
|
43083
43276
|
const bySource = /* @__PURE__ */ new Map();
|
|
43084
43277
|
for (const e of activeEdges) {
|
|
@@ -43094,7 +43287,7 @@ function computePortPts(edges, nodeMap, direction) {
|
|
|
43094
43287
|
).sort((a, b) => direction === "LR" ? a.t.y - b.t.y : a.t.x - b.t.x);
|
|
43095
43288
|
const n = sorted.length;
|
|
43096
43289
|
for (let i = 0; i < n; i++) {
|
|
43097
|
-
const frac = n === 1 ? 0.5 :
|
|
43290
|
+
const frac = n === 1 ? 0.5 : PAD2 + (1 - 2 * PAD2) * i / (n - 1);
|
|
43098
43291
|
const { e, t } = sorted[i];
|
|
43099
43292
|
const isBackward = direction === "LR" ? t.x < source.x : t.y < source.y;
|
|
43100
43293
|
if (direction === "LR") {
|
|
@@ -43124,7 +43317,7 @@ function computePortPts(edges, nodeMap, direction) {
|
|
|
43124
43317
|
).sort((a, b) => direction === "LR" ? a.s.y - b.s.y : a.s.x - b.s.x);
|
|
43125
43318
|
const n = sorted.length;
|
|
43126
43319
|
for (let i = 0; i < n; i++) {
|
|
43127
|
-
const frac = n === 1 ? 0.5 :
|
|
43320
|
+
const frac = n === 1 ? 0.5 : PAD2 + (1 - 2 * PAD2) * i / (n - 1);
|
|
43128
43321
|
const { e, s } = sorted[i];
|
|
43129
43322
|
const isBackward = direction === "LR" ? target.x < s.x : target.y < s.y;
|
|
43130
43323
|
if (direction === "LR") {
|
|
@@ -52917,6 +53110,7 @@ function renderJourneyMap(container, parsed, palette, isDark, options) {
|
|
|
52917
53110
|
y,
|
|
52918
53111
|
score,
|
|
52919
53112
|
palette,
|
|
53113
|
+
isDark,
|
|
52920
53114
|
SCORE_LABEL_R
|
|
52921
53115
|
);
|
|
52922
53116
|
if (!exportDims) {
|
|
@@ -52948,7 +53142,14 @@ function renderJourneyMap(container, parsed, palette, isDark, options) {
|
|
|
52948
53142
|
const allSteps = parsed.phases.length > 0 ? parsed.phases.flatMap((p) => p.steps) : parsed.steps;
|
|
52949
53143
|
for (const pt of layout.curvePoints) {
|
|
52950
53144
|
const step = allSteps[pt.stepIndex];
|
|
52951
|
-
const faceG = renderScoreFace(
|
|
53145
|
+
const faceG = renderScoreFace(
|
|
53146
|
+
curveG,
|
|
53147
|
+
pt.x,
|
|
53148
|
+
pt.y,
|
|
53149
|
+
pt.score,
|
|
53150
|
+
palette,
|
|
53151
|
+
isDark
|
|
53152
|
+
);
|
|
52952
53153
|
addEmotionLabel(faceG, pt, palette);
|
|
52953
53154
|
if (step) {
|
|
52954
53155
|
faceG.attr("data-line-number", step.lineNumber);
|
|
@@ -52974,7 +53175,14 @@ function renderJourneyMap(container, parsed, palette, isDark, options) {
|
|
|
52974
53175
|
const pt = layout.curvePoints[0];
|
|
52975
53176
|
const allSteps = parsed.phases.length > 0 ? parsed.phases.flatMap((p) => p.steps) : parsed.steps;
|
|
52976
53177
|
const step = allSteps[pt.stepIndex];
|
|
52977
|
-
const faceG = renderScoreFace(
|
|
53178
|
+
const faceG = renderScoreFace(
|
|
53179
|
+
curveG,
|
|
53180
|
+
pt.x,
|
|
53181
|
+
pt.y,
|
|
53182
|
+
pt.score,
|
|
53183
|
+
palette,
|
|
53184
|
+
isDark
|
|
53185
|
+
);
|
|
52978
53186
|
addEmotionLabel(faceG, pt, palette);
|
|
52979
53187
|
if (step) {
|
|
52980
53188
|
faceG.attr("data-line-number", step.lineNumber);
|
|
@@ -53071,6 +53279,7 @@ function renderJourneyMap(container, parsed, palette, isDark, options) {
|
|
|
53071
53279
|
faceCy,
|
|
53072
53280
|
step.score,
|
|
53073
53281
|
palette,
|
|
53282
|
+
isDark,
|
|
53074
53283
|
COLLAPSED_FACE_R
|
|
53075
53284
|
);
|
|
53076
53285
|
faceG.attr("data-line-number", step.lineNumber);
|
|
@@ -53174,7 +53383,7 @@ function renderJourneyMap(container, parsed, palette, isDark, options) {
|
|
|
53174
53383
|
const fcy = parseFloat(el.attr("data-cy") ?? "0");
|
|
53175
53384
|
el.attr(
|
|
53176
53385
|
"transform",
|
|
53177
|
-
`translate(${fcx},${fcy}) scale(
|
|
53386
|
+
`translate(${fcx},${fcy}) scale(${FACE_HOVER_SCALE}) translate(${-fcx},${-fcy})`
|
|
53178
53387
|
);
|
|
53179
53388
|
} else {
|
|
53180
53389
|
el.attr("transform", null);
|
|
@@ -53220,12 +53429,12 @@ function renderJourneyMap(container, parsed, palette, isDark, options) {
|
|
|
53220
53429
|
PADDING2,
|
|
53221
53430
|
Math.min(fcx - bw / 2, layout.totalWidth - PADDING2 - bw)
|
|
53222
53431
|
);
|
|
53223
|
-
const by = Math.max(PADDING2, fcy -
|
|
53432
|
+
const by = Math.max(PADDING2, fcy - FACE_HOVER_R - THOUGHT_GAP - bh);
|
|
53224
53433
|
const scoreColor = scoreToColor(score, palette);
|
|
53225
53434
|
const tintedBg = mix(scoreColor, palette.surface, 20);
|
|
53226
53435
|
const g = overlayG.append("g").attr("class", "journey-thought-hover");
|
|
53227
53436
|
g.append("rect").attr("x", bx).attr("y", by).attr("width", bw).attr("height", bh).attr("rx", CARD_RADIUS).attr("fill", tintedBg).attr("stroke", scoreColor).attr("stroke-width", CARD_STROKE_WIDTH2);
|
|
53228
|
-
g.append("line").attr("x1", fcx).attr("y1", by + bh).attr("x2", fcx).attr("y2", fcy -
|
|
53437
|
+
g.append("line").attr("x1", fcx).attr("y1", by + bh).attr("x2", fcx).attr("y2", fcy - FACE_HOVER_R - 1).attr("stroke", scoreColor).attr("stroke-width", CARD_STROKE_WIDTH2);
|
|
53229
53438
|
const centerX = bx + bw / 2;
|
|
53230
53439
|
for (let i = 0; i < lines.length; i++) {
|
|
53231
53440
|
g.append("text").attr("x", centerX).attr("y", by + THOUGHT_PAD_Y + (i + 1) * THOUGHT_LINE_H - 2).attr("text-anchor", "middle").attr("font-size", THOUGHT_FONT).attr("font-style", "italic").attr("fill", palette.textMuted).text(lines[i]);
|
|
@@ -53468,24 +53677,23 @@ function renderPersonaSilhouette(parent, cx, cy, color, palette, scale = 1) {
|
|
|
53468
53677
|
`M ${cx} ${cy - 12 * s} C ${cx + 10 * s} ${cy - 12 * s}, ${cx + 9 * s} ${cy + 2 * s}, ${cx + 6 * s} ${cy + 6 * s} Q ${cx} ${cy + 9 * s}, ${cx - 6 * s} ${cy + 6 * s} C ${cx - 9 * s} ${cy + 2 * s}, ${cx - 10 * s} ${cy - 12 * s}, ${cx} ${cy - 12 * s} Z`
|
|
53469
53678
|
).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", 1.2);
|
|
53470
53679
|
}
|
|
53471
|
-
function renderScoreFace(parent, cx, cy, score, palette, radius) {
|
|
53680
|
+
function renderScoreFace(parent, cx, cy, score, palette, isDark, radius) {
|
|
53472
53681
|
const r = radius ?? FACE_RADIUS;
|
|
53473
53682
|
const color = scoreToColor(score, palette);
|
|
53474
53683
|
const g = parent.append("g").attr("class", "journey-face").attr("data-cx", cx).attr("data-cy", cy);
|
|
53475
|
-
|
|
53476
|
-
|
|
53477
|
-
|
|
53478
|
-
|
|
53479
|
-
palette.textOnFillDark
|
|
53480
|
-
);
|
|
53684
|
+
const faceFill = shapeFill(palette, color, isDark);
|
|
53685
|
+
g.append("circle").attr("cx", cx).attr("cy", cy).attr("r", r + 1).attr("fill", palette.bg);
|
|
53686
|
+
g.append("circle").attr("cx", cx).attr("cy", cy).attr("r", r).attr("fill", faceFill).attr("stroke", color).attr("stroke-width", 2);
|
|
53687
|
+
const eyeColor = color;
|
|
53481
53688
|
const eyeY = cy - r * 0.15;
|
|
53482
53689
|
const eyeSpacing = r * 0.32;
|
|
53483
53690
|
const eyeR = r * 0.12;
|
|
53484
53691
|
g.append("circle").attr("cx", cx - eyeSpacing).attr("cy", eyeY).attr("r", eyeR).attr("fill", eyeColor);
|
|
53485
53692
|
g.append("circle").attr("cx", cx + eyeSpacing).attr("cy", eyeY).attr("r", eyeR).attr("fill", eyeColor);
|
|
53486
|
-
const
|
|
53487
|
-
const
|
|
53488
|
-
const
|
|
53693
|
+
const mouthW = r * 0.46;
|
|
53694
|
+
const curve = (score - 3) / 2 * r * 0.42;
|
|
53695
|
+
const apexY = cy + r * 0.32;
|
|
53696
|
+
const mouthY = apexY - curve / 2;
|
|
53489
53697
|
g.append("path").attr(
|
|
53490
53698
|
"d",
|
|
53491
53699
|
`M ${cx - mouthW} ${mouthY} Q ${cx} ${mouthY + curve} ${cx + mouthW} ${mouthY}`
|
|
@@ -53556,7 +53764,7 @@ function renderJourneyMapForExport(content, theme, palette) {
|
|
|
53556
53764
|
}
|
|
53557
53765
|
return svgEl.outerHTML;
|
|
53558
53766
|
}
|
|
53559
|
-
var d3, d3Shape10, DIAGRAM_PADDING13, PADDING2, CARD_PADDING_X3, CARD_PADDING_Y3, CARD_HEADER_HEIGHT3, CARD_STROKE_WIDTH2, CARD_META_LINE_HEIGHT3, CARD_GAP_INTERNAL, COLUMN_RADIUS2, COLUMN_HEADER_HEIGHT2, COLUMN_PADDING3, FONT_SIZE_TITLE, FONT_SIZE_PHASE, FONT_SIZE_STEP, FONT_SIZE_META, GRID_LINE_OPACITY, CURVE_STROKE_WIDTH, FACE_RADIUS, DIM_HOVER, TITLE_LINE_HEIGHT, EMOTION_LABEL_MAX_WIDTH, EMOTION_LABEL_FONT_SIZE, ICON_THUMBS_DOWN, ICON_THUMBS_UP, ICON_THOUGHT;
|
|
53767
|
+
var d3, d3Shape10, DIAGRAM_PADDING13, PADDING2, CARD_PADDING_X3, CARD_PADDING_Y3, CARD_HEADER_HEIGHT3, CARD_STROKE_WIDTH2, CARD_META_LINE_HEIGHT3, CARD_GAP_INTERNAL, COLUMN_RADIUS2, COLUMN_HEADER_HEIGHT2, COLUMN_PADDING3, FONT_SIZE_TITLE, FONT_SIZE_PHASE, FONT_SIZE_STEP, FONT_SIZE_META, GRID_LINE_OPACITY, CURVE_STROKE_WIDTH, FACE_RADIUS, FACE_HOVER_SCALE, FACE_HOVER_R, DIM_HOVER, TITLE_LINE_HEIGHT, EMOTION_LABEL_MAX_WIDTH, EMOTION_LABEL_FONT_SIZE, ICON_THUMBS_DOWN, ICON_THUMBS_UP, ICON_THOUGHT;
|
|
53560
53768
|
var init_renderer17 = __esm({
|
|
53561
53769
|
"src/journey-map/renderer.ts"() {
|
|
53562
53770
|
"use strict";
|
|
@@ -53592,6 +53800,8 @@ var init_renderer17 = __esm({
|
|
|
53592
53800
|
GRID_LINE_OPACITY = 0.15;
|
|
53593
53801
|
CURVE_STROKE_WIDTH = 2.5;
|
|
53594
53802
|
FACE_RADIUS = 14;
|
|
53803
|
+
FACE_HOVER_SCALE = 1.5;
|
|
53804
|
+
FACE_HOVER_R = (FACE_RADIUS + 1) * FACE_HOVER_SCALE;
|
|
53595
53805
|
DIM_HOVER = 0.25;
|
|
53596
53806
|
TITLE_LINE_HEIGHT = 16;
|
|
53597
53807
|
EMOTION_LABEL_MAX_WIDTH = 180;
|
|
@@ -56630,7 +56840,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
56630
56840
|
const akRef = resolved.regions.some((r) => r.iso === "US-AK") || resolved.pois.some((p) => inAlaska(p.lon, p.lat));
|
|
56631
56841
|
const hiRef = resolved.regions.some((r) => r.iso === "US-HI") || resolved.pois.some((p) => inHawaii(p.lon, p.lat));
|
|
56632
56842
|
if (resolved.projection === "albers-usa" && usLayer && (akRef || hiRef)) {
|
|
56633
|
-
const
|
|
56843
|
+
const PAD2 = 8;
|
|
56634
56844
|
const GAP = 12;
|
|
56635
56845
|
const yB = height - FIT_PAD;
|
|
56636
56846
|
const BW = 8;
|
|
@@ -56673,22 +56883,22 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
56673
56883
|
const f = usLayer.get(iso);
|
|
56674
56884
|
if (!f) return boxX;
|
|
56675
56885
|
const x0 = boxX;
|
|
56676
|
-
const iw = Math.min(iwReq, width - FIT_PAD - x0 - 2 *
|
|
56886
|
+
const iw = Math.min(iwReq, width - FIT_PAD - x0 - 2 * PAD2);
|
|
56677
56887
|
if (iw < 24) return boxX;
|
|
56678
|
-
const xr = x0 + iw + 2 *
|
|
56888
|
+
const xr = x0 + iw + 2 * PAD2;
|
|
56679
56889
|
const floor = coastFloor(x0, xr);
|
|
56680
56890
|
const topGuess = floor > -Infinity ? floor + GAP : yB - height * 0.42;
|
|
56681
56891
|
proj.fitWidth(iw, f);
|
|
56682
56892
|
const bb = (0, import_d3_geo2.geoPath)(proj).bounds(f);
|
|
56683
56893
|
const sh = Number.isFinite(bb[0][0]) ? bb[1][1] - bb[0][1] : iw;
|
|
56684
|
-
const needH = sh + 2 *
|
|
56894
|
+
const needH = sh + 2 * PAD2;
|
|
56685
56895
|
let topFit = topGuess;
|
|
56686
56896
|
const bottom = Math.min(topFit + needH, yB);
|
|
56687
56897
|
if (bottom - topFit < needH) topFit = bottom - needH;
|
|
56688
56898
|
proj.fitExtent(
|
|
56689
56899
|
[
|
|
56690
|
-
[x0 +
|
|
56691
|
-
[xr -
|
|
56900
|
+
[x0 + PAD2, topFit + PAD2],
|
|
56901
|
+
[xr - PAD2, bottom - PAD2]
|
|
56692
56902
|
],
|
|
56693
56903
|
f
|
|
56694
56904
|
);
|
|
@@ -58212,15 +58422,15 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
58212
58422
|
}
|
|
58213
58423
|
}
|
|
58214
58424
|
if (regionLabelGuards.length > 0) {
|
|
58215
|
-
const
|
|
58425
|
+
const PAD2 = 2;
|
|
58216
58426
|
const poiRects = labels.filter((l) => l.poiId !== void 0 && l.hidden !== true).map((l) => {
|
|
58217
58427
|
const w = measureLegendText(l.text, FONT2);
|
|
58218
58428
|
const x = l.anchor === "start" ? l.x : l.anchor === "end" ? l.x - w : l.x - w / 2;
|
|
58219
58429
|
return {
|
|
58220
|
-
x: x -
|
|
58430
|
+
x: x - PAD2,
|
|
58221
58431
|
y: l.y - FONT2,
|
|
58222
|
-
w: w + 2 *
|
|
58223
|
-
h: FONT2 * 1.4 + 2 *
|
|
58432
|
+
w: w + 2 * PAD2,
|
|
58433
|
+
h: FONT2 * 1.4 + 2 * PAD2
|
|
58224
58434
|
};
|
|
58225
58435
|
});
|
|
58226
58436
|
for (const g of regionLabelGuards) {
|
|
@@ -58845,7 +59055,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
58845
59055
|
if (poiLabels.length) {
|
|
58846
59056
|
const patchBlurId = nid("dgmo-map-label-patch-blur");
|
|
58847
59057
|
defs.append("filter").attr("id", patchBlurId).attr("x", "-50%").attr("y", "-50%").attr("width", "200%").attr("height", "200%").append("feGaussianBlur").attr("in", "SourceGraphic").attr("stdDeviation", 2.5);
|
|
58848
|
-
const
|
|
59058
|
+
const PAD2 = 8;
|
|
58849
59059
|
const buildPatch = (labels, maskId, decoCluster) => {
|
|
58850
59060
|
if (!labels.length) return;
|
|
58851
59061
|
const patchMask = defs.append("mask").attr("id", maskId).attr("maskUnits", "userSpaceOnUse").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height);
|
|
@@ -58861,10 +59071,10 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
58861
59071
|
const h = th + 6;
|
|
58862
59072
|
blobs.append("rect").attr("x", cx - w / 2).attr("y", cy - h / 2).attr("width", w).attr("height", h).attr("rx", h / 2).attr("fill", "white");
|
|
58863
59073
|
blobRects.push({
|
|
58864
|
-
x0: cx - w / 2 -
|
|
58865
|
-
y0: cy - h / 2 -
|
|
58866
|
-
x1: cx + w / 2 +
|
|
58867
|
-
y1: cy + h / 2 +
|
|
59074
|
+
x0: cx - w / 2 - PAD2,
|
|
59075
|
+
y0: cy - h / 2 - PAD2,
|
|
59076
|
+
x1: cx + w / 2 + PAD2,
|
|
59077
|
+
y1: cy + h / 2 + PAD2
|
|
58868
59078
|
});
|
|
58869
59079
|
}
|
|
58870
59080
|
const gPatch = svg.append("g").attr("class", "dgmo-map-label-patch").attr("mask", `url(#${maskId})`).style("pointer-events", "none");
|
|
@@ -60282,13 +60492,13 @@ function renderTreemap(container, parsed, palette, isDark, exportDims, options =
|
|
|
60282
60492
|
g.append("text").attr("class", "dgmo-treemap-header-value").attr("x", w - ICON_RESERVE - 4).attr("y", 13).attr("text-anchor", "end").attr("font-size", 10.5).attr("fill", ink).attr("opacity", 0.75).text(valStr);
|
|
60283
60493
|
}
|
|
60284
60494
|
}
|
|
60285
|
-
const
|
|
60495
|
+
const PAD2 = Math.max(4, Math.min(14, Math.floor(Math.min(w, h) / 5)));
|
|
60286
60496
|
const MIN_FS = 7;
|
|
60287
|
-
if (!cell.isContainer && w >= 2 *
|
|
60288
|
-
const maxW = w - 2 *
|
|
60497
|
+
if (!cell.isContainer && w >= 2 * PAD2 + 8 && h >= 2 * PAD2 + 8) {
|
|
60498
|
+
const maxW = w - 2 * PAD2;
|
|
60289
60499
|
const horizMinW = measureText(cell.label, MIN_FS) * 1.06;
|
|
60290
|
-
if (horizMinW > maxW && h > w * 1.25 && h - 2 *
|
|
60291
|
-
drawVerticalLabel(g, cell.label, w, h,
|
|
60500
|
+
if (horizMinW > maxW && h > w * 1.25 && h - 2 * PAD2 > maxW) {
|
|
60501
|
+
drawVerticalLabel(g, cell.label, w, h, PAD2, ink);
|
|
60292
60502
|
if (drillable && w > 30 && h > 22) drawFocusIcon(g, w, ink, 9);
|
|
60293
60503
|
continue;
|
|
60294
60504
|
}
|
|
@@ -60299,8 +60509,8 @@ function renderTreemap(container, parsed, palette, isDark, exportDims, options =
|
|
|
60299
60509
|
const nameOpacity = 0.95 - tg * 0.5;
|
|
60300
60510
|
const vfs = clamp3(Math.round(fs * 0.42), 11, 28);
|
|
60301
60511
|
const valOpacity = Math.max(0.45, nameOpacity - 0.1);
|
|
60302
|
-
let y =
|
|
60303
|
-
g.append("text").attr("class", "dgmo-treemap-label").attr("x",
|
|
60512
|
+
let y = PAD2 + Math.round(fs * 0.78);
|
|
60513
|
+
g.append("text").attr("class", "dgmo-treemap-label").attr("x", PAD2).attr("y", y).attr("font-size", fs).attr("font-weight", 600).attr("fill", ink).attr("opacity", nameOpacity).text(clipLabel(cell.label, maxW, fs));
|
|
60304
60514
|
const valParts = [
|
|
60305
60515
|
opts.noValues ? "" : compactNumber2(cell.value),
|
|
60306
60516
|
opts.noPercent ? "" : formatPct(cell.pctOfRoot)
|
|
@@ -60308,12 +60518,12 @@ function renderTreemap(container, parsed, palette, isDark, exportDims, options =
|
|
|
60308
60518
|
const combined = valParts.join(" \xB7 ");
|
|
60309
60519
|
const nameBaseY = y;
|
|
60310
60520
|
const addLineAt = (text, yy, size, opacity) => {
|
|
60311
|
-
g.append("text").attr("class", "dgmo-treemap-value").attr("x",
|
|
60521
|
+
g.append("text").attr("class", "dgmo-treemap-value").attr("x", PAD2).attr("y", yy).attr("font-size", size).attr("fill", ink).attr("opacity", opacity).text(text);
|
|
60312
60522
|
};
|
|
60313
60523
|
if (combined) {
|
|
60314
60524
|
const fitsW = measureText(combined, vfs) <= maxW;
|
|
60315
60525
|
const valY = y + lineDrop(fs, vfs);
|
|
60316
|
-
const roomBelow = valY + descent(vfs) <= h -
|
|
60526
|
+
const roomBelow = valY + descent(vfs) <= h - PAD2;
|
|
60317
60527
|
if (fitsW && roomBelow) {
|
|
60318
60528
|
addLineAt(combined, valY, vfs, valOpacity);
|
|
60319
60529
|
} else if (fitsW) {
|
|
@@ -60321,24 +60531,24 @@ function renderTreemap(container, parsed, palette, isDark, exportDims, options =
|
|
|
60321
60531
|
const rendered = clipLabel(cell.label, maxW, fs);
|
|
60322
60532
|
const nW = measureText(rendered, fs) * 1.12;
|
|
60323
60533
|
const gap = Math.max(12, Math.round(fs * 0.25));
|
|
60324
|
-
if (
|
|
60325
|
-
g.append("text").attr("class", "dgmo-treemap-value").attr("x",
|
|
60534
|
+
if (PAD2 + nW + gap + measureText(combined, ivfs) <= w - PAD2) {
|
|
60535
|
+
g.append("text").attr("class", "dgmo-treemap-value").attr("x", PAD2 + nW + gap).attr("y", nameBaseY).attr("font-size", ivfs).attr("fill", ink).attr("opacity", valOpacity).text(combined);
|
|
60326
60536
|
}
|
|
60327
60537
|
} else if (valParts.length === 2) {
|
|
60328
60538
|
const d1 = lineDrop(fs, vfs);
|
|
60329
|
-
if (y + d1 + descent(vfs) <= h -
|
|
60539
|
+
if (y + d1 + descent(vfs) <= h - PAD2) {
|
|
60330
60540
|
y += d1;
|
|
60331
60541
|
addLineAt(valParts[0], y, vfs, valOpacity);
|
|
60332
60542
|
}
|
|
60333
60543
|
const pfs = Math.max(10, Math.round(vfs * 0.9));
|
|
60334
60544
|
const d2 = lineDrop(vfs, pfs);
|
|
60335
|
-
if (y + d2 + descent(pfs) <= h -
|
|
60545
|
+
if (y + d2 + descent(pfs) <= h - PAD2) {
|
|
60336
60546
|
y += d2;
|
|
60337
60547
|
addLineAt(valParts[1], y, pfs, valOpacity);
|
|
60338
60548
|
}
|
|
60339
60549
|
} else {
|
|
60340
60550
|
const onlyY = y + lineDrop(fs, vfs);
|
|
60341
|
-
if (onlyY + descent(vfs) <= h -
|
|
60551
|
+
if (onlyY + descent(vfs) <= h - PAD2) {
|
|
60342
60552
|
addLineAt(combined, onlyY, vfs, valOpacity);
|
|
60343
60553
|
}
|
|
60344
60554
|
}
|
|
@@ -68485,6 +68695,144 @@ function decodeDiagramUrl(hash) {
|
|
|
68485
68695
|
init_dgmo_router();
|
|
68486
68696
|
init_palettes();
|
|
68487
68697
|
init_diagnostics();
|
|
68698
|
+
|
|
68699
|
+
// src/error-card.ts
|
|
68700
|
+
init_text_measure();
|
|
68701
|
+
init_fonts();
|
|
68702
|
+
var MONO_FAMILY = "ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace";
|
|
68703
|
+
var W2 = 660;
|
|
68704
|
+
var PAD = 24;
|
|
68705
|
+
var CONTENT_W = W2 - PAD * 2;
|
|
68706
|
+
var MAX_ERRORS = 4;
|
|
68707
|
+
var MONO_CH = 0.6;
|
|
68708
|
+
var CODE_FS = 12.5;
|
|
68709
|
+
function renderErrorCard(errors, source, palette, theme) {
|
|
68710
|
+
const c = palette[theme === "dark" ? "dark" : "light"];
|
|
68711
|
+
const isTransparent = theme === "transparent";
|
|
68712
|
+
const card = c.surface;
|
|
68713
|
+
const codeBg = c.bg;
|
|
68714
|
+
const border = c.border;
|
|
68715
|
+
const danger = c.destructive ?? c.colors.red;
|
|
68716
|
+
const text = c.text;
|
|
68717
|
+
const muted = c.textMuted;
|
|
68718
|
+
const srcLines = source.split("\n");
|
|
68719
|
+
const shown = errors.slice(0, MAX_ERRORS);
|
|
68720
|
+
const overflow = errors.length - shown.length;
|
|
68721
|
+
const parts = [];
|
|
68722
|
+
let y = PAD + 8;
|
|
68723
|
+
parts.push(frownMark(PAD + 14, y + 12, danger));
|
|
68724
|
+
parts.push(
|
|
68725
|
+
`<text x="${PAD + 38}" y="${y + 11}" fill="${text}" font-family="${FONT_FAMILY}" font-size="16" font-weight="700">Couldn't render this diagram</text>`,
|
|
68726
|
+
`<text x="${W2 - PAD}" y="${y + 10}" text-anchor="end" fill="${muted}" font-family="${FONT_FAMILY}" font-size="12" font-weight="600" letter-spacing="0.5">dgmo</text>`
|
|
68727
|
+
);
|
|
68728
|
+
y += 24;
|
|
68729
|
+
const errLabel = errors.length === 1 ? "1 error" : `${errors.length} errors`;
|
|
68730
|
+
parts.push(
|
|
68731
|
+
`<text x="${PAD + 38}" y="${y + 4}" fill="${muted}" font-family="${FONT_FAMILY}" font-size="12.5">${errLabel} \u2014 fix the lines below and re-render</text>`
|
|
68732
|
+
);
|
|
68733
|
+
y += 22;
|
|
68734
|
+
parts.push(
|
|
68735
|
+
`<line x1="${PAD}" y1="${y}" x2="${W2 - PAD}" y2="${y}" stroke="${border}" stroke-width="1"/>`
|
|
68736
|
+
);
|
|
68737
|
+
y += 24;
|
|
68738
|
+
for (const e of shown) {
|
|
68739
|
+
const hasLine = e.line > 0;
|
|
68740
|
+
let msgX = PAD;
|
|
68741
|
+
if (hasLine) {
|
|
68742
|
+
const label = e.column ? `Line ${e.line}:${e.column}` : `Line ${e.line}`;
|
|
68743
|
+
const badgeW = 14 + label.length * 7;
|
|
68744
|
+
parts.push(
|
|
68745
|
+
`<rect x="${PAD}" y="${y - 13}" width="${badgeW}" height="19" rx="4" fill="${danger}"/>`,
|
|
68746
|
+
`<text x="${PAD + badgeW / 2}" y="${y + 1}" text-anchor="middle" fill="${c.bg}" font-family="${FONT_FAMILY}" font-size="11.5" font-weight="700">${escapeXml(label)}</text>`
|
|
68747
|
+
);
|
|
68748
|
+
msgX = PAD + badgeW + 12;
|
|
68749
|
+
}
|
|
68750
|
+
const lines = wrapMessage(e.message, CONTENT_W - (msgX - PAD), CONTENT_W);
|
|
68751
|
+
lines.forEach((line11, i) => {
|
|
68752
|
+
parts.push(
|
|
68753
|
+
`<text x="${i === 0 ? msgX : PAD}" y="${y + 1}" fill="${text}" font-family="${FONT_FAMILY}" font-size="13">${escapeXml(line11)}</text>`
|
|
68754
|
+
);
|
|
68755
|
+
if (i < lines.length - 1) y += 18;
|
|
68756
|
+
});
|
|
68757
|
+
y += 24;
|
|
68758
|
+
const raw = hasLine ? srcLines[e.line - 1] : void 0;
|
|
68759
|
+
if (raw !== void 0 && raw.trim().length > 0) {
|
|
68760
|
+
const gutter = `${e.line}`;
|
|
68761
|
+
const gutterW = gutter.length * CODE_FS * MONO_CH + 16;
|
|
68762
|
+
const codeX = PAD + gutterW;
|
|
68763
|
+
const codeMaxW = CONTENT_W - gutterW - 12;
|
|
68764
|
+
const codeText = truncateText(
|
|
68765
|
+
raw.replace(/\t/g, " "),
|
|
68766
|
+
CODE_FS,
|
|
68767
|
+
codeMaxW
|
|
68768
|
+
);
|
|
68769
|
+
const hasCaret = e.column !== void 0 && e.column > 0;
|
|
68770
|
+
const blockH = hasCaret ? 40 : 26;
|
|
68771
|
+
parts.push(
|
|
68772
|
+
`<rect x="${PAD}" y="${y - 14}" width="${CONTENT_W}" height="${blockH}" rx="5" fill="${codeBg}" stroke="${border}" stroke-width="1"/>`,
|
|
68773
|
+
`<line x1="${codeX - 8}" y1="${y - 14}" x2="${codeX - 8}" y2="${y - 14 + blockH}" stroke="${border}" stroke-width="1"/>`,
|
|
68774
|
+
`<text x="${PAD + 8}" y="${y + 3}" fill="${muted}" font-family="${MONO_FAMILY}" font-size="${CODE_FS}">${escapeXml(gutter)}</text>`,
|
|
68775
|
+
`<text x="${codeX}" y="${y + 3}" fill="${text}" font-family="${MONO_FAMILY}" font-size="${CODE_FS}" xml:space="preserve">${escapeXml(codeText)}</text>`
|
|
68776
|
+
);
|
|
68777
|
+
if (hasCaret) {
|
|
68778
|
+
const caretX = codeX + (e.column - 1) * CODE_FS * MONO_CH;
|
|
68779
|
+
parts.push(
|
|
68780
|
+
`<text x="${caretX}" y="${y + 17}" fill="${danger}" font-family="${MONO_FAMILY}" font-size="${CODE_FS}" font-weight="700">^</text>`
|
|
68781
|
+
);
|
|
68782
|
+
y += 14;
|
|
68783
|
+
}
|
|
68784
|
+
y += 24;
|
|
68785
|
+
}
|
|
68786
|
+
y += 14;
|
|
68787
|
+
}
|
|
68788
|
+
if (overflow > 0) {
|
|
68789
|
+
parts.push(
|
|
68790
|
+
`<text x="${PAD}" y="${y}" fill="${muted}" font-family="${FONT_FAMILY}" font-size="12.5" font-style="italic">+ ${overflow} more error${overflow === 1 ? "" : "s"}</text>`
|
|
68791
|
+
);
|
|
68792
|
+
y += 22;
|
|
68793
|
+
}
|
|
68794
|
+
const height = Math.round(y + PAD - 14);
|
|
68795
|
+
const pageBg = isTransparent ? "" : `<rect width="100%" height="100%" fill="${c.bg}"/>`;
|
|
68796
|
+
return [
|
|
68797
|
+
`<svg xmlns="http://www.w3.org/2000/svg" width="${W2}" height="${height}" viewBox="0 0 ${W2} ${height}" font-family="${FONT_FAMILY}">`,
|
|
68798
|
+
pageBg,
|
|
68799
|
+
`<rect x="0.5" y="0.5" width="${W2 - 1}" height="${height - 1}" rx="10" fill="${card}" stroke="${border}" stroke-width="1"/>`,
|
|
68800
|
+
parts.join(""),
|
|
68801
|
+
`</svg>`
|
|
68802
|
+
].join("");
|
|
68803
|
+
}
|
|
68804
|
+
function wrapMessage(message, firstWidth, fullWidth) {
|
|
68805
|
+
const words = message.split(/\s+/).filter(Boolean);
|
|
68806
|
+
if (words.length === 0) return [""];
|
|
68807
|
+
const lines = [];
|
|
68808
|
+
let cur = "";
|
|
68809
|
+
for (const word of words) {
|
|
68810
|
+
const limit = lines.length === 0 ? firstWidth : fullWidth;
|
|
68811
|
+
const test = cur ? `${cur} ${word}` : word;
|
|
68812
|
+
if (measureText(test, 13) <= limit || !cur) {
|
|
68813
|
+
cur = test;
|
|
68814
|
+
} else {
|
|
68815
|
+
lines.push(cur);
|
|
68816
|
+
cur = word;
|
|
68817
|
+
}
|
|
68818
|
+
}
|
|
68819
|
+
if (cur) lines.push(cur);
|
|
68820
|
+
return lines;
|
|
68821
|
+
}
|
|
68822
|
+
function frownMark(cx, cy, color) {
|
|
68823
|
+
const r = 12;
|
|
68824
|
+
return [
|
|
68825
|
+
`<circle cx="${cx}" cy="${cy}" r="${r}" fill="none" stroke="${color}" stroke-width="2"/>`,
|
|
68826
|
+
`<circle cx="${cx - 4.5}" cy="${cy - 3}" r="1.6" fill="${color}"/>`,
|
|
68827
|
+
`<circle cx="${cx + 4.5}" cy="${cy - 3}" r="1.6" fill="${color}"/>`,
|
|
68828
|
+
`<path d="M ${cx - 5} ${cy + 6} Q ${cx} ${cy + 1} ${cx + 5} ${cy + 6}" fill="none" stroke="${color}" stroke-width="2" stroke-linecap="round"/>`
|
|
68829
|
+
].join("");
|
|
68830
|
+
}
|
|
68831
|
+
function escapeXml(s) {
|
|
68832
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
68833
|
+
}
|
|
68834
|
+
|
|
68835
|
+
// src/index.ts
|
|
68488
68836
|
init_palettes();
|
|
68489
68837
|
|
|
68490
68838
|
// src/themes.ts
|
|
@@ -68824,25 +69172,10 @@ async function render2(text, options) {
|
|
|
68824
69172
|
return result;
|
|
68825
69173
|
}
|
|
68826
69174
|
return {
|
|
68827
|
-
svg:
|
|
69175
|
+
svg: renderErrorCard(errors, text, palette, options?.theme),
|
|
68828
69176
|
diagnostics: result.diagnostics
|
|
68829
69177
|
};
|
|
68830
69178
|
}
|
|
68831
|
-
function renderErrorSvg(errors, palette, theme) {
|
|
68832
|
-
const colors = palette[theme === "dark" ? "dark" : "light"];
|
|
68833
|
-
const bg = theme === "transparent" ? "transparent" : colors.bg;
|
|
68834
|
-
const fg = colors.destructive ?? colors.text;
|
|
68835
|
-
const muted = colors.textMuted ?? colors.text;
|
|
68836
|
-
const lines = errors.slice(0, 5).map((e) => formatDgmoError(e));
|
|
68837
|
-
const height = 60 + lines.length * 20;
|
|
68838
|
-
const body = lines.map(
|
|
68839
|
-
(line11, i) => `<text x="20" y="${60 + i * 20}" fill="${fg}" font-family="ui-monospace, monospace" font-size="12">${escapeXml(line11)}</text>`
|
|
68840
|
-
).join("");
|
|
68841
|
-
return `<svg xmlns="http://www.w3.org/2000/svg" width="640" height="${height}" viewBox="0 0 640 ${height}"><rect width="100%" height="100%" fill="${bg}"/><text x="20" y="34" fill="${muted}" font-family="system-ui, sans-serif" font-size="13" font-weight="600">DGMO parse error</text>${body}</svg>`;
|
|
68842
|
-
}
|
|
68843
|
-
function escapeXml(s) {
|
|
68844
|
-
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
68845
|
-
}
|
|
68846
69179
|
function encodeDiagramUrl2(text, options) {
|
|
68847
69180
|
const internalTheme = options?.theme === "light" || options?.theme === "dark" ? options.theme : void 0;
|
|
68848
69181
|
const result = encodeDiagramUrl(text, {
|