@bendyline/squisq 2.13.7 → 2.13.9

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.
@@ -9,7 +9,7 @@ import {
9
9
  expectedSyllablesAt,
10
10
  flattenRenderableBlocks,
11
11
  wordPosAtExpectedSyllables
12
- } from "./chunk-TTJZXUQA.js";
12
+ } from "./chunk-L3VQQ3WT.js";
13
13
 
14
14
  // src/narration/types.ts
15
15
  var DEFAULT_FEATURE_CONFIG = Object.freeze({
@@ -32,7 +32,7 @@ import {
32
32
  profileBlockContents,
33
33
  renderMarkdownBlocksHtml,
34
34
  treeToTemplateData
35
- } from "./chunk-NGQ5TJVX.js";
35
+ } from "./chunk-R2J7CQJZ.js";
36
36
  import {
37
37
  anchorPoint,
38
38
  base64ToUtf8,
@@ -12615,6 +12615,7 @@ export {
12615
12615
  videoWithCaption,
12616
12616
  videoPullQuote,
12617
12617
  dataTable,
12618
+ normalizeChartTable,
12618
12619
  buildChartData,
12619
12620
  BLOCK_MEDIA_LAYOUT_POLICIES,
12620
12621
  getBlockMediaLayoutPolicy,
@@ -12661,6 +12662,7 @@ export {
12661
12662
  parseYamlSubset,
12662
12663
  findFirstTable,
12663
12664
  extractTableData,
12665
+ detectPromotableBodyAnnotation,
12664
12666
  getPinnedBlockMeta,
12665
12667
  markdownToDoc,
12666
12668
  flattenBlocks,
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-FTN6SGW5.js";
4
4
  import {
5
5
  applySavedPresentation
6
- } from "./chunk-CJYN3MTX.js";
6
+ } from "./chunk-VMKRN7TB.js";
7
7
  import {
8
8
  SHAPE_NAMES,
9
9
  buildChartData,
@@ -31,7 +31,7 @@ import {
31
31
  templateRegistry,
32
32
  writeCustomTemplatesToFrontmatter,
33
33
  writeCustomThemesToFrontmatter
34
- } from "./chunk-TTJZXUQA.js";
34
+ } from "./chunk-L3VQQ3WT.js";
35
35
  import {
36
36
  ASCII_TREE_VOCAB,
37
37
  ASCII_VOCAB,
@@ -54,7 +54,7 @@ import {
54
54
  toCells,
55
55
  toGrid,
56
56
  traceBoxes
57
- } from "./chunk-NGQ5TJVX.js";
57
+ } from "./chunk-R2J7CQJZ.js";
58
58
  import {
59
59
  iconMarker
60
60
  } from "./chunk-7ZAAICW4.js";
@@ -5282,12 +5282,13 @@ function renderAsciiDiagram(diagram2, options = {}) {
5282
5282
  const vocab = (options.style ?? diagram2.style) === "ascii" ? ASCII_VOCAB : UNICODE_VOCAB;
5283
5283
  if (diagram2.nodes.length === 0) return "";
5284
5284
  const placed = layoutNodes(diagram2.nodes, diagram2.edges);
5285
+ const routes = planRoutesWithRoom(diagram2.edges, placed);
5285
5286
  const canvas = new Canvas();
5286
5287
  const drawOrder = [...placed.values()].sort(
5287
5288
  (a, b) => a.depth - b.depth || a.rect.r0 - b.rect.r0 || a.rect.c0 - b.rect.c0
5288
5289
  );
5289
5290
  for (const p of drawOrder) drawBox(canvas, p, vocab);
5290
- drawEdges(canvas, diagram2.edges, placed, vocab);
5291
+ drawEdges(canvas, routes, placed, vocab);
5291
5292
  return canvas.emit();
5292
5293
  }
5293
5294
  function computeSideDegrees(nodes, edges) {
@@ -5527,7 +5528,40 @@ function drawBox(canvas, p, vocab) {
5527
5528
  });
5528
5529
  }
5529
5530
  }
5530
- function drawEdges(canvas, edges, placed, vocab) {
5531
+ var OPPOSITE_SIDE = {
5532
+ top: "bottom",
5533
+ bottom: "top",
5534
+ left: "right",
5535
+ right: "left"
5536
+ };
5537
+ function planRoutesWithRoom(edges, placed) {
5538
+ const maxInserts = 4 * edges.length + 8;
5539
+ for (let inserted = 0; ; inserted++) {
5540
+ const { routes, room } = planRoutes(edges, placed);
5541
+ if (!room || inserted >= maxInserts) return routes;
5542
+ insertLine(placed, room);
5543
+ }
5544
+ }
5545
+ function insertLine(placed, { axis, after }) {
5546
+ const bump = (v) => v > after ? v + 1 : v;
5547
+ for (const p of placed.values()) {
5548
+ const r = p.rect;
5549
+ p.rect = axis === "row" ? { ...r, r0: bump(r.r0), r1: bump(r.r1) } : { ...r, c0: bump(r.c0), c1: bump(r.c1) };
5550
+ }
5551
+ }
5552
+ function roomBeside(side, rect) {
5553
+ switch (side) {
5554
+ case "bottom":
5555
+ return { axis: "row", after: rect.r1 };
5556
+ case "top":
5557
+ return { axis: "row", after: rect.r0 - 1 };
5558
+ case "right":
5559
+ return { axis: "col", after: rect.c1 };
5560
+ case "left":
5561
+ return { axis: "col", after: rect.c0 - 1 };
5562
+ }
5563
+ }
5564
+ function planRoutes(edges, placed) {
5531
5565
  const sorted = [...edges].sort(
5532
5566
  (a, b) => a.source.localeCompare(b.source) || a.target.localeCompare(b.target) || (a.label ?? "").localeCompare(b.label ?? "")
5533
5567
  );
@@ -5561,6 +5595,20 @@ function drawEdges(canvas, edges, placed, vocab) {
5561
5595
  });
5562
5596
  }
5563
5597
  const attachment = assignAttachments(plans, placed);
5598
+ const straight = resolveStraightRuns(plans, placed, attachment);
5599
+ const jogs = assignJogStaggers(plans, placed, attachment, straight);
5600
+ let room = jogs.room;
5601
+ plans.forEach((plan, i) => {
5602
+ if (room || routeAxis(plan) === null) return;
5603
+ const s = placed.get(plan.sourceId).rect;
5604
+ const t = placed.get(plan.targetId).rect;
5605
+ const lane = jogLane(plan, s, t);
5606
+ const needed = straight[i] ? plan.biDir ? 2 : 1 : 2;
5607
+ if (freeLines(lane) < needed) room = roomBeside(plan.exitSide, s);
5608
+ });
5609
+ return { routes: { plans, attachment, straight, staggers: jogs.staggers }, room };
5610
+ }
5611
+ function drawEdges(canvas, { plans, attachment, straight, staggers }, placed, vocab) {
5564
5612
  const sideLabelRequests = [];
5565
5613
  plans.forEach(
5566
5614
  (plan, i) => routeEdge(
@@ -5569,6 +5617,7 @@ function drawEdges(canvas, edges, placed, vocab) {
5569
5617
  i,
5570
5618
  placed,
5571
5619
  attachment,
5620
+ { straight: straight[i], stagger: staggers[i] },
5572
5621
  vocab,
5573
5622
  (candidates, label) => sideLabelRequests.push({ candidates, label })
5574
5623
  )
@@ -5645,12 +5694,14 @@ function assignAttachments(plans, placed) {
5645
5694
  for (const [sideKey, list2] of [...bySide.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {
5646
5695
  const [nodeId, side] = sideKey.split("|");
5647
5696
  const node = placed.get(nodeId);
5697
+ const horizontal = side === "top" || side === "bottom";
5648
5698
  list2.sort((a, b) => {
5649
5699
  const ra = placed.get(a.otherId).rect;
5650
5700
  const rb = placed.get(b.otherId).rect;
5651
- return ra.r0 - rb.r0 || ra.c0 - rb.c0 || a.otherId.localeCompare(b.otherId);
5701
+ const along = horizontal ? ra.c0 + ra.c1 - (rb.c0 + rb.c1) : ra.r0 + ra.r1 - (rb.r0 + rb.r1);
5702
+ const across = horizontal ? ra.r0 - rb.r0 : ra.c0 - rb.c0;
5703
+ return along || across || a.otherId.localeCompare(b.otherId);
5652
5704
  });
5653
- const horizontal = side === "top" || side === "bottom";
5654
5705
  const from = horizontal ? node.rect.c0 + 1 : node.rect.r0 + 1;
5655
5706
  const to = horizontal ? node.rect.c1 - 1 : node.rect.r1 - 1;
5656
5707
  const inner = Math.max(1, to - from + 1);
@@ -5685,15 +5736,128 @@ function assignAttachments(plans, placed) {
5685
5736
  }
5686
5737
  return result;
5687
5738
  }
5688
- function routeEdge(canvas, plan, planIdx, placed, attachment, vocab, deferSideLabel) {
5739
+ function routeAxis(plan) {
5740
+ if (plan.enterSide !== OPPOSITE_SIDE[plan.exitSide]) return null;
5741
+ return plan.exitSide === "bottom" || plan.exitSide === "top" ? "vertical" : "horizontal";
5742
+ }
5743
+ function jogLane(plan, s, t) {
5744
+ const [exitLine, enterLine] = plan.exitSide === "bottom" ? [s.r1, t.r0] : plan.exitSide === "top" ? [s.r0, t.r1] : plan.exitSide === "right" ? [s.c1, t.c0] : [s.c0, t.c1];
5745
+ const dir = plan.exitSide === "bottom" || plan.exitSide === "right" ? 1 : -1;
5746
+ return {
5747
+ dir,
5748
+ mid: Math.floor((exitLine + enterLine) / 2),
5749
+ firstFree: exitLine + dir,
5750
+ lastFree: enterLine - dir
5751
+ };
5752
+ }
5753
+ function freeLines(lane) {
5754
+ return (lane.lastFree - lane.firstFree) * lane.dir + 1;
5755
+ }
5756
+ function straightRunFits(s, t, exitPos, vertical) {
5757
+ return vertical ? exitPos >= t.c0 + 1 && exitPos <= t.c1 - 1 && exitPos >= s.c0 + 1 && exitPos <= s.c1 - 1 : exitPos >= t.r0 + 1 && exitPos <= t.r1 - 1 && exitPos >= s.r0 + 1 && exitPos <= s.r1 - 1;
5758
+ }
5759
+ function resolveStraightRuns(plans, placed, attachment) {
5760
+ const rectOf = (id) => placed.get(id).rect;
5761
+ const slot = (i, end) => attachment.get(`${i}:${end}`);
5762
+ const axes = plans.map(routeAxis);
5763
+ const straight = plans.map(
5764
+ (plan, i) => axes[i] !== null && straightRunFits(
5765
+ rectOf(plan.sourceId),
5766
+ rectOf(plan.targetId),
5767
+ slot(i, "exit").pos,
5768
+ axes[i] === "vertical"
5769
+ )
5770
+ );
5771
+ const cellOn = (j, side) => {
5772
+ const plan = plans[j];
5773
+ if (axes[j] === null) return null;
5774
+ if (`${plan.sourceId}|${plan.exitSide}` === side) return slot(j, "exit").pos;
5775
+ if (`${plan.targetId}|${plan.enterSide}` !== side) return null;
5776
+ const t = rectOf(plan.targetId);
5777
+ const lane = jogLane(plan, rectOf(plan.sourceId), t);
5778
+ if (!straight[j] && freeLines(lane) >= 2) return slot(j, "enter").pos;
5779
+ return axes[j] === "vertical" ? clamp2(slot(j, "exit").pos, t.c0 + 1, t.c1 - 1) : clamp2(slot(j, "exit").pos, t.r0 + 1, t.r1 - 1);
5780
+ };
5781
+ const clashes = (side, cell, self) => plans.some((_, j) => {
5782
+ const other = j === self ? null : cellOn(j, side);
5783
+ return other !== null && Math.abs(other - cell) <= 1;
5784
+ });
5785
+ for (let changed = true; changed; ) {
5786
+ changed = false;
5787
+ plans.forEach((plan, i) => {
5788
+ if (!straight[i]) return;
5789
+ const targetSide = `${plan.targetId}|${plan.enterSide}`;
5790
+ if (!clashes(targetSide, slot(i, "exit").pos, i)) return;
5791
+ const s = rectOf(plan.sourceId);
5792
+ const t = rectOf(plan.targetId);
5793
+ const port = slot(i, "enter").pos;
5794
+ const realign = straightRunFits(s, t, port, axes[i] === "vertical") && !clashes(`${plan.sourceId}|${plan.exitSide}`, port, i) && !clashes(targetSide, port, i);
5795
+ if (realign) slot(i, "exit").pos = port;
5796
+ else straight[i] = false;
5797
+ changed = true;
5798
+ });
5799
+ }
5800
+ return straight;
5801
+ }
5802
+ function assignJogStaggers(plans, placed, attachment, straight) {
5803
+ const staircases = /* @__PURE__ */ new Map();
5804
+ const staggers = plans.map((plan, i) => {
5805
+ const exit = attachment.get(`${i}:exit`);
5806
+ const enter = attachment.get(`${i}:enter`);
5807
+ const basis = enter.count > exit.count ? enter : exit;
5808
+ const s = placed.get(plan.sourceId).rect;
5809
+ const t = placed.get(plan.targetId).rect;
5810
+ const lane = jogLane(plan, s, t);
5811
+ if (routeAxis(plan) !== null && !straight[i] && freeLines(lane) >= 2) {
5812
+ const fanIn = basis === enter;
5813
+ const heading = Math.sign(enter.pos - exit.pos);
5814
+ const key = fanIn ? `${plan.targetId}|${plan.enterSide}|${heading}` : `${plan.sourceId}|${plan.exitSide}|${heading}`;
5815
+ const jog = {
5816
+ planIdx: i,
5817
+ outerness: fanIn ? -enter.pos * heading : exit.pos * heading,
5818
+ toward: fanIn ? lane.dir : lane.dir === 1 ? -1 : 1,
5819
+ lane,
5820
+ fanIn,
5821
+ room: fanIn ? roomBeside(plan.enterSide, t) : roomBeside(plan.exitSide, s)
5822
+ };
5823
+ staircases.set(key, [...staircases.get(key) ?? [], jog]);
5824
+ }
5825
+ return basis.index - Math.floor((basis.count - 1) / 2);
5826
+ });
5827
+ let room = null;
5828
+ for (const jogs of staircases.values()) {
5829
+ if (jogs.length < 2) continue;
5830
+ jogs.sort((a, b) => b.outerness - a.outerness || a.planIdx - b.planIdx);
5831
+ const half = Math.floor((jogs.length - 1) / 2);
5832
+ const lines = jogs.map((jog, rank) => jog.lane.mid + jog.toward * (half - rank));
5833
+ const shift = jogs[0].fanIn ? staircaseShift(jogs, lines, { spareArrowLine: true, spareExitLine: true }) : staircaseShift(jogs, lines, { spareArrowLine: true }) ?? staircaseShift(jogs, lines, {});
5834
+ if (shift === null) {
5835
+ room ?? (room = jogs[0].room);
5836
+ continue;
5837
+ }
5838
+ jogs.forEach((jog, k) => {
5839
+ staggers[jog.planIdx] = lines[k] + shift - jog.lane.mid;
5840
+ });
5841
+ }
5842
+ return { staggers, room };
5843
+ }
5844
+ function staircaseShift(jogs, lines, spare) {
5845
+ let lo = -Infinity;
5846
+ let hi = Infinity;
5847
+ jogs.forEach(({ lane }, k) => {
5848
+ const first = spare.spareExitLine ? lane.firstFree + lane.dir : lane.firstFree;
5849
+ const last = spare.spareArrowLine ? lane.lastFree - lane.dir : lane.lastFree;
5850
+ lo = Math.max(lo, Math.min(first, last) - lines[k]);
5851
+ hi = Math.min(hi, Math.max(first, last) - lines[k]);
5852
+ if ((last - first) * lane.dir < 0) hi = -Infinity;
5853
+ });
5854
+ return lo <= hi ? clamp2(0, lo, hi) : null;
5855
+ }
5856
+ function routeEdge(canvas, plan, planIdx, placed, attachment, shape, vocab, deferSideLabel) {
5689
5857
  const s = placed.get(plan.sourceId).rect;
5690
5858
  const t = placed.get(plan.targetId).rect;
5691
- const exitSlot = attachment.get(`${planIdx}:exit`);
5692
- const enterSlot = attachment.get(`${planIdx}:enter`);
5693
- const exitPos = exitSlot.pos;
5694
- const enterPos = enterSlot.pos;
5695
- const basis = enterSlot.count > exitSlot.count ? enterSlot : exitSlot;
5696
- const stagger = basis.index - Math.floor((basis.count - 1) / 2);
5859
+ const exitPos = attachment.get(`${planIdx}:exit`).pos;
5860
+ const enterPos = attachment.get(`${planIdx}:enter`).pos;
5697
5861
  const junction = (r, c, side) => {
5698
5862
  const ch = side === "top" ? vocab.stemUp : side === "bottom" ? vocab.stemDown : side === "left" ? vocab.stemLeft : vocab.stemRight;
5699
5863
  canvas.set(r, c, ch, "junction");
@@ -5705,7 +5869,8 @@ function routeEdge(canvas, plan, planIdx, placed, attachment, vocab, deferSideLa
5705
5869
  label: normalizeEdgeLabel(plan.edge.label),
5706
5870
  vocab,
5707
5871
  junction,
5708
- stagger,
5872
+ straight: shape.straight,
5873
+ stagger: shape.stagger,
5709
5874
  deferSideLabel
5710
5875
  };
5711
5876
  if (plan.exitSide === "bottom" && plan.enterSide === "top") {
@@ -5743,8 +5908,7 @@ function drawVertical(args, s, t, exitCol, enterCol, dir) {
5743
5908
  const hi = Math.max(rA, rB);
5744
5909
  for (let r = lo; r <= hi; r++) canvas.drawEdgeCell(r, col, vocab.v, "line-v", vocab);
5745
5910
  };
5746
- const straightOk = exitCol >= t.c0 + 1 && exitCol <= t.c1 - 1 && exitCol >= s.c0 + 1 && exitCol <= s.c1 - 1;
5747
- if (straightOk || gap < 2) {
5911
+ if (args.straight || gap < 2) {
5748
5912
  const sCol = clamp2(exitCol, s.c0 + 1, s.c1 - 1);
5749
5913
  const tCol = clamp2(exitCol, t.c0 + 1, t.c1 - 1);
5750
5914
  junction(exitRow, sCol, dir === 1 ? "bottom" : "top");
@@ -5877,8 +6041,7 @@ function drawHorizontal(args, s, t, exitRow, enterRow, dir) {
5877
6041
  canvas.drawEdgeCell(row, lo + i, ch, ch === vocab.h ? "line-h" : "label", vocab);
5878
6042
  });
5879
6043
  };
5880
- const straightOk = exitRow >= t.r0 + 1 && exitRow <= t.r1 - 1 && exitRow >= s.r0 + 1 && exitRow <= s.r1 - 1;
5881
- if (straightOk || gap < 2) {
6044
+ if (args.straight || gap < 2) {
5882
6045
  const sRow = clamp2(exitRow, s.r0 + 1, s.r1 - 1);
5883
6046
  const tRow = clamp2(exitRow, t.r0 + 1, t.r1 - 1);
5884
6047
  junction(sRow, exitCol, dir === 1 ? "right" : "left");