@diagrammo/dgmo 0.93.0 → 0.95.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.
Files changed (122) hide show
  1. package/dist/advanced.d.ts +98 -21
  2. package/dist/advanced.js +79 -61
  3. package/dist/block.d.ts +6 -0
  4. package/dist/block.js +23 -20
  5. package/dist/chart-meta.js +9 -9
  6. package/dist/{charts-d3-ERYYVGP6.js → charts-d3-SZV2SFTM.js} +2 -2
  7. package/dist/{chunk-J6AEKIRQ.js → chunk-2I4UQG7W.js} +1 -1
  8. package/dist/{chunk-LDDDKWL6.js → chunk-2J2CWWWK.js} +1 -1
  9. package/dist/{chunk-QDRCWVV3.js → chunk-4EX4OKGZ.js} +71 -8
  10. package/dist/{chunk-A5WIAMCT.js → chunk-4UVCTLRH.js} +1 -1
  11. package/dist/{chunk-KCMGIYPO.js → chunk-5XBYLYYI.js} +1 -1
  12. package/dist/{chunk-XUTR7GNT.js → chunk-62GLKE6Q.js} +68 -29
  13. package/dist/{chunk-D6PVMUCX.js → chunk-67N26CER.js} +4 -4
  14. package/dist/{chunk-IIV4SMJL.js → chunk-6EFCOES2.js} +370 -285
  15. package/dist/{chunk-TNV4F5WA.js → chunk-7IALGIOI.js} +2 -2
  16. package/dist/{chunk-MB2SQF7N.js → chunk-7WEYXYLC.js} +1 -1
  17. package/dist/{chunk-4RY5D5RE.js → chunk-AM42TLSZ.js} +98 -93
  18. package/dist/{chunk-J43OCO22.js → chunk-BCV2VJTM.js} +2 -2
  19. package/dist/{chunk-7OWK5K5C.js → chunk-BH2SF4TT.js} +2 -2
  20. package/dist/{chunk-UVX3IYXF.js → chunk-BTP2BMWN.js} +4 -4
  21. package/dist/{chunk-MUJVNSEW.js → chunk-C6G36F5S.js} +1 -1
  22. package/dist/{chunk-ZTLMEBAC.js → chunk-E7F76M3U.js} +208 -26
  23. package/dist/{chunk-AUS7V54P.js → chunk-ERT7XDQW.js} +1 -1
  24. package/dist/{chunk-WK5QEYFA.js → chunk-EXHXTMVR.js} +3 -3
  25. package/dist/{chunk-YXXIRM4C.js → chunk-FWVE373X.js} +2 -2
  26. package/dist/{chunk-EQWC76GQ.js → chunk-GWQRTA5W.js} +2 -2
  27. package/dist/{chunk-GJXMG4S3.js → chunk-HHVIE45A.js} +1 -1
  28. package/dist/{chunk-4FT5KQ7H.js → chunk-IGJEKO2P.js} +1 -1
  29. package/dist/{chunk-KRU2LCIP.js → chunk-IHN6WDEY.js} +1 -1
  30. package/dist/{chunk-QT3KDDXK.js → chunk-IN7XI6NO.js} +0 -7
  31. package/dist/{chunk-NMK7KJZZ.js → chunk-IQN2NGEU.js} +4 -4
  32. package/dist/{chunk-M6ZQAFPD.js → chunk-IY62DXT2.js} +1 -1
  33. package/dist/{chunk-4WQX55VX.js → chunk-IZHGT5HD.js} +31 -5
  34. package/dist/{chunk-CYDM2XII.js → chunk-JJ7RGTAU.js} +56 -7
  35. package/dist/{chunk-NJJCTEBM.js → chunk-KLBTJEIK.js} +1 -1
  36. package/dist/{chunk-KHL652SX.js → chunk-KSZB7TIY.js} +1 -1
  37. package/dist/{chunk-KPSSNGAE.js → chunk-L5S32VZJ.js} +4 -4
  38. package/dist/{chunk-472EOHVW.js → chunk-LAXMUSGW.js} +31 -5
  39. package/dist/{chunk-M4NV5PPU.js → chunk-LJGE43SG.js} +1 -1
  40. package/dist/{chunk-VSOZZYLK.js → chunk-NERQSSYD.js} +20 -9
  41. package/dist/{chunk-UG7AQQNR.js → chunk-OSSTOSXU.js} +2 -2
  42. package/dist/{chunk-YDZIVDVR.js → chunk-P5XA627W.js} +7 -7
  43. package/dist/{chunk-DRQSB72S.js → chunk-PGBTUGDB.js} +2 -2
  44. package/dist/{chunk-65GPEV5V.js → chunk-QKPOIJBT.js} +2 -2
  45. package/dist/{chunk-QJOVZ4TC.js → chunk-QPQWY5RU.js} +1 -1
  46. package/dist/{chunk-P7TRFL4P.js → chunk-R46N5KR4.js} +2 -0
  47. package/dist/{chunk-LNVB75QU.js → chunk-RBVFNUAL.js} +1 -1
  48. package/dist/{chunk-DAHQL57W.js → chunk-RITTLIDJ.js} +1 -1
  49. package/dist/{chunk-2TFXRBCD.js → chunk-RQTDUZUH.js} +3 -3
  50. package/dist/{chunk-Q7Y6JQ3R.js → chunk-S4SJ4LLY.js} +1 -1
  51. package/dist/{chunk-LUDUDBO6.js → chunk-S5Y3OO3V.js} +2 -2
  52. package/dist/{chunk-3GCASUWA.js → chunk-TASRGDYP.js} +1 -1
  53. package/dist/{chunk-5HAYT43L.js → chunk-U6VS3T2M.js} +19 -3
  54. package/dist/{chunk-42UJ23H3.js → chunk-UIEKW4SG.js} +1 -0
  55. package/dist/{chunk-IESUM4N5.js → chunk-USE6HIOZ.js} +95 -62
  56. package/dist/{chunk-FIYW7JW4.js → chunk-USZLHYEQ.js} +1 -1
  57. package/dist/{chunk-U7U64UUN.js → chunk-V5D6GDNK.js} +4 -4
  58. package/dist/{chunk-ADVGV3P7.js → chunk-VB4VMB2I.js} +7 -5
  59. package/dist/{chunk-CQYFZOUC.js → chunk-VBMRZCMQ.js} +1 -1
  60. package/dist/{chunk-USAGHYRD.js → chunk-VF7IKIRS.js} +2 -2
  61. package/dist/{chunk-EJS3K44P.js → chunk-VGAMBOOC.js} +5 -3
  62. package/dist/{chunk-P5FUWXPW.js → chunk-VTESGA5F.js} +7 -5
  63. package/dist/chunk-WTTIODDV.js +9 -0
  64. package/dist/{chunk-5CBX66KB.js → chunk-XJQ6Z3FO.js} +2 -2
  65. package/dist/{chunk-KPGPK4SK.js → chunk-XOMIYMQ3.js} +6 -6
  66. package/dist/{chunk-KCHQVED5.js → chunk-YQMIKX54.js} +43 -7
  67. package/dist/completion-registry.js +3 -0
  68. package/dist/copy-image.d.ts +34 -0
  69. package/dist/copy-image.js +96 -0
  70. package/dist/countdown.js +1 -1
  71. package/dist/{dgmo-router-CZN36TR3.js → dgmo-router-6YLKM6WU.js} +13 -13
  72. package/dist/{dimensions-7HHKO5BS.js → dimensions-DS6FWLRY.js} +2 -2
  73. package/dist/{flowchart-parser-4MZPWYK6.js → flowchart-parser-J3VWIFWB.js} +5 -5
  74. package/dist/{flowchart-renderer-5XDN575E.js → flowchart-renderer-FECH5KK5.js} +14 -12
  75. package/dist/index.js +19 -19
  76. package/dist/layout-5SZ5A64I.js +24 -0
  77. package/dist/{layout-5GHV7HNM.js → layout-EWXHEXNS.js} +11 -10
  78. package/dist/{layout-QXGPY7KA.js → layout-TIBRMWHL.js} +7 -6
  79. package/dist/layout-VDCJOZSH.js +11 -0
  80. package/dist/layout-YBMT74MG.js +24 -0
  81. package/dist/{layout-search-EMTCDC3C.js → layout-search-AWPJWBKT.js} +9 -8
  82. package/dist/{parser-R3LPEQIT.js → parser-AR2GON37.js} +2 -2
  83. package/dist/{parser-YX72VLDZ.js → parser-BTSTKY5G.js} +5 -5
  84. package/dist/{parser-OGF2CDA6.js → parser-MA7L3XND.js} +5 -5
  85. package/dist/{parser-VKYUAT4Y.js → parser-ZRIZFDZY.js} +5 -5
  86. package/dist/{redraw-T324XAF3.js → redraw-AHW7EUUF.js} +2 -2
  87. package/dist/{redraw-MSXU4ZD2.js → redraw-STZ4WJAI.js} +3 -3
  88. package/dist/{renderer-HYGTMBHT.js → renderer-2LYX6NHN.js} +3 -3
  89. package/dist/{renderer-XJMVG2WJ.js → renderer-2QPHDBZY.js} +5 -5
  90. package/dist/{renderer-GPAVVUET.js → renderer-3NLDX7DQ.js} +3 -3
  91. package/dist/{renderer-IHCWBFPI.js → renderer-4VGO27EE.js} +14 -13
  92. package/dist/{renderer-JJ4QW3SK.js → renderer-6BDK47V6.js} +1 -1
  93. package/dist/{renderer-FL7EOSBU.js → renderer-7OGGV327.js} +3 -3
  94. package/dist/{renderer-5ITLW7MX.js → renderer-ACQQ2JXA.js} +6 -4
  95. package/dist/{renderer-37PLQHVB.js → renderer-BXD5KVSR.js} +2 -2
  96. package/dist/{renderer-TSCSZ6CL.js → renderer-HX6ICPDX.js} +2 -2
  97. package/dist/{renderer-BO73LSVT.js → renderer-IGSHD3OT.js} +4 -4
  98. package/dist/{renderer-DD6T3C4J.js → renderer-ISQJ2ELA.js} +2 -2
  99. package/dist/{renderer-CNRQFIEI.js → renderer-IVHD7ENY.js} +4 -4
  100. package/dist/{renderer-POBGKIUT.js → renderer-IXBOT6DU.js} +3 -3
  101. package/dist/{renderer-GFALLIYT.js → renderer-JYHA6R2D.js} +3 -3
  102. package/dist/{renderer-GOXAP2IE.js → renderer-KJ3V5BYP.js} +2 -2
  103. package/dist/{renderer-GFGFHYWY.js → renderer-MWZC7TMD.js} +2 -2
  104. package/dist/{renderer-3F47TPZ2.js → renderer-O6RP52CQ.js} +2 -2
  105. package/dist/{renderer-PBKTAWQV.js → renderer-P3WR7TKD.js} +14 -13
  106. package/dist/{renderer-VDBNC7A6.js → renderer-QTPWRRJ7.js} +2 -2
  107. package/dist/{renderer-J3QWK6IM.js → renderer-RUSQJFFC.js} +3 -3
  108. package/dist/{renderer-7Y3LR4R2.js → renderer-TINHO2IO.js} +2 -2
  109. package/dist/{renderer-J6H4Q3RM.js → renderer-UGW4N2W5.js} +4 -3
  110. package/dist/{renderer-EVKWGUGT.js → renderer-UTEEJDGB.js} +4 -3
  111. package/dist/{renderer-ISDKO3DI.js → renderer-WPN2SXGT.js} +2 -2
  112. package/dist/{renderer-6GJWADLO.js → renderer-XCLARXCK.js} +2 -2
  113. package/dist/{renderer-RDI2RYUP.js → renderer-XDX6S7OV.js} +3 -3
  114. package/dist/{renderer-VI34SD5V.js → renderer-Y47EM337.js} +6 -6
  115. package/dist/{renderer-HJ54YXT3.js → renderer-ZV6KCLCL.js} +14 -14
  116. package/dist/{state-parser-NPYTMRXP.js → state-parser-PMNHLHLE.js} +5 -5
  117. package/dist/{state-renderer-44K2KDX7.js → state-renderer-JQ5DS66J.js} +14 -13
  118. package/docs/language-reference.md +2 -2
  119. package/package.json +5 -1
  120. package/dist/layout-33FHGDEV.js +0 -23
  121. package/dist/layout-FTOGDNUL.js +0 -23
  122. package/dist/layout-J3AGFZZ7.js +0 -10
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  drawCylinderCard,
3
3
  drawQueueCard
4
- } from "./chunk-KRU2LCIP.js";
4
+ } from "./chunk-IHN6WDEY.js";
5
5
  import {
6
6
  CYLINDER_RY,
7
7
  QUEUE_CAP
@@ -9,7 +9,7 @@ import {
9
9
  import {
10
10
  WHITEBOARD_COLORS,
11
11
  WHITEBOARD_NOTE_COLOR
12
- } from "./chunk-P7TRFL4P.js";
12
+ } from "./chunk-R46N5KR4.js";
13
13
  import {
14
14
  renderChartTitle
15
15
  } from "./chunk-6XLMTAEX.js";
@@ -132,6 +132,17 @@ function pieceContains(p, px, py) {
132
132
  function whiteboardShapeContains(shape, point) {
133
133
  return piecesOf(shape).some((p) => pieceContains(p, point.x, point.y));
134
134
  }
135
+ function whiteboardLabelPosition(shape, elements) {
136
+ if (shape.labelPosition) return shape.labelPosition;
137
+ return shape.shape === "rectangle" && whiteboardEnclosesAny(shape, elements) ? "top" : "middle";
138
+ }
139
+ function whiteboardEnclosesAny(outer, elements) {
140
+ const x1 = outer.x + outer.width;
141
+ const y1 = outer.y + outer.height;
142
+ return elements.some(
143
+ (el) => el !== outer && (el.kind === "shape" || el.kind === "note" || el.kind === "image") && el.x >= outer.x && el.y >= outer.y && el.x + el.width <= x1 && el.y + el.height <= y1 && !(el.x === outer.x && el.y === outer.y && el.width === outer.width && el.height === outer.height)
144
+ );
145
+ }
135
146
  function whiteboardShapeAt(point, elements) {
136
147
  for (let i = elements.length - 1; i >= 0; i--) {
137
148
  const el = elements[i];
@@ -331,9 +342,35 @@ function whiteboardSegmentMidpoint(s) {
331
342
  y: (s.y1 + 2 * s.cy + s.y2) / 4
332
343
  };
333
344
  }
345
+ var DRAW_BAND = {
346
+ image: 0,
347
+ shape: 1,
348
+ note: 1,
349
+ arrow: 1,
350
+ line: 1,
351
+ text: 2,
352
+ ink: 3
353
+ };
354
+ function whiteboardDrawBand(el) {
355
+ return DRAW_BAND[el.kind];
356
+ }
357
+ function whiteboardDrawOrder(elements) {
358
+ const key = elements.map((el, i) => {
359
+ if (el.kind !== "arrow" && el.kind !== "line") return i;
360
+ const { from, to } = whiteboardConnectorAttachments(el, elements);
361
+ const last = Math.max(from, to);
362
+ return last > i ? last + 0.5 : i;
363
+ });
364
+ return elements.map((_, i) => i).sort(
365
+ (a, b) => DRAW_BAND[elements[a].kind] - DRAW_BAND[elements[b].kind] || key[a] - key[b] || a - b
366
+ );
367
+ }
334
368
 
335
369
  // src/whiteboard/label.ts
336
370
  var WHITEBOARD_LABEL_FONT = 14;
371
+ var WHITEBOARD_CONTAINER_FONT = 16;
372
+ var WHITEBOARD_CONTAINER_WEIGHT = 600;
373
+ var CONTAINER_GAP = 4;
337
374
  var WHITEBOARD_NOTE_FONT = 12;
338
375
  var WHITEBOARD_LABEL_LINE = 1.25;
339
376
  var LABEL_PAD = 8;
@@ -370,20 +407,22 @@ function wrapWhiteboardLabel(label, box) {
370
407
  const font = "kind" in box && box.kind === "note" ? WHITEBOARD_NOTE_FONT : WHITEBOARD_LABEL_FONT;
371
408
  return label.split("\n").flatMap((line) => line ? wrapTextToWidth(line, font, width) : [""]);
372
409
  }
373
- function fitWhiteboardLabel(label, box) {
410
+ function fitWhiteboardLabel(label, box, opts = {}) {
374
411
  const isNote = "kind" in box && box.kind === "note";
375
- const full = isNote ? WHITEBOARD_NOTE_FONT : WHITEBOARD_LABEL_FONT;
412
+ const full = opts.font ?? (isNote ? WHITEBOARD_NOTE_FONT : WHITEBOARD_LABEL_FONT);
376
413
  const pad = isNote ? WHITEBOARD_NOTE_PAD : LABEL_PAD;
377
414
  if (!label) return { lines: [], font: full, top: pad };
415
+ const bold = opts.bold ?? false;
378
416
  const width = whiteboardLabelWidth(box);
379
- const height = whiteboardLabelHeight(box);
417
+ const height = opts.height ?? whiteboardLabelHeight(box);
418
+ const measure = (l, font2) => measureText(l, font2, { bold });
380
419
  const wrap = (font2, hardBreak) => label.split("\n").flatMap(
381
- (line) => line ? wrapTextToWidth(line, font2, width, { hardBreak }) : [""]
420
+ (line) => line ? wrapTextToWidth(line, font2, width, { hardBreak, bold }) : [""]
382
421
  );
383
422
  const tall = (n, font2) => n * font2 * WHITEBOARD_LABEL_LINE > height;
384
423
  for (let font2 = full; font2 >= WHITEBOARD_LABEL_MIN_FONT; font2--) {
385
424
  const lines2 = wrap(font2, false);
386
- if (!tall(lines2.length, font2) && lines2.every((l) => measureText(l, font2) <= width))
425
+ if (!tall(lines2.length, font2) && lines2.every((l) => measure(l, font2) <= width))
387
426
  return { lines: lines2, font: font2, top: pad };
388
427
  }
389
428
  const font = WHITEBOARD_LABEL_MIN_FONT;
@@ -399,11 +438,76 @@ function fitWhiteboardLabel(label, box) {
399
438
  if (lines.length <= room) return { lines, font, top };
400
439
  const kept = lines.slice(0, room);
401
440
  let last = kept[room - 1];
402
- while (last && measureText(`${last}\u2026`, font) > width)
441
+ while (last && measure(`${last}\u2026`, font) > width)
403
442
  last = [...last].slice(0, -1).join("");
404
443
  kept[room - 1] = `${last.trimEnd()}\u2026`;
405
444
  return { lines: kept, font, top };
406
445
  }
446
+ function whiteboardLabelCentreY(box, position, blockHeight) {
447
+ if (position === "middle") return box.y + box.height / 2;
448
+ const innerTop = box.y + (box.height - whiteboardLabelHeight(box)) / 2;
449
+ return innerTop + blockHeight / 2;
450
+ }
451
+ function whiteboardShapeLabel(el, elements, text = el.label) {
452
+ const block = (n, font2) => n * font2 * WHITEBOARD_LABEL_LINE;
453
+ const top = whiteboardLabelPosition(el, elements) === "top";
454
+ const inset = (el.height - whiteboardLabelHeight(el)) / 2;
455
+ const innerTop = el.y + inset;
456
+ const innerBottom = el.y + el.height - inset;
457
+ const spans = [];
458
+ for (const o of elements) {
459
+ if (o === el) continue;
460
+ if (o.kind !== "shape" && o.kind !== "note" && o.kind !== "image") continue;
461
+ const ox1 = o.x + o.width;
462
+ const oy1 = o.y + o.height;
463
+ const overlaps = o.x < el.x + el.width && ox1 > el.x && o.y < el.y + el.height && oy1 > el.y;
464
+ const encloses = o.x <= el.x && o.y <= el.y && ox1 >= el.x + el.width && oy1 >= el.y + el.height;
465
+ if (overlaps && !encloses)
466
+ spans.push([o.y - CONTAINER_GAP, oy1 + CONTAINER_GAP]);
467
+ }
468
+ spans.sort((a, b) => a[0] - b[0]);
469
+ const strips = [];
470
+ let from = innerTop;
471
+ for (const [y0, y1] of spans) {
472
+ if (y0 > from) strips.push([from, Math.min(y0, innerBottom)]);
473
+ from = Math.max(from, y1);
474
+ }
475
+ if (from < innerBottom) strips.push([from, innerBottom]);
476
+ const floorLine = block(1, WHITEBOARD_LABEL_MIN_FONT);
477
+ const roomy = strips.filter(([a, b]) => b - a >= floorLine);
478
+ const font = top ? WHITEBOARD_CONTAINER_FONT : WHITEBOARD_LABEL_FONT;
479
+ const opts = top ? { font, bold: true } : {};
480
+ const into = ([a, b], centre) => {
481
+ const fit2 = fitWhiteboardLabel(text, el, { ...opts, height: b - a });
482
+ const h = block(fit2.lines.length, fit2.font);
483
+ const cy = Math.min(Math.max(centre, a + h / 2), b - h / 2);
484
+ return { lines: fit2.lines, font: fit2.font, bold: top, cy, onEdge: false };
485
+ };
486
+ if (top) {
487
+ const first = roomy[0];
488
+ if (first?.[0] === innerTop) return into(first, -Infinity);
489
+ const last = roomy.at(-1);
490
+ if (last?.[1] === innerBottom) return into(last, Infinity);
491
+ } else {
492
+ const mid = el.y + el.height / 2;
493
+ const strip = roomy.find(([a, b]) => a <= mid && mid <= b) ?? roomy.reduce(
494
+ (best, s) => !best || s[1] - s[0] > best[1] - best[0] ? s : best,
495
+ void 0
496
+ );
497
+ if (strip) return into(strip, mid);
498
+ }
499
+ const fit = fitWhiteboardLabel(text.replace(/\n/g, " "), el, {
500
+ ...opts,
501
+ height: block(1, font)
502
+ });
503
+ return {
504
+ lines: fit.lines.slice(0, 1),
505
+ font: fit.font,
506
+ bold: top,
507
+ cy: el.y,
508
+ onEdge: true
509
+ };
510
+ }
407
511
 
408
512
  // src/whiteboard/renderer.ts
409
513
  function visibleWhiteboardIndices(parsed, options = {}) {
@@ -477,8 +581,8 @@ var SAFE_IMAGE_HREF_RE = /^(https?:|blob:|data:image\/)/i;
477
581
  function labelLines(label) {
478
582
  return label.split("\n");
479
583
  }
480
- function widest(lines, font) {
481
- return Math.max(0, ...lines.map((l) => measureText(l, font)));
584
+ function widest(lines, font, bold = false) {
585
+ return Math.max(0, ...lines.map((l) => measureText(l, font, { bold })));
482
586
  }
483
587
  function grow(b, x0, y0, x1, y1) {
484
588
  b.minX = Math.min(b.minX, x0, x1);
@@ -498,6 +602,7 @@ function whiteboardBounds(parsed, options = {}) {
498
602
  maxY: -Infinity
499
603
  };
500
604
  const elements = visibleWhiteboardElements(parsed, options);
605
+ const labelAt = placeConnectorLabels(elements, parsed.elements);
501
606
  for (const el of elements) {
502
607
  switch (el.kind) {
503
608
  case "shape":
@@ -527,7 +632,7 @@ function whiteboardBounds(parsed, options = {}) {
527
632
  }
528
633
  if (el.label) {
529
634
  const lines = labelLines(el.label);
530
- const { x: mx, y: my } = whiteboardSegmentMidpoint(s);
635
+ const { x: mx, y: my } = labelAt.get(el);
531
636
  const hw = widest(lines, WHITEBOARD_LABEL_FONT) / 2 + 4;
532
637
  const hh = WHITEBOARD_LABEL_FONT + (lines.length - 1) * WHITEBOARD_LABEL_FONT * WHITEBOARD_LABEL_LINE / 2;
533
638
  grow(b, mx - hw, my - hh, mx + hw, my + hh);
@@ -578,6 +683,78 @@ function curveTrim(s, end, len) {
578
683
  }
579
684
  return (near + far) / 2;
580
685
  }
686
+ var LABEL_SLIDE_STEP = 0.05;
687
+ var LABEL_SLIDE_TRIES = 8;
688
+ var LABEL_CLEAR = 5;
689
+ function boxesOverlap(a, b) {
690
+ return a.x0 < b.x1 && b.x0 < a.x1 && a.y0 < b.y1 && b.y0 < a.y1;
691
+ }
692
+ function connectorLabelBox(lines, x, y) {
693
+ const hw = widest(lines, WHITEBOARD_LABEL_FONT) / 2 + LABEL_CLEAR;
694
+ const hh = lines.length * WHITEBOARD_LABEL_FONT * WHITEBOARD_LABEL_LINE / 2 + LABEL_CLEAR;
695
+ return { x0: x - hw, y0: y - hh, x1: x + hw, y1: y + hh };
696
+ }
697
+ function authoredTextBoxes(elements, all) {
698
+ const boxes = [];
699
+ for (const el of elements) {
700
+ if (el.kind === "text") {
701
+ const lines = labelLines(el.text);
702
+ boxes.push({
703
+ x0: el.x,
704
+ y0: el.y,
705
+ x1: el.x + widest(lines, WHITEBOARD_TEXT_FONT),
706
+ y1: el.y + lines.length * WHITEBOARD_TEXT_FONT * WHITEBOARD_LABEL_LINE
707
+ });
708
+ } else if (el.kind === "note") {
709
+ boxes.push({
710
+ x0: el.x,
711
+ y0: el.y,
712
+ x1: el.x + el.width,
713
+ y1: el.y + Math.max(el.height, noteTextHeight(el))
714
+ });
715
+ } else if (el.kind === "shape" && el.label) {
716
+ const { lines, font, bold, cy } = whiteboardShapeLabel(el, all);
717
+ if (lines.length === 0) continue;
718
+ const cx = el.x + el.width / 2 + whiteboardLabelShift(el);
719
+ const hh = lines.length * font * WHITEBOARD_LABEL_LINE / 2;
720
+ const hw = widest(lines, font, bold) / 2;
721
+ boxes.push({ x0: cx - hw, y0: cy - hh, x1: cx + hw, y1: cy + hh });
722
+ }
723
+ }
724
+ return boxes;
725
+ }
726
+ function placeConnectorLabels(elements, all) {
727
+ const placed = /* @__PURE__ */ new Map();
728
+ const taken = authoredTextBoxes(elements, all);
729
+ for (const el of elements) {
730
+ if (el.kind !== "arrow" && el.kind !== "line" || !el.label) continue;
731
+ const lines = labelLines(el.label);
732
+ const s = clipWhiteboardConnector(el, elements);
733
+ const mid = whiteboardSegmentMidpoint(s);
734
+ let at = mid;
735
+ const clears = (p) => {
736
+ const box = connectorLabelBox(lines, p.x, p.y);
737
+ return !taken.some((t) => boxesOverlap(box, t));
738
+ };
739
+ if (!clears(mid)) {
740
+ search: for (let k = 1; k <= LABEL_SLIDE_TRIES; k++) {
741
+ for (const t of [
742
+ 0.5 - k * LABEL_SLIDE_STEP,
743
+ 0.5 + k * LABEL_SLIDE_STEP
744
+ ]) {
745
+ const p = segmentPoint(s, t);
746
+ if (clears(p)) {
747
+ at = p;
748
+ break search;
749
+ }
750
+ }
751
+ }
752
+ }
753
+ placed.set(el, at);
754
+ taken.push(connectorLabelBox(lines, at.x, at.y));
755
+ }
756
+ return placed;
757
+ }
581
758
  function whiteboardConnectorPaint(s, heads) {
582
759
  const polygon = (tip, ux, uy, head) => {
583
760
  const bx = tip.x - ux * head;
@@ -665,6 +842,7 @@ function renderWhiteboard(container, parsed, palette, isDark, options = {}) {
665
842
  const titleOffset = showTitle ? TITLE_BAND : 0;
666
843
  const elements = visibleWhiteboardElements(parsed, options);
667
844
  const b = whiteboardBounds(parsed, options);
845
+ const labelAt = placeConnectorLabels(elements, parsed.elements);
668
846
  const contentW = b.maxX - b.minX;
669
847
  const contentH = b.maxY - b.minY;
670
848
  const titleW = showTitle ? measureText(parsed.title, TITLE_FONT_SIZE, { bold: true }) : 0;
@@ -708,11 +886,16 @@ function renderWhiteboard(container, parsed, palette, isDark, options = {}) {
708
886
  }
709
887
  const canvas = svg.append("g").attr("class", "whiteboard-canvas").attr("transform", `translate(${round2(tx)},${round2(ty)})`);
710
888
  const halo = palette.bg;
711
- const centredLabel = (g, { lines, font }, cx, cy, color, ground) => {
889
+ const centredLabel = (g, {
890
+ lines,
891
+ font,
892
+ bold
893
+ }, cx, cy, color, ground) => {
712
894
  if (lines.length === 0) return;
713
895
  const lh = font * WHITEBOARD_LABEL_LINE;
714
896
  const top = cy - lines.length * lh / 2 + lh * BASELINE;
715
897
  const t = g.append("text").attr("class", "whiteboard-label").attr("text-anchor", "middle").attr("font-size", font).attr("fill", color).attr("stroke", ground).attr("stroke-width", LABEL_HALO).attr("stroke-linejoin", "round").attr("paint-order", "stroke");
898
+ if (bold) t.attr("font-weight", WHITEBOARD_CONTAINER_WEIGHT);
716
899
  appendLines(t, lines, cx, top, lh);
717
900
  };
718
901
  const drawImage = (g, el) => {
@@ -753,13 +936,14 @@ function renderWhiteboard(container, parsed, palette, isDark, options = {}) {
753
936
  drawQueueCard(inner, el.width, el.height, fill, stroke);
754
937
  }
755
938
  }
939
+ const label = whiteboardShapeLabel(el, parsed.elements);
756
940
  centredLabel(
757
941
  g,
758
- fitWhiteboardLabel(el.label, el),
942
+ label,
759
943
  cx + whiteboardLabelShift(el),
760
- cy,
944
+ label.cy,
761
945
  labelColor,
762
- fill === "none" ? halo : fill
946
+ label.onEdge || fill === "none" ? halo : fill
763
947
  );
764
948
  break;
765
949
  }
@@ -814,7 +998,7 @@ function renderWhiteboard(container, parsed, palette, isDark, options = {}) {
814
998
  }
815
999
  if (el.label) {
816
1000
  const lines = labelLines(el.label);
817
- const mid = whiteboardSegmentMidpoint(s);
1001
+ const mid = labelAt.get(el);
818
1002
  const mx = round2(mid.x);
819
1003
  const lh = WHITEBOARD_LABEL_FONT * WHITEBOARD_LABEL_LINE;
820
1004
  const firstY = mid.y + WHITEBOARD_LABEL_FONT * 0.35 - (lines.length - 1) * lh / 2;
@@ -851,17 +1035,8 @@ function renderWhiteboard(container, parsed, palette, isDark, options = {}) {
851
1035
  };
852
1036
  for (const el of inDrawOrder(elements)) drawElement(el);
853
1037
  }
854
- var DRAW_BAND = {
855
- image: 0,
856
- shape: 1,
857
- note: 2,
858
- arrow: 3,
859
- line: 3,
860
- text: 4,
861
- ink: 5
862
- };
863
1038
  function inDrawOrder(elements) {
864
- return elements.map((el, i) => ({ el, i })).sort((a, b) => DRAW_BAND[a.el.kind] - DRAW_BAND[b.el.kind] || a.i - b.i).map(({ el }) => el);
1039
+ return whiteboardDrawOrder(elements).map((i) => elements[i]);
865
1040
  }
866
1041
  function appendLines(t, lines, x, firstY, lh) {
867
1042
  lines.forEach((ln, i) => {
@@ -876,12 +1051,17 @@ function round2(n) {
876
1051
  export {
877
1052
  whiteboardNoteFold,
878
1053
  whiteboardShapeContains,
1054
+ whiteboardLabelPosition,
879
1055
  whiteboardShapeAt,
880
1056
  whiteboardConnectorAttachments,
881
1057
  clipWhiteboardConnector,
882
1058
  whiteboardBendHandle,
883
1059
  whiteboardBendFor,
884
1060
  whiteboardSegmentMidpoint,
1061
+ whiteboardDrawBand,
1062
+ whiteboardDrawOrder,
1063
+ WHITEBOARD_CONTAINER_FONT,
1064
+ WHITEBOARD_CONTAINER_WEIGHT,
885
1065
  WHITEBOARD_NOTE_FONT,
886
1066
  WHITEBOARD_LABEL_MIN_FONT,
887
1067
  whiteboardLabelWidth,
@@ -889,6 +1069,8 @@ export {
889
1069
  whiteboardLabelHeight,
890
1070
  wrapWhiteboardLabel,
891
1071
  fitWhiteboardLabel,
1072
+ whiteboardLabelCentreY,
1073
+ whiteboardShapeLabel,
892
1074
  visibleWhiteboardIndices,
893
1075
  visibleWhiteboardElements,
894
1076
  IMAGE_NOT_UPLOADED,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  acyclicOrient
3
- } from "./chunk-EJS3K44P.js";
3
+ } from "./chunk-VGAMBOOC.js";
4
4
 
5
5
  // src/swimlane/layout.ts
6
6
  var MARGIN = 30;
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  searchPlacement
3
- } from "./chunk-LDDDKWL6.js";
3
+ } from "./chunk-2J2CWWWK.js";
4
4
  import {
5
5
  noteCanvasShift,
6
6
  placeNotes,
7
7
  resolveNotes
8
- } from "./chunk-NJJCTEBM.js";
8
+ } from "./chunk-KLBTJEIK.js";
9
9
  import {
10
10
  noteBoxSize
11
- } from "./chunk-D6PVMUCX.js";
11
+ } from "./chunk-67N26CER.js";
12
12
 
13
13
  // src/graph/layout.ts
14
14
  import dagre from "@dagrejs/dagre";
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-VLC6WNRD.js";
7
7
  import {
8
8
  parseInlineMarkdown
9
- } from "./chunk-65GPEV5V.js";
9
+ } from "./chunk-QKPOIJBT.js";
10
10
  import {
11
11
  FONT_FAMILY
12
12
  } from "./chunk-ICLB27PZ.js";
@@ -82,7 +82,7 @@ function renderGoalForExport(container, parsed, palette, isDark, exportDims) {
82
82
  renderGoal(container, parsed, palette, isDark, exportDims);
83
83
  }
84
84
  function displayLen(token) {
85
- return token.replace(/\[(.+?)\]\((.+?)\)/g, "$1").replace(/\*\*|__|\*|_|`/g, "").length;
85
+ return token.replace(/\[([^[\]\n\r]+)\]\((?:[^()\n\r]|\([^()\n\r]*\))+\)/g, "$1").replace(/\*\*|__|\*|_|`/g, "").length;
86
86
  }
87
87
  function wrapText(text, maxChars) {
88
88
  const words = text.split(/\s+/);
@@ -8,10 +8,10 @@ import {
8
8
  } from "./chunk-VLC6WNRD.js";
9
9
  import {
10
10
  wrapDescriptionLines
11
- } from "./chunk-MB2SQF7N.js";
11
+ } from "./chunk-7WEYXYLC.js";
12
12
  import {
13
13
  renderInlineText
14
- } from "./chunk-65GPEV5V.js";
14
+ } from "./chunk-QKPOIJBT.js";
15
15
  import {
16
16
  FONT_FAMILY
17
17
  } from "./chunk-ICLB27PZ.js";
@@ -3,7 +3,7 @@ import {
3
3
  mapLegendConfig,
4
4
  mapLegendGroups,
5
5
  parsePathRings
6
- } from "./chunk-4RY5D5RE.js";
6
+ } from "./chunk-AM42TLSZ.js";
7
7
  import {
8
8
  buildSwatches
9
9
  } from "./chunk-T7NWBVSC.js";
@@ -10,7 +10,7 @@ import {
10
10
  } from "./chunk-CN4RDJDV.js";
11
11
  import {
12
12
  layoutInlineHeader
13
- } from "./chunk-42UJ23H3.js";
13
+ } from "./chunk-UIEKW4SG.js";
14
14
  import {
15
15
  TITLE_FONT_SIZE,
16
16
  TITLE_FONT_WEIGHT,
@@ -43,7 +43,7 @@ import {
43
43
  } from "./chunk-IYULMRBE.js";
44
44
  import {
45
45
  renderInlineText
46
- } from "./chunk-65GPEV5V.js";
46
+ } from "./chunk-QKPOIJBT.js";
47
47
  import {
48
48
  FONT_FAMILY
49
49
  } from "./chunk-ICLB27PZ.js";
@@ -4,11 +4,6 @@ import {
4
4
  wrapTextToWidth
5
5
  } from "./chunk-KAO7JL4I.js";
6
6
 
7
- // src/boxes-and-lines/node-metrics.ts
8
- var PHI = 1.618;
9
- var NODE_HEIGHT = 60;
10
- var NODE_WIDTH = Math.round(NODE_HEIGHT * PHI);
11
-
12
7
  // src/boxes-and-lines/label-placement.ts
13
8
  import { curveBasis } from "d3-shape";
14
9
  var EDGE_LABEL_FONT_SIZE = 11;
@@ -426,8 +421,6 @@ function placeEdgeLabels(layout, opts) {
426
421
  }
427
422
 
428
423
  export {
429
- NODE_HEIGHT,
430
- NODE_WIDTH,
431
424
  EDGE_LABEL_FONT_SIZE,
432
425
  BOX_CLEAR_PAD,
433
426
  LABEL_REACH_WIDE,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  layoutERDiagram
3
- } from "./chunk-TNV4F5WA.js";
3
+ } from "./chunk-7IALGIOI.js";
4
4
  import {
5
5
  serializeSvg
6
6
  } from "./chunk-CYRB2JTN.js";
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-24YPR5EH.js";
10
10
  import {
11
11
  layoutInlineHeader
12
- } from "./chunk-42UJ23H3.js";
12
+ } from "./chunk-UIEKW4SG.js";
13
13
  import {
14
14
  TITLE_FONT_SIZE,
15
15
  TITLE_FONT_WEIGHT,
@@ -28,14 +28,14 @@ import {
28
28
  } from "./chunk-JILEYZ2V.js";
29
29
  import {
30
30
  parseERDiagram
31
- } from "./chunk-Q7Y6JQ3R.js";
31
+ } from "./chunk-S4SJ4LLY.js";
32
32
  import {
33
33
  NOTE_BADGE_RADIUS,
34
34
  noteConnectorPoints,
35
35
  renderNoteBadge,
36
36
  renderNoteBox,
37
37
  renderNoteConnector
38
- } from "./chunk-D6PVMUCX.js";
38
+ } from "./chunk-67N26CER.js";
39
39
  import {
40
40
  FONT_FAMILY
41
41
  } from "./chunk-ICLB27PZ.js";
@@ -7,7 +7,7 @@ import {
7
7
  import {
8
8
  resolveNotes,
9
9
  tryCollectNote
10
- } from "./chunk-NJJCTEBM.js";
10
+ } from "./chunk-KLBTJEIK.js";
11
11
  import {
12
12
  displayName,
13
13
  normalizeName
@@ -3,14 +3,14 @@ import {
3
3
  capLabelColumn,
4
4
  computeTimeTicks,
5
5
  showFullOnHover
6
- } from "./chunk-VSOZZYLK.js";
6
+ } from "./chunk-NERQSSYD.js";
7
7
  import {
8
8
  ScaleContext
9
9
  } from "./chunk-24YPR5EH.js";
10
10
  import {
11
11
  INLINE_HEADER_PAD,
12
12
  layoutInlineHeader
13
- } from "./chunk-42UJ23H3.js";
13
+ } from "./chunk-UIEKW4SG.js";
14
14
  import {
15
15
  TITLE_FONT_SIZE,
16
16
  TITLE_FONT_WEIGHT,
@@ -1448,10 +1448,14 @@ function renderErasAndMarkers(g, svg, resolved, xScale, innerHeight, palette, er
1448
1448
  const eraEndDate = parseDateStringToDate(era.endDate);
1449
1449
  const eraG = g.append("g").attr("class", "gantt-era-group").attr("data-line-number", String(era.lineNumber));
1450
1450
  const eraRect = eraG.append("rect").attr("class", "gantt-era").attr("x", sx).attr("y", 0).attr("width", ex - sx).attr("height", innerHeight).attr("fill", color).attr("opacity", baseEraOpacity);
1451
- const eraLabelMaxW = Math.max(0, ex - sx - 8);
1451
+ const [plotStart, plotEnd] = xScale.range();
1452
+ const vsx = Math.max(sx, plotStart);
1453
+ const vex = Math.min(ex, plotEnd);
1454
+ if (vex <= vsx) continue;
1455
+ const eraLabelMaxW = Math.max(0, vex - vsx - 8);
1452
1456
  const eraDisplayLabel = truncateLegendText(era.label, 10, eraLabelMaxW);
1453
1457
  const eraTruncated = eraDisplayLabel !== era.label;
1454
- const eraLabel = eraG.append("text").attr("class", "gantt-era-label").attr("x", (sx + ex) / 2).attr("y", eraLabelY).attr("text-anchor", "middle").attr("font-size", 10).attr("fill", color).attr("opacity", 0.7).style("cursor", "pointer").text(eraDisplayLabel);
1458
+ const eraLabel = eraG.append("text").attr("class", "gantt-era-label").attr("x", (vsx + vex) / 2).attr("y", eraLabelY).attr("text-anchor", "middle").attr("font-size", 10).attr("fill", color).attr("opacity", 0.7).style("cursor", "pointer").text(eraDisplayLabel);
1455
1459
  eraG.on("mouseenter", () => {
1456
1460
  g.selectAll(".gantt-task").attr(
1457
1461
  "opacity",
@@ -2105,6 +2109,18 @@ function dateToFractionalYear(d) {
2105
2109
  const fraction = (d.getTime() - startOfYear.getTime()) / (endOfYear.getTime() - startOfYear.getTime());
2106
2110
  return y + fraction;
2107
2111
  }
2112
+ function fractionalYearToDate(frac) {
2113
+ const y = Math.floor(frac);
2114
+ const startOfYear = new Date(y, 0, 1);
2115
+ const endOfYear = new Date(y + 1, 0, 1);
2116
+ return new Date(
2117
+ startOfYear.getTime() + (frac - y) * (endOfYear.getTime() - startOfYear.getTime())
2118
+ );
2119
+ }
2120
+ var EXACT_FRACTIONAL_YEAR = {
2121
+ toFractionalYear: dateToFractionalYear,
2122
+ fromFractionalYear: fractionalYearToDate
2123
+ };
2108
2124
  function diamondPoints(cx, cy, size) {
2109
2125
  const half = size / 2;
2110
2126
  return `${cx},${cy - half} ${cx + half},${cy} ${cx},${cy + half} ${cx - half},${cy}`;
@@ -2188,7 +2204,17 @@ function renderTimeScaleHorizontal(g, scale, _innerWidth, innerHeight, textColor
2188
2204
  const domain = scale.domain();
2189
2205
  const domainMin = domain[0];
2190
2206
  const domainMax = domain[1];
2191
- const ticks = computeTimeTicks(domainMin, domainMax, scale);
2207
+ const ticks = computeTimeTicks(
2208
+ domainMin,
2209
+ domainMax,
2210
+ scale,
2211
+ void 0,
2212
+ void 0,
2213
+ void 0,
2214
+ void 0,
2215
+ void 0,
2216
+ EXACT_FRACTIONAL_YEAR
2217
+ );
2192
2218
  if (ticks.length < 2) return;
2193
2219
  const tickLen = 6;
2194
2220
  const opacity = 0.4;