@diagrammo/dgmo 0.39.0 → 0.40.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 +324 -116
- package/dist/advanced.js +324 -116
- package/dist/auto.cjs +325 -117
- package/dist/auto.js +92 -92
- package/dist/auto.mjs +325 -117
- package/dist/cli.cjs +115 -115
- package/dist/index.cjs +502 -171
- package/dist/index.js +502 -171
- 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 +91 -1
- 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.js
CHANGED
|
@@ -103,7 +103,7 @@ function vennAliasKeywordRemovedMessage(args) {
|
|
|
103
103
|
return `Venn 'alias' keyword was removed. Use 'as' instead \u2014 '${args.name} as ${args.alias}'.`;
|
|
104
104
|
}
|
|
105
105
|
function pipeOperatorRemovedMessage() {
|
|
106
|
-
return `'|'
|
|
106
|
+
return `'|' is no longer metadata syntax \u2014 write metadata inline as 'key: value' (e.g. "Name color: red"), or remove the '|'.`;
|
|
107
107
|
}
|
|
108
108
|
function ganttBarePercentRemovedMessage(percent) {
|
|
109
109
|
return `Bare-percent progress shorthand '| ${percent}' was removed. Use 'progress: ${percent.replace(/%$/, "")}' (integer 0\u2013100, no '%').`;
|
|
@@ -13629,7 +13629,8 @@ function buildScatterOption(parsed, palette, isDark, textColor, axisLineColor, g
|
|
|
13629
13629
|
solid: parsed.solidFill === true
|
|
13630
13630
|
}),
|
|
13631
13631
|
borderColor: catColor,
|
|
13632
|
-
borderWidth: CHART_BORDER_WIDTH
|
|
13632
|
+
borderWidth: CHART_BORDER_WIDTH,
|
|
13633
|
+
opacity: SCATTER_FILL_OPACITY
|
|
13633
13634
|
},
|
|
13634
13635
|
label: labelConfig,
|
|
13635
13636
|
emphasis: emphasisConfig,
|
|
@@ -13656,6 +13657,7 @@ function buildScatterOption(parsed, palette, isDark, textColor, axisLineColor, g
|
|
|
13656
13657
|
{
|
|
13657
13658
|
type: "scatter",
|
|
13658
13659
|
data,
|
|
13660
|
+
itemStyle: { opacity: SCATTER_FILL_OPACITY },
|
|
13659
13661
|
label: labelConfig,
|
|
13660
13662
|
emphasis: emphasisConfig,
|
|
13661
13663
|
blur: blurConfig
|
|
@@ -14961,7 +14963,7 @@ async function renderExtendedChartForExport(content, theme, palette) {
|
|
|
14961
14963
|
chart.dispose();
|
|
14962
14964
|
}
|
|
14963
14965
|
}
|
|
14964
|
-
var 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;
|
|
14966
|
+
var 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;
|
|
14965
14967
|
var init_echarts = __esm({
|
|
14966
14968
|
"src/echarts.ts"() {
|
|
14967
14969
|
"use strict";
|
|
@@ -15015,6 +15017,7 @@ var init_echarts = __esm({
|
|
|
15015
15017
|
tooltip: { show: false }
|
|
15016
15018
|
};
|
|
15017
15019
|
CHART_BORDER_WIDTH = 2;
|
|
15020
|
+
SCATTER_FILL_OPACITY = 0.65;
|
|
15018
15021
|
VALID_EXTENDED_TYPES = /* @__PURE__ */ new Set([
|
|
15019
15022
|
"sankey",
|
|
15020
15023
|
"chord",
|
|
@@ -15290,8 +15293,61 @@ function parseEventLine(content, palette) {
|
|
|
15290
15293
|
EVENT_LINE_DIAGNOSTIC_CODES.NO_EVENTS
|
|
15291
15294
|
);
|
|
15292
15295
|
}
|
|
15296
|
+
if (options.scale) {
|
|
15297
|
+
validateEraDateOrder(result.events, result.eras, pushWarning);
|
|
15298
|
+
}
|
|
15293
15299
|
return result;
|
|
15294
15300
|
}
|
|
15301
|
+
function validateEraDateOrder(events, eras, pushWarning) {
|
|
15302
|
+
if (eras.length < 2) return;
|
|
15303
|
+
const order = new Map(eras.map((e, i) => [e.name, i]));
|
|
15304
|
+
const dated = events.filter(
|
|
15305
|
+
(e) => e.dateValue !== null && e.era !== null && order.has(e.era)
|
|
15306
|
+
);
|
|
15307
|
+
if (dated.length === 0) return;
|
|
15308
|
+
const perEra = /* @__PURE__ */ new Map();
|
|
15309
|
+
for (const ev of dated) {
|
|
15310
|
+
const idx = order.get(ev.era);
|
|
15311
|
+
const cur = perEra.get(idx);
|
|
15312
|
+
if (!cur) {
|
|
15313
|
+
perEra.set(idx, { min: ev, max: ev });
|
|
15314
|
+
} else {
|
|
15315
|
+
if (ev.dateValue < cur.min.dateValue) cur.min = ev;
|
|
15316
|
+
if (ev.dateValue > cur.max.dateValue) cur.max = ev;
|
|
15317
|
+
}
|
|
15318
|
+
}
|
|
15319
|
+
const n = eras.length;
|
|
15320
|
+
const prefixMax = new Array(n).fill(null);
|
|
15321
|
+
const suffixMin = new Array(n).fill(null);
|
|
15322
|
+
for (let k = 1; k < n; k++) {
|
|
15323
|
+
const prev = perEra.get(k - 1)?.max ?? null;
|
|
15324
|
+
const carried = prefixMax[k - 1] ?? null;
|
|
15325
|
+
prefixMax[k] = prev && (!carried || prev.dateValue > carried.dateValue) ? prev : carried;
|
|
15326
|
+
}
|
|
15327
|
+
for (let k = n - 2; k >= 0; k--) {
|
|
15328
|
+
const next = perEra.get(k + 1)?.min ?? null;
|
|
15329
|
+
const carried = suffixMin[k + 1] ?? null;
|
|
15330
|
+
suffixMin[k] = next && (!carried || next.dateValue < carried.dateValue) ? next : carried;
|
|
15331
|
+
}
|
|
15332
|
+
for (const ev of dated) {
|
|
15333
|
+
const k = order.get(ev.era);
|
|
15334
|
+
const ahead = suffixMin[k];
|
|
15335
|
+
const behind = prefixMax[k];
|
|
15336
|
+
if (ahead && ev.dateValue > ahead.dateValue) {
|
|
15337
|
+
pushWarning(
|
|
15338
|
+
ev.lineNumber,
|
|
15339
|
+
`"${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.`,
|
|
15340
|
+
EVENT_LINE_DIAGNOSTIC_CODES.ERA_DATE_ORDER
|
|
15341
|
+
);
|
|
15342
|
+
} else if (behind && ev.dateValue < behind.dateValue) {
|
|
15343
|
+
pushWarning(
|
|
15344
|
+
ev.lineNumber,
|
|
15345
|
+
`"${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.`,
|
|
15346
|
+
EVENT_LINE_DIAGNOSTIC_CODES.ERA_DATE_ORDER
|
|
15347
|
+
);
|
|
15348
|
+
}
|
|
15349
|
+
}
|
|
15350
|
+
}
|
|
15295
15351
|
function parseEventHeader(trimmed, lineNumber, era, aliasMap, diagnostics, pushWarning) {
|
|
15296
15352
|
let date = null;
|
|
15297
15353
|
let dateValue = null;
|
|
@@ -15358,7 +15414,8 @@ var init_parser13 = __esm({
|
|
|
15358
15414
|
EVENT_LINE_DIAGNOSTIC_CODES = {
|
|
15359
15415
|
NO_EVENTS: "E_EVENT_LINE_NO_EVENTS",
|
|
15360
15416
|
BAD_DATE: "E_EVENT_LINE_BAD_DATE",
|
|
15361
|
-
UNSUPPORTED: "E_EVENT_LINE_UNSUPPORTED"
|
|
15417
|
+
UNSUPPORTED: "E_EVENT_LINE_UNSUPPORTED",
|
|
15418
|
+
ERA_DATE_ORDER: "E_EVENT_LINE_ERA_DATE_ORDER"
|
|
15362
15419
|
};
|
|
15363
15420
|
NON_ISO_DATE_RE = /^\d{1,4}[/.]\d/;
|
|
15364
15421
|
SIDE_RE = /^side\s+(above|below|alternate)\b/i;
|
|
@@ -26295,9 +26352,6 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
|
|
|
26295
26352
|
const hasExpandedEra = parsed.events.some(
|
|
26296
26353
|
(e) => e.era && eraByName.has(e.era) && !collapsedSet.has(e.era)
|
|
26297
26354
|
);
|
|
26298
|
-
const anyCollapsed = parsed.events.some(
|
|
26299
|
-
(e) => e.era && collapsedSet.has(e.era)
|
|
26300
|
-
);
|
|
26301
26355
|
const sideOpt = parsed.options.side;
|
|
26302
26356
|
const alternate = sideOpt === "alternate";
|
|
26303
26357
|
const eraSide = alternate ? "below" : sideOpt === "above" ? "below" : "above";
|
|
@@ -26364,7 +26418,8 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
|
|
|
26364
26418
|
x: 0,
|
|
26365
26419
|
side,
|
|
26366
26420
|
lane: 0,
|
|
26367
|
-
left: 0
|
|
26421
|
+
left: 0,
|
|
26422
|
+
spanHalf: 0
|
|
26368
26423
|
};
|
|
26369
26424
|
}
|
|
26370
26425
|
const era = slot.era;
|
|
@@ -26377,19 +26432,19 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
|
|
|
26377
26432
|
palette.textOnFillLight,
|
|
26378
26433
|
palette.textOnFillDark
|
|
26379
26434
|
);
|
|
26380
|
-
|
|
26381
|
-
|
|
26382
|
-
const
|
|
26435
|
+
let spanLo = null;
|
|
26436
|
+
let spanHi = null;
|
|
26437
|
+
for (const m of slot.members) {
|
|
26438
|
+
if (m.dateValue === null) continue;
|
|
26439
|
+
if (spanLo === null || m.dateValue < spanLo) spanLo = m.dateValue;
|
|
26440
|
+
if (spanHi === null || m.dateValue > spanHi) spanHi = m.dateValue;
|
|
26441
|
+
}
|
|
26442
|
+
const repDateValue = spanLo !== null && spanHi !== null ? (spanLo + spanHi) / 2 : null;
|
|
26443
|
+
const memberStrs = slot.members.map(
|
|
26383
26444
|
(m) => `\u2022 ${m.date ? `${m.date} ` : ""}${m.label}`
|
|
26384
26445
|
);
|
|
26385
|
-
const bulletColors =
|
|
26446
|
+
const bulletColors = slot.members.map(eventColor);
|
|
26386
26447
|
const lines = wrapDescription(memberStrs, charsPerLine);
|
|
26387
|
-
if (overflow) {
|
|
26388
|
-
lines.push({
|
|
26389
|
-
text: `+${slot.members.length - (ERA_MEMBER_MAX - 1)} more`,
|
|
26390
|
-
kind: "plain"
|
|
26391
|
-
});
|
|
26392
|
-
}
|
|
26393
26448
|
return {
|
|
26394
26449
|
kind: "era",
|
|
26395
26450
|
event: null,
|
|
@@ -26397,7 +26452,7 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
|
|
|
26397
26452
|
members: slot.members,
|
|
26398
26453
|
label: era.name,
|
|
26399
26454
|
date: null,
|
|
26400
|
-
dateValue:
|
|
26455
|
+
dateValue: repDateValue,
|
|
26401
26456
|
lineNumber: era.lineNumber,
|
|
26402
26457
|
eraName: era.name,
|
|
26403
26458
|
color: solid,
|
|
@@ -26409,87 +26464,189 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
|
|
|
26409
26464
|
x: 0,
|
|
26410
26465
|
side,
|
|
26411
26466
|
lane: 0,
|
|
26412
|
-
left: 0
|
|
26467
|
+
left: 0,
|
|
26468
|
+
spanHalf: 0
|
|
26413
26469
|
};
|
|
26414
26470
|
});
|
|
26415
|
-
const scaled = parsed.options.scale &&
|
|
26471
|
+
const scaled = parsed.options.scale && placed.every((p) => p.dateValue !== null);
|
|
26416
26472
|
const innerW = width - H_MARGIN * 2;
|
|
26417
|
-
|
|
26418
|
-
|
|
26419
|
-
|
|
26420
|
-
|
|
26421
|
-
|
|
26422
|
-
|
|
26473
|
+
const MIN_DOT_GAP = 16;
|
|
26474
|
+
const STRETCH_CAP = 8;
|
|
26475
|
+
const COLLAPSE_W = 64;
|
|
26476
|
+
const SEG_GAP = 16;
|
|
26477
|
+
const segments = [];
|
|
26478
|
+
let run = [];
|
|
26479
|
+
const flushRun = () => {
|
|
26480
|
+
if (!run.length) return;
|
|
26481
|
+
const ds = run.map((e) => e.dateValue);
|
|
26482
|
+
segments.push({
|
|
26483
|
+
kind: "run",
|
|
26484
|
+
events: run,
|
|
26485
|
+
lo: Math.min(...ds),
|
|
26486
|
+
hi: Math.max(...ds)
|
|
26423
26487
|
});
|
|
26424
|
-
|
|
26425
|
-
|
|
26426
|
-
|
|
26427
|
-
|
|
26428
|
-
|
|
26429
|
-
|
|
26430
|
-
|
|
26488
|
+
run = [];
|
|
26489
|
+
};
|
|
26490
|
+
for (const p of placed) {
|
|
26491
|
+
if (p.kind === "era") {
|
|
26492
|
+
flushRun();
|
|
26493
|
+
segments.push({ kind: "capsule", p });
|
|
26494
|
+
} else {
|
|
26495
|
+
run.push(p);
|
|
26496
|
+
}
|
|
26497
|
+
}
|
|
26498
|
+
flushRun();
|
|
26499
|
+
const totalRunTime = segments.reduce(
|
|
26500
|
+
(s, seg) => s + (seg.kind === "run" ? seg.hi - seg.lo : 0),
|
|
26501
|
+
0
|
|
26502
|
+
);
|
|
26503
|
+
const place = (stretch) => {
|
|
26504
|
+
if (scaled) {
|
|
26505
|
+
const pxPerUnit = totalRunTime > 0 ? innerW * stretch / totalRunTime : 0;
|
|
26506
|
+
let cursor = H_MARGIN;
|
|
26507
|
+
for (const seg of segments) {
|
|
26508
|
+
if (seg.kind === "capsule") {
|
|
26509
|
+
seg.p.x = cursor + COLLAPSE_W / 2;
|
|
26510
|
+
seg.p.spanHalf = COLLAPSE_W / 2;
|
|
26511
|
+
cursor += COLLAPSE_W + SEG_GAP;
|
|
26512
|
+
} else {
|
|
26513
|
+
for (const e of seg.events) {
|
|
26514
|
+
e.x = cursor + (e.dateValue - seg.lo) * pxPerUnit;
|
|
26515
|
+
e.spanHalf = 0;
|
|
26516
|
+
}
|
|
26517
|
+
cursor += (seg.hi - seg.lo) * pxPerUnit + SEG_GAP;
|
|
26518
|
+
}
|
|
26519
|
+
}
|
|
26520
|
+
let prevX = -Infinity;
|
|
26521
|
+
let prevVal = null;
|
|
26522
|
+
for (const p of [...placed].sort((a, b) => a.x - b.x)) {
|
|
26523
|
+
if (p.kind === "era") {
|
|
26524
|
+
prevX = p.x + p.spanHalf;
|
|
26525
|
+
prevVal = null;
|
|
26526
|
+
continue;
|
|
26527
|
+
}
|
|
26528
|
+
if (p.dateValue === prevVal) {
|
|
26529
|
+
p.x = prevX;
|
|
26530
|
+
continue;
|
|
26531
|
+
}
|
|
26532
|
+
if (p.x < prevX + MIN_DOT_GAP) p.x = prevX + MIN_DOT_GAP;
|
|
26533
|
+
prevX = p.x;
|
|
26534
|
+
prevVal = p.dateValue;
|
|
26535
|
+
}
|
|
26536
|
+
} else {
|
|
26537
|
+
placed.forEach((p) => {
|
|
26538
|
+
p.spanHalf = 0;
|
|
26539
|
+
});
|
|
26540
|
+
const n = placed.length;
|
|
26541
|
+
const spacing = n > 1 ? Math.max(MIN_SPACING, innerW / (n - 1)) : 0;
|
|
26542
|
+
placed.forEach((p, i) => {
|
|
26543
|
+
p.x = H_MARGIN + i * spacing;
|
|
26544
|
+
});
|
|
26545
|
+
}
|
|
26546
|
+
for (const side of ["above", "below"]) {
|
|
26547
|
+
const arr = placed.filter((p) => p.side === side).sort((a, b) => a.x - b.x);
|
|
26548
|
+
const laneRight = [];
|
|
26549
|
+
for (let i = 0; i < arr.length; i++) {
|
|
26550
|
+
const p = arr[i];
|
|
26551
|
+
const next = arr[i + 1];
|
|
26552
|
+
const crowdedRight = !!next && next.x - p.x < CARD_W + FAN_GAP;
|
|
26553
|
+
const preferred = crowdedRight ? p.x - CARD_W + CARD_INSET : p.x - CARD_W / 2;
|
|
26554
|
+
const maxLeft = p.x - CARD_INSET;
|
|
26555
|
+
const minLeft = p.x - CARD_W + CARD_INSET;
|
|
26556
|
+
let lane = laneRight.length;
|
|
26557
|
+
let left = Math.max(preferred, minLeft);
|
|
26558
|
+
for (let l = 0; l < laneRight.length; l++) {
|
|
26559
|
+
const want = Math.max(preferred, laneRight[l] + FAN_GAP, minLeft);
|
|
26560
|
+
if (want <= maxLeft) {
|
|
26561
|
+
lane = l;
|
|
26562
|
+
left = want;
|
|
26563
|
+
break;
|
|
26564
|
+
}
|
|
26565
|
+
}
|
|
26566
|
+
p.lane = lane;
|
|
26567
|
+
p.left = Math.max(6, left);
|
|
26568
|
+
laneRight[lane] = p.left + CARD_W;
|
|
26569
|
+
}
|
|
26570
|
+
}
|
|
26571
|
+
};
|
|
26572
|
+
const derive = () => {
|
|
26573
|
+
const contentW2 = Math.max(
|
|
26574
|
+
width,
|
|
26575
|
+
Math.max(...placed.map((p) => p.x + p.spanHalf)) + H_MARGIN,
|
|
26576
|
+
Math.max(...placed.map((p) => p.left + CARD_W)) + 6
|
|
26577
|
+
);
|
|
26578
|
+
const laneOffset = { above: [], below: [] };
|
|
26579
|
+
for (const side of ["above", "below"]) {
|
|
26580
|
+
const laneH = [];
|
|
26581
|
+
for (const p of placed) {
|
|
26582
|
+
if (p.side !== side) continue;
|
|
26583
|
+
laneH[p.lane] = Math.max(laneH[p.lane] ?? 0, p.cardH);
|
|
26584
|
+
}
|
|
26585
|
+
const off = [];
|
|
26586
|
+
let acc = 0;
|
|
26587
|
+
for (let l = 0; l < laneH.length; l++) {
|
|
26588
|
+
off[l] = acc;
|
|
26589
|
+
acc += (laneH[l] ?? 0) + LANE_GAP;
|
|
26431
26590
|
}
|
|
26432
|
-
|
|
26433
|
-
prevX = p.x;
|
|
26434
|
-
prevVal = p.dateValue;
|
|
26591
|
+
laneOffset[side] = off;
|
|
26435
26592
|
}
|
|
26593
|
+
const laneNear2 = (p) => (p.side === "above" ? LEADER_ABOVE : LEADER_BELOW) + (laneOffset[p.side][p.lane] ?? 0);
|
|
26594
|
+
const ext = (side) => Math.max(
|
|
26595
|
+
0,
|
|
26596
|
+
...placed.filter((p) => p.side === side).map((p) => laneNear2(p) + p.cardH)
|
|
26597
|
+
);
|
|
26598
|
+
const dateAbove = placed.some((p) => p.side === "below" && p.date);
|
|
26599
|
+
const dateBelow = placed.some((p) => p.side === "above" && p.date);
|
|
26600
|
+
const contentAbove = Math.max(
|
|
26601
|
+
ext("above"),
|
|
26602
|
+
dateAbove ? DATE_OFFSET + 10 : 0
|
|
26603
|
+
);
|
|
26604
|
+
const contentBelow = Math.max(
|
|
26605
|
+
ext("below"),
|
|
26606
|
+
dateBelow ? DATE_OFFSET + 10 : 0
|
|
26607
|
+
);
|
|
26608
|
+
const aboveExt = contentAbove + (hasExpandedEra && eraSide === "above" ? ERA_BLOCK : 0);
|
|
26609
|
+
const belowExt = contentBelow + (hasExpandedEra && eraSide === "below" ? ERA_BLOCK : 0);
|
|
26610
|
+
const TOP_PAD = 14;
|
|
26611
|
+
const BOT_PAD = 14;
|
|
26612
|
+
const spineY2 = topUsed + TOP_PAD + aboveExt;
|
|
26613
|
+
const eraBaseY2 = eraSide === "above" ? spineY2 - (contentAbove + 14) : spineY2 + (contentBelow + 14);
|
|
26614
|
+
const contentH = spineY2 + belowExt + BOT_PAD;
|
|
26615
|
+
const totalH2 = Math.max(heightHint, contentH);
|
|
26616
|
+
return { contentW: contentW2, contentH, totalH: totalH2, spineY: spineY2, eraBaseY: eraBaseY2, laneNear: laneNear2 };
|
|
26617
|
+
};
|
|
26618
|
+
const envStretch = Number(
|
|
26619
|
+
globalThis.process?.env?.["DGMO_EVT_STRETCH"]
|
|
26620
|
+
);
|
|
26621
|
+
let layout;
|
|
26622
|
+
if (Number.isFinite(envStretch) && envStretch > 0) {
|
|
26623
|
+
place(envStretch);
|
|
26624
|
+
layout = derive();
|
|
26436
26625
|
} else {
|
|
26437
|
-
|
|
26438
|
-
|
|
26439
|
-
|
|
26440
|
-
|
|
26441
|
-
|
|
26442
|
-
|
|
26443
|
-
|
|
26444
|
-
|
|
26445
|
-
|
|
26446
|
-
|
|
26447
|
-
|
|
26448
|
-
|
|
26449
|
-
|
|
26450
|
-
|
|
26451
|
-
|
|
26452
|
-
|
|
26453
|
-
|
|
26454
|
-
let left = Math.max(preferred, minLeft);
|
|
26455
|
-
for (let l = 0; l < laneRight.length; l++) {
|
|
26456
|
-
const want = Math.max(preferred, laneRight[l] + FAN_GAP, minLeft);
|
|
26457
|
-
if (want <= maxLeft) {
|
|
26458
|
-
lane = l;
|
|
26459
|
-
left = want;
|
|
26460
|
-
break;
|
|
26626
|
+
place(1);
|
|
26627
|
+
layout = derive();
|
|
26628
|
+
const panelAspect = width / heightHint;
|
|
26629
|
+
const aspectOf = (l) => l.contentW / l.contentH;
|
|
26630
|
+
if (scaled && layout.contentH > heightHint && aspectOf(layout) < panelAspect) {
|
|
26631
|
+
place(STRETCH_CAP);
|
|
26632
|
+
const capped = derive();
|
|
26633
|
+
if (aspectOf(capped) <= panelAspect) {
|
|
26634
|
+
layout = capped;
|
|
26635
|
+
} else {
|
|
26636
|
+
let loF = 1;
|
|
26637
|
+
let hiF = STRETCH_CAP;
|
|
26638
|
+
for (let it = 0; it < 8; it++) {
|
|
26639
|
+
const mid = (loF + hiF) / 2;
|
|
26640
|
+
place(mid);
|
|
26641
|
+
if (aspectOf(derive()) >= panelAspect) hiF = mid;
|
|
26642
|
+
else loF = mid;
|
|
26461
26643
|
}
|
|
26644
|
+
place(hiF);
|
|
26645
|
+
layout = derive();
|
|
26462
26646
|
}
|
|
26463
|
-
p.lane = lane;
|
|
26464
|
-
p.left = Math.max(6, left);
|
|
26465
|
-
laneRight[lane] = p.left + CARD_W;
|
|
26466
26647
|
}
|
|
26467
26648
|
}
|
|
26468
|
-
const contentW =
|
|
26469
|
-
width,
|
|
26470
|
-
Math.max(...placed.map((p) => p.x)) + H_MARGIN,
|
|
26471
|
-
Math.max(...placed.map((p) => p.left + CARD_W)) + 6
|
|
26472
|
-
);
|
|
26473
|
-
const rowGap = (side) => Math.max(0, ...placed.filter((p) => p.side === side).map((p) => p.cardH)) + LANE_GAP;
|
|
26474
|
-
const rowGapA = rowGap("above");
|
|
26475
|
-
const rowGapB = rowGap("below");
|
|
26476
|
-
const ext = (side) => Math.max(
|
|
26477
|
-
0,
|
|
26478
|
-
...placed.filter((p) => p.side === side).map(
|
|
26479
|
-
(p) => (side === "above" ? LEADER_ABOVE : LEADER_BELOW) + p.lane * (side === "above" ? rowGapA : rowGapB) + p.cardH
|
|
26480
|
-
)
|
|
26481
|
-
);
|
|
26482
|
-
const dateAbove = placed.some((p) => p.side === "below" && p.date);
|
|
26483
|
-
const dateBelow = placed.some((p) => p.side === "above" && p.date);
|
|
26484
|
-
const contentAbove = Math.max(ext("above"), dateAbove ? DATE_OFFSET + 10 : 0);
|
|
26485
|
-
const contentBelow = Math.max(ext("below"), dateBelow ? DATE_OFFSET + 10 : 0);
|
|
26486
|
-
const aboveExt = contentAbove + (hasExpandedEra && eraSide === "above" ? ERA_BLOCK : 0);
|
|
26487
|
-
const belowExt = contentBelow + (hasExpandedEra && eraSide === "below" ? ERA_BLOCK : 0);
|
|
26488
|
-
const TOP_PAD = 14;
|
|
26489
|
-
const BOT_PAD = 14;
|
|
26490
|
-
const spineY = topUsed + TOP_PAD + aboveExt;
|
|
26491
|
-
const eraBaseY = eraSide === "above" ? spineY - (contentAbove + 14) : spineY + (contentBelow + 14);
|
|
26492
|
-
const totalH = Math.max(heightHint, spineY + belowExt + BOT_PAD);
|
|
26649
|
+
const { contentW, totalH, spineY, eraBaseY, laneNear } = layout;
|
|
26493
26650
|
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);
|
|
26494
26651
|
svg.append("rect").attr("width", contentW).attr("height", totalH).attr("fill", palette.bg);
|
|
26495
26652
|
if (showTitle) {
|
|
@@ -26517,12 +26674,11 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
|
|
|
26517
26674
|
activeGroup
|
|
26518
26675
|
});
|
|
26519
26676
|
}
|
|
26520
|
-
const
|
|
26521
|
-
const
|
|
26522
|
-
const x1 = Math.max(...xs);
|
|
26677
|
+
const x0 = Math.min(...placed.map((p) => p.x - p.spanHalf));
|
|
26678
|
+
const x1 = Math.max(...placed.map((p) => p.x + p.spanHalf));
|
|
26523
26679
|
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");
|
|
26524
26680
|
const geo = placed.map((p) => {
|
|
26525
|
-
const near = p.side === "above" ? spineY -
|
|
26681
|
+
const near = p.side === "above" ? spineY - laneNear(p) : spineY + laneNear(p);
|
|
26526
26682
|
const top = p.side === "above" ? near - p.cardH : near;
|
|
26527
26683
|
return { p, near, top };
|
|
26528
26684
|
});
|
|
@@ -26634,7 +26790,7 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
|
|
|
26634
26790
|
for (const p of placed) {
|
|
26635
26791
|
if (p.kind === "era") {
|
|
26636
26792
|
const col = p.color;
|
|
26637
|
-
const half = Math.
|
|
26793
|
+
const half = Math.max(16, p.spanHalf);
|
|
26638
26794
|
const spineLeft = x0 - 20;
|
|
26639
26795
|
const spineRight = x1 + 20;
|
|
26640
26796
|
const bx0 = Math.max(spineLeft, p.x - half);
|
|
@@ -26645,6 +26801,11 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
|
|
|
26645
26801
|
"d",
|
|
26646
26802
|
`M${bx0},${spineY} L${bx0},${barY} L${bx1},${barY} L${bx1},${spineY}`
|
|
26647
26803
|
).attr("fill", "none").attr("stroke", col).attr("stroke-width", 1.5).attr("stroke-linecap", "round").attr("stroke-linejoin", "round");
|
|
26804
|
+
const breakCx = (bx0 + bx1) / 2;
|
|
26805
|
+
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");
|
|
26806
|
+
for (const d of axisBreakPaths(breakCx, spineY)) {
|
|
26807
|
+
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);
|
|
26808
|
+
}
|
|
26648
26809
|
if (onClickItem) {
|
|
26649
26810
|
const ln = p.lineNumber;
|
|
26650
26811
|
eg.style("cursor", "pointer").on("click", () => onClickItem(ln));
|
|
@@ -26678,13 +26839,23 @@ function renderEventLine(container, parsed, palette, isDark, onClickItem, export
|
|
|
26678
26839
|
}
|
|
26679
26840
|
const clampX = (v) => Math.max(4, Math.min(contentW - 4, v));
|
|
26680
26841
|
const cap = eraSide === "above" ? 1 : -1;
|
|
26681
|
-
|
|
26682
|
-
|
|
26842
|
+
const drawn = runs.filter((r) => !r.collapsed).map((r) => ({
|
|
26843
|
+
run: r,
|
|
26844
|
+
x0: clampX(r.firstX - ERA_BRACKET_PAD),
|
|
26845
|
+
x1: clampX(r.lastX + ERA_BRACKET_PAD)
|
|
26846
|
+
})).sort((a, b) => a.run.firstX - b.run.firstX);
|
|
26847
|
+
for (let i = 1; i < drawn.length; i++) {
|
|
26848
|
+
const prev = drawn[i - 1];
|
|
26849
|
+
const cur = drawn[i];
|
|
26850
|
+
if (prev.x1 <= cur.x0) continue;
|
|
26851
|
+
const mid = (prev.run.lastX + cur.run.firstX) / 2;
|
|
26852
|
+
prev.x1 = Math.max(prev.run.lastX, Math.min(prev.x1, mid - ERA_SEAM_GAP));
|
|
26853
|
+
cur.x0 = Math.min(cur.run.firstX, Math.max(cur.x0, mid + ERA_SEAM_GAP));
|
|
26854
|
+
}
|
|
26855
|
+
for (const { run: r, x0: x02, x1: x12 } of drawn) {
|
|
26683
26856
|
const neutral = !r.era.color;
|
|
26684
26857
|
const col = neutral ? palette.text : resolveColor(r.era.color, palette) ?? palette.text;
|
|
26685
26858
|
const op = neutral ? 0.5 : 0.85;
|
|
26686
|
-
const x02 = clampX(r.firstX - 14);
|
|
26687
|
-
const x12 = clampX(r.lastX + 14);
|
|
26688
26859
|
const y = eraBaseY;
|
|
26689
26860
|
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);
|
|
26690
26861
|
eg.append("path").attr(
|
|
@@ -26710,6 +26881,22 @@ function renderEventLineForExport(container, parsed, palette, isDark, exportDims
|
|
|
26710
26881
|
tagOverride
|
|
26711
26882
|
);
|
|
26712
26883
|
}
|
|
26884
|
+
function axisBreakPaths(cx, cy) {
|
|
26885
|
+
const HUMPS = 2;
|
|
26886
|
+
const STEPS = 14;
|
|
26887
|
+
const wave = (x0) => {
|
|
26888
|
+
let d = "";
|
|
26889
|
+
for (let i = 0; i <= STEPS; i++) {
|
|
26890
|
+
const t = i / STEPS;
|
|
26891
|
+
const y = cy - BREAK_HALF_H + t * 2 * BREAK_HALF_H;
|
|
26892
|
+
const x = x0 + BREAK_AMP * Math.sin(t * Math.PI * HUMPS);
|
|
26893
|
+
d += `${i === 0 ? "M" : "L"}${x.toFixed(2)},${y.toFixed(2)}`;
|
|
26894
|
+
if (i < STEPS) d += " ";
|
|
26895
|
+
}
|
|
26896
|
+
return d;
|
|
26897
|
+
};
|
|
26898
|
+
return [wave(cx - BREAK_GAP / 2), wave(cx + BREAK_GAP / 2)];
|
|
26899
|
+
}
|
|
26713
26900
|
function wrapDescription(lines, charsPerLine) {
|
|
26714
26901
|
const out = [];
|
|
26715
26902
|
for (const line11 of lines) {
|
|
@@ -26739,7 +26926,7 @@ function renderBody(cardG, lines, bodyColor, palette, startBaseline = CARD_BODY_
|
|
|
26739
26926
|
y += DESC_LINE_H;
|
|
26740
26927
|
}
|
|
26741
26928
|
}
|
|
26742
|
-
var 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
|
|
26929
|
+
var 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;
|
|
26743
26930
|
var init_renderer = __esm({
|
|
26744
26931
|
"src/event-line/renderer.ts"() {
|
|
26745
26932
|
"use strict";
|
|
@@ -26773,9 +26960,13 @@ var init_renderer = __esm({
|
|
|
26773
26960
|
DATE_OFFSET = 28;
|
|
26774
26961
|
ERA_BLOCK = 30;
|
|
26775
26962
|
ERA_BRACKET_CAP = 8;
|
|
26963
|
+
ERA_BRACKET_PAD = 14;
|
|
26964
|
+
ERA_SEAM_GAP = 3;
|
|
26965
|
+
BREAK_HALF_H = 6;
|
|
26966
|
+
BREAK_AMP = 2.2;
|
|
26967
|
+
BREAK_GAP = 5;
|
|
26776
26968
|
ERA_LEG = 13;
|
|
26777
26969
|
ERA_LABEL_FONT = 11.5;
|
|
26778
|
-
ERA_MEMBER_MAX = 6;
|
|
26779
26970
|
}
|
|
26780
26971
|
});
|
|
26781
26972
|
|
|
@@ -26918,13 +27109,13 @@ function renderVersionControl(container, parsed, palette, isDark, onClickItem, e
|
|
|
26918
27109
|
}
|
|
26919
27110
|
const showTitle = !!parsed.title;
|
|
26920
27111
|
const titleH = showTitle ? TITLE_AREA2 : 0;
|
|
26921
|
-
const
|
|
27112
|
+
const W3 = Math.round(contentW);
|
|
26922
27113
|
const H2 = Math.round(contentH + titleH);
|
|
26923
27114
|
const exportMode = !!exportDims;
|
|
26924
|
-
const svg = d3Selection7.select(container).append("svg").attr("width",
|
|
26925
|
-
svg.append("rect").attr("width",
|
|
27115
|
+
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);
|
|
27116
|
+
svg.append("rect").attr("width", W3).attr("height", H2).attr("fill", palette.bg);
|
|
26926
27117
|
if (showTitle) {
|
|
26927
|
-
const t = svg.append("text").attr("class", "chart-title").attr("x",
|
|
27118
|
+
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);
|
|
26928
27119
|
if (onClickItem && parsed.titleLineNumber && !exportMode) {
|
|
26929
27120
|
const ln = parsed.titleLineNumber;
|
|
26930
27121
|
t.style("cursor", "pointer").on("click", () => onClickItem(ln));
|
|
@@ -32705,7 +32896,7 @@ function findClearPosition(w, h, points, obstacles) {
|
|
|
32705
32896
|
}
|
|
32706
32897
|
function resolveLabelOverlaps(boxes) {
|
|
32707
32898
|
const MAX_PASSES = 8;
|
|
32708
|
-
const
|
|
32899
|
+
const PAD2 = 4;
|
|
32709
32900
|
for (let pass = 0; pass < MAX_PASSES; pass++) {
|
|
32710
32901
|
let moved = false;
|
|
32711
32902
|
for (let i = 0; i < boxes.length; i++) {
|
|
@@ -32714,8 +32905,8 @@ function resolveLabelOverlaps(boxes) {
|
|
|
32714
32905
|
const b = boxes[j];
|
|
32715
32906
|
const dx = Math.abs(a.cx - b.cx);
|
|
32716
32907
|
const dy = Math.abs(a.cy - b.cy);
|
|
32717
|
-
const overlapX = (a.w + b.w) / 2 +
|
|
32718
|
-
const overlapY = (a.h + b.h) / 2 +
|
|
32908
|
+
const overlapX = (a.w + b.w) / 2 + PAD2 - dx;
|
|
32909
|
+
const overlapY = (a.h + b.h) / 2 + PAD2 - dy;
|
|
32719
32910
|
if (overlapX > 0 && overlapY > 0) {
|
|
32720
32911
|
const shift = overlapY / 2 + 1;
|
|
32721
32912
|
if (a.cy < b.cy) {
|
|
@@ -43096,7 +43287,7 @@ function buildPathD(pts, direction) {
|
|
|
43096
43287
|
function computePortPts(edges, nodeMap, direction) {
|
|
43097
43288
|
const srcPts = /* @__PURE__ */ new Map();
|
|
43098
43289
|
const tgtPts = /* @__PURE__ */ new Map();
|
|
43099
|
-
const
|
|
43290
|
+
const PAD2 = 0.1;
|
|
43100
43291
|
const activeEdges = edges.filter((e) => e.points.length > 0);
|
|
43101
43292
|
const bySource = /* @__PURE__ */ new Map();
|
|
43102
43293
|
for (const e of activeEdges) {
|
|
@@ -43112,7 +43303,7 @@ function computePortPts(edges, nodeMap, direction) {
|
|
|
43112
43303
|
).sort((a, b) => direction === "LR" ? a.t.y - b.t.y : a.t.x - b.t.x);
|
|
43113
43304
|
const n = sorted.length;
|
|
43114
43305
|
for (let i = 0; i < n; i++) {
|
|
43115
|
-
const frac = n === 1 ? 0.5 :
|
|
43306
|
+
const frac = n === 1 ? 0.5 : PAD2 + (1 - 2 * PAD2) * i / (n - 1);
|
|
43116
43307
|
const { e, t } = sorted[i];
|
|
43117
43308
|
const isBackward = direction === "LR" ? t.x < source.x : t.y < source.y;
|
|
43118
43309
|
if (direction === "LR") {
|
|
@@ -43142,7 +43333,7 @@ function computePortPts(edges, nodeMap, direction) {
|
|
|
43142
43333
|
).sort((a, b) => direction === "LR" ? a.s.y - b.s.y : a.s.x - b.s.x);
|
|
43143
43334
|
const n = sorted.length;
|
|
43144
43335
|
for (let i = 0; i < n; i++) {
|
|
43145
|
-
const frac = n === 1 ? 0.5 :
|
|
43336
|
+
const frac = n === 1 ? 0.5 : PAD2 + (1 - 2 * PAD2) * i / (n - 1);
|
|
43146
43337
|
const { e, s } = sorted[i];
|
|
43147
43338
|
const isBackward = direction === "LR" ? target.x < s.x : target.y < s.y;
|
|
43148
43339
|
if (direction === "LR") {
|
|
@@ -52935,6 +53126,7 @@ function renderJourneyMap(container, parsed, palette, isDark, options) {
|
|
|
52935
53126
|
y,
|
|
52936
53127
|
score,
|
|
52937
53128
|
palette,
|
|
53129
|
+
isDark,
|
|
52938
53130
|
SCORE_LABEL_R
|
|
52939
53131
|
);
|
|
52940
53132
|
if (!exportDims) {
|
|
@@ -52966,7 +53158,14 @@ function renderJourneyMap(container, parsed, palette, isDark, options) {
|
|
|
52966
53158
|
const allSteps = parsed.phases.length > 0 ? parsed.phases.flatMap((p) => p.steps) : parsed.steps;
|
|
52967
53159
|
for (const pt of layout.curvePoints) {
|
|
52968
53160
|
const step = allSteps[pt.stepIndex];
|
|
52969
|
-
const faceG = renderScoreFace(
|
|
53161
|
+
const faceG = renderScoreFace(
|
|
53162
|
+
curveG,
|
|
53163
|
+
pt.x,
|
|
53164
|
+
pt.y,
|
|
53165
|
+
pt.score,
|
|
53166
|
+
palette,
|
|
53167
|
+
isDark
|
|
53168
|
+
);
|
|
52970
53169
|
addEmotionLabel(faceG, pt, palette);
|
|
52971
53170
|
if (step) {
|
|
52972
53171
|
faceG.attr("data-line-number", step.lineNumber);
|
|
@@ -52992,7 +53191,14 @@ function renderJourneyMap(container, parsed, palette, isDark, options) {
|
|
|
52992
53191
|
const pt = layout.curvePoints[0];
|
|
52993
53192
|
const allSteps = parsed.phases.length > 0 ? parsed.phases.flatMap((p) => p.steps) : parsed.steps;
|
|
52994
53193
|
const step = allSteps[pt.stepIndex];
|
|
52995
|
-
const faceG = renderScoreFace(
|
|
53194
|
+
const faceG = renderScoreFace(
|
|
53195
|
+
curveG,
|
|
53196
|
+
pt.x,
|
|
53197
|
+
pt.y,
|
|
53198
|
+
pt.score,
|
|
53199
|
+
palette,
|
|
53200
|
+
isDark
|
|
53201
|
+
);
|
|
52996
53202
|
addEmotionLabel(faceG, pt, palette);
|
|
52997
53203
|
if (step) {
|
|
52998
53204
|
faceG.attr("data-line-number", step.lineNumber);
|
|
@@ -53089,6 +53295,7 @@ function renderJourneyMap(container, parsed, palette, isDark, options) {
|
|
|
53089
53295
|
faceCy,
|
|
53090
53296
|
step.score,
|
|
53091
53297
|
palette,
|
|
53298
|
+
isDark,
|
|
53092
53299
|
COLLAPSED_FACE_R
|
|
53093
53300
|
);
|
|
53094
53301
|
faceG.attr("data-line-number", step.lineNumber);
|
|
@@ -53192,7 +53399,7 @@ function renderJourneyMap(container, parsed, palette, isDark, options) {
|
|
|
53192
53399
|
const fcy = parseFloat(el.attr("data-cy") ?? "0");
|
|
53193
53400
|
el.attr(
|
|
53194
53401
|
"transform",
|
|
53195
|
-
`translate(${fcx},${fcy}) scale(
|
|
53402
|
+
`translate(${fcx},${fcy}) scale(${FACE_HOVER_SCALE}) translate(${-fcx},${-fcy})`
|
|
53196
53403
|
);
|
|
53197
53404
|
} else {
|
|
53198
53405
|
el.attr("transform", null);
|
|
@@ -53238,12 +53445,12 @@ function renderJourneyMap(container, parsed, palette, isDark, options) {
|
|
|
53238
53445
|
PADDING2,
|
|
53239
53446
|
Math.min(fcx - bw / 2, layout.totalWidth - PADDING2 - bw)
|
|
53240
53447
|
);
|
|
53241
|
-
const by = Math.max(PADDING2, fcy -
|
|
53448
|
+
const by = Math.max(PADDING2, fcy - FACE_HOVER_R - THOUGHT_GAP - bh);
|
|
53242
53449
|
const scoreColor = scoreToColor(score, palette);
|
|
53243
53450
|
const tintedBg = mix(scoreColor, palette.surface, 20);
|
|
53244
53451
|
const g = overlayG.append("g").attr("class", "journey-thought-hover");
|
|
53245
53452
|
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);
|
|
53246
|
-
g.append("line").attr("x1", fcx).attr("y1", by + bh).attr("x2", fcx).attr("y2", fcy -
|
|
53453
|
+
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);
|
|
53247
53454
|
const centerX = bx + bw / 2;
|
|
53248
53455
|
for (let i = 0; i < lines.length; i++) {
|
|
53249
53456
|
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]);
|
|
@@ -53486,24 +53693,23 @@ function renderPersonaSilhouette(parent, cx, cy, color, palette, scale = 1) {
|
|
|
53486
53693
|
`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`
|
|
53487
53694
|
).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", 1.2);
|
|
53488
53695
|
}
|
|
53489
|
-
function renderScoreFace(parent, cx, cy, score, palette, radius) {
|
|
53696
|
+
function renderScoreFace(parent, cx, cy, score, palette, isDark, radius) {
|
|
53490
53697
|
const r = radius ?? FACE_RADIUS;
|
|
53491
53698
|
const color = scoreToColor(score, palette);
|
|
53492
53699
|
const g = parent.append("g").attr("class", "journey-face").attr("data-cx", cx).attr("data-cy", cy);
|
|
53493
|
-
|
|
53494
|
-
|
|
53495
|
-
|
|
53496
|
-
|
|
53497
|
-
palette.textOnFillDark
|
|
53498
|
-
);
|
|
53700
|
+
const faceFill = shapeFill(palette, color, isDark);
|
|
53701
|
+
g.append("circle").attr("cx", cx).attr("cy", cy).attr("r", r + 1).attr("fill", palette.bg);
|
|
53702
|
+
g.append("circle").attr("cx", cx).attr("cy", cy).attr("r", r).attr("fill", faceFill).attr("stroke", color).attr("stroke-width", 2);
|
|
53703
|
+
const eyeColor = color;
|
|
53499
53704
|
const eyeY = cy - r * 0.15;
|
|
53500
53705
|
const eyeSpacing = r * 0.32;
|
|
53501
53706
|
const eyeR = r * 0.12;
|
|
53502
53707
|
g.append("circle").attr("cx", cx - eyeSpacing).attr("cy", eyeY).attr("r", eyeR).attr("fill", eyeColor);
|
|
53503
53708
|
g.append("circle").attr("cx", cx + eyeSpacing).attr("cy", eyeY).attr("r", eyeR).attr("fill", eyeColor);
|
|
53504
|
-
const
|
|
53505
|
-
const
|
|
53506
|
-
const
|
|
53709
|
+
const mouthW = r * 0.46;
|
|
53710
|
+
const curve = (score - 3) / 2 * r * 0.42;
|
|
53711
|
+
const apexY = cy + r * 0.32;
|
|
53712
|
+
const mouthY = apexY - curve / 2;
|
|
53507
53713
|
g.append("path").attr(
|
|
53508
53714
|
"d",
|
|
53509
53715
|
`M ${cx - mouthW} ${mouthY} Q ${cx} ${mouthY + curve} ${cx + mouthW} ${mouthY}`
|
|
@@ -53574,7 +53780,7 @@ function renderJourneyMapForExport(content, theme, palette) {
|
|
|
53574
53780
|
}
|
|
53575
53781
|
return svgEl.outerHTML;
|
|
53576
53782
|
}
|
|
53577
|
-
var 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;
|
|
53783
|
+
var 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;
|
|
53578
53784
|
var init_renderer17 = __esm({
|
|
53579
53785
|
"src/journey-map/renderer.ts"() {
|
|
53580
53786
|
"use strict";
|
|
@@ -53608,6 +53814,8 @@ var init_renderer17 = __esm({
|
|
|
53608
53814
|
GRID_LINE_OPACITY = 0.15;
|
|
53609
53815
|
CURVE_STROKE_WIDTH = 2.5;
|
|
53610
53816
|
FACE_RADIUS = 14;
|
|
53817
|
+
FACE_HOVER_SCALE = 1.5;
|
|
53818
|
+
FACE_HOVER_R = (FACE_RADIUS + 1) * FACE_HOVER_SCALE;
|
|
53611
53819
|
DIM_HOVER = 0.25;
|
|
53612
53820
|
TITLE_LINE_HEIGHT = 16;
|
|
53613
53821
|
EMOTION_LABEL_MAX_WIDTH = 180;
|
|
@@ -56657,7 +56865,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
56657
56865
|
const akRef = resolved.regions.some((r) => r.iso === "US-AK") || resolved.pois.some((p) => inAlaska(p.lon, p.lat));
|
|
56658
56866
|
const hiRef = resolved.regions.some((r) => r.iso === "US-HI") || resolved.pois.some((p) => inHawaii(p.lon, p.lat));
|
|
56659
56867
|
if (resolved.projection === "albers-usa" && usLayer && (akRef || hiRef)) {
|
|
56660
|
-
const
|
|
56868
|
+
const PAD2 = 8;
|
|
56661
56869
|
const GAP = 12;
|
|
56662
56870
|
const yB = height - FIT_PAD;
|
|
56663
56871
|
const BW = 8;
|
|
@@ -56700,22 +56908,22 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
56700
56908
|
const f = usLayer.get(iso);
|
|
56701
56909
|
if (!f) return boxX;
|
|
56702
56910
|
const x0 = boxX;
|
|
56703
|
-
const iw = Math.min(iwReq, width - FIT_PAD - x0 - 2 *
|
|
56911
|
+
const iw = Math.min(iwReq, width - FIT_PAD - x0 - 2 * PAD2);
|
|
56704
56912
|
if (iw < 24) return boxX;
|
|
56705
|
-
const xr = x0 + iw + 2 *
|
|
56913
|
+
const xr = x0 + iw + 2 * PAD2;
|
|
56706
56914
|
const floor = coastFloor(x0, xr);
|
|
56707
56915
|
const topGuess = floor > -Infinity ? floor + GAP : yB - height * 0.42;
|
|
56708
56916
|
proj.fitWidth(iw, f);
|
|
56709
56917
|
const bb = geoPath(proj).bounds(f);
|
|
56710
56918
|
const sh = Number.isFinite(bb[0][0]) ? bb[1][1] - bb[0][1] : iw;
|
|
56711
|
-
const needH = sh + 2 *
|
|
56919
|
+
const needH = sh + 2 * PAD2;
|
|
56712
56920
|
let topFit = topGuess;
|
|
56713
56921
|
const bottom = Math.min(topFit + needH, yB);
|
|
56714
56922
|
if (bottom - topFit < needH) topFit = bottom - needH;
|
|
56715
56923
|
proj.fitExtent(
|
|
56716
56924
|
[
|
|
56717
|
-
[x0 +
|
|
56718
|
-
[xr -
|
|
56925
|
+
[x0 + PAD2, topFit + PAD2],
|
|
56926
|
+
[xr - PAD2, bottom - PAD2]
|
|
56719
56927
|
],
|
|
56720
56928
|
f
|
|
56721
56929
|
);
|
|
@@ -58239,15 +58447,15 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
58239
58447
|
}
|
|
58240
58448
|
}
|
|
58241
58449
|
if (regionLabelGuards.length > 0) {
|
|
58242
|
-
const
|
|
58450
|
+
const PAD2 = 2;
|
|
58243
58451
|
const poiRects = labels.filter((l) => l.poiId !== void 0 && l.hidden !== true).map((l) => {
|
|
58244
58452
|
const w = measureLegendText(l.text, FONT2);
|
|
58245
58453
|
const x = l.anchor === "start" ? l.x : l.anchor === "end" ? l.x - w : l.x - w / 2;
|
|
58246
58454
|
return {
|
|
58247
|
-
x: x -
|
|
58455
|
+
x: x - PAD2,
|
|
58248
58456
|
y: l.y - FONT2,
|
|
58249
|
-
w: w + 2 *
|
|
58250
|
-
h: FONT2 * 1.4 + 2 *
|
|
58457
|
+
w: w + 2 * PAD2,
|
|
58458
|
+
h: FONT2 * 1.4 + 2 * PAD2
|
|
58251
58459
|
};
|
|
58252
58460
|
});
|
|
58253
58461
|
for (const g of regionLabelGuards) {
|
|
@@ -58871,7 +59079,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
58871
59079
|
if (poiLabels.length) {
|
|
58872
59080
|
const patchBlurId = nid("dgmo-map-label-patch-blur");
|
|
58873
59081
|
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);
|
|
58874
|
-
const
|
|
59082
|
+
const PAD2 = 8;
|
|
58875
59083
|
const buildPatch = (labels, maskId, decoCluster) => {
|
|
58876
59084
|
if (!labels.length) return;
|
|
58877
59085
|
const patchMask = defs.append("mask").attr("id", maskId).attr("maskUnits", "userSpaceOnUse").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height);
|
|
@@ -58887,10 +59095,10 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
58887
59095
|
const h = th + 6;
|
|
58888
59096
|
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");
|
|
58889
59097
|
blobRects.push({
|
|
58890
|
-
x0: cx - w / 2 -
|
|
58891
|
-
y0: cy - h / 2 -
|
|
58892
|
-
x1: cx + w / 2 +
|
|
58893
|
-
y1: cy + h / 2 +
|
|
59098
|
+
x0: cx - w / 2 - PAD2,
|
|
59099
|
+
y0: cy - h / 2 - PAD2,
|
|
59100
|
+
x1: cx + w / 2 + PAD2,
|
|
59101
|
+
y1: cy + h / 2 + PAD2
|
|
58894
59102
|
});
|
|
58895
59103
|
}
|
|
58896
59104
|
const gPatch = svg.append("g").attr("class", "dgmo-map-label-patch").attr("mask", `url(#${maskId})`).style("pointer-events", "none");
|
|
@@ -60311,13 +60519,13 @@ function renderTreemap(container, parsed, palette, isDark, exportDims, options =
|
|
|
60311
60519
|
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);
|
|
60312
60520
|
}
|
|
60313
60521
|
}
|
|
60314
|
-
const
|
|
60522
|
+
const PAD2 = Math.max(4, Math.min(14, Math.floor(Math.min(w, h) / 5)));
|
|
60315
60523
|
const MIN_FS = 7;
|
|
60316
|
-
if (!cell.isContainer && w >= 2 *
|
|
60317
|
-
const maxW = w - 2 *
|
|
60524
|
+
if (!cell.isContainer && w >= 2 * PAD2 + 8 && h >= 2 * PAD2 + 8) {
|
|
60525
|
+
const maxW = w - 2 * PAD2;
|
|
60318
60526
|
const horizMinW = measureText(cell.label, MIN_FS) * 1.06;
|
|
60319
|
-
if (horizMinW > maxW && h > w * 1.25 && h - 2 *
|
|
60320
|
-
drawVerticalLabel(g, cell.label, w, h,
|
|
60527
|
+
if (horizMinW > maxW && h > w * 1.25 && h - 2 * PAD2 > maxW) {
|
|
60528
|
+
drawVerticalLabel(g, cell.label, w, h, PAD2, ink);
|
|
60321
60529
|
if (drillable && w > 30 && h > 22) drawFocusIcon(g, w, ink, 9);
|
|
60322
60530
|
continue;
|
|
60323
60531
|
}
|
|
@@ -60328,8 +60536,8 @@ function renderTreemap(container, parsed, palette, isDark, exportDims, options =
|
|
|
60328
60536
|
const nameOpacity = 0.95 - tg * 0.5;
|
|
60329
60537
|
const vfs = clamp3(Math.round(fs * 0.42), 11, 28);
|
|
60330
60538
|
const valOpacity = Math.max(0.45, nameOpacity - 0.1);
|
|
60331
|
-
let y =
|
|
60332
|
-
g.append("text").attr("class", "dgmo-treemap-label").attr("x",
|
|
60539
|
+
let y = PAD2 + Math.round(fs * 0.78);
|
|
60540
|
+
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));
|
|
60333
60541
|
const valParts = [
|
|
60334
60542
|
opts.noValues ? "" : compactNumber2(cell.value),
|
|
60335
60543
|
opts.noPercent ? "" : formatPct(cell.pctOfRoot)
|
|
@@ -60337,12 +60545,12 @@ function renderTreemap(container, parsed, palette, isDark, exportDims, options =
|
|
|
60337
60545
|
const combined = valParts.join(" \xB7 ");
|
|
60338
60546
|
const nameBaseY = y;
|
|
60339
60547
|
const addLineAt = (text, yy, size, opacity) => {
|
|
60340
|
-
g.append("text").attr("class", "dgmo-treemap-value").attr("x",
|
|
60548
|
+
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);
|
|
60341
60549
|
};
|
|
60342
60550
|
if (combined) {
|
|
60343
60551
|
const fitsW = measureText(combined, vfs) <= maxW;
|
|
60344
60552
|
const valY = y + lineDrop(fs, vfs);
|
|
60345
|
-
const roomBelow = valY + descent(vfs) <= h -
|
|
60553
|
+
const roomBelow = valY + descent(vfs) <= h - PAD2;
|
|
60346
60554
|
if (fitsW && roomBelow) {
|
|
60347
60555
|
addLineAt(combined, valY, vfs, valOpacity);
|
|
60348
60556
|
} else if (fitsW) {
|
|
@@ -60350,24 +60558,24 @@ function renderTreemap(container, parsed, palette, isDark, exportDims, options =
|
|
|
60350
60558
|
const rendered = clipLabel(cell.label, maxW, fs);
|
|
60351
60559
|
const nW = measureText(rendered, fs) * 1.12;
|
|
60352
60560
|
const gap = Math.max(12, Math.round(fs * 0.25));
|
|
60353
|
-
if (
|
|
60354
|
-
g.append("text").attr("class", "dgmo-treemap-value").attr("x",
|
|
60561
|
+
if (PAD2 + nW + gap + measureText(combined, ivfs) <= w - PAD2) {
|
|
60562
|
+
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);
|
|
60355
60563
|
}
|
|
60356
60564
|
} else if (valParts.length === 2) {
|
|
60357
60565
|
const d1 = lineDrop(fs, vfs);
|
|
60358
|
-
if (y + d1 + descent(vfs) <= h -
|
|
60566
|
+
if (y + d1 + descent(vfs) <= h - PAD2) {
|
|
60359
60567
|
y += d1;
|
|
60360
60568
|
addLineAt(valParts[0], y, vfs, valOpacity);
|
|
60361
60569
|
}
|
|
60362
60570
|
const pfs = Math.max(10, Math.round(vfs * 0.9));
|
|
60363
60571
|
const d2 = lineDrop(vfs, pfs);
|
|
60364
|
-
if (y + d2 + descent(pfs) <= h -
|
|
60572
|
+
if (y + d2 + descent(pfs) <= h - PAD2) {
|
|
60365
60573
|
y += d2;
|
|
60366
60574
|
addLineAt(valParts[1], y, pfs, valOpacity);
|
|
60367
60575
|
}
|
|
60368
60576
|
} else {
|
|
60369
60577
|
const onlyY = y + lineDrop(fs, vfs);
|
|
60370
|
-
if (onlyY + descent(vfs) <= h -
|
|
60578
|
+
if (onlyY + descent(vfs) <= h - PAD2) {
|
|
60371
60579
|
addLineAt(combined, onlyY, vfs, valOpacity);
|
|
60372
60580
|
}
|
|
60373
60581
|
}
|
|
@@ -68490,6 +68698,144 @@ function decodeDiagramUrl(hash) {
|
|
|
68490
68698
|
init_dgmo_router();
|
|
68491
68699
|
init_palettes();
|
|
68492
68700
|
init_diagnostics();
|
|
68701
|
+
|
|
68702
|
+
// src/error-card.ts
|
|
68703
|
+
init_text_measure();
|
|
68704
|
+
init_fonts();
|
|
68705
|
+
var MONO_FAMILY = "ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace";
|
|
68706
|
+
var W2 = 660;
|
|
68707
|
+
var PAD = 24;
|
|
68708
|
+
var CONTENT_W = W2 - PAD * 2;
|
|
68709
|
+
var MAX_ERRORS = 4;
|
|
68710
|
+
var MONO_CH = 0.6;
|
|
68711
|
+
var CODE_FS = 12.5;
|
|
68712
|
+
function renderErrorCard(errors, source, palette, theme) {
|
|
68713
|
+
const c = palette[theme === "dark" ? "dark" : "light"];
|
|
68714
|
+
const isTransparent = theme === "transparent";
|
|
68715
|
+
const card = c.surface;
|
|
68716
|
+
const codeBg = c.bg;
|
|
68717
|
+
const border = c.border;
|
|
68718
|
+
const danger = c.destructive ?? c.colors.red;
|
|
68719
|
+
const text = c.text;
|
|
68720
|
+
const muted = c.textMuted;
|
|
68721
|
+
const srcLines = source.split("\n");
|
|
68722
|
+
const shown = errors.slice(0, MAX_ERRORS);
|
|
68723
|
+
const overflow = errors.length - shown.length;
|
|
68724
|
+
const parts = [];
|
|
68725
|
+
let y = PAD + 8;
|
|
68726
|
+
parts.push(frownMark(PAD + 14, y + 12, danger));
|
|
68727
|
+
parts.push(
|
|
68728
|
+
`<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>`,
|
|
68729
|
+
`<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>`
|
|
68730
|
+
);
|
|
68731
|
+
y += 24;
|
|
68732
|
+
const errLabel = errors.length === 1 ? "1 error" : `${errors.length} errors`;
|
|
68733
|
+
parts.push(
|
|
68734
|
+
`<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>`
|
|
68735
|
+
);
|
|
68736
|
+
y += 22;
|
|
68737
|
+
parts.push(
|
|
68738
|
+
`<line x1="${PAD}" y1="${y}" x2="${W2 - PAD}" y2="${y}" stroke="${border}" stroke-width="1"/>`
|
|
68739
|
+
);
|
|
68740
|
+
y += 24;
|
|
68741
|
+
for (const e of shown) {
|
|
68742
|
+
const hasLine = e.line > 0;
|
|
68743
|
+
let msgX = PAD;
|
|
68744
|
+
if (hasLine) {
|
|
68745
|
+
const label = e.column ? `Line ${e.line}:${e.column}` : `Line ${e.line}`;
|
|
68746
|
+
const badgeW = 14 + label.length * 7;
|
|
68747
|
+
parts.push(
|
|
68748
|
+
`<rect x="${PAD}" y="${y - 13}" width="${badgeW}" height="19" rx="4" fill="${danger}"/>`,
|
|
68749
|
+
`<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>`
|
|
68750
|
+
);
|
|
68751
|
+
msgX = PAD + badgeW + 12;
|
|
68752
|
+
}
|
|
68753
|
+
const lines = wrapMessage(e.message, CONTENT_W - (msgX - PAD), CONTENT_W);
|
|
68754
|
+
lines.forEach((line11, i) => {
|
|
68755
|
+
parts.push(
|
|
68756
|
+
`<text x="${i === 0 ? msgX : PAD}" y="${y + 1}" fill="${text}" font-family="${FONT_FAMILY}" font-size="13">${escapeXml(line11)}</text>`
|
|
68757
|
+
);
|
|
68758
|
+
if (i < lines.length - 1) y += 18;
|
|
68759
|
+
});
|
|
68760
|
+
y += 24;
|
|
68761
|
+
const raw = hasLine ? srcLines[e.line - 1] : void 0;
|
|
68762
|
+
if (raw !== void 0 && raw.trim().length > 0) {
|
|
68763
|
+
const gutter = `${e.line}`;
|
|
68764
|
+
const gutterW = gutter.length * CODE_FS * MONO_CH + 16;
|
|
68765
|
+
const codeX = PAD + gutterW;
|
|
68766
|
+
const codeMaxW = CONTENT_W - gutterW - 12;
|
|
68767
|
+
const codeText = truncateText(
|
|
68768
|
+
raw.replace(/\t/g, " "),
|
|
68769
|
+
CODE_FS,
|
|
68770
|
+
codeMaxW
|
|
68771
|
+
);
|
|
68772
|
+
const hasCaret = e.column !== void 0 && e.column > 0;
|
|
68773
|
+
const blockH = hasCaret ? 40 : 26;
|
|
68774
|
+
parts.push(
|
|
68775
|
+
`<rect x="${PAD}" y="${y - 14}" width="${CONTENT_W}" height="${blockH}" rx="5" fill="${codeBg}" stroke="${border}" stroke-width="1"/>`,
|
|
68776
|
+
`<line x1="${codeX - 8}" y1="${y - 14}" x2="${codeX - 8}" y2="${y - 14 + blockH}" stroke="${border}" stroke-width="1"/>`,
|
|
68777
|
+
`<text x="${PAD + 8}" y="${y + 3}" fill="${muted}" font-family="${MONO_FAMILY}" font-size="${CODE_FS}">${escapeXml(gutter)}</text>`,
|
|
68778
|
+
`<text x="${codeX}" y="${y + 3}" fill="${text}" font-family="${MONO_FAMILY}" font-size="${CODE_FS}" xml:space="preserve">${escapeXml(codeText)}</text>`
|
|
68779
|
+
);
|
|
68780
|
+
if (hasCaret) {
|
|
68781
|
+
const caretX = codeX + (e.column - 1) * CODE_FS * MONO_CH;
|
|
68782
|
+
parts.push(
|
|
68783
|
+
`<text x="${caretX}" y="${y + 17}" fill="${danger}" font-family="${MONO_FAMILY}" font-size="${CODE_FS}" font-weight="700">^</text>`
|
|
68784
|
+
);
|
|
68785
|
+
y += 14;
|
|
68786
|
+
}
|
|
68787
|
+
y += 24;
|
|
68788
|
+
}
|
|
68789
|
+
y += 14;
|
|
68790
|
+
}
|
|
68791
|
+
if (overflow > 0) {
|
|
68792
|
+
parts.push(
|
|
68793
|
+
`<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>`
|
|
68794
|
+
);
|
|
68795
|
+
y += 22;
|
|
68796
|
+
}
|
|
68797
|
+
const height = Math.round(y + PAD - 14);
|
|
68798
|
+
const pageBg = isTransparent ? "" : `<rect width="100%" height="100%" fill="${c.bg}"/>`;
|
|
68799
|
+
return [
|
|
68800
|
+
`<svg xmlns="http://www.w3.org/2000/svg" width="${W2}" height="${height}" viewBox="0 0 ${W2} ${height}" font-family="${FONT_FAMILY}">`,
|
|
68801
|
+
pageBg,
|
|
68802
|
+
`<rect x="0.5" y="0.5" width="${W2 - 1}" height="${height - 1}" rx="10" fill="${card}" stroke="${border}" stroke-width="1"/>`,
|
|
68803
|
+
parts.join(""),
|
|
68804
|
+
`</svg>`
|
|
68805
|
+
].join("");
|
|
68806
|
+
}
|
|
68807
|
+
function wrapMessage(message, firstWidth, fullWidth) {
|
|
68808
|
+
const words = message.split(/\s+/).filter(Boolean);
|
|
68809
|
+
if (words.length === 0) return [""];
|
|
68810
|
+
const lines = [];
|
|
68811
|
+
let cur = "";
|
|
68812
|
+
for (const word of words) {
|
|
68813
|
+
const limit = lines.length === 0 ? firstWidth : fullWidth;
|
|
68814
|
+
const test = cur ? `${cur} ${word}` : word;
|
|
68815
|
+
if (measureText(test, 13) <= limit || !cur) {
|
|
68816
|
+
cur = test;
|
|
68817
|
+
} else {
|
|
68818
|
+
lines.push(cur);
|
|
68819
|
+
cur = word;
|
|
68820
|
+
}
|
|
68821
|
+
}
|
|
68822
|
+
if (cur) lines.push(cur);
|
|
68823
|
+
return lines;
|
|
68824
|
+
}
|
|
68825
|
+
function frownMark(cx, cy, color) {
|
|
68826
|
+
const r = 12;
|
|
68827
|
+
return [
|
|
68828
|
+
`<circle cx="${cx}" cy="${cy}" r="${r}" fill="none" stroke="${color}" stroke-width="2"/>`,
|
|
68829
|
+
`<circle cx="${cx - 4.5}" cy="${cy - 3}" r="1.6" fill="${color}"/>`,
|
|
68830
|
+
`<circle cx="${cx + 4.5}" cy="${cy - 3}" r="1.6" fill="${color}"/>`,
|
|
68831
|
+
`<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"/>`
|
|
68832
|
+
].join("");
|
|
68833
|
+
}
|
|
68834
|
+
function escapeXml(s) {
|
|
68835
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
68836
|
+
}
|
|
68837
|
+
|
|
68838
|
+
// src/index.ts
|
|
68493
68839
|
init_palettes();
|
|
68494
68840
|
|
|
68495
68841
|
// src/themes.ts
|
|
@@ -68829,25 +69175,10 @@ async function render2(text, options) {
|
|
|
68829
69175
|
return result;
|
|
68830
69176
|
}
|
|
68831
69177
|
return {
|
|
68832
|
-
svg:
|
|
69178
|
+
svg: renderErrorCard(errors, text, palette, options?.theme),
|
|
68833
69179
|
diagnostics: result.diagnostics
|
|
68834
69180
|
};
|
|
68835
69181
|
}
|
|
68836
|
-
function renderErrorSvg(errors, palette, theme) {
|
|
68837
|
-
const colors = palette[theme === "dark" ? "dark" : "light"];
|
|
68838
|
-
const bg = theme === "transparent" ? "transparent" : colors.bg;
|
|
68839
|
-
const fg = colors.destructive ?? colors.text;
|
|
68840
|
-
const muted = colors.textMuted ?? colors.text;
|
|
68841
|
-
const lines = errors.slice(0, 5).map((e) => formatDgmoError(e));
|
|
68842
|
-
const height = 60 + lines.length * 20;
|
|
68843
|
-
const body = lines.map(
|
|
68844
|
-
(line11, i) => `<text x="20" y="${60 + i * 20}" fill="${fg}" font-family="ui-monospace, monospace" font-size="12">${escapeXml(line11)}</text>`
|
|
68845
|
-
).join("");
|
|
68846
|
-
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>`;
|
|
68847
|
-
}
|
|
68848
|
-
function escapeXml(s) {
|
|
68849
|
-
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
68850
|
-
}
|
|
68851
69182
|
function encodeDiagramUrl2(text, options) {
|
|
68852
69183
|
const internalTheme = options?.theme === "light" || options?.theme === "dark" ? options.theme : void 0;
|
|
68853
69184
|
const result = encodeDiagramUrl(text, {
|