@nowline/embed 0.5.0 → 0.6.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.
@@ -1,4 +1,4 @@
1
- /*! @nowline/embed 0.5.0 sha=04bdff9 built=2026-06-01T06:46:51Z */
1
+ /*! @nowline/embed 0.6.0 sha=e2e4d9d built=2026-06-06T04:33:35Z */
2
2
  var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -6372,6 +6372,250 @@ var init_node_read_file = __esm({
6372
6372
  }
6373
6373
  });
6374
6374
 
6375
+ // ../layout/dist/capacity.js
6376
+ var BUILTIN_CAPACITY_ICONS = /* @__PURE__ */ new Set([
6377
+ "none",
6378
+ "multiplier",
6379
+ "person",
6380
+ "people",
6381
+ "points",
6382
+ "time"
6383
+ ]);
6384
+ var POSITIVE_INT_RE = /^\d+$/;
6385
+ var POSITIVE_DECIMAL_RE = /^\d+\.\d+$/;
6386
+ var POSITIVE_PERCENT_RE = /^\d+(?:\.\d+)?%$/;
6387
+ function parseCapacityValue(raw) {
6388
+ if (!raw)
6389
+ return null;
6390
+ if (POSITIVE_INT_RE.test(raw)) {
6391
+ const n = parseInt(raw, 10);
6392
+ return n > 0 ? n : null;
6393
+ }
6394
+ if (POSITIVE_DECIMAL_RE.test(raw)) {
6395
+ const n = parseFloat(raw);
6396
+ return Number.isFinite(n) && n > 0 ? n : null;
6397
+ }
6398
+ if (POSITIVE_PERCENT_RE.test(raw)) {
6399
+ const n = parseFloat(raw.slice(0, -1)) / 100;
6400
+ return Number.isFinite(n) && n > 0 ? n : null;
6401
+ }
6402
+ return null;
6403
+ }
6404
+ function formatCapacityNumber(value) {
6405
+ if (Number.isInteger(value))
6406
+ return String(value);
6407
+ let s = value.toFixed(6);
6408
+ s = s.replace(/0+$/, "");
6409
+ s = s.replace(/\.$/, "");
6410
+ return s;
6411
+ }
6412
+ function propKey(prop) {
6413
+ return prop.key.endsWith(":") ? prop.key.slice(0, -1) : prop.key;
6414
+ }
6415
+ function symbolUnicode(decl) {
6416
+ for (const p of decl.properties) {
6417
+ if (propKey(p) === "unicode" && p.value)
6418
+ return p.value;
6419
+ }
6420
+ return void 0;
6421
+ }
6422
+ function resolveCapacityIcon(icon, symbols) {
6423
+ if (icon === "none")
6424
+ return null;
6425
+ if (BUILTIN_CAPACITY_ICONS.has(icon)) {
6426
+ return {
6427
+ kind: "builtin",
6428
+ name: icon
6429
+ };
6430
+ }
6431
+ const custom = symbols.get(icon);
6432
+ if (custom) {
6433
+ const unicode = symbolUnicode(custom);
6434
+ return { kind: "literal", text: unicode ?? icon };
6435
+ }
6436
+ return { kind: "literal", text: icon };
6437
+ }
6438
+ function estimateCapacitySuffixWidth(text, icon, fontSizePx) {
6439
+ if (!icon)
6440
+ return text.length * fontSizePx * 0.58;
6441
+ if (icon.kind === "builtin" && icon.name === "multiplier") {
6442
+ return (text.length + 1) * fontSizePx * 0.58;
6443
+ }
6444
+ const glyphWidthEm = 1;
6445
+ const gapEm = 0.1;
6446
+ return text.length * fontSizePx * 0.58 + (gapEm + glyphWidthEm) * fontSizePx;
6447
+ }
6448
+
6449
+ // ../layout/dist/frame-tab-geometry.js
6450
+ var FRAME_TAB_TITLE_PX_PER_CHAR = 6.5;
6451
+ var FRAME_TAB_OWNER_PX_PER_CHAR = 5;
6452
+ var FRAME_TAB_INNER_GAP_PX = 6;
6453
+ var FRAME_TAB_LEFT_INSET_PX = 12;
6454
+ var FRAME_TAB_RIGHT_INSET_PX = 12;
6455
+ var FRAME_TAB_MIN_WIDTH_PX = 56;
6456
+ var FRAME_TAB_OFFSET_FROM_BOX_PX = 10;
6457
+ function frameTabGeometry(boxX, title, owner, capacityBadgeWidth = 0, footnoteIndicatorWidth = 0) {
6458
+ const tabX = boxX + FRAME_TAB_OFFSET_FROM_BOX_PX;
6459
+ const titleX = tabX + FRAME_TAB_LEFT_INSET_PX;
6460
+ const titleTextWidth = title.length * FRAME_TAB_TITLE_PX_PER_CHAR;
6461
+ let cursorX = titleX + titleTextWidth;
6462
+ let ownerTextWidth = 0;
6463
+ let ownerX = 0;
6464
+ if (owner) {
6465
+ ownerTextWidth = `owner: ${owner}`.length * FRAME_TAB_OWNER_PX_PER_CHAR;
6466
+ ownerX = cursorX + FRAME_TAB_INNER_GAP_PX;
6467
+ cursorX = ownerX + ownerTextWidth;
6468
+ }
6469
+ let badgeX = 0;
6470
+ if (capacityBadgeWidth > 0) {
6471
+ badgeX = cursorX + FRAME_TAB_INNER_GAP_PX;
6472
+ cursorX = badgeX + capacityBadgeWidth;
6473
+ }
6474
+ let footnoteRightX = 0;
6475
+ if (footnoteIndicatorWidth > 0) {
6476
+ footnoteRightX = cursorX + FRAME_TAB_INNER_GAP_PX + footnoteIndicatorWidth;
6477
+ cursorX = footnoteRightX;
6478
+ }
6479
+ const contentW = cursorX - tabX + FRAME_TAB_RIGHT_INSET_PX;
6480
+ const tabW = Math.max(FRAME_TAB_MIN_WIDTH_PX, contentW);
6481
+ return {
6482
+ titleTextWidth,
6483
+ ownerTextWidth,
6484
+ capacityBadgeWidth,
6485
+ footnoteIndicatorWidth,
6486
+ titleX,
6487
+ ownerX,
6488
+ badgeX,
6489
+ footnoteRightX,
6490
+ tabX,
6491
+ tabW,
6492
+ rightX: tabX + tabW
6493
+ };
6494
+ }
6495
+
6496
+ // ../layout/dist/header-card-geometry.js
6497
+ var HEADER_CARD_PADDING_X = 16;
6498
+ var HEADER_CARD_PADDING_TOP = 26;
6499
+ var HEADER_CARD_PADDING_BOTTOM = 14;
6500
+ var HEADER_TITLE_LINE_HEIGHT_PX = 20;
6501
+ var HEADER_AUTHOR_LINE_HEIGHT_PX = 14;
6502
+ var HEADER_TITLE_TO_AUTHOR_GAP_PX = 18;
6503
+ var HEADER_TITLE_FONT_SIZE_PX = 16;
6504
+ var HEADER_AUTHOR_FONT_SIZE_PX = 11;
6505
+
6506
+ // ../layout/dist/include-chrome-geometry.js
6507
+ var INCLUDE_CHROME_OFFSET_FROM_BOX_PX = 24;
6508
+ var INCLUDE_CHROME_TAB_LEFT_INSET_PX = 10;
6509
+ var INCLUDE_CHROME_TAB_RIGHT_INSET_PX = 10;
6510
+ var INCLUDE_CHROME_TAB_LABEL_PER_CHAR_PX = 6;
6511
+ var INCLUDE_CHROME_TAB_MIN_WIDTH_PX = 60;
6512
+ var INCLUDE_CHROME_BADGE_GAP_PX = 6;
6513
+ var INCLUDE_CHROME_BADGE_SIZE_PX = 18;
6514
+ var INCLUDE_CHROME_SOURCE_GAP_PX = 6;
6515
+ var INCLUDE_CHROME_SOURCE_PER_CHAR_PX = 5.5;
6516
+ var INCLUDE_CHROME_SOURCE_HALO_PAD_PX = 3;
6517
+ function includeChromeGeometry(boxX, label, sourcePath) {
6518
+ const tabX = boxX + INCLUDE_CHROME_OFFSET_FROM_BOX_PX;
6519
+ const tabLabelX = tabX + INCLUDE_CHROME_TAB_LEFT_INSET_PX;
6520
+ const labelTextWidth = label.length * INCLUDE_CHROME_TAB_LABEL_PER_CHAR_PX;
6521
+ const tabWidth = Math.max(INCLUDE_CHROME_TAB_MIN_WIDTH_PX, labelTextWidth + INCLUDE_CHROME_TAB_LEFT_INSET_PX + INCLUDE_CHROME_TAB_RIGHT_INSET_PX);
6522
+ const badgeX = tabX + tabWidth + INCLUDE_CHROME_BADGE_GAP_PX;
6523
+ const badgeRightX = badgeX + INCLUDE_CHROME_BADGE_SIZE_PX;
6524
+ let sourceTextWidth = 0;
6525
+ let sourceTextX = 0;
6526
+ let sourceHaloX = 0;
6527
+ let sourceHaloWidth = 0;
6528
+ let chromeRightX = badgeRightX;
6529
+ if (sourcePath) {
6530
+ sourceTextX = badgeRightX + INCLUDE_CHROME_SOURCE_GAP_PX;
6531
+ sourceTextWidth = sourcePath.length * INCLUDE_CHROME_SOURCE_PER_CHAR_PX;
6532
+ sourceHaloX = sourceTextX - INCLUDE_CHROME_SOURCE_HALO_PAD_PX;
6533
+ sourceHaloWidth = sourceTextWidth + INCLUDE_CHROME_SOURCE_HALO_PAD_PX * 2;
6534
+ chromeRightX = sourceHaloX + sourceHaloWidth;
6535
+ }
6536
+ return {
6537
+ labelTextWidth,
6538
+ sourceTextWidth,
6539
+ tabX,
6540
+ tabWidth,
6541
+ tabLabelX,
6542
+ badgeX,
6543
+ badgeSize: INCLUDE_CHROME_BADGE_SIZE_PX,
6544
+ sourceHaloX,
6545
+ sourceHaloWidth,
6546
+ sourceTextX,
6547
+ chromeRightX
6548
+ };
6549
+ }
6550
+
6551
+ // ../layout/dist/item-bar-geometry.js
6552
+ var ITEM_CAPTION_INSET_X_PX = 12;
6553
+ var ITEM_CAPTION_SPILL_GAP_PX = 6;
6554
+ var ITEM_CAPTION_TITLE_BASELINE_OFFSET_PX = 20;
6555
+ var ITEM_CAPTION_META_BASELINE_OFFSET_PX = 38;
6556
+ var ITEM_CAPTION_TITLE_FONT_SIZE_PX = 13;
6557
+ var ITEM_CAPTION_META_FONT_SIZE_PX = 11;
6558
+ var ITEM_STATUS_DOT_INSET_RIGHT_PX = 12;
6559
+ var ITEM_STATUS_DOT_INSET_TOP_PX = 12;
6560
+ var ITEM_STATUS_DOT_RADIUS_PX = 5;
6561
+ var ITEM_FOOTNOTE_INDICATOR_INSET_RIGHT_PX = 22;
6562
+ var ITEM_FOOTNOTE_INDICATOR_BASELINE_OFFSET_PX = 14;
6563
+ var ITEM_FOOTNOTE_INDICATOR_STEP_PX = 8;
6564
+ var ITEM_LINK_ICON_TILE_SIZE_PX = 14;
6565
+ var ITEM_LINK_ICON_INSET_PX = 6;
6566
+ var ITEM_DECORATION_SPILL_GAP_PX = 4;
6567
+ var MIN_BAR_WIDTH_FOR_DOT_PX = ITEM_STATUS_DOT_INSET_RIGHT_PX + ITEM_STATUS_DOT_RADIUS_PX;
6568
+ var MIN_BAR_WIDTH_FOR_LINK_AND_DOT_PX = ITEM_LINK_ICON_INSET_PX + ITEM_LINK_ICON_TILE_SIZE_PX + ITEM_DECORATION_SPILL_GAP_PX + ITEM_STATUS_DOT_INSET_RIGHT_PX + ITEM_STATUS_DOT_RADIUS_PX;
6569
+ var MIN_BAR_WIDTH_FOR_FOOTNOTE_PX = ITEM_FOOTNOTE_INDICATOR_INSET_RIGHT_PX + 1;
6570
+ var INLINE_DATE_GLYPH_TILE_SIZE_PX = 12;
6571
+ var INLINE_DATE_GLYPH_INSET_LEFT_PX = 6;
6572
+ var INLINE_DATE_GLYPH_INSET_RIGHT_PX = 6;
6573
+ var INLINE_DATE_GLYPH_INSET_TOP_PX = 5;
6574
+ var INLINE_DATE_GLYPH_GAP_PX = ITEM_DECORATION_SPILL_GAP_PX;
6575
+ var MIN_BAR_WIDTH_FOR_INLINE_DATE_PX = INLINE_DATE_GLYPH_INSET_LEFT_PX + INLINE_DATE_GLYPH_TILE_SIZE_PX + INLINE_DATE_GLYPH_GAP_PX + INLINE_DATE_GLYPH_TILE_SIZE_PX + INLINE_DATE_GLYPH_INSET_RIGHT_PX;
6576
+ var LABEL_CHIP_HEIGHT_PX = 13;
6577
+ var LABEL_CHIP_GAP_ABOVE_PROGRESS_STRIP_PX = 3;
6578
+ var LABEL_CHIP_GAP_BETWEEN_PX = 4;
6579
+ var LABEL_CHIP_ROW_GAP_PX = 4;
6580
+ var LABEL_CHIP_ROW_STEP_PX = LABEL_CHIP_HEIGHT_PX + LABEL_CHIP_ROW_GAP_PX;
6581
+ var SPILL_ROW_SLACK_FRACTION = 0.25;
6582
+ function packSpillChips(chips, barVisualWidth) {
6583
+ if (chips.length === 0)
6584
+ return { rows: [[]], expanded: false };
6585
+ const rows = [[]];
6586
+ let used = 0;
6587
+ let rowCap = barVisualWidth;
6588
+ let expanded = false;
6589
+ for (const chip of chips) {
6590
+ const row = rows[rows.length - 1];
6591
+ const needed = (row.length === 0 ? 0 : LABEL_CHIP_GAP_BETWEEN_PX) + chip.width;
6592
+ const wouldBe = used + needed;
6593
+ if (wouldBe <= rowCap) {
6594
+ row.push(chip);
6595
+ used = wouldBe;
6596
+ continue;
6597
+ }
6598
+ if (row.length === 0) {
6599
+ row.push(chip);
6600
+ used = chip.width;
6601
+ continue;
6602
+ }
6603
+ const overflow = wouldBe - rowCap;
6604
+ const slack = chip.width * SPILL_ROW_SLACK_FRACTION;
6605
+ if (!expanded && overflow <= slack) {
6606
+ row.push(chip);
6607
+ used = wouldBe;
6608
+ rowCap = wouldBe;
6609
+ expanded = true;
6610
+ continue;
6611
+ }
6612
+ rows.push([chip]);
6613
+ used = chip.width;
6614
+ rowCap = barVisualWidth;
6615
+ }
6616
+ return { rows, expanded };
6617
+ }
6618
+
6375
6619
  // ../core/dist/diagnostics/index.js
6376
6620
  var LANGIUM_LEXING_ERROR = "lexing-error";
6377
6621
  var LANGIUM_PARSING_ERROR = "parsing-error";
@@ -29140,15 +29384,15 @@ function applyRoadmapMode(target, child, childConfig, mode, childPath, childRelP
29140
29384
  message: `${category} "${name}" from ${basename(childPath)} is shadowed by the parent's definition.`,
29141
29385
  sourcePath: childPath
29142
29386
  });
29143
- mergeMap(target.persons, child.persons, (name) => warn(name, "Person"));
29144
- mergeMap(target.teams, child.teams, (name) => warn(name, "Team"));
29145
- mergeMap(target.anchors, child.anchors, (name) => warn(name, "Anchor"));
29146
- mergeMap(target.labels, child.labels, (name) => warn(name, "Label"));
29147
- mergeMap(target.sizes, child.sizes, (name) => warn(name, "Size"));
29148
- mergeMap(target.statuses, child.statuses, (name) => warn(name, "Status"));
29149
- mergeMap(target.swimlanes, child.swimlanes, (name) => warn(name, "Swimlane"));
29150
- mergeMap(target.milestones, child.milestones, (name) => warn(name, "Milestone"));
29151
- mergeMap(target.footnotes, child.footnotes, (name) => warn(name, "Footnote"));
29387
+ mergeContentMap(target.persons, child.persons, (name) => warn(name, "Person"));
29388
+ mergeContentMap(target.teams, child.teams, (name) => warn(name, "Team"));
29389
+ mergeContentMap(target.anchors, child.anchors, (name) => warn(name, "Anchor"));
29390
+ mergeContentMap(target.labels, child.labels, (name) => warn(name, "Label"));
29391
+ mergeContentMap(target.sizes, child.sizes, (name) => warn(name, "Size"));
29392
+ mergeContentMap(target.statuses, child.statuses, (name) => warn(name, "Status"));
29393
+ mergeContentMap(target.swimlanes, child.swimlanes, (name) => warn(name, "Swimlane"));
29394
+ mergeContentMap(target.milestones, child.milestones, (name) => warn(name, "Milestone"));
29395
+ mergeContentMap(target.footnotes, child.footnotes, (name) => warn(name, "Footnote"));
29152
29396
  if (child.roadmap && !target.roadmap) {
29153
29397
  target.roadmap = child.roadmap;
29154
29398
  }
@@ -29162,6 +29406,19 @@ function mergeMap(target, source, onConflict) {
29162
29406
  target.set(name, value);
29163
29407
  }
29164
29408
  }
29409
+ function mergeContentMap(target, source, onConflict) {
29410
+ for (const [name, value] of source) {
29411
+ if (!value.name && value.title) {
29412
+ target.set(uniqueMapKey(target, slugifyTitle(value.title)), value);
29413
+ continue;
29414
+ }
29415
+ if (target.has(name)) {
29416
+ onConflict(name);
29417
+ continue;
29418
+ }
29419
+ target.set(name, value);
29420
+ }
29421
+ }
29165
29422
  function mergeLocalConfig(config2, file) {
29166
29423
  for (const entry of file.configEntries) {
29167
29424
  addConfigEntry(config2, entry);
@@ -29188,51 +29445,92 @@ function addConfigEntry(config2, entry) {
29188
29445
  }
29189
29446
  }
29190
29447
  }
29448
+ function collectExplicitRoadmapIds(entries) {
29449
+ const reserved = {
29450
+ swimlanes: /* @__PURE__ */ new Set(),
29451
+ persons: /* @__PURE__ */ new Set(),
29452
+ teams: /* @__PURE__ */ new Set(),
29453
+ anchors: /* @__PURE__ */ new Set(),
29454
+ labels: /* @__PURE__ */ new Set(),
29455
+ sizes: /* @__PURE__ */ new Set(),
29456
+ statuses: /* @__PURE__ */ new Set(),
29457
+ milestones: /* @__PURE__ */ new Set(),
29458
+ footnotes: /* @__PURE__ */ new Set()
29459
+ };
29460
+ for (const entry of entries) {
29461
+ const name = entry.name;
29462
+ if (!name)
29463
+ continue;
29464
+ if (isSwimlaneDeclaration(entry))
29465
+ reserved.swimlanes.add(name);
29466
+ else if (isPersonDeclaration(entry))
29467
+ reserved.persons.add(name);
29468
+ else if (isTeamDeclaration(entry))
29469
+ reserved.teams.add(name);
29470
+ else if (isAnchorDeclaration(entry))
29471
+ reserved.anchors.add(name);
29472
+ else if (isLabelDeclaration(entry))
29473
+ reserved.labels.add(name);
29474
+ else if (isSizeDeclaration(entry))
29475
+ reserved.sizes.add(name);
29476
+ else if (isStatusDeclaration(entry))
29477
+ reserved.statuses.add(name);
29478
+ else if (isMilestoneDeclaration(entry))
29479
+ reserved.milestones.add(name);
29480
+ else if (isFootnoteDeclaration(entry))
29481
+ reserved.footnotes.add(name);
29482
+ }
29483
+ return reserved;
29484
+ }
29191
29485
  function mergeLocalContent(content, file) {
29192
29486
  if (file.roadmapDecl && !content.roadmap) {
29193
29487
  content.roadmap = file.roadmapDecl;
29194
29488
  }
29489
+ const reserved = collectExplicitRoadmapIds(file.roadmapEntries);
29195
29490
  for (const entry of file.roadmapEntries) {
29196
- addRoadmapEntry(content, entry);
29491
+ addRoadmapEntry(content, entry, reserved);
29197
29492
  }
29198
29493
  }
29199
- function addRoadmapEntry(content, entry) {
29200
- if (isSwimlaneDeclaration(entry)) {
29201
- if (entry.name && !content.swimlanes.has(entry.name)) {
29202
- content.swimlanes.set(entry.name, entry);
29494
+ function slugifyTitle(title) {
29495
+ return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "entity";
29496
+ }
29497
+ function uniqueMapKey(map2, base, reserved) {
29498
+ const taken = (key) => map2.has(key) || (reserved?.has(key) ?? false);
29499
+ if (!taken(base))
29500
+ return base;
29501
+ let n = 2;
29502
+ while (taken(`${base}-${n}`))
29503
+ n++;
29504
+ return `${base}-${n}`;
29505
+ }
29506
+ function addByKey(map2, entry, reserved) {
29507
+ if (entry.name) {
29508
+ if (!map2.has(entry.name)) {
29509
+ map2.set(entry.name, entry);
29203
29510
  }
29511
+ } else if (entry.title) {
29512
+ map2.set(uniqueMapKey(map2, slugifyTitle(entry.title), reserved), entry);
29513
+ }
29514
+ }
29515
+ function addRoadmapEntry(content, entry, reserved) {
29516
+ if (isSwimlaneDeclaration(entry)) {
29517
+ addByKey(content.swimlanes, entry, reserved.swimlanes);
29204
29518
  } else if (isPersonDeclaration(entry)) {
29205
- if (entry.name && !content.persons.has(entry.name)) {
29206
- content.persons.set(entry.name, entry);
29207
- }
29519
+ addByKey(content.persons, entry, reserved.persons);
29208
29520
  } else if (isTeamDeclaration(entry)) {
29209
- if (entry.name && !content.teams.has(entry.name)) {
29210
- content.teams.set(entry.name, entry);
29211
- }
29521
+ addByKey(content.teams, entry, reserved.teams);
29212
29522
  } else if (isAnchorDeclaration(entry)) {
29213
- if (entry.name && !content.anchors.has(entry.name)) {
29214
- content.anchors.set(entry.name, entry);
29215
- }
29523
+ addByKey(content.anchors, entry, reserved.anchors);
29216
29524
  } else if (isLabelDeclaration(entry)) {
29217
- if (entry.name && !content.labels.has(entry.name)) {
29218
- content.labels.set(entry.name, entry);
29219
- }
29525
+ addByKey(content.labels, entry, reserved.labels);
29220
29526
  } else if (isSizeDeclaration(entry)) {
29221
- if (entry.name && !content.sizes.has(entry.name)) {
29222
- content.sizes.set(entry.name, entry);
29223
- }
29527
+ addByKey(content.sizes, entry, reserved.sizes);
29224
29528
  } else if (isStatusDeclaration(entry)) {
29225
- if (entry.name && !content.statuses.has(entry.name)) {
29226
- content.statuses.set(entry.name, entry);
29227
- }
29529
+ addByKey(content.statuses, entry, reserved.statuses);
29228
29530
  } else if (isMilestoneDeclaration(entry)) {
29229
- if (entry.name && !content.milestones.has(entry.name)) {
29230
- content.milestones.set(entry.name, entry);
29231
- }
29531
+ addByKey(content.milestones, entry, reserved.milestones);
29232
29532
  } else if (isFootnoteDeclaration(entry)) {
29233
- if (entry.name && !content.footnotes.has(entry.name)) {
29234
- content.footnotes.set(entry.name, entry);
29235
- }
29533
+ addByKey(content.footnotes, entry, reserved.footnotes);
29236
29534
  }
29237
29535
  }
29238
29536
 
@@ -29268,7 +29566,7 @@ var STYLE_PROP_KEYS = /* @__PURE__ */ new Set([
29268
29566
  "timeline-position",
29269
29567
  "minor-grid"
29270
29568
  ]);
29271
- var BUILTIN_CAPACITY_ICONS = /* @__PURE__ */ new Set([
29569
+ var BUILTIN_CAPACITY_ICONS2 = /* @__PURE__ */ new Set([
29272
29570
  "none",
29273
29571
  "multiplier",
29274
29572
  "person",
@@ -29277,7 +29575,7 @@ var BUILTIN_CAPACITY_ICONS = /* @__PURE__ */ new Set([
29277
29575
  "time"
29278
29576
  ]);
29279
29577
  var BUILTIN_ICON_NAMES = /* @__PURE__ */ new Set([
29280
- ...BUILTIN_CAPACITY_ICONS,
29578
+ ...BUILTIN_CAPACITY_ICONS2,
29281
29579
  "shield",
29282
29580
  "warning",
29283
29581
  "lock",
@@ -29454,7 +29752,7 @@ function suggestKey(key, candidates, cap = 2) {
29454
29752
  }
29455
29753
  return best;
29456
29754
  }
29457
- function propKey(prop) {
29755
+ function propKey2(prop) {
29458
29756
  return prop.key.endsWith(":") ? prop.key.slice(0, -1) : prop.key;
29459
29757
  }
29460
29758
  var DURATION_RE = /^\d+(?:\.\d+)?[dwmqy]$/;
@@ -29465,7 +29763,7 @@ var VERSION_RE = /^v\d+$/;
29465
29763
  var INTEGER_RE = /^\d+$/;
29466
29764
  var BARE_DURATION_SUFFIX_RE = /^[dwmqy]$/;
29467
29765
  var POSITIVE_NUMBER_RE = /^\d+(\.\d+)?$/;
29468
- var POSITIVE_PERCENT_RE = /^\d+(\.\d+)?%$/;
29766
+ var POSITIVE_PERCENT_RE2 = /^\d+(\.\d+)?%$/;
29469
29767
  var POSITIVE_DECIMAL_FRACTION_RE = /^\d+\.\d+$/;
29470
29768
  var POSITIVE_INTEGER_RE = /^\d+$/;
29471
29769
  var ASCII_FALLBACK_RE = /^[\x20-\x7E]{1,3}$/;
@@ -29473,7 +29771,7 @@ var BCP47_RE = /^[a-zA-Z]{2,3}(-[a-zA-Z]{2}|-\d{3})?$/;
29473
29771
  var INCLUDE_MODES = /* @__PURE__ */ new Set(["merge", "ignore", "isolate"]);
29474
29772
  var DIRECTIVE_FIELDS = /* @__PURE__ */ new Set(["locale"]);
29475
29773
  function resolveLocalStart(file) {
29476
- const prop = file?.roadmapDecl?.properties.find((p) => propKey(p) === "start");
29774
+ const prop = file?.roadmapDecl?.properties.find((p) => propKey2(p) === "start");
29477
29775
  if (!prop)
29478
29776
  return { kind: "missing" };
29479
29777
  const raw = prop.value;
@@ -29661,7 +29959,7 @@ var NowlineValidator = class {
29661
29959
  checkDirectiveProperties(directive, accept) {
29662
29960
  const seen = /* @__PURE__ */ new Set();
29663
29961
  for (const prop of directive.properties) {
29664
- const key = propKey(prop);
29962
+ const key = propKey2(prop);
29665
29963
  if (!DIRECTIVE_FIELDS.has(key)) {
29666
29964
  acceptTr(accept, "error", { node: prop, property: "key" }, "NL.E0102", {
29667
29965
  key,
@@ -29765,7 +30063,7 @@ var NowlineValidator = class {
29765
30063
  }
29766
30064
  // --- Property value validation (general) ---
29767
30065
  checkPropertyValues(prop, accept) {
29768
- const key = propKey(prop);
30066
+ const key = propKey2(prop);
29769
30067
  const val = prop.value;
29770
30068
  const vals = prop.values;
29771
30069
  const allValues = val ? [val] : vals;
@@ -29850,7 +30148,7 @@ var NowlineValidator = class {
29850
30148
  accept("error", `Invalid swimlane capacity "${val}". Use a positive integer (e.g. capacity:5) or decimal (e.g. capacity:1.5). Percent literals are not allowed on swimlanes.`, { node: prop, property: "value" });
29851
30149
  }
29852
30150
  } else {
29853
- if (POSITIVE_PERCENT_RE.test(val)) {
30151
+ if (POSITIVE_PERCENT_RE2.test(val)) {
29854
30152
  const pct = parseFloat(val);
29855
30153
  if (pct <= 0) {
29856
30154
  accept("error", `Item capacity "${val}" must be positive.`, {
@@ -29885,7 +30183,7 @@ var NowlineValidator = class {
29885
30183
  }
29886
30184
  if (val === UTILIZATION_NONE)
29887
30185
  break;
29888
- if (POSITIVE_PERCENT_RE.test(val)) {
30186
+ if (POSITIVE_PERCENT_RE2.test(val)) {
29889
30187
  if (parseFloat(val) <= 0) {
29890
30188
  accept("error", `${key} value "${val}" must be positive.`, {
29891
30189
  node: prop,
@@ -29938,14 +30236,14 @@ var NowlineValidator = class {
29938
30236
  }
29939
30237
  // --- Rule 11: Anchor requires date: ---
29940
30238
  checkAnchorRequiredDate(anchor, accept) {
29941
- const dateProp = anchor.properties.find((p) => propKey(p) === "date");
30239
+ const dateProp = anchor.properties.find((p) => propKey2(p) === "date");
29942
30240
  if (!dateProp) {
29943
30241
  acceptTr(accept, "error", { node: anchor }, "NL.E0500", { name: displayName(anchor) });
29944
30242
  }
29945
30243
  }
29946
30244
  // --- R2 + R3: anchor must not precede roadmap start; dated roadmap requires start: ---
29947
30245
  checkAnchorAgainstStart(anchor, accept) {
29948
- const dateProp = anchor.properties.find((p) => propKey(p) === "date");
30246
+ const dateProp = anchor.properties.find((p) => propKey2(p) === "date");
29949
30247
  if (!dateProp?.value)
29950
30248
  return;
29951
30249
  const raw = dateProp.value;
@@ -29976,8 +30274,8 @@ var NowlineValidator = class {
29976
30274
  }
29977
30275
  // --- Rule 12: Milestone requires date: or after: ---
29978
30276
  checkMilestoneRequirement(milestone, accept) {
29979
- const hasDate = milestone.properties.some((p) => propKey(p) === "date");
29980
- const hasAfter = milestone.properties.some((p) => propKey(p) === "after");
30277
+ const hasDate = milestone.properties.some((p) => propKey2(p) === "date");
30278
+ const hasAfter = milestone.properties.some((p) => propKey2(p) === "after");
29981
30279
  if (!hasDate && !hasAfter) {
29982
30280
  acceptTr(accept, "error", { node: milestone }, "NL.E0503", {
29983
30281
  name: displayName(milestone)
@@ -29986,7 +30284,7 @@ var NowlineValidator = class {
29986
30284
  }
29987
30285
  // --- R2 + R3: dated milestone must not precede roadmap start ---
29988
30286
  checkMilestoneAgainstStart(milestone, accept) {
29989
- const dateProp = milestone.properties.find((p) => propKey(p) === "date");
30287
+ const dateProp = milestone.properties.find((p) => propKey2(p) === "date");
29990
30288
  if (!dateProp?.value)
29991
30289
  return;
29992
30290
  const raw = dateProp.value;
@@ -30018,7 +30316,7 @@ var NowlineValidator = class {
30018
30316
  }
30019
30317
  // --- Rule 13: Footnote requires on ---
30020
30318
  checkFootnoteOn(footnote, accept) {
30021
- const hasOn = footnote.properties.some((p) => propKey(p) === "on");
30319
+ const hasOn = footnote.properties.some((p) => propKey2(p) === "on");
30022
30320
  if (!hasOn) {
30023
30321
  acceptTr(accept, "error", { node: footnote }, "NL.E0505");
30024
30322
  }
@@ -30031,15 +30329,15 @@ var NowlineValidator = class {
30031
30329
  // a clear nudge toward the spec-mandated direction.
30032
30330
  checkNoFootnoteProperty(node, accept) {
30033
30331
  for (const prop of node.properties) {
30034
- if (propKey(prop) === "footnote") {
30332
+ if (propKey2(prop) === "footnote") {
30035
30333
  accept("error", `Property "footnote:" is not valid on ${describeNode(node)}. Footnotes attach via "on:" on the footnote declaration \u2014 declare \`footnote <id> on:<target-id>\` instead.`, { node: prop });
30036
30334
  }
30037
30335
  }
30038
30336
  }
30039
30337
  // --- Rule 10: Item requires either size: or duration: ---
30040
30338
  checkItemRequiredDuration(item, accept) {
30041
- const hasDuration = item.properties.some((p) => propKey(p) === "duration");
30042
- const hasSize = item.properties.some((p) => propKey(p) === "size");
30339
+ const hasDuration = item.properties.some((p) => propKey2(p) === "duration");
30340
+ const hasSize = item.properties.some((p) => propKey2(p) === "size");
30043
30341
  if (!hasDuration && !hasSize) {
30044
30342
  acceptTr(accept, "error", { node: item }, "NL.E0600", { name: displayName(item) });
30045
30343
  }
@@ -30047,7 +30345,7 @@ var NowlineValidator = class {
30047
30345
  // --- Parallel/group rule 3: size/duration/remaining/capacity not valid on parallel/group ---
30048
30346
  checkNoComputedProperties(node, accept) {
30049
30347
  for (const prop of node.properties) {
30050
- const key = propKey(prop);
30348
+ const key = propKey2(prop);
30051
30349
  if (key === "size" || key === "duration" || key === "remaining" || key === "capacity") {
30052
30350
  accept("error", `"${key}" is not valid on ${node.$type === "ParallelBlock" ? "parallel" : "group"} (computed from children).`, {
30053
30351
  node: prop
@@ -30074,7 +30372,7 @@ var NowlineValidator = class {
30074
30372
  // --- Rule 20: Raw style properties banned on roadmap-section entities ---
30075
30373
  checkNoRawStyleProperties(node, accept) {
30076
30374
  for (const prop of node.properties) {
30077
- const key = propKey(prop);
30375
+ const key = propKey2(prop);
30078
30376
  if (STYLE_PROP_KEYS.has(key)) {
30079
30377
  accept("error", `Raw style property "${key}" is not allowed on ${describeNode(node)}. Declare a named style in config and reference it via "style:id".`, { node: prop });
30080
30378
  }
@@ -30099,7 +30397,7 @@ var NowlineValidator = class {
30099
30397
  return;
30100
30398
  const computedBanned = node.$type === "ParallelBlock" || node.$type === "GroupBlock" ? /* @__PURE__ */ new Set(["size", "duration", "remaining", "capacity"]) : null;
30101
30399
  for (const prop of node.properties) {
30102
- const key = propKey(prop);
30400
+ const key = propKey2(prop);
30103
30401
  if (known.has(key))
30104
30402
  continue;
30105
30403
  if (UNIVERSAL_ENTITY_PROPS.has(key))
@@ -30130,7 +30428,7 @@ var NowlineValidator = class {
30130
30428
  // enforced by checkSymbolReferences at file scope so style blocks and
30131
30429
  // `default <entity>` lines share a single code path.
30132
30430
  checkStylePropertyEnum(prop, accept) {
30133
- const key = propKey(prop);
30431
+ const key = propKey2(prop);
30134
30432
  const val = prop.value;
30135
30433
  if (key === "bg" || key === "fg" || key === "text") {
30136
30434
  if (!isColorValue(val)) {
@@ -30156,7 +30454,7 @@ var NowlineValidator = class {
30156
30454
  }
30157
30455
  // --- Size declaration: rule 5 (effort: required), rule 4 (id format) ---
30158
30456
  checkSizeDeclaration(decl, accept) {
30159
- const effortProp = decl.properties.find((p) => propKey(p) === "effort");
30457
+ const effortProp = decl.properties.find((p) => propKey2(p) === "effort");
30160
30458
  if (!effortProp) {
30161
30459
  accept("error", `Size "${displayName(decl)}" requires an "effort:" property.`, {
30162
30460
  node: decl
@@ -30200,8 +30498,8 @@ var NowlineValidator = class {
30200
30498
  checkUtilizationOrdering(decl, accept) {
30201
30499
  if (isDefaultDeclaration(decl) && decl.entityType !== "swimlane")
30202
30500
  return;
30203
- const warnProp = decl.properties.find((p) => propKey(p) === "utilization-warn-at");
30204
- const overProp = decl.properties.find((p) => propKey(p) === "utilization-over-at");
30501
+ const warnProp = decl.properties.find((p) => propKey2(p) === "utilization-warn-at");
30502
+ const overProp = decl.properties.find((p) => propKey2(p) === "utilization-over-at");
30205
30503
  if (!warnProp || !overProp)
30206
30504
  return;
30207
30505
  const warn = parseUtilizationFraction(warnProp.value);
@@ -30234,7 +30532,7 @@ var NowlineValidator = class {
30234
30532
  const banned = DEFAULT_BANNED[decl.entityType];
30235
30533
  if (banned) {
30236
30534
  for (const prop of decl.properties) {
30237
- const key = propKey(prop);
30535
+ const key = propKey2(prop);
30238
30536
  if (banned.has(key)) {
30239
30537
  accept("error", `"${key}" cannot be set on "default ${decl.entityType}". Identity-defining, sizing, sequencing, reference, and prose properties must be explicit on each entity.`, { node: prop });
30240
30538
  }
@@ -30245,7 +30543,7 @@ var NowlineValidator = class {
30245
30543
  // Rule 8: custom calendar requires all four fields.
30246
30544
  checkCalendarBlockConsistency(file, accept) {
30247
30545
  const calendarBlocks = file.configEntries.filter(isCalendarBlock);
30248
- const calendarProp = file.roadmapDecl?.properties.find((p) => propKey(p) === "calendar");
30546
+ const calendarProp = file.roadmapDecl?.properties.find((p) => propKey2(p) === "calendar");
30249
30547
  const calendarMode = calendarProp?.value;
30250
30548
  if (calendarBlocks.length > 0 && calendarMode !== "custom") {
30251
30549
  for (const block2 of calendarBlocks) {
@@ -30257,7 +30555,7 @@ var NowlineValidator = class {
30257
30555
  }
30258
30556
  if (calendarMode === "custom" && calendarBlocks.length > 0) {
30259
30557
  for (const block2 of calendarBlocks) {
30260
- const presentKeys = new Set(block2.properties.map((p) => propKey(p)));
30558
+ const presentKeys = new Set(block2.properties.map((p) => propKey2(p)));
30261
30559
  for (const field of CALENDAR_FIELDS) {
30262
30560
  if (!presentKeys.has(field)) {
30263
30561
  accept("error", `calendar:custom requires "${field}" in the calendar config block.`, { node: block2 });
@@ -30270,7 +30568,7 @@ var NowlineValidator = class {
30270
30568
  checkCalendarBlock(block2, accept) {
30271
30569
  const seen = /* @__PURE__ */ new Set();
30272
30570
  for (const prop of block2.properties) {
30273
- const key = propKey(prop);
30571
+ const key = propKey2(prop);
30274
30572
  if (!CALENDAR_FIELDS.has(key)) {
30275
30573
  accept("error", `Unknown calendar property "${key}". Allowed: ${[...CALENDAR_FIELDS].join(", ")}.`, { node: prop, property: "key" });
30276
30574
  continue;
@@ -30294,7 +30592,7 @@ var NowlineValidator = class {
30294
30592
  checkScaleBlock(block2, accept) {
30295
30593
  const seen = /* @__PURE__ */ new Set();
30296
30594
  for (const prop of block2.properties) {
30297
- const key = propKey(prop);
30595
+ const key = propKey2(prop);
30298
30596
  if (!SCALE_FIELDS.has(key)) {
30299
30597
  accept("error", `Unknown scale property "${key}". Allowed: ${[...SCALE_FIELDS].join(", ")}.`, { node: prop, property: "key" });
30300
30598
  continue;
@@ -30330,7 +30628,7 @@ var NowlineValidator = class {
30330
30628
  for (let i = 0; i < file.roadmapEntries.length; i++) {
30331
30629
  const entry = file.roadmapEntries[i];
30332
30630
  visitPropertiesDeep(entry, (prop) => {
30333
- const key = propKey(prop);
30631
+ const key = propKey2(prop);
30334
30632
  if (key === "size" && prop.value) {
30335
30633
  const val = prop.value;
30336
30634
  const declIdx = sizeOrder.get(val);
@@ -30369,7 +30667,7 @@ var NowlineValidator = class {
30369
30667
  const declaredIds = collectReferenceableIds(file);
30370
30668
  const visit = (entry) => {
30371
30669
  visitPropertiesDeep(entry, (prop) => {
30372
- const key = propKey(prop);
30670
+ const key = propKey2(prop);
30373
30671
  if (key !== "after" && key !== "before" && key !== "on")
30374
30672
  return;
30375
30673
  const vals = prop.value ? [prop.value] : prop.values;
@@ -30408,7 +30706,7 @@ var NowlineValidator = class {
30408
30706
  const props = entry.properties ?? [];
30409
30707
  const allowed = isItemDeclaration(entry) || isParallelBlock(entry) || isGroupBlock(entry);
30410
30708
  for (const prop of props) {
30411
- const key = propKey(prop);
30709
+ const key = propKey2(prop);
30412
30710
  if (key !== "after" && key !== "before")
30413
30711
  continue;
30414
30712
  const vals = prop.value ? [prop.value] : prop.values;
@@ -30473,7 +30771,7 @@ var NowlineValidator = class {
30473
30771
  if (!idName)
30474
30772
  return;
30475
30773
  for (const prop of props) {
30476
- const key = propKey(prop);
30774
+ const key = propKey2(prop);
30477
30775
  if (key === "after") {
30478
30776
  const refs = prop.value ? [prop.value] : prop.values;
30479
30777
  for (const r of refs) {
@@ -30593,7 +30891,7 @@ var NowlineValidator = class {
30593
30891
  if (decl.name && BUILTIN_ICON_NAMES.has(decl.name)) {
30594
30892
  accept("error", `Symbol id "${decl.name}" collides with a built-in icon name. Reserved built-ins: ${[...BUILTIN_ICON_NAMES].sort().join(", ")}.`, { node: decl, property: "name" });
30595
30893
  }
30596
- const unicodeProp = decl.properties.find((p) => propKey(p) === "unicode");
30894
+ const unicodeProp = decl.properties.find((p) => propKey2(p) === "unicode");
30597
30895
  if (!unicodeProp) {
30598
30896
  accept("error", `Symbol "${displayName(decl)}" requires a "unicode:" property (e.g. unicode:"\u{1F4B0}" or unicode:"\\u{1F464}").`, { node: decl });
30599
30897
  } else if (!unicodeProp.value || unicodeProp.value.length === 0) {
@@ -30602,7 +30900,7 @@ var NowlineValidator = class {
30602
30900
  property: "value"
30603
30901
  });
30604
30902
  }
30605
- const asciiProp = decl.properties.find((p) => propKey(p) === "ascii");
30903
+ const asciiProp = decl.properties.find((p) => propKey2(p) === "ascii");
30606
30904
  if (asciiProp) {
30607
30905
  const raw = asciiProp.value ?? "";
30608
30906
  if (!ASCII_FALLBACK_RE.test(raw)) {
@@ -30610,7 +30908,7 @@ var NowlineValidator = class {
30610
30908
  }
30611
30909
  }
30612
30910
  for (const prop of decl.properties) {
30613
- const key = propKey(prop);
30911
+ const key = propKey2(prop);
30614
30912
  if (key !== "unicode" && key !== "ascii" && key !== "link" && key !== "description") {
30615
30913
  accept("error", `Unknown symbol property "${key}". Allowed: unicode, ascii, link, description.`, { node: prop, property: "key" });
30616
30914
  }
@@ -30651,13 +30949,13 @@ var NowlineValidator = class {
30651
30949
  return;
30652
30950
  if (!isIdentifier(val))
30653
30951
  return;
30654
- if (key === "capacity-icon" && BUILTIN_CAPACITY_ICONS.has(val))
30952
+ if (key === "capacity-icon" && BUILTIN_CAPACITY_ICONS2.has(val))
30655
30953
  return;
30656
30954
  if (key === "icon" && BUILTIN_ICON_NAMES.has(val))
30657
30955
  return;
30658
30956
  const declIdx = symbolOrder.get(val);
30659
30957
  if (declIdx === void 0) {
30660
- const builtins = key === "capacity-icon" ? [...BUILTIN_CAPACITY_ICONS].sort().join(", ") : [...BUILTIN_ICON_NAMES].sort().join(", ");
30958
+ const builtins = key === "capacity-icon" ? [...BUILTIN_CAPACITY_ICONS2].sort().join(", ") : [...BUILTIN_ICON_NAMES].sort().join(", ");
30661
30959
  accept("error", `${key}: "${val}" is neither a built-in (${builtins}) nor a declared symbol. Add "symbol ${val} unicode:..." earlier in config or use a quoted Unicode literal.`, { node: propNode, property: "value" });
30662
30960
  } else if (declIdx >= entryIdx) {
30663
30961
  accept("error", `${key}: symbol "${val}" is referenced before its declaration. Move "symbol ${val}" above this entry.`, { node: propNode, property: "value" });
@@ -30667,11 +30965,11 @@ var NowlineValidator = class {
30667
30965
  const entry = file.configEntries[i];
30668
30966
  if (isStyleDeclaration(entry)) {
30669
30967
  for (const sp of entry.properties) {
30670
- checkRef(i, propKey(sp), sp.value, sp);
30968
+ checkRef(i, propKey2(sp), sp.value, sp);
30671
30969
  }
30672
30970
  } else if (isDefaultDeclaration(entry)) {
30673
30971
  for (const ep of entry.properties) {
30674
- checkRef(i, propKey(ep), ep.value, ep);
30972
+ checkRef(i, propKey2(ep), ep.value, ep);
30675
30973
  }
30676
30974
  }
30677
30975
  }
@@ -30707,7 +31005,7 @@ function isUtilizationAllowedHere(parent) {
30707
31005
  function parseUtilizationFraction(val) {
30708
31006
  if (!val || val === UTILIZATION_NONE)
30709
31007
  return null;
30710
- if (POSITIVE_PERCENT_RE.test(val)) {
31008
+ if (POSITIVE_PERCENT_RE2.test(val)) {
30711
31009
  const n = parseFloat(val);
30712
31010
  return Number.isFinite(n) && n > 0 ? n / 100 : null;
30713
31011
  }
@@ -30876,315 +31174,6 @@ function createNowlineServices(context = {}) {
30876
31174
  return { shared, Nowline };
30877
31175
  }
30878
31176
 
30879
- // ../browser/dist/diagnostic-row.js
30880
- function fromLangiumDiagnostic(diag, file) {
30881
- return {
30882
- severity: diag.severity === 2 ? "warning" : "error",
30883
- // resolveDiagnosticCode prefers the stable validator code (NL.Exxxx)
30884
- // carried in `data` so the preview table matches the CLI / Problems
30885
- // panel, then falls back to Langium's `code`, then a message heuristic.
30886
- code: resolveDiagnosticCode(diag),
30887
- message: diag.message,
30888
- suggestion: extractSuggestion(diag.message),
30889
- file,
30890
- line: (diag.range?.start.line ?? 0) + 1,
30891
- column: (diag.range?.start.character ?? 0) + 1
30892
- };
30893
- }
30894
- function fromParserError(err, file) {
30895
- return {
30896
- severity: "error",
30897
- code: "parse-error",
30898
- message: err.message,
30899
- file,
30900
- line: err.token?.startLine ?? 1,
30901
- column: err.token?.startColumn ?? 1
30902
- };
30903
- }
30904
- function fromLexerError(err, file) {
30905
- return {
30906
- severity: "error",
30907
- code: "lex-error",
30908
- message: err.message,
30909
- file,
30910
- line: err.line ?? 1,
30911
- column: err.column ?? 1
30912
- };
30913
- }
30914
- function fromResolveDiagnostic(diag) {
30915
- return {
30916
- severity: diag.severity,
30917
- code: "include",
30918
- message: diag.message,
30919
- file: diag.sourcePath,
30920
- line: diag.line !== void 0 ? diag.line + 1 : 1,
30921
- column: 1
30922
- };
30923
- }
30924
- function fromRenderWarning(message, file, severity = "warning") {
30925
- return {
30926
- severity,
30927
- code: "render.warning",
30928
- message,
30929
- file,
30930
- line: 1,
30931
- column: 1
30932
- };
30933
- }
30934
-
30935
- // ../browser/dist/no-op-include-resolver.js
30936
- var NOWLINE_BROWSER_NOOP_INCLUDE_TAG = "__nowline_browser_noop_include__";
30937
- async function noOpIncludeReadFile(absPath) {
30938
- throw new Error(`${NOWLINE_BROWSER_NOOP_INCLUDE_TAG}: include "${absPath}" was skipped \u2014 running in single-file mode.`);
30939
- }
30940
- function isNoOpIncludeDiagnosticMessage(message) {
30941
- return message.includes(NOWLINE_BROWSER_NOOP_INCLUDE_TAG);
30942
- }
30943
-
30944
- // ../layout/dist/capacity.js
30945
- var BUILTIN_CAPACITY_ICONS2 = /* @__PURE__ */ new Set([
30946
- "none",
30947
- "multiplier",
30948
- "person",
30949
- "people",
30950
- "points",
30951
- "time"
30952
- ]);
30953
- var POSITIVE_INT_RE = /^\d+$/;
30954
- var POSITIVE_DECIMAL_RE = /^\d+\.\d+$/;
30955
- var POSITIVE_PERCENT_RE2 = /^\d+(?:\.\d+)?%$/;
30956
- function parseCapacityValue(raw) {
30957
- if (!raw)
30958
- return null;
30959
- if (POSITIVE_INT_RE.test(raw)) {
30960
- const n = parseInt(raw, 10);
30961
- return n > 0 ? n : null;
30962
- }
30963
- if (POSITIVE_DECIMAL_RE.test(raw)) {
30964
- const n = parseFloat(raw);
30965
- return Number.isFinite(n) && n > 0 ? n : null;
30966
- }
30967
- if (POSITIVE_PERCENT_RE2.test(raw)) {
30968
- const n = parseFloat(raw.slice(0, -1)) / 100;
30969
- return Number.isFinite(n) && n > 0 ? n : null;
30970
- }
30971
- return null;
30972
- }
30973
- function formatCapacityNumber(value) {
30974
- if (Number.isInteger(value))
30975
- return String(value);
30976
- let s = value.toFixed(6);
30977
- s = s.replace(/0+$/, "");
30978
- s = s.replace(/\.$/, "");
30979
- return s;
30980
- }
30981
- function propKey2(prop) {
30982
- return prop.key.endsWith(":") ? prop.key.slice(0, -1) : prop.key;
30983
- }
30984
- function symbolUnicode(decl) {
30985
- for (const p of decl.properties) {
30986
- if (propKey2(p) === "unicode" && p.value)
30987
- return p.value;
30988
- }
30989
- return void 0;
30990
- }
30991
- function resolveCapacityIcon(icon, symbols) {
30992
- if (icon === "none")
30993
- return null;
30994
- if (BUILTIN_CAPACITY_ICONS2.has(icon)) {
30995
- return {
30996
- kind: "builtin",
30997
- name: icon
30998
- };
30999
- }
31000
- const custom = symbols.get(icon);
31001
- if (custom) {
31002
- const unicode = symbolUnicode(custom);
31003
- return { kind: "literal", text: unicode ?? icon };
31004
- }
31005
- return { kind: "literal", text: icon };
31006
- }
31007
- function estimateCapacitySuffixWidth(text, icon, fontSizePx) {
31008
- if (!icon)
31009
- return text.length * fontSizePx * 0.58;
31010
- if (icon.kind === "builtin" && icon.name === "multiplier") {
31011
- return (text.length + 1) * fontSizePx * 0.58;
31012
- }
31013
- const glyphWidthEm = 1;
31014
- const gapEm = 0.1;
31015
- return text.length * fontSizePx * 0.58 + (gapEm + glyphWidthEm) * fontSizePx;
31016
- }
31017
-
31018
- // ../layout/dist/frame-tab-geometry.js
31019
- var FRAME_TAB_TITLE_PX_PER_CHAR = 6.5;
31020
- var FRAME_TAB_OWNER_PX_PER_CHAR = 5;
31021
- var FRAME_TAB_INNER_GAP_PX = 6;
31022
- var FRAME_TAB_LEFT_INSET_PX = 12;
31023
- var FRAME_TAB_RIGHT_INSET_PX = 12;
31024
- var FRAME_TAB_MIN_WIDTH_PX = 56;
31025
- var FRAME_TAB_OFFSET_FROM_BOX_PX = 10;
31026
- function frameTabGeometry(boxX, title, owner, capacityBadgeWidth = 0, footnoteIndicatorWidth = 0) {
31027
- const tabX = boxX + FRAME_TAB_OFFSET_FROM_BOX_PX;
31028
- const titleX = tabX + FRAME_TAB_LEFT_INSET_PX;
31029
- const titleTextWidth = title.length * FRAME_TAB_TITLE_PX_PER_CHAR;
31030
- let cursorX = titleX + titleTextWidth;
31031
- let ownerTextWidth = 0;
31032
- let ownerX = 0;
31033
- if (owner) {
31034
- ownerTextWidth = `owner: ${owner}`.length * FRAME_TAB_OWNER_PX_PER_CHAR;
31035
- ownerX = cursorX + FRAME_TAB_INNER_GAP_PX;
31036
- cursorX = ownerX + ownerTextWidth;
31037
- }
31038
- let badgeX = 0;
31039
- if (capacityBadgeWidth > 0) {
31040
- badgeX = cursorX + FRAME_TAB_INNER_GAP_PX;
31041
- cursorX = badgeX + capacityBadgeWidth;
31042
- }
31043
- let footnoteRightX = 0;
31044
- if (footnoteIndicatorWidth > 0) {
31045
- footnoteRightX = cursorX + FRAME_TAB_INNER_GAP_PX + footnoteIndicatorWidth;
31046
- cursorX = footnoteRightX;
31047
- }
31048
- const contentW = cursorX - tabX + FRAME_TAB_RIGHT_INSET_PX;
31049
- const tabW = Math.max(FRAME_TAB_MIN_WIDTH_PX, contentW);
31050
- return {
31051
- titleTextWidth,
31052
- ownerTextWidth,
31053
- capacityBadgeWidth,
31054
- footnoteIndicatorWidth,
31055
- titleX,
31056
- ownerX,
31057
- badgeX,
31058
- footnoteRightX,
31059
- tabX,
31060
- tabW,
31061
- rightX: tabX + tabW
31062
- };
31063
- }
31064
-
31065
- // ../layout/dist/header-card-geometry.js
31066
- var HEADER_CARD_PADDING_X = 16;
31067
- var HEADER_CARD_PADDING_TOP = 26;
31068
- var HEADER_CARD_PADDING_BOTTOM = 14;
31069
- var HEADER_TITLE_LINE_HEIGHT_PX = 20;
31070
- var HEADER_AUTHOR_LINE_HEIGHT_PX = 14;
31071
- var HEADER_TITLE_TO_AUTHOR_GAP_PX = 18;
31072
- var HEADER_TITLE_FONT_SIZE_PX = 16;
31073
- var HEADER_AUTHOR_FONT_SIZE_PX = 11;
31074
-
31075
- // ../layout/dist/include-chrome-geometry.js
31076
- var INCLUDE_CHROME_OFFSET_FROM_BOX_PX = 24;
31077
- var INCLUDE_CHROME_TAB_LEFT_INSET_PX = 10;
31078
- var INCLUDE_CHROME_TAB_RIGHT_INSET_PX = 10;
31079
- var INCLUDE_CHROME_TAB_LABEL_PER_CHAR_PX = 6;
31080
- var INCLUDE_CHROME_TAB_MIN_WIDTH_PX = 60;
31081
- var INCLUDE_CHROME_BADGE_GAP_PX = 6;
31082
- var INCLUDE_CHROME_BADGE_SIZE_PX = 18;
31083
- var INCLUDE_CHROME_SOURCE_GAP_PX = 6;
31084
- var INCLUDE_CHROME_SOURCE_PER_CHAR_PX = 5.5;
31085
- var INCLUDE_CHROME_SOURCE_HALO_PAD_PX = 3;
31086
- function includeChromeGeometry(boxX, label, sourcePath) {
31087
- const tabX = boxX + INCLUDE_CHROME_OFFSET_FROM_BOX_PX;
31088
- const tabLabelX = tabX + INCLUDE_CHROME_TAB_LEFT_INSET_PX;
31089
- const labelTextWidth = label.length * INCLUDE_CHROME_TAB_LABEL_PER_CHAR_PX;
31090
- const tabWidth = Math.max(INCLUDE_CHROME_TAB_MIN_WIDTH_PX, labelTextWidth + INCLUDE_CHROME_TAB_LEFT_INSET_PX + INCLUDE_CHROME_TAB_RIGHT_INSET_PX);
31091
- const badgeX = tabX + tabWidth + INCLUDE_CHROME_BADGE_GAP_PX;
31092
- const badgeRightX = badgeX + INCLUDE_CHROME_BADGE_SIZE_PX;
31093
- let sourceTextWidth = 0;
31094
- let sourceTextX = 0;
31095
- let sourceHaloX = 0;
31096
- let sourceHaloWidth = 0;
31097
- let chromeRightX = badgeRightX;
31098
- if (sourcePath) {
31099
- sourceTextX = badgeRightX + INCLUDE_CHROME_SOURCE_GAP_PX;
31100
- sourceTextWidth = sourcePath.length * INCLUDE_CHROME_SOURCE_PER_CHAR_PX;
31101
- sourceHaloX = sourceTextX - INCLUDE_CHROME_SOURCE_HALO_PAD_PX;
31102
- sourceHaloWidth = sourceTextWidth + INCLUDE_CHROME_SOURCE_HALO_PAD_PX * 2;
31103
- chromeRightX = sourceHaloX + sourceHaloWidth;
31104
- }
31105
- return {
31106
- labelTextWidth,
31107
- sourceTextWidth,
31108
- tabX,
31109
- tabWidth,
31110
- tabLabelX,
31111
- badgeX,
31112
- badgeSize: INCLUDE_CHROME_BADGE_SIZE_PX,
31113
- sourceHaloX,
31114
- sourceHaloWidth,
31115
- sourceTextX,
31116
- chromeRightX
31117
- };
31118
- }
31119
-
31120
- // ../layout/dist/item-bar-geometry.js
31121
- var ITEM_CAPTION_INSET_X_PX = 12;
31122
- var ITEM_CAPTION_SPILL_GAP_PX = 6;
31123
- var ITEM_CAPTION_TITLE_BASELINE_OFFSET_PX = 20;
31124
- var ITEM_CAPTION_META_BASELINE_OFFSET_PX = 38;
31125
- var ITEM_CAPTION_TITLE_FONT_SIZE_PX = 13;
31126
- var ITEM_CAPTION_META_FONT_SIZE_PX = 11;
31127
- var ITEM_STATUS_DOT_INSET_RIGHT_PX = 12;
31128
- var ITEM_STATUS_DOT_INSET_TOP_PX = 12;
31129
- var ITEM_STATUS_DOT_RADIUS_PX = 5;
31130
- var ITEM_FOOTNOTE_INDICATOR_INSET_RIGHT_PX = 22;
31131
- var ITEM_FOOTNOTE_INDICATOR_BASELINE_OFFSET_PX = 14;
31132
- var ITEM_FOOTNOTE_INDICATOR_STEP_PX = 8;
31133
- var ITEM_LINK_ICON_TILE_SIZE_PX = 14;
31134
- var ITEM_LINK_ICON_INSET_PX = 6;
31135
- var ITEM_DECORATION_SPILL_GAP_PX = 4;
31136
- var MIN_BAR_WIDTH_FOR_DOT_PX = ITEM_STATUS_DOT_INSET_RIGHT_PX + ITEM_STATUS_DOT_RADIUS_PX;
31137
- var MIN_BAR_WIDTH_FOR_LINK_AND_DOT_PX = ITEM_LINK_ICON_INSET_PX + ITEM_LINK_ICON_TILE_SIZE_PX + ITEM_DECORATION_SPILL_GAP_PX + ITEM_STATUS_DOT_INSET_RIGHT_PX + ITEM_STATUS_DOT_RADIUS_PX;
31138
- var MIN_BAR_WIDTH_FOR_FOOTNOTE_PX = ITEM_FOOTNOTE_INDICATOR_INSET_RIGHT_PX + 1;
31139
- var INLINE_DATE_GLYPH_TILE_SIZE_PX = 12;
31140
- var INLINE_DATE_GLYPH_INSET_LEFT_PX = 6;
31141
- var INLINE_DATE_GLYPH_INSET_RIGHT_PX = 6;
31142
- var INLINE_DATE_GLYPH_INSET_TOP_PX = 5;
31143
- var INLINE_DATE_GLYPH_GAP_PX = ITEM_DECORATION_SPILL_GAP_PX;
31144
- var MIN_BAR_WIDTH_FOR_INLINE_DATE_PX = INLINE_DATE_GLYPH_INSET_LEFT_PX + INLINE_DATE_GLYPH_TILE_SIZE_PX + INLINE_DATE_GLYPH_GAP_PX + INLINE_DATE_GLYPH_TILE_SIZE_PX + INLINE_DATE_GLYPH_INSET_RIGHT_PX;
31145
- var LABEL_CHIP_HEIGHT_PX = 13;
31146
- var LABEL_CHIP_GAP_ABOVE_PROGRESS_STRIP_PX = 3;
31147
- var LABEL_CHIP_GAP_BETWEEN_PX = 4;
31148
- var LABEL_CHIP_ROW_GAP_PX = 4;
31149
- var LABEL_CHIP_ROW_STEP_PX = LABEL_CHIP_HEIGHT_PX + LABEL_CHIP_ROW_GAP_PX;
31150
- var SPILL_ROW_SLACK_FRACTION = 0.25;
31151
- function packSpillChips(chips, barVisualWidth) {
31152
- if (chips.length === 0)
31153
- return { rows: [[]], expanded: false };
31154
- const rows = [[]];
31155
- let used = 0;
31156
- let rowCap = barVisualWidth;
31157
- let expanded = false;
31158
- for (const chip of chips) {
31159
- const row = rows[rows.length - 1];
31160
- const needed = (row.length === 0 ? 0 : LABEL_CHIP_GAP_BETWEEN_PX) + chip.width;
31161
- const wouldBe = used + needed;
31162
- if (wouldBe <= rowCap) {
31163
- row.push(chip);
31164
- used = wouldBe;
31165
- continue;
31166
- }
31167
- if (row.length === 0) {
31168
- row.push(chip);
31169
- used = chip.width;
31170
- continue;
31171
- }
31172
- const overflow = wouldBe - rowCap;
31173
- const slack = chip.width * SPILL_ROW_SLACK_FRACTION;
31174
- if (!expanded && overflow <= slack) {
31175
- row.push(chip);
31176
- used = wouldBe;
31177
- rowCap = wouldBe;
31178
- expanded = true;
31179
- continue;
31180
- }
31181
- rows.push([chip]);
31182
- used = chip.width;
31183
- rowCap = barVisualWidth;
31184
- }
31185
- return { rows, expanded };
31186
- }
31187
-
31188
31177
  // ../layout/dist/dsl-utils.js
31189
31178
  function stripColon(key) {
31190
31179
  return key.endsWith(":") ? key.slice(0, -1) : key;
@@ -32942,7 +32931,8 @@ var GroupNode = class {
32942
32931
  const startX = cursor.x;
32943
32932
  const title = node.title ?? node.name;
32944
32933
  const previousFlowKey = ctx.currentFlowKey;
32945
- ctx.currentFlowKey = `${previousFlowKey}/group:${node.name ?? "g"}`;
32934
+ ctx.nextGroupId += 1;
32935
+ ctx.currentFlowKey = `${previousFlowKey}/group:${node.name ?? `group-${ctx.nextGroupId}`}`;
32946
32936
  const hasChiclet = style.bg !== "none" && style.bg !== "#ffffff" && Boolean(title);
32947
32937
  const topPad = hasChiclet ? GROUP_TITLE_TAB_HEIGHT_PX + GROUP_TITLE_TAB_GUTTER_PX : 0;
32948
32938
  const bottomPad = hasChiclet ? GROUP_BOTTOM_PAD_PX : 0;
@@ -33131,7 +33121,8 @@ var ParallelNode = class {
33131
33121
  let maxRight = startX;
33132
33122
  let accumulatedHeight = 0;
33133
33123
  const previousFlowKey = ctx.currentFlowKey;
33134
- const parId = node.name ?? "p";
33124
+ ctx.nextParallelId += 1;
33125
+ const parId = node.name ?? `parallel-${ctx.nextParallelId}`;
33135
33126
  let childIndex = 0;
33136
33127
  for (const child of node.content) {
33137
33128
  if (child.$type === "DescriptionDirective")
@@ -35727,13 +35718,17 @@ function buildIncludeRegions(regions, ctx, startY, deps) {
35727
35718
  chartTopY: innerStartY,
35728
35719
  chartBottomY: innerStartY,
35729
35720
  swimlaneBottomY: innerStartY,
35730
- chartRightX: ctx.chartRightX
35721
+ chartRightX: ctx.chartRightX,
35722
+ nextParallelId: 0,
35723
+ nextGroupId: 0
35731
35724
  };
35732
35725
  const nestedSwimlanes = [];
35733
35726
  let cursorY = innerStartY;
35734
35727
  let bandIndex = 0;
35735
35728
  let nestedContentRightX = childCtx.timeline.originX;
35736
35729
  for (const lane of region.content.swimlanes.values()) {
35730
+ childCtx.nextParallelId = 0;
35731
+ childCtx.nextGroupId = 0;
35737
35732
  const { positioned, usedHeight, usedRightX } = new SwimlaneNode({ lane, bandIndex }, deps).place({ x: childCtx.timeline.originX, y: cursorY }, childCtx);
35738
35733
  nestedSwimlanes.push(positioned);
35739
35734
  cursorY += usedHeight;
@@ -36081,7 +36076,9 @@ var RoadmapNode = class {
36081
36076
  chartTopY: timelineY + timelineHeightBudget,
36082
36077
  chartBottomY: 0,
36083
36078
  swimlaneBottomY: 0,
36084
- chartRightX: finalChartRightX
36079
+ chartRightX: finalChartRightX,
36080
+ nextParallelId: 0,
36081
+ nextGroupId: 0
36085
36082
  };
36086
36083
  for (const e of datePinnedEntries) {
36087
36084
  const placement = markerRowPlacements.get(e.id);
@@ -36101,6 +36098,8 @@ var RoadmapNode = class {
36101
36098
  const swimlaneDefaultStyle = resolveStyle("swimlane", [], styleCtx);
36102
36099
  const interBandGapPx = SPACING_PX[swimlaneDefaultStyle.spacing] ?? 0;
36103
36100
  const runSwimlaneLoop = () => {
36101
+ ctx.nextParallelId = 0;
36102
+ ctx.nextGroupId = 0;
36104
36103
  const out = [];
36105
36104
  let cursorY = ctx.chartTopY;
36106
36105
  let bIndex = 0;
@@ -36779,24 +36778,25 @@ function sequenceItem(node, cursor, ctx, ownerOverride) {
36779
36778
  if (id) {
36780
36779
  ctx.entityLeftEdges.set(id, logicalLeft);
36781
36780
  ctx.entityRightEdges.set(id, logicalRight);
36782
- ctx.entityMidpoints.set(id, {
36783
- x: (logicalLeft + logicalRight) / 2,
36784
- y: itemBox.y + itemBox.height / 2
36785
- });
36786
- ctx.entityVisualLeftX.set(id, itemBox.x);
36787
- ctx.entityVisualRightX.set(id, itemBox.x + itemBox.width);
36788
- const arrowSource = textSpills ? {
36789
- x: itemBox.x + itemBox.width,
36790
- y: itemBox.y + itemBox.height - PROGRESS_STRIP_HEIGHT_PX / 2
36791
- } : {
36792
- x: itemBox.x + itemBox.width,
36793
- y: itemBox.y + itemBox.height / 2
36794
- };
36795
- ctx.itemArrowSource.set(id, arrowSource);
36796
- ctx.itemFlowKey.set(id, ctx.currentFlowKey);
36797
- const slackAttachY = textSpills ? itemBox.y + itemBox.height - PROGRESS_STRIP_HEIGHT_PX / 2 : itemBox.y + itemBox.height / 2;
36798
- ctx.itemSlackAttachY.set(id, slackAttachY);
36799
36781
  }
36782
+ const drawKey = id ?? syntheticItemKey(node);
36783
+ ctx.entityMidpoints.set(drawKey, {
36784
+ x: (logicalLeft + logicalRight) / 2,
36785
+ y: itemBox.y + itemBox.height / 2
36786
+ });
36787
+ ctx.entityVisualLeftX.set(drawKey, itemBox.x);
36788
+ ctx.entityVisualRightX.set(drawKey, itemBox.x + itemBox.width);
36789
+ const arrowSource = textSpills ? {
36790
+ x: itemBox.x + itemBox.width,
36791
+ y: itemBox.y + itemBox.height - PROGRESS_STRIP_HEIGHT_PX / 2
36792
+ } : {
36793
+ x: itemBox.x + itemBox.width,
36794
+ y: itemBox.y + itemBox.height / 2
36795
+ };
36796
+ ctx.itemArrowSource.set(drawKey, arrowSource);
36797
+ ctx.itemFlowKey.set(drawKey, ctx.currentFlowKey);
36798
+ const slackAttachY = textSpills ? itemBox.y + itemBox.height - PROGRESS_STRIP_HEIGHT_PX / 2 : itemBox.y + itemBox.height / 2;
36799
+ ctx.itemSlackAttachY.set(drawKey, slackAttachY);
36800
36800
  cursor.x = logicalRight;
36801
36801
  cursor.maxX = Math.max(cursor.maxX, cursor.x);
36802
36802
  cursor.height = Math.max(cursor.height, ctx.bandScale.step() + chipBarExtra);
@@ -36866,6 +36866,10 @@ function sequenceOne(node, cursor, ctx) {
36866
36866
  function estimateTextWidth2(text, fontSize) {
36867
36867
  return text.length * fontSize * 0.58;
36868
36868
  }
36869
+ function syntheticItemKey(node) {
36870
+ const start = node.$cstNode?.range.start;
36871
+ return `#item@${start ? start.line + 1 : 0}:${start ? start.character + 1 : 0}`;
36872
+ }
36869
36873
  function computeChipBarExtra(chipsOutside, captionSpills, chipRowCount, bandwidth, hasMeta) {
36870
36874
  if (chipRowCount === 0)
36871
36875
  return 0;
@@ -37221,8 +37225,7 @@ function collectItems(swimlanes) {
37221
37225
  const out = /* @__PURE__ */ new Map();
37222
37226
  const walk2 = (node) => {
37223
37227
  if (isItemDeclaration(node)) {
37224
- if (node.name)
37225
- out.set(node.name, node);
37228
+ out.set(node.name ?? syntheticItemKey(node), node);
37226
37229
  return;
37227
37230
  }
37228
37231
  if (isParallelBlock(node)) {
@@ -37267,6 +37270,176 @@ function layoutRoadmap(file, resolved, options = {}) {
37267
37270
  });
37268
37271
  }
37269
37272
 
37273
+ // ../layout/dist/resolve-today.js
37274
+ var TimezoneError = class extends Error {
37275
+ constructor(message) {
37276
+ super(message);
37277
+ this.name = "TimezoneError";
37278
+ }
37279
+ };
37280
+ function normalizeZone(raw) {
37281
+ if (!raw || raw.toLowerCase() === "local")
37282
+ return { kind: "local" };
37283
+ if (raw.toUpperCase() === "UTC")
37284
+ return { kind: "utc" };
37285
+ if (raw === "Z")
37286
+ return { kind: "offset", ms: 0 };
37287
+ const offsetMatch = /^([+-])(\d{2})(?::?(\d{2}))?$/.exec(raw);
37288
+ if (offsetMatch) {
37289
+ const sign = offsetMatch[1] === "+" ? 1 : -1;
37290
+ const hours = parseInt(offsetMatch[2], 10);
37291
+ const minutes = offsetMatch[3] !== void 0 ? parseInt(offsetMatch[3], 10) : 0;
37292
+ if (hours > 23 || minutes > 59) {
37293
+ throw new TimezoneError(`nowline: invalid timezone offset "${raw}". Hours must be 0\u201323 and minutes 0\u201359.`);
37294
+ }
37295
+ return { kind: "offset", ms: sign * (hours * 60 + minutes) * 6e4 };
37296
+ }
37297
+ try {
37298
+ const canonical = Intl.DateTimeFormat(void 0, { timeZone: raw }).resolvedOptions().timeZone;
37299
+ return { kind: "iana", name: canonical };
37300
+ } catch {
37301
+ throw new TimezoneError(`nowline: unrecognised timezone "${raw}". Use "local", "UTC", an ISO 8601 offset (e.g. "+05:30", "-07:00", "Z"), or an IANA timezone name (e.g. "America/Los_Angeles", "Asia/Kolkata").`);
37302
+ }
37303
+ }
37304
+ function civilDateInZone(instant, zone) {
37305
+ switch (zone.kind) {
37306
+ case "local": {
37307
+ return new Date(Date.UTC(instant.getFullYear(), instant.getMonth(), instant.getDate()));
37308
+ }
37309
+ case "utc": {
37310
+ return new Date(Date.UTC(instant.getUTCFullYear(), instant.getUTCMonth(), instant.getUTCDate()));
37311
+ }
37312
+ case "offset": {
37313
+ const shifted = new Date(instant.getTime() + zone.ms);
37314
+ return new Date(Date.UTC(shifted.getUTCFullYear(), shifted.getUTCMonth(), shifted.getUTCDate()));
37315
+ }
37316
+ case "iana": {
37317
+ const parts = new Intl.DateTimeFormat("en-CA", {
37318
+ timeZone: zone.name,
37319
+ year: "numeric",
37320
+ month: "2-digit",
37321
+ day: "2-digit"
37322
+ }).formatToParts(instant);
37323
+ let y = 0;
37324
+ let m = 0;
37325
+ let d = 0;
37326
+ for (const p of parts) {
37327
+ if (p.type === "year")
37328
+ y = parseInt(p.value, 10);
37329
+ else if (p.type === "month")
37330
+ m = parseInt(p.value, 10) - 1;
37331
+ else if (p.type === "day")
37332
+ d = parseInt(p.value, 10);
37333
+ }
37334
+ return new Date(Date.UTC(y, m, d));
37335
+ }
37336
+ }
37337
+ }
37338
+ var BARE_DATE_RE = /^(\d{4})-(\d{2})-(\d{2})$/;
37339
+ var ISO_WITH_OFFSET_RE = /^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?)(Z|([+-])(\d{2})(?::?(\d{2}))?)$/;
37340
+ var ISO_FLOATING_RE = /^(\d{4})-(\d{2})-(\d{2})T\d{2}:\d{2}:\d{2}(?:\.\d+)?$/;
37341
+ function resolveToday(opts = {}) {
37342
+ const zone = opts.zone ?? { kind: "local" };
37343
+ const clock = opts.clock ?? (() => /* @__PURE__ */ new Date());
37344
+ const now = opts.now;
37345
+ if (now === "-" || now === null)
37346
+ return void 0;
37347
+ if (now instanceof Date)
37348
+ return now;
37349
+ if (now !== void 0) {
37350
+ const bareMatch = BARE_DATE_RE.exec(now);
37351
+ if (bareMatch) {
37352
+ return new Date(Date.UTC(parseInt(bareMatch[1], 10), parseInt(bareMatch[2], 10) - 1, parseInt(bareMatch[3], 10)));
37353
+ }
37354
+ const withOffset = ISO_WITH_OFFSET_RE.exec(now);
37355
+ if (withOffset) {
37356
+ const instant = new Date(now);
37357
+ if (!Number.isNaN(instant.getTime())) {
37358
+ const suffix = withOffset[2];
37359
+ if (suffix === "Z") {
37360
+ return civilDateInZone(instant, { kind: "utc" });
37361
+ }
37362
+ const sign = withOffset[3] === "+" ? 1 : -1;
37363
+ const hh = parseInt(withOffset[4], 10);
37364
+ const mm = withOffset[5] !== void 0 ? parseInt(withOffset[5], 10) : 0;
37365
+ const offsetMs = sign * (hh * 60 + mm) * 6e4;
37366
+ return civilDateInZone(instant, { kind: "offset", ms: offsetMs });
37367
+ }
37368
+ }
37369
+ const floating = ISO_FLOATING_RE.exec(now);
37370
+ if (floating) {
37371
+ return new Date(Date.UTC(parseInt(floating[1], 10), parseInt(floating[2], 10) - 1, parseInt(floating[3], 10)));
37372
+ }
37373
+ return void 0;
37374
+ }
37375
+ return civilDateInZone(clock(), zone);
37376
+ }
37377
+
37378
+ // ../browser/dist/diagnostic-row.js
37379
+ function fromLangiumDiagnostic(diag, file) {
37380
+ return {
37381
+ severity: diag.severity === 2 ? "warning" : "error",
37382
+ // resolveDiagnosticCode prefers the stable validator code (NL.Exxxx)
37383
+ // carried in `data` so the preview table matches the CLI / Problems
37384
+ // panel, then falls back to Langium's `code`, then a message heuristic.
37385
+ code: resolveDiagnosticCode(diag),
37386
+ message: diag.message,
37387
+ suggestion: extractSuggestion(diag.message),
37388
+ file,
37389
+ line: (diag.range?.start.line ?? 0) + 1,
37390
+ column: (diag.range?.start.character ?? 0) + 1
37391
+ };
37392
+ }
37393
+ function fromParserError(err, file) {
37394
+ return {
37395
+ severity: "error",
37396
+ code: "parse-error",
37397
+ message: err.message,
37398
+ file,
37399
+ line: err.token?.startLine ?? 1,
37400
+ column: err.token?.startColumn ?? 1
37401
+ };
37402
+ }
37403
+ function fromLexerError(err, file) {
37404
+ return {
37405
+ severity: "error",
37406
+ code: "lex-error",
37407
+ message: err.message,
37408
+ file,
37409
+ line: err.line ?? 1,
37410
+ column: err.column ?? 1
37411
+ };
37412
+ }
37413
+ function fromResolveDiagnostic(diag) {
37414
+ return {
37415
+ severity: diag.severity,
37416
+ code: "include",
37417
+ message: diag.message,
37418
+ file: diag.sourcePath,
37419
+ line: diag.line !== void 0 ? diag.line + 1 : 1,
37420
+ column: 1
37421
+ };
37422
+ }
37423
+ function fromRenderWarning(message, file, severity = "warning") {
37424
+ return {
37425
+ severity,
37426
+ code: "render.warning",
37427
+ message,
37428
+ file,
37429
+ line: 1,
37430
+ column: 1
37431
+ };
37432
+ }
37433
+
37434
+ // ../browser/dist/no-op-include-resolver.js
37435
+ var NOWLINE_BROWSER_NOOP_INCLUDE_TAG = "__nowline_browser_noop_include__";
37436
+ async function noOpIncludeReadFile(absPath) {
37437
+ throw new Error(`${NOWLINE_BROWSER_NOOP_INCLUDE_TAG}: include "${absPath}" was skipped \u2014 running in single-file mode.`);
37438
+ }
37439
+ function isNoOpIncludeDiagnosticMessage(message) {
37440
+ return message.includes(NOWLINE_BROWSER_NOOP_INCLUDE_TAG);
37441
+ }
37442
+
37270
37443
  // ../renderer/dist/svg/icons.js
37271
37444
  var CAPACITY_ICON_SVG = {
37272
37445
  // Lucide `user` — a single figure (head + shoulders).
@@ -37767,9 +37940,9 @@ var WEIGHT_NUM = {
37767
37940
  function textSizePx(bucket) {
37768
37941
  return TEXT_SIZE_PX[bucket] ?? 14;
37769
37942
  }
37770
- function fontAttrs(style, overrideSize) {
37943
+ function fontAttrs(style, fonts, overrideSize) {
37771
37944
  return {
37772
- "font-family": FONT_STACK[style.font],
37945
+ "font-family": fonts[style.font],
37773
37946
  "font-size": overrideSize ?? textSizePx(style.textSize),
37774
37947
  "font-weight": WEIGHT_NUM[style.weight] ?? 400,
37775
37948
  "font-style": style.italic ? "italic" : "normal",
@@ -37908,7 +38081,7 @@ function rectFrame(x, y, w, h, style, extra = {}) {
37908
38081
  ...extra
37909
38082
  });
37910
38083
  }
37911
- function renderHeader(h, idPrefix, palette) {
38084
+ function renderHeader(h, idPrefix, palette, fonts) {
37912
38085
  const cardX = h.box.x + h.cardBox.x;
37913
38086
  const cardY = h.box.y + h.cardBox.y;
37914
38087
  const cardWidth = h.cardBox.width;
@@ -37932,7 +38105,7 @@ function renderHeader(h, idPrefix, palette) {
37932
38105
  titleParts.push(textTag({
37933
38106
  x: num(cardX + HEADER_CARD_PADDING_X),
37934
38107
  y: num(cardY + HEADER_CARD_PADDING_TOP + i * HEADER_TITLE_LINE_HEIGHT_PX),
37935
- "font-family": FONT_STACK[h.style.font],
38108
+ "font-family": fonts[h.style.font],
37936
38109
  "font-size": HEADER_TITLE_FONT_SIZE_PX,
37937
38110
  "font-weight": 600,
37938
38111
  fill: h.style.text
@@ -37946,7 +38119,7 @@ function renderHeader(h, idPrefix, palette) {
37946
38119
  authorParts.push(textTag({
37947
38120
  x: num(cardX + HEADER_CARD_PADDING_X),
37948
38121
  y: num(lastTitleY + HEADER_TITLE_TO_AUTHOR_GAP_PX + j * HEADER_AUTHOR_LINE_HEIGHT_PX),
37949
- "font-family": FONT_STACK[h.style.font],
38122
+ "font-family": fonts[h.style.font],
37950
38123
  "font-size": HEADER_AUTHOR_FONT_SIZE_PX,
37951
38124
  fill: authorColor
37952
38125
  }, line));
@@ -37989,7 +38162,7 @@ function renderGridLines(t, swimlaneTopY, palette) {
37989
38162
  }
37990
38163
  return tag("g", { "data-layer": "grid" }, parts.join(""));
37991
38164
  }
37992
- function renderTimeline(t, palette) {
38165
+ function renderTimeline(t, palette, fonts) {
37993
38166
  const panelFill = palette.timeline.panelFill;
37994
38167
  const borderColor = palette.timeline.border;
37995
38168
  const labelColor = palette.timeline.labelText;
@@ -38051,7 +38224,7 @@ function renderTimeline(t, palette) {
38051
38224
  parts.push(textTag({
38052
38225
  x: num(tick.labelX),
38053
38226
  y: num(tickPanelY + TIMELINE_TICK_LABEL_BASELINE_OFFSET_PX),
38054
- "font-family": FONT_STACK.sans,
38227
+ "font-family": fonts.sans,
38055
38228
  "font-size": 10,
38056
38229
  fill: labelColor,
38057
38230
  "text-anchor": "middle"
@@ -38061,7 +38234,7 @@ function renderTimeline(t, palette) {
38061
38234
  parts.push(textTag({
38062
38235
  x: num(tick.labelX),
38063
38236
  y: num(bottomTickPanelY + TIMELINE_TICK_LABEL_BASELINE_OFFSET_PX),
38064
- "font-family": FONT_STACK.sans,
38237
+ "font-family": fonts.sans,
38065
38238
  "font-size": 10,
38066
38239
  fill: labelColor,
38067
38240
  "text-anchor": "middle"
@@ -38070,7 +38243,7 @@ function renderTimeline(t, palette) {
38070
38243
  }
38071
38244
  return tag("g", { "data-layer": "timeline" }, parts.join(""));
38072
38245
  }
38073
- function renderNowline(n, palette) {
38246
+ function renderNowline(n, palette, fonts) {
38074
38247
  if (!n)
38075
38248
  return "";
38076
38249
  const color2 = palette.nowline.stroke;
@@ -38084,7 +38257,7 @@ function renderNowline(n, palette) {
38084
38257
  "stroke-width": NOWLINE_STROKE_WIDTH_PX
38085
38258
  });
38086
38259
  const pillBg = renderNowPillBg(n, color2);
38087
- const label = renderNowPillLabel(n, labelTextColor);
38260
+ const label = renderNowPillLabel(n, labelTextColor, fonts);
38088
38261
  return tag("g", { "data-layer": "nowline" }, line + pillBg + label);
38089
38262
  }
38090
38263
  function squaredEdgeX(n) {
@@ -38137,7 +38310,7 @@ function renderNowPillBg(n, color2) {
38137
38310
  ].join(" ");
38138
38311
  return tag("path", { d, fill: color2 });
38139
38312
  }
38140
- function renderNowPillLabel(n, labelTextColor) {
38313
+ function renderNowPillLabel(n, labelTextColor, fonts) {
38141
38314
  const baselineY = n.pillTopY + NOW_PILL_LABEL_BASELINE_OFFSET_PX;
38142
38315
  const edgeX = squaredEdgeX(n);
38143
38316
  let labelX;
@@ -38155,14 +38328,14 @@ function renderNowPillLabel(n, labelTextColor) {
38155
38328
  return textTag({
38156
38329
  x: num(labelX),
38157
38330
  y: num(baselineY),
38158
- "font-family": FONT_STACK.sans,
38331
+ "font-family": fonts.sans,
38159
38332
  "font-size": NOW_PILL_LABEL_FONT_SIZE_PX,
38160
38333
  "font-weight": 700,
38161
38334
  fill: labelTextColor,
38162
38335
  "text-anchor": textAnchor
38163
38336
  }, n.label);
38164
38337
  }
38165
- function renderItem(i, options, idPrefix, palette) {
38338
+ function renderItem(i, options, idPrefix, palette, fonts) {
38166
38339
  const parts = [];
38167
38340
  const shadow = shadowFilterUrl(idPrefix, i.style.shadow);
38168
38341
  parts.push(rectFrame(i.box.x, i.box.y, i.box.width, i.box.height, i.style, {
@@ -38214,7 +38387,7 @@ function renderItem(i, options, idPrefix, palette) {
38214
38387
  parts.push(textTag({
38215
38388
  x: num(captionX),
38216
38389
  y: num(i.box.y + ITEM_CAPTION_TITLE_BASELINE_OFFSET_PX),
38217
- "font-family": FONT_STACK[i.style.font],
38390
+ "font-family": fonts[i.style.font],
38218
38391
  "font-size": ITEM_CAPTION_TITLE_FONT_SIZE_PX,
38219
38392
  "font-weight": 600,
38220
38393
  fill: titleColor
@@ -38227,7 +38400,7 @@ function renderItem(i, options, idPrefix, palette) {
38227
38400
  x: captionX,
38228
38401
  baselineY: i.box.y + ITEM_CAPTION_META_BASELINE_OFFSET_PX,
38229
38402
  fontSize: ITEM_CAPTION_META_FONT_SIZE_PX,
38230
- fontFamily: FONT_STACK[i.style.font],
38403
+ fontFamily: fonts[i.style.font],
38231
38404
  color: metaColor
38232
38405
  }));
38233
38406
  }
@@ -38240,7 +38413,7 @@ function renderItem(i, options, idPrefix, palette) {
38240
38413
  parts.push(textTag({
38241
38414
  x: num(fx),
38242
38415
  y: num(footnoteY),
38243
- "font-family": FONT_STACK.sans,
38416
+ "font-family": fonts.sans,
38244
38417
  "font-size": 10,
38245
38418
  "font-weight": 700,
38246
38419
  fill: captionOutsideTextColor
@@ -38254,7 +38427,7 @@ function renderItem(i, options, idPrefix, palette) {
38254
38427
  parts.push(textTag({
38255
38428
  x: num(fx),
38256
38429
  y: num(footnoteY),
38257
- "font-family": FONT_STACK.sans,
38430
+ "font-family": fonts.sans,
38258
38431
  "font-size": 10,
38259
38432
  "font-weight": 700,
38260
38433
  fill: i.style.text,
@@ -38315,7 +38488,7 @@ function renderItem(i, options, idPrefix, palette) {
38315
38488
  parts.push(textTag({
38316
38489
  x: num(i.overflowBox.x + i.overflowBox.width / 2),
38317
38490
  y: num(i.overflowBox.y + i.overflowBox.height / 2 + 3),
38318
- "font-family": FONT_STACK.sans,
38491
+ "font-family": fonts.sans,
38319
38492
  "font-size": 9,
38320
38493
  "font-weight": 700,
38321
38494
  fill: captionColor,
@@ -38339,13 +38512,13 @@ function renderItem(i, options, idPrefix, palette) {
38339
38512
  parts.push(textTag({
38340
38513
  x: num(chip.box.x + chip.box.width / 2),
38341
38514
  y: num(chip.box.y + chip.box.height / 2 + 3),
38342
- ...fontAttrs(chip.style, TEXT_SIZE_PX.xs),
38515
+ ...fontAttrs(chip.style, fonts, TEXT_SIZE_PX.xs),
38343
38516
  "text-anchor": "middle"
38344
38517
  }, chip.text));
38345
38518
  }
38346
38519
  return tag("g", { "data-layer": "item", "data-id": i.id ?? null }, parts.join(""));
38347
38520
  }
38348
- function renderGroup(g, options, idPrefix, palette) {
38521
+ function renderGroup(g, options, idPrefix, palette, fonts) {
38349
38522
  const parts = [];
38350
38523
  const hasFill = g.style.bg !== "none" && g.style.bg !== "#ffffff";
38351
38524
  if (hasFill) {
@@ -38376,7 +38549,7 @@ function renderGroup(g, options, idPrefix, palette) {
38376
38549
  parts.push(textTag({
38377
38550
  x: num(tabX + GROUP_TITLE_TAB_PAD_X_PX),
38378
38551
  y: num(tabY + GROUP_TITLE_TAB_LABEL_BASELINE_OFFSET_PX),
38379
- "font-family": FONT_STACK[g.style.font],
38552
+ "font-family": fonts[g.style.font],
38380
38553
  "font-size": GROUP_TITLE_TAB_LABEL_FONT_SIZE_PX,
38381
38554
  "font-weight": 600,
38382
38555
  fill: "#ffffff"
@@ -38401,19 +38574,19 @@ function renderGroup(g, options, idPrefix, palette) {
38401
38574
  parts.push(textTag({
38402
38575
  x: num(g.box.x + 6),
38403
38576
  y: num(g.box.y - 2),
38404
- ...fontAttrs(g.style, TEXT_SIZE_PX.xs),
38577
+ ...fontAttrs(g.style, fonts, TEXT_SIZE_PX.xs),
38405
38578
  "fill-opacity": 0.7
38406
38579
  }, g.title));
38407
38580
  }
38408
38581
  }
38409
38582
  parts.push(renderInlineDatePins(g.inlineDatePins, g.style.fg));
38410
38583
  for (const c of g.children) {
38411
- parts.push(renderTrackChild(c, options, idPrefix, palette));
38584
+ parts.push(renderTrackChild(c, options, idPrefix, palette, fonts));
38412
38585
  }
38413
38586
  void palette;
38414
38587
  return tag("g", { "data-layer": "group", "data-id": g.id ?? null }, parts.join(""));
38415
38588
  }
38416
- function renderParallel(p, options, idPrefix, palette) {
38589
+ function renderParallel(p, options, idPrefix, palette, fonts) {
38417
38590
  const parts = [];
38418
38591
  if (p.style.bracket === "solid" || p.style.bracket === "dashed") {
38419
38592
  const padding = 12;
@@ -38444,22 +38617,22 @@ function renderParallel(p, options, idPrefix, palette) {
38444
38617
  parts.push(textTag({
38445
38618
  x: num(p.box.x + 4),
38446
38619
  y: num(p.box.y - 2),
38447
- ...fontAttrs(p.style, TEXT_SIZE_PX.xs),
38620
+ ...fontAttrs(p.style, fonts, TEXT_SIZE_PX.xs),
38448
38621
  "fill-opacity": 0.7
38449
38622
  }, p.title));
38450
38623
  }
38451
38624
  parts.push(renderInlineDatePins(p.inlineDatePins, p.style.fg));
38452
38625
  for (const c of p.children) {
38453
- parts.push(renderTrackChild(c, options, idPrefix, palette));
38626
+ parts.push(renderTrackChild(c, options, idPrefix, palette, fonts));
38454
38627
  }
38455
38628
  return tag("g", { "data-layer": "parallel", "data-id": p.id ?? null }, parts.join(""));
38456
38629
  }
38457
- function renderTrackChild(c, options, idPrefix, palette) {
38630
+ function renderTrackChild(c, options, idPrefix, palette, fonts) {
38458
38631
  if (c.kind === "item")
38459
- return renderItem(c, options, idPrefix, palette);
38632
+ return renderItem(c, options, idPrefix, palette, fonts);
38460
38633
  if (c.kind === "group")
38461
- return renderGroup(c, options, idPrefix, palette);
38462
- return renderParallel(c, options, idPrefix, palette);
38634
+ return renderGroup(c, options, idPrefix, palette, fonts);
38635
+ return renderParallel(c, options, idPrefix, palette, fonts);
38463
38636
  }
38464
38637
  var LANE_UTILIZATION_HEIGHT_PX = 2;
38465
38638
  function utilizationColor(classification, palette) {
@@ -38508,7 +38681,7 @@ function renderSwimlaneBg(s, palette) {
38508
38681
  "stroke-width": 1
38509
38682
  }));
38510
38683
  }
38511
- function renderSwimlane(s, options, idPrefix, palette) {
38684
+ function renderSwimlane(s, options, idPrefix, palette, fonts) {
38512
38685
  const tabFill = palette.swimlane.tabFill;
38513
38686
  const tabStroke = palette.swimlane.tabStroke;
38514
38687
  const tabText = palette.swimlane.tabText;
@@ -38538,7 +38711,7 @@ function renderSwimlane(s, options, idPrefix, palette) {
38538
38711
  parts.push(textTag({
38539
38712
  x: num(tab.titleX),
38540
38713
  y: num(labelY),
38541
- "font-family": FONT_STACK[s.style.font],
38714
+ "font-family": fonts[s.style.font],
38542
38715
  "font-size": 12,
38543
38716
  "font-weight": 600,
38544
38717
  fill: tabText
@@ -38547,19 +38720,19 @@ function renderSwimlane(s, options, idPrefix, palette) {
38547
38720
  parts.push(textTag({
38548
38721
  x: num(tab.ownerX),
38549
38722
  y: num(labelY),
38550
- "font-family": FONT_STACK[s.style.font],
38723
+ "font-family": fonts[s.style.font],
38551
38724
  "font-size": 10,
38552
38725
  fill: ownerText
38553
38726
  }, `owner: ${s.owner}`));
38554
38727
  }
38555
38728
  if (s.capacity) {
38556
- parts.push(renderCapacitySuffix(s.capacity, void 0, tab.badgeX, labelY, LANE_BADGE_FONT_SIZE_PX, FONT_STACK[s.style.font], ownerText));
38729
+ parts.push(renderCapacitySuffix(s.capacity, void 0, tab.badgeX, labelY, LANE_BADGE_FONT_SIZE_PX, fonts[s.style.font], ownerText));
38557
38730
  }
38558
38731
  if (footnoteIndicatorText) {
38559
38732
  parts.push(textTag({
38560
38733
  x: num(tab.footnoteRightX),
38561
38734
  y: num(tabY + 14),
38562
- "font-family": FONT_STACK.sans,
38735
+ "font-family": fonts.sans,
38563
38736
  "font-size": LANE_BADGE_FONT_SIZE_PX,
38564
38737
  "font-weight": 700,
38565
38738
  fill: footnoteColor,
@@ -38568,12 +38741,12 @@ function renderSwimlane(s, options, idPrefix, palette) {
38568
38741
  }
38569
38742
  }
38570
38743
  for (const c of s.children) {
38571
- parts.push(renderTrackChild(c, options, idPrefix, palette));
38744
+ parts.push(renderTrackChild(c, options, idPrefix, palette, fonts));
38572
38745
  }
38573
38746
  parts.push(renderLaneUtilization(s, palette));
38574
38747
  return tag("g", { "data-layer": "swimlane", "data-id": s.id ?? null }, parts.join(""));
38575
38748
  }
38576
- function renderAnchor(a, palette) {
38749
+ function renderAnchor(a, palette, fonts) {
38577
38750
  const size = a.radius;
38578
38751
  const cx = a.center.x;
38579
38752
  const cy = a.center.y;
@@ -38590,7 +38763,7 @@ function renderAnchor(a, palette) {
38590
38763
  const labelAttrs = {
38591
38764
  x: num(labelX),
38592
38765
  y: num(cy + 4),
38593
- "font-family": FONT_STACK.sans,
38766
+ "font-family": fonts.sans,
38594
38767
  "font-size": 10,
38595
38768
  fill: labelColor
38596
38769
  };
@@ -38611,7 +38784,7 @@ function renderAnchorCutLine(a, palette) {
38611
38784
  "stroke-dasharray": "1 3"
38612
38785
  });
38613
38786
  }
38614
- function renderMilestone(m, palette) {
38787
+ function renderMilestone(m, palette, fonts) {
38615
38788
  const cx = m.center.x;
38616
38789
  const cy = m.center.y;
38617
38790
  const r = m.radius;
@@ -38627,7 +38800,7 @@ function renderMilestone(m, palette) {
38627
38800
  const labelAttrs = {
38628
38801
  x: num(labelX),
38629
38802
  y: num(cy + 4),
38630
- "font-family": FONT_STACK.sans,
38803
+ "font-family": fonts.sans,
38631
38804
  "font-size": 10,
38632
38805
  "font-weight": 600,
38633
38806
  fill: labelColor
@@ -38712,7 +38885,7 @@ function roundedOrthogonalPath(points, radius) {
38712
38885
  }
38713
38886
  return parts.join(" ");
38714
38887
  }
38715
- function renderFootnotes(f, idPrefix, palette) {
38888
+ function renderFootnotes(f, idPrefix, palette, fonts) {
38716
38889
  if (f.entries.length === 0)
38717
38890
  return "";
38718
38891
  const panelFill = palette.footnotePanel.fill;
@@ -38737,7 +38910,7 @@ function renderFootnotes(f, idPrefix, palette) {
38737
38910
  parts.push(textTag({
38738
38911
  x: num(f.box.x + FOOTNOTE_PANEL_PADDING_PX),
38739
38912
  y: num(f.box.y + FOOTNOTE_HEADER_BASELINE_OFFSET_PX),
38740
- "font-family": FONT_STACK.sans,
38913
+ "font-family": fonts.sans,
38741
38914
  "font-size": 12,
38742
38915
  "font-weight": 700,
38743
38916
  fill: headerColor
@@ -38750,7 +38923,7 @@ function renderFootnotes(f, idPrefix, palette) {
38750
38923
  parts.push(textTag({
38751
38924
  x: num(numberX),
38752
38925
  y: num(y),
38753
- "font-family": FONT_STACK.sans,
38926
+ "font-family": fonts.sans,
38754
38927
  "font-size": 10,
38755
38928
  "font-weight": 700,
38756
38929
  fill: numberColor
@@ -38758,7 +38931,7 @@ function renderFootnotes(f, idPrefix, palette) {
38758
38931
  parts.push(textTag({
38759
38932
  x: num(titleX),
38760
38933
  y: num(y),
38761
- "font-family": FONT_STACK.sans,
38934
+ "font-family": fonts.sans,
38762
38935
  "font-size": 11,
38763
38936
  "font-weight": 600,
38764
38937
  fill: titleColor
@@ -38767,7 +38940,7 @@ function renderFootnotes(f, idPrefix, palette) {
38767
38940
  parts.push(textTag({
38768
38941
  x: num(titleX + Math.max(120, e.title.length * 6)),
38769
38942
  y: num(y),
38770
- "font-family": FONT_STACK.sans,
38943
+ "font-family": fonts.sans,
38771
38944
  "font-size": 11,
38772
38945
  fill: descColor
38773
38946
  }, `\u2014 ${e.description}`));
@@ -38775,7 +38948,7 @@ function renderFootnotes(f, idPrefix, palette) {
38775
38948
  });
38776
38949
  return tag("g", { "data-layer": "footnotes" }, parts.join(""));
38777
38950
  }
38778
- function renderIncludeRegion(r, options, idPrefix, palette) {
38951
+ function renderIncludeRegion(r, options, idPrefix, palette, fonts) {
38779
38952
  const border = palette.includeRegion.border;
38780
38953
  const fill = palette.includeRegion.fill;
38781
38954
  const tabFill = palette.includeRegion.tabFill;
@@ -38817,7 +38990,7 @@ function renderIncludeRegion(r, options, idPrefix, palette) {
38817
38990
  const tabLabel = textTag({
38818
38991
  x: num(chrome.tabLabelX),
38819
38992
  y: num(tabY + FRAME_TAB_LABEL_BASELINE_OFFSET_PX),
38820
- "font-family": FONT_STACK.sans,
38993
+ "font-family": fonts.sans,
38821
38994
  "font-size": 11,
38822
38995
  "font-weight": 600,
38823
38996
  fill: tabText
@@ -38856,14 +39029,14 @@ function renderIncludeRegion(r, options, idPrefix, palette) {
38856
39029
  const sourceText = textTag({
38857
39030
  x: num(chrome.sourceTextX),
38858
39031
  y: num(sourceTextY),
38859
- "font-family": FONT_STACK.mono,
39032
+ "font-family": fonts.mono,
38860
39033
  "font-size": sourceFontSize,
38861
39034
  fill: badgeText
38862
39035
  }, r.sourcePath);
38863
- const nested = r.nestedSwimlanes.map((s) => renderSwimlane(s, options, idPrefix, palette)).join("");
39036
+ const nested = r.nestedSwimlanes.map((s) => renderSwimlane(s, options, idPrefix, palette, fonts)).join("");
38864
39037
  return tag("g", { "data-layer": "include" }, region + nested + tab + tabLabel + badge + glyph + sourceHalo + sourceText);
38865
39038
  }
38866
- function renderAttributionMark(model) {
39039
+ function renderAttributionMark(model, fonts) {
38867
39040
  const muted = model.palette.attribution.mark;
38868
39041
  const accent = model.palette.attribution.link;
38869
39042
  if (model.swimlanes.length === 0)
@@ -38874,14 +39047,14 @@ function renderAttributionMark(model) {
38874
39047
  const inner = textTag({
38875
39048
  x: "0",
38876
39049
  y: baselineY,
38877
- "font-family": FONT_STACK.sans,
39050
+ "font-family": fonts.sans,
38878
39051
  "font-size": ATTRIBUTION_PREFIX_FONT_SIZE,
38879
39052
  "font-weight": 400,
38880
39053
  fill: muted
38881
39054
  }, ATTRIBUTION_TEXT) + textTag({
38882
39055
  x: ATTRIBUTION_NOW_LOGICAL_X,
38883
39056
  y: baselineY,
38884
- "font-family": FONT_STACK.sans,
39057
+ "font-family": fonts.sans,
38885
39058
  "font-size": ATTRIBUTION_WORDMARK_FONT_SIZE,
38886
39059
  "font-weight": 700,
38887
39060
  fill: muted
@@ -38894,7 +39067,7 @@ function renderAttributionMark(model) {
38894
39067
  }) + textTag({
38895
39068
  x: ATTRIBUTION_INE_LOGICAL_X,
38896
39069
  y: baselineY,
38897
- "font-family": FONT_STACK.sans,
39070
+ "font-family": fonts.sans,
38898
39071
  "font-size": ATTRIBUTION_WORDMARK_FONT_SIZE,
38899
39072
  "font-weight": 400,
38900
39073
  fill: muted
@@ -38959,6 +39132,7 @@ async function renderSvg(model, options = {}) {
38959
39132
  const ids = new IdGenerator(options.idPrefix ?? "nl");
38960
39133
  const idPrefix = ids.next("root");
38961
39134
  const palette = model.palette;
39135
+ const fonts = options.fontFamilies ?? FONT_STACK;
38962
39136
  const parts = [];
38963
39137
  const arrowFillNeutral = palette.arrowhead.neutral;
38964
39138
  const arrowFillLight = palette.arrowhead.light;
@@ -38973,7 +39147,7 @@ async function renderSvg(model, options = {}) {
38973
39147
  height: num(model.height),
38974
39148
  fill: model.backgroundColor
38975
39149
  }));
38976
- parts.push(renderTimeline(model.timeline, palette));
39150
+ parts.push(renderTimeline(model.timeline, palette, fonts));
38977
39151
  for (const s of model.swimlanes)
38978
39152
  parts.push(renderSwimlaneBg(s, palette));
38979
39153
  parts.push(renderGridLines(model.timeline, model.chartBox.y, palette));
@@ -38982,9 +39156,9 @@ async function renderSvg(model, options = {}) {
38982
39156
  parts.push(renderEdge(e, palette));
38983
39157
  }
38984
39158
  for (const s of model.swimlanes)
38985
- parts.push(renderSwimlane(s, options, idPrefix, palette));
39159
+ parts.push(renderSwimlane(s, options, idPrefix, palette, fonts));
38986
39160
  for (const r of model.includes)
38987
- parts.push(renderIncludeRegion(r, options, idPrefix, palette));
39161
+ parts.push(renderIncludeRegion(r, options, idPrefix, palette, fonts));
38988
39162
  for (const e of model.edges) {
38989
39163
  if (e.kind !== "underBar")
38990
39164
  parts.push(renderEdge(e, palette));
@@ -38994,13 +39168,13 @@ async function renderSvg(model, options = {}) {
38994
39168
  for (const m of model.milestones)
38995
39169
  parts.push(renderMilestoneCutLine(m, palette));
38996
39170
  for (const a of model.anchors)
38997
- parts.push(renderAnchor(a, palette));
39171
+ parts.push(renderAnchor(a, palette, fonts));
38998
39172
  for (const m of model.milestones)
38999
- parts.push(renderMilestone(m, palette));
39000
- parts.push(renderNowline(model.nowline, palette));
39001
- parts.push(renderFootnotes(model.footnotes, idPrefix, palette));
39002
- parts.push(renderHeader(model.header, idPrefix, palette));
39003
- parts.push(renderAttributionMark(model));
39173
+ parts.push(renderMilestone(m, palette, fonts));
39174
+ parts.push(renderNowline(model.nowline, palette, fonts));
39175
+ parts.push(renderFootnotes(model.footnotes, idPrefix, palette, fonts));
39176
+ parts.push(renderHeader(model.header, idPrefix, palette, fonts));
39177
+ parts.push(renderAttributionMark(model, fonts));
39004
39178
  if (model.header.logo && options.assetResolver) {
39005
39179
  const logoSvg = await embedLogo(model.header.logo.assetRef ?? "", options.assetResolver, idPrefix, options, model.header.logo.box.x, model.header.logo.box.y, Math.max(model.header.logo.box.width, model.header.logo.box.height));
39006
39180
  if (logoSvg)
@@ -39073,7 +39247,30 @@ async function renderSource(source, options = {}) {
39073
39247
  if (rows.some((r) => r.severity === "error")) {
39074
39248
  return { kind: "diagnostics", diagnostics: rows };
39075
39249
  }
39076
- const today = options.today === null ? void 0 : options.today;
39250
+ let zone;
39251
+ if (options.timezone) {
39252
+ try {
39253
+ zone = normalizeZone(options.timezone);
39254
+ } catch (err) {
39255
+ if (err instanceof TimezoneError) {
39256
+ return {
39257
+ kind: "diagnostics",
39258
+ diagnostics: [
39259
+ {
39260
+ severity: "error",
39261
+ code: "invalid-timezone",
39262
+ message: err.message,
39263
+ file: filePath,
39264
+ line: 1,
39265
+ column: 1
39266
+ }
39267
+ ]
39268
+ };
39269
+ }
39270
+ throw err;
39271
+ }
39272
+ }
39273
+ const today = resolveToday({ now: options.today, zone });
39077
39274
  const model = layoutRoadmap(parsed.ast, resolved, {
39078
39275
  theme: options.theme,
39079
39276
  today,
@@ -39088,7 +39285,8 @@ async function renderSource(source, options = {}) {
39088
39285
  assetResolver: options.assetResolver,
39089
39286
  noLinks: !showLinks,
39090
39287
  strict,
39091
- warn: (msg) => warnMessages.push(msg)
39288
+ warn: (msg) => warnMessages.push(msg),
39289
+ fontFamilies: options.fontFamilies
39092
39290
  });
39093
39291
  const warnings = warnMessages.map((m) => fromRenderWarning(m, filePath, strict ? "error" : "warning"));
39094
39292
  if (strict && warnings.length > 0) {
@@ -39118,6 +39316,7 @@ async function renderSource2(source, options = {}) {
39118
39316
  filePath: EMBED_SOURCE_PATH,
39119
39317
  theme: options.theme,
39120
39318
  today: options.today,
39319
+ timezone: options.timezone,
39121
39320
  locale: options.locale,
39122
39321
  width: options.width,
39123
39322
  idPrefix: options.idPrefix,
@@ -39747,6 +39946,7 @@ async function runAutoScan(inputs) {
39747
39946
  locale: inputs.locale,
39748
39947
  width: inputs.width,
39749
39948
  today: inputs.today,
39949
+ timezone: inputs.timezone,
39750
39950
  idPrefix
39751
39951
  };
39752
39952
  const parent = target.parentElement;
@@ -39819,8 +40019,8 @@ function effectiveTheme(theme, systemTheme) {
39819
40019
  }
39820
40020
 
39821
40021
  // src/index.ts
39822
- var version = true ? "0.5.0" : "0.0.0";
39823
- var sha = true ? "04bdff9" : "unknown";
40022
+ var version = true ? "0.6.0" : "0.0.0";
40023
+ var sha = true ? "e2e4d9d" : "unknown";
39824
40024
  var DEFAULT_SELECTOR = "pre code.language-nowline, code.language-nowline";
39825
40025
  var initialConfig = {
39826
40026
  theme: "auto",
@@ -39838,7 +40038,8 @@ function initialize(options = {}) {
39838
40038
  selector: options.selector ?? config.selector,
39839
40039
  locale: options.locale ?? config.locale,
39840
40040
  width: options.width ?? config.width,
39841
- today: options.today ?? config.today,
40041
+ today: options.today !== void 0 ? options.today : config.today,
40042
+ timezone: options.timezone ?? config.timezone,
39842
40043
  share: options.share ?? config.share,
39843
40044
  sourceUrl: options.sourceUrl ?? config.sourceUrl,
39844
40045
  // Re-read `prefers-color-scheme` on every initialize() so callers
@@ -39853,7 +40054,8 @@ function renderOptionsFromConfig() {
39853
40054
  theme: effectiveTheme(config.theme, config.systemTheme),
39854
40055
  locale: config.locale,
39855
40056
  width: config.width,
39856
- today: config.today
40057
+ today: config.today,
40058
+ timezone: config.timezone
39857
40059
  };
39858
40060
  }
39859
40061
  async function render(source, options = {}) {
@@ -39872,7 +40074,8 @@ async function init(overrides) {
39872
40074
  theme: overrides?.theme ?? renderOptionsFromConfig().theme,
39873
40075
  locale: overrides?.locale ?? config.locale,
39874
40076
  width: overrides?.width ?? config.width,
39875
- today: overrides?.today ?? config.today,
40077
+ today: overrides?.today !== void 0 ? overrides.today : config.today,
40078
+ timezone: overrides?.timezone ?? config.timezone,
39876
40079
  share: overrides?.share ?? config.share,
39877
40080
  sourceUrl: overrides?.sourceUrl ?? config.sourceUrl,
39878
40081
  document: overrides?.document