@cardenelabs/cdl 0.52.0 → 0.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,20 @@ CDL (Chainome Diagram Language) の主要変更履歴。
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.53.0] - 2026-09-11
9
+
10
+ ### Fixed
11
+
12
+ - **短い縦の線で、両端の多重度が詰まって 1 つの札に見えるのを直した** (#829)
13
+
14
+ 縦に隣り合う箱をつなぐ線は、箱の間隔 (100) がそのまま線の長さになる。 両端に多重度を書くと、
15
+ 出どころの字と行き先の字が線の同じ側に縦に並び、間が 10 しか空かなかった。 2 行の札のように
16
+ 読まれ、どちらの端の数かが分からなかった。
17
+
18
+ 縦の間隔を決める計算に端の字を入れた。 両端に字がある線は、2 つの字の間が字と自分の端の間 (22) の
19
+ 2 倍以上空く長さまで間隔を広げる。 間隔は図の中で全て同じ値に揃える規則のままなので、その図の
20
+ 縦の間隔が全て広がる。 片方の端にだけ字がある線はいまの間隔で足り、見た目は変わらない。
21
+
8
22
  ## [0.52.0] - 2026-09-11
9
23
 
10
24
  ### Added
@@ -2448,7 +2462,8 @@ Initial OSS release.
2448
2462
  使わない = annotated tag を push しても GitHub Release は作られず、 Release を作っていない版で
2449
2463
  行き止まりになる。
2450
2464
 
2451
- [Unreleased]: https://github.com/cardene777/cdl/compare/v0.52.0...HEAD
2465
+ [Unreleased]: https://github.com/cardene777/cdl/compare/v0.53.0...HEAD
2466
+ [0.53.0]: https://github.com/cardene777/cdl/compare/v0.52.0...v0.53.0
2452
2467
  [0.52.0]: https://github.com/cardene777/cdl/compare/v0.51.0...v0.52.0
2453
2468
  [0.51.0]: https://github.com/cardene777/cdl/compare/v0.50.0...v0.51.0
2454
2469
  [0.50.0]: https://github.com/cardene777/cdl/compare/v0.49.0...v0.50.0
package/dist/index.cjs CHANGED
@@ -20532,6 +20532,87 @@ function requiredRowsWidth(rows, kind) {
20532
20532
  return Math.ceil(kind === "storage" ? storage : generic);
20533
20533
  }
20534
20534
 
20535
+ // src/layout/head-label.ts
20536
+ var \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2 = 22;
20537
+ var \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 = 8;
20538
+ var \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055 = EDGE_LABEL_TEXT.sub.fontSize;
20539
+ var \u7BB1\u306E\u9AD8\u3055 = Math.round(\u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055 * 1.2);
20540
+ var BASELINE_RATIO = 0.8;
20541
+ var \u4E21\u7AEF\u306E\u5B57\u306E\u9593 = \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2 * 2;
20542
+ function \u7AEF\u306E\u5B57\u306B\u8981\u308B\u7DDA\u306E\u9577\u3055(edge) {
20543
+ const \u4E00\u3064\u5206 = \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2 + \u7BB1\u306E\u9AD8\u3055;
20544
+ const \u6570 = [edge.headLabel, edge.tailLabel].filter((t) => t?.trim()).length;
20545
+ if (\u6570 === 0) return 0;
20546
+ if (\u6570 === 1) return \u4E00\u3064\u5206;
20547
+ return \u4E00\u3064\u5206 * 2 + \u4E21\u7AEF\u306E\u5B57\u306E\u9593;
20548
+ }
20549
+ function \u5411\u304D\u3092\u53D6\u308B(end, \u5019\u88DC) {
20550
+ for (const p of \u5019\u88DC) {
20551
+ if (!p) continue;
20552
+ const dx = end.x - p.x;
20553
+ const dy = end.y - p.y;
20554
+ const len = Math.hypot(dx, dy);
20555
+ if (len > 1e-6) return { end, ux: dx / len, uy: dy / len };
20556
+ }
20557
+ return null;
20558
+ }
20559
+ function \u7AEF\u3067\u306E\u5411\u304D(d, \u7AEF) {
20560
+ const segs = extractPathSegments(d);
20561
+ if (segs.length === 0) return null;
20562
+ if (\u7AEF === "head") {
20563
+ const last = segs[segs.length - 1];
20564
+ const end2 = { x: last.x2, y: last.y2 };
20565
+ const \u5019\u88DC2 = segs.slice().reverse().flatMap((s) => [s.cmd === "Q" ? s.ctrl?.[0] : s.cmd === "C" ? s.ctrl?.[1] : void 0, { x: s.x1, y: s.y1 }]);
20566
+ return \u5411\u304D\u3092\u53D6\u308B(end2, \u5019\u88DC2);
20567
+ }
20568
+ const first = segs[0];
20569
+ const end = { x: first.x1, y: first.y1 };
20570
+ const \u5019\u88DC = segs.flatMap((s) => [...s.ctrl ?? [], { x: s.x2, y: s.y2 }]);
20571
+ return \u5411\u304D\u3092\u53D6\u308B(end, \u5019\u88DC);
20572
+ }
20573
+ function \u7AEF\u306E\u5B57\u3092\u7F6E\u304F(edge, \u7AEF = "head") {
20574
+ const text = (\u7AEF === "head" ? edge.headLabel : edge.tailLabel)?.trim();
20575
+ if (!text) return null;
20576
+ const \u5411\u304D = \u7AEF\u3067\u306E\u5411\u304D(edge.d, \u7AEF);
20577
+ if (!\u5411\u304D) return null;
20578
+ const { end, ux, uy } = \u5411\u304D;
20579
+ const bx = end.x - ux * \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2;
20580
+ const by = end.y - uy * \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2;
20581
+ const w = measureTextWidth(text, {
20582
+ fontSize: \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055,
20583
+ fontWeight: EDGE_LABEL_TEXT.sub.fontWeight,
20584
+ fontFamily: "mono"
20585
+ });
20586
+ const h = \u7BB1\u306E\u9AD8\u3055;
20587
+ const \u672D = hasRenderedLabel(edge) && edge.labelX !== void 0 && edge.labelY !== void 0 ? { x: edge.labelX, y: edge.labelY } : null;
20588
+ let anchor;
20589
+ let box;
20590
+ if (Math.abs(ux) >= Math.abs(uy)) {
20591
+ const \u53F3\u3078\u9032\u3080 = ux > 0;
20592
+ const \u4E0A\u306B\u7F6E\u304F = \u672D !== null && \u672D.y > by;
20593
+ anchor = \u53F3\u3078\u9032\u3080 ? "end" : "start";
20594
+ box = {
20595
+ x: \u53F3\u3078\u9032\u3080 ? bx - w : bx,
20596
+ y: \u4E0A\u306B\u7F6E\u304F ? by - \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 - h : by + \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593,
20597
+ w,
20598
+ h
20599
+ };
20600
+ } else {
20601
+ const \u4E0B\u3078\u9032\u3080 = uy > 0;
20602
+ const \u53F3\u306B\u7F6E\u304F = \u672D !== null && \u672D.x < bx;
20603
+ anchor = \u53F3\u306B\u7F6E\u304F ? "start" : "end";
20604
+ box = {
20605
+ x: \u53F3\u306B\u7F6E\u304F ? bx + \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 : bx - \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 - w,
20606
+ y: \u4E0B\u3078\u9032\u3080 ? by - h : by,
20607
+ w,
20608
+ h
20609
+ };
20610
+ }
20611
+ const x = anchor === "start" ? box.x : box.x + box.w;
20612
+ const y = box.y + (h - \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055) / 2 + \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055 * BASELINE_RATIO;
20613
+ return { x, y, anchor, box };
20614
+ }
20615
+
20535
20616
  // src/layout/nodes.ts
20536
20617
  function autoStorageHeight(n, defaultH) {
20537
20618
  if (n.kind !== "storage") return n.h ?? defaultH;
@@ -20553,7 +20634,7 @@ function autoRowsWidth(n, defaultW) {
20553
20634
  const required = requiredRowsWidth(n.rows, n.kind);
20554
20635
  return Math.max(defaultW, required);
20555
20636
  }
20556
- function \u7BB1\u306E\u9AD8\u3055(n, \u65E2\u5B9Ah) {
20637
+ function \u7BB1\u306E\u9AD8\u30552(n, \u65E2\u5B9Ah) {
20557
20638
  if (n.h != null) return n.h;
20558
20639
  if (n.kind === "storage") return autoStorageHeight(n, \u65E2\u5B9Ah);
20559
20640
  return \u4E2D\u8EAB\u304B\u3089\u51FA\u3059\u9AD8\u3055(n.kind, \u65E2\u5B9Ah, {
@@ -20567,8 +20648,8 @@ function requiredStackGapForEdgeLabels(diag, allStacks) {
20567
20648
  const byId = new Map(diag.nodes.map((n) => [n.id, n]));
20568
20649
  const rankOf = new Map(allStacks.map((stack, i) => [stack, i]));
20569
20650
  const pillHsByGap = /* @__PURE__ */ new Map();
20651
+ let \u7AEF\u306E\u5B57\u306E\u8981\u6C42 = 0;
20570
20652
  for (const e of diag.edges) {
20571
- if (!hasRenderedLabel(e)) continue;
20572
20653
  const from = byId.get(e.from);
20573
20654
  const to = byId.get(e.to);
20574
20655
  if (!from || !to) continue;
@@ -20577,10 +20658,12 @@ function requiredStackGapForEdgeLabels(diag, allStacks) {
20577
20658
  const toRank = rankOf.get(to.stack);
20578
20659
  if (fromRank === void 0 || toRank === void 0) continue;
20579
20660
  if (Math.abs(fromRank - toRank) !== 1) continue;
20661
+ \u7AEF\u306E\u5B57\u306E\u8981\u6C42 = Math.max(\u7AEF\u306E\u5B57\u306E\u8981\u6C42, \u7AEF\u306E\u5B57\u306B\u8981\u308B\u7DDA\u306E\u9577\u3055(e));
20662
+ if (!hasRenderedLabel(e)) continue;
20580
20663
  const key = `${from.lane}::${Math.min(fromRank, toRank)}`;
20581
20664
  pillHsByGap.set(key, [...pillHsByGap.get(key) ?? [], labelPillH(e.sub)]);
20582
20665
  }
20583
- let required = 0;
20666
+ let required = \u7AEF\u306E\u5B57\u306E\u8981\u6C42;
20584
20667
  for (const pillHs of pillHsByGap.values()) {
20585
20668
  required = Math.max(required, requiredVerticalLabelGap(pillHs));
20586
20669
  }
@@ -20592,7 +20675,7 @@ function layoutNodes(diag, lanes) {
20592
20675
  const rowH = /* @__PURE__ */ new Map();
20593
20676
  for (const stack of allStacks) {
20594
20677
  const nodesAtStack = diag.nodes.filter((n) => n.stack === stack);
20595
- const h = Math.max(...nodesAtStack.map((n) => \u7BB1\u306E\u9AD8\u3055(n, NODE_SIZE[n.kind].h)));
20678
+ const h = Math.max(...nodesAtStack.map((n) => \u7BB1\u306E\u9AD8\u30552(n, NODE_SIZE[n.kind].h)));
20596
20679
  rowH.set(stack, h);
20597
20680
  }
20598
20681
  const rowCy = /* @__PURE__ */ new Map();
@@ -20646,7 +20729,7 @@ function layoutNodes(diag, lanes) {
20646
20729
  const \u6BB5\u306E\u82AF = rowCy.get(n.stack);
20647
20730
  const \u6BB5\u306E\u9AD8\u3055 = rowH.get(n.stack);
20648
20731
  const \u81EA\u524D\u306E\u9AD8\u3055 = n.rowMarks !== void 0;
20649
- const h = n.h ?? (\u81EA\u524D\u306E\u9AD8\u3055 ? \u7BB1\u306E\u9AD8\u3055(n, size.h) : \u6BB5\u306E\u9AD8\u3055);
20732
+ const h = n.h ?? (\u81EA\u524D\u306E\u9AD8\u3055 ? \u7BB1\u306E\u9AD8\u30552(n, size.h) : \u6BB5\u306E\u9AD8\u3055);
20650
20733
  const cy = \u6BB5\u306E\u82AF;
20651
20734
  const w = autoRowsWidth(n, size.w);
20652
20735
  out.push({
@@ -22935,79 +23018,6 @@ function \u7B49\u5E45\u306E\u5B57(text, fontSize) {
22935
23018
  });
22936
23019
  return out;
22937
23020
  }
22938
-
22939
- // src/layout/head-label.ts
22940
- var \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2 = 22;
22941
- var \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 = 8;
22942
- var \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055 = EDGE_LABEL_TEXT.sub.fontSize;
22943
- var \u7BB1\u306E\u9AD8\u30552 = Math.round(\u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055 * 1.2);
22944
- var BASELINE_RATIO = 0.8;
22945
- function \u5411\u304D\u3092\u53D6\u308B(end, \u5019\u88DC) {
22946
- for (const p of \u5019\u88DC) {
22947
- if (!p) continue;
22948
- const dx = end.x - p.x;
22949
- const dy = end.y - p.y;
22950
- const len = Math.hypot(dx, dy);
22951
- if (len > 1e-6) return { end, ux: dx / len, uy: dy / len };
22952
- }
22953
- return null;
22954
- }
22955
- function \u7AEF\u3067\u306E\u5411\u304D(d, \u7AEF) {
22956
- const segs = extractPathSegments(d);
22957
- if (segs.length === 0) return null;
22958
- if (\u7AEF === "head") {
22959
- const last = segs[segs.length - 1];
22960
- const end2 = { x: last.x2, y: last.y2 };
22961
- const \u5019\u88DC2 = segs.slice().reverse().flatMap((s) => [s.cmd === "Q" ? s.ctrl?.[0] : s.cmd === "C" ? s.ctrl?.[1] : void 0, { x: s.x1, y: s.y1 }]);
22962
- return \u5411\u304D\u3092\u53D6\u308B(end2, \u5019\u88DC2);
22963
- }
22964
- const first = segs[0];
22965
- const end = { x: first.x1, y: first.y1 };
22966
- const \u5019\u88DC = segs.flatMap((s) => [...s.ctrl ?? [], { x: s.x2, y: s.y2 }]);
22967
- return \u5411\u304D\u3092\u53D6\u308B(end, \u5019\u88DC);
22968
- }
22969
- function \u7AEF\u306E\u5B57\u3092\u7F6E\u304F(edge, \u7AEF = "head") {
22970
- const text = (\u7AEF === "head" ? edge.headLabel : edge.tailLabel)?.trim();
22971
- if (!text) return null;
22972
- const \u5411\u304D = \u7AEF\u3067\u306E\u5411\u304D(edge.d, \u7AEF);
22973
- if (!\u5411\u304D) return null;
22974
- const { end, ux, uy } = \u5411\u304D;
22975
- const bx = end.x - ux * \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2;
22976
- const by = end.y - uy * \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2;
22977
- const w = measureTextWidth(text, {
22978
- fontSize: \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055,
22979
- fontWeight: EDGE_LABEL_TEXT.sub.fontWeight,
22980
- fontFamily: "mono"
22981
- });
22982
- const h = \u7BB1\u306E\u9AD8\u30552;
22983
- const \u672D = hasRenderedLabel(edge) && edge.labelX !== void 0 && edge.labelY !== void 0 ? { x: edge.labelX, y: edge.labelY } : null;
22984
- let anchor;
22985
- let box;
22986
- if (Math.abs(ux) >= Math.abs(uy)) {
22987
- const \u53F3\u3078\u9032\u3080 = ux > 0;
22988
- const \u4E0A\u306B\u7F6E\u304F = \u672D !== null && \u672D.y > by;
22989
- anchor = \u53F3\u3078\u9032\u3080 ? "end" : "start";
22990
- box = {
22991
- x: \u53F3\u3078\u9032\u3080 ? bx - w : bx,
22992
- y: \u4E0A\u306B\u7F6E\u304F ? by - \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 - h : by + \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593,
22993
- w,
22994
- h
22995
- };
22996
- } else {
22997
- const \u4E0B\u3078\u9032\u3080 = uy > 0;
22998
- const \u53F3\u306B\u7F6E\u304F = \u672D !== null && \u672D.x < bx;
22999
- anchor = \u53F3\u306B\u7F6E\u304F ? "start" : "end";
23000
- box = {
23001
- x: \u53F3\u306B\u7F6E\u304F ? bx + \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 : bx - \u7AEF\u306E\u5B57\u3068\u7DDA\u306E\u9699\u9593 - w,
23002
- y: \u4E0B\u3078\u9032\u3080 ? by - h : by,
23003
- w,
23004
- h
23005
- };
23006
- }
23007
- const x = anchor === "start" ? box.x : box.x + box.w;
23008
- const y = box.y + (h - \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055) / 2 + \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055 * BASELINE_RATIO;
23009
- return { x, y, anchor, box };
23010
- }
23011
23021
  function defaultEdgeWidth(active) {
23012
23022
  return active ? 2.5 : 1.25;
23013
23023
  }