@cardenelabs/cdl 0.48.0 → 0.50.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,43 @@ CDL (Chainome Diagram Language) の主要変更履歴。
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.50.0] - 2026-09-11
9
+
10
+ ### Fixed
11
+
12
+ - **等幅の文字で `[` と `]` が隣り合うと四角 1 つに見えるのを直した** (#817)
13
+
14
+ 見本帳のクラス図で、型の `string[]` が画面では `string□` と読めた。 等幅の書体 (`JetBrains Mono`) の
15
+ `[` と `]` は横棒が字の枠いっぱいまで伸びており、図を画面の幅に合わせて縮めると (画面上 14px 前後)
16
+ 2 本の横棒がつながる。 合字ではない (合字を止めても変わらない)。
17
+
18
+ engine が等幅の書体で描く全ての文字で、 `[]` の間にだけ字の大きさの 0.08 倍の隙間を足す。
19
+ 隙間は `<tspan dx>` で足すので、 文字の中身 (`textContent`) は `string[]` のまま変わらない。
20
+
21
+ ## [0.49.0] - 2026-09-11
22
+
23
+ ### Added
24
+
25
+ - **`clearance` の違反に、 engine がなぜ直せなかったかを添える** (#810)
26
+
27
+ 違反の報告は「どの 2 つが何 px で、要求が何 px か」 しか持たず、なぜ engine が直せなかったかを
28
+ 知るには逃がし pass まで層を 3 つ読む必要があった。 札が絡む違反に `reason` を付け、
29
+ 各向きを誰が塞いだかを 1 行で返す。
30
+
31
+ ```
32
+ detail: edge-label:code-exchange ↔ edge-path:api-client gap=10.0px (need 14px)
33
+ reason: 逃げ場なし: 上=edge-label:consent-client (36→0) / 下=edge-label:token-issue (36→28) / 左=上限 200 を越える / 右=上限 200 を越える
34
+ ```
35
+
36
+ `(36→0)` は塞いだ相手との隙間が、動かす前と動かした後でいくつになるか。
37
+
38
+ 理由は **最終の位置から測り直す**。 逃がし pass と同じ候補と同じ判定 (`札の移動を塞ぐ相手を探す`)
39
+ を使うので、報告と実物がずれない。 どれか 1 つの向きでも安全なら理由を付けない
40
+ (動けるのに塞がれているとは言わない)。
41
+
42
+ `detail` は変えない = 消費側が `detail` から id を読んでいる。 `layoutWithValidation` の
43
+ console 出力は `(diagram=...)` の後ろに理由を足す。
44
+
8
45
  ## [0.48.0] - 2026-09-11
9
46
 
10
47
  ### Fixed
@@ -2381,7 +2418,9 @@ Initial OSS release.
2381
2418
  使わない = annotated tag を push しても GitHub Release は作られず、 Release を作っていない版で
2382
2419
  行き止まりになる。
2383
2420
 
2384
- [Unreleased]: https://github.com/cardene777/cdl/compare/v0.48.0...HEAD
2421
+ [Unreleased]: https://github.com/cardene777/cdl/compare/v0.50.0...HEAD
2422
+ [0.50.0]: https://github.com/cardene777/cdl/compare/v0.49.0...v0.50.0
2423
+ [0.49.0]: https://github.com/cardene777/cdl/compare/v0.48.0...v0.49.0
2385
2424
  [0.48.0]: https://github.com/cardene777/cdl/compare/v0.47.0...v0.48.0
2386
2425
  [0.47.0]: https://github.com/cardene777/cdl/compare/v0.46.0...v0.47.0
2387
2426
  [0.46.0]: https://github.com/cardene777/cdl/compare/v0.45.0...v0.46.0
package/dist/index.cjs CHANGED
@@ -13167,7 +13167,7 @@ function resolveEdgeLabelOverlapsWithChainAndPropagate(edges, obstacles, minClea
13167
13167
  { axis: "y", sign: dy >= 0 ? 1 : -1 },
13168
13168
  { axis: "x", sign: dx >= 0 ? 1 : -1 }
13169
13169
  ];
13170
- const \u52D5\u304B\u3057\u305F\u7BB1 = (axis, sign) => ({
13170
+ const \u52D5\u304B\u3057\u305F\u7BB12 = (axis, sign) => ({
13171
13171
  ...label,
13172
13172
  x: label.x + (axis === "x" ? sign * \u91CF : 0),
13173
13173
  y: label.y + (axis === "y" ? sign * \u91CF : 0)
@@ -13192,7 +13192,7 @@ function resolveEdgeLabelOverlapsWithChainAndPropagate(edges, obstacles, minClea
13192
13192
  return false;
13193
13193
  };
13194
13194
  for (const \u5019 of \u5019\u88DC) {
13195
- if (\u60AA\u304F\u3059\u308B(\u52D5\u304B\u3057\u305F\u7BB1(\u5019.axis, \u5019.sign))) continue;
13195
+ if (\u60AA\u304F\u3059\u308B(\u52D5\u304B\u3057\u305F\u7BB12(\u5019.axis, \u5019.sign))) continue;
13196
13196
  out.push({
13197
13197
  target: { kind: "label", id: label.id },
13198
13198
  axis: \u5019.axis,
@@ -13358,15 +13358,7 @@ function resolveEdgeLabelOverlapsWithChainAndPropagate(edges, obstacles, minClea
13358
13358
  edgePathShifts: edgePathShiftMap
13359
13359
  };
13360
13360
  }
13361
- function resolveLabelClearanceAfterPathPasses(edges, obstacles, maxIter = 8) {
13362
- if (edges.length === 0) return edges;
13363
- const labeledIds = new Set(
13364
- edges.filter((e) => e.label?.trim() || e.sub?.trim()).map((e) => e.id)
13365
- );
13366
- if (labeledIds.size === 0) return edges;
13367
- const \u7BB1\u305F\u3061 = obstacles.filter((o) => o.kind === "node" || o.kind === "lane-label");
13368
- const edgeById = /* @__PURE__ */ new Map();
13369
- for (const e of edges) edgeById.set(e.id, e);
13361
+ function \u7DDA\u306E\u6E2C\u308A\u65B9\u3092\u4F5C\u308B() {
13370
13362
  const \u533A\u9593cache = /* @__PURE__ */ new Map();
13371
13363
  const \u533A\u9593 = (id, d) => {
13372
13364
  const hit = \u533A\u9593cache.get(id);
@@ -13402,7 +13394,143 @@ function resolveLabelClearanceAfterPathPasses(edges, obstacles, maxIter = 8) {
13402
13394
  const dy = Math.max(0, Math.max(box.y - (b.y + b.h), b.y - (box.y + box.h)));
13403
13395
  return Math.hypot(dx, dy) >= \u4F59\u88D5;
13404
13396
  };
13405
- const \u6700\u5927\u79FB\u52D5 = CHAIN_SHIFT_MAX_ACCUMULATED * 2;
13397
+ return { \u533A\u9593, \u9060\u3044 };
13398
+ }
13399
+ var \u672D\u306E\u6700\u5927\u79FB\u52D5 = CHAIN_SHIFT_MAX_ACCUMULATED * 2;
13400
+ var \u96E2\u308C\u91CF = (a, b) => ({
13401
+ x: Math.max(a.x - (b.x + b.w), b.x - (a.x + a.w)),
13402
+ y: Math.max(a.y - (b.y + b.h), b.y - (a.y + a.h))
13403
+ });
13404
+ var \u52D5\u304B\u3057\u305F\u7BB1 = (box, axis, sign, amount) => ({
13405
+ ...box,
13406
+ x: box.x + (axis === "x" ? sign * amount : 0),
13407
+ y: box.y + (axis === "y" ? sign * amount : 0)
13408
+ });
13409
+ function \u672D\u306E\u79FB\u52D5\u3092\u585E\u3050\u76F8\u624B\u3092\u63A2\u3059(\u5468\u308A, label, \u884C\u304D\u5148) {
13410
+ const { \u7BB1\u305F\u3061, labels, edges, edgeById, \u6E2C\u308A\u65B9 } = \u5468\u308A;
13411
+ for (const obs of \u7BB1\u305F\u3061) {
13412
+ const \u524D = computeGap(label, obs);
13413
+ const \u5F8C = computeGap(\u884C\u304D\u5148, obs);
13414
+ if (\u5F8C < Math.min(\u524D, requiredNearClearance("edge-label", obs.kind))) return { \u76F8\u624B: `${obs.kind}:${obs.id}`, \u524D, \u5F8C };
13415
+ }
13416
+ const \u672D\u306E\u8981\u6C42 = requiredNearClearance("edge-label", "edge-label");
13417
+ for (const \u4ED6 of labels) {
13418
+ if (\u4ED6.id === label.id) continue;
13419
+ const \u524D = computeGap(label, \u4ED6);
13420
+ const \u5F8C = computeGap(\u884C\u304D\u5148, \u4ED6);
13421
+ if (\u5F8C < Math.min(\u524D, \u672D\u306E\u8981\u6C42)) return { \u76F8\u624B: `edge-label:${\u4ED6.id}`, \u524D, \u5F8C };
13422
+ }
13423
+ const \u81EA\u5206 = edgeById.get(label.id);
13424
+ const \u81EA\u5206\u306E\u533A\u9593 = \u81EA\u5206 ? \u6E2C\u308A\u65B9.\u533A\u9593(\u81EA\u5206.id, \u81EA\u5206.d) : [];
13425
+ if (\u81EA\u5206\u306E\u533A\u9593.length > 0) {
13426
+ const \u524D = measurePathLabelGapSegs(\u81EA\u5206\u306E\u533A\u9593, label);
13427
+ const \u5F8C = measurePathLabelGapSegs(\u81EA\u5206\u306E\u533A\u9593, \u884C\u304D\u5148);
13428
+ if (\u5F8C > Math.max(\u524D, DIST_LABEL_PATH_MAX)) return { \u76F8\u624B: "\u81EA\u5206\u306E\u7DDA", \u524D, \u5F8C };
13429
+ }
13430
+ for (const \u76F8\u624B of edges) {
13431
+ if (\u76F8\u624B.id === label.id) continue;
13432
+ if (\u6E2C\u308A\u65B9.\u9060\u3044(label, \u76F8\u624B.id, \u76F8\u624B.d, LABEL_TO_PATH_CLEARANCE) && \u6E2C\u308A\u65B9.\u9060\u3044(\u884C\u304D\u5148, \u76F8\u624B.id, \u76F8\u624B.d, LABEL_TO_PATH_CLEARANCE)) continue;
13433
+ const segs = segmentsExcludingOwnPath(\u6E2C\u308A\u65B9.\u533A\u9593(\u76F8\u624B.id, \u76F8\u624B.d), \u81EA\u5206\u306E\u533A\u9593);
13434
+ if (segs.length === 0) continue;
13435
+ const \u524D = measurePathLabelGapSegs(segs, label);
13436
+ const \u5F8C = measurePathLabelGapSegs(segs, \u884C\u304D\u5148);
13437
+ if (\u5F8C < Math.min(\u524D, LABEL_TO_PATH_CLEARANCE)) return { \u76F8\u624B: `edge-path:${\u76F8\u624B.id}`, \u524D, \u5F8C };
13438
+ }
13439
+ return null;
13440
+ }
13441
+ function \u77E9\u5F62\u306E\u5019\u88DC(label, static\u7BB1, required) {
13442
+ const sep = \u96E2\u308C\u91CF(label, static\u7BB1);
13443
+ const \u5411\u304D = (axis) => {
13444
+ const a = axis === "x" ? label.x + label.w / 2 : label.y + label.h / 2;
13445
+ const b = axis === "x" ? static\u7BB1.x + static\u7BB1.w / 2 : static\u7BB1.y + static\u7BB1.h / 2;
13446
+ return a >= b ? 1 : -1;
13447
+ };
13448
+ return [
13449
+ { axis: "x", sign: \u5411\u304D("x"), amount: required - sep.x + NEAR_MISS_MARGIN },
13450
+ { axis: "y", sign: \u5411\u304D("y"), amount: required - sep.y + NEAR_MISS_MARGIN }
13451
+ ];
13452
+ }
13453
+ function \u7DDA\u304B\u3089\u96E2\u308C\u308B\u91CF(segs, label, gap, axis, sign) {
13454
+ const \u6700\u5927\u79FB\u52D5 = \u672D\u306E\u6700\u5927\u79FB\u52D5;
13455
+ const \u6E80\u305F\u3059 = (\u91CF) => measurePathLabelGapSegs(segs, \u52D5\u304B\u3057\u305F\u7BB1(label, axis, sign, \u91CF)) >= LABEL_TO_PATH_CLEARANCE;
13456
+ let lo = 0;
13457
+ let hi = Math.max(4, LABEL_TO_PATH_CLEARANCE - gap);
13458
+ while (!\u6E80\u305F\u3059(hi)) {
13459
+ if (hi >= \u6700\u5927\u79FB\u52D5) return null;
13460
+ lo = hi;
13461
+ hi = Math.min(hi * 2, \u6700\u5927\u79FB\u52D5);
13462
+ }
13463
+ for (let k = 0; k < 12; k += 1) {
13464
+ const mid = (lo + hi) / 2;
13465
+ if (\u6E80\u305F\u3059(mid)) hi = mid;
13466
+ else lo = mid;
13467
+ }
13468
+ return hi + NEAR_MISS_MARGIN;
13469
+ }
13470
+ var \u5411\u304D\u306E\u9806 = [
13471
+ { axis: "y", sign: -1, \u540D\u524D: "\u4E0A" },
13472
+ { axis: "y", sign: 1, \u540D\u524D: "\u4E0B" },
13473
+ { axis: "x", sign: -1, \u540D\u524D: "\u5DE6" },
13474
+ { axis: "x", sign: 1, \u540D\u524D: "\u53F3" }
13475
+ ];
13476
+ function \u672D\u304C\u52D5\u3051\u306A\u3044\u7406\u7531(labelId, \u76F8\u624B, edges, obstacles) {
13477
+ const edgeById = new Map(edges.map((e) => [e.id, e]));
13478
+ const \u81EA\u5206 = edgeById.get(labelId);
13479
+ if (!\u81EA\u5206) return null;
13480
+ const labels = edges.filter((e) => e.label?.trim() || e.sub?.trim()).map((e) => ({ kind: "edge-label", id: e.id, ...computeLabelBBoxWorld(e) }));
13481
+ const label = labels.find((l) => l.id === labelId);
13482
+ if (!label) return null;
13483
+ const \u6E2C\u308A\u65B9 = \u7DDA\u306E\u6E2C\u308A\u65B9\u3092\u4F5C\u308B();
13484
+ const \u5468\u308A = {
13485
+ \u7BB1\u305F\u3061: obstacles.filter((o) => o.kind === "node" || o.kind === "lane-label"),
13486
+ labels,
13487
+ edges,
13488
+ edgeById,
13489
+ \u6E2C\u308A\u65B9
13490
+ };
13491
+ const \u5019\u88DC = [];
13492
+ if (\u76F8\u624B.kind === "edge-path") {
13493
+ const \u7DDA = edgeById.get(\u76F8\u624B.id);
13494
+ if (!\u7DDA) return null;
13495
+ const segs = segmentsExcludingOwnPath(\u6E2C\u308A\u65B9.\u533A\u9593(\u7DDA.id, \u7DDA.d), \u6E2C\u308A\u65B9.\u533A\u9593(\u81EA\u5206.id, \u81EA\u5206.d));
13496
+ if (segs.length === 0) return null;
13497
+ const gap = measurePathLabelGapSegs(segs, label);
13498
+ for (const \u5411\u304D of \u5411\u304D\u306E\u9806) {
13499
+ \u5019\u88DC.push({ axis: \u5411\u304D.axis, sign: \u5411\u304D.sign, amount: \u7DDA\u304B\u3089\u96E2\u308C\u308B\u91CF(segs, label, gap, \u5411\u304D.axis, \u5411\u304D.sign) });
13500
+ }
13501
+ } else {
13502
+ const required = requiredNearClearance("edge-label", \u76F8\u624B.kind);
13503
+ for (const c of \u77E9\u5F62\u306E\u5019\u88DC(label, \u76F8\u624B, required)) {
13504
+ if (c.amount > 0) \u5019\u88DC.push(c);
13505
+ }
13506
+ }
13507
+ if (\u5019\u88DC.length === 0) return null;
13508
+ const \u7406\u7531 = [];
13509
+ for (const c of \u5019\u88DC) {
13510
+ const \u9806 = \u5411\u304D\u306E\u9806.findIndex((v) => v.axis === c.axis && v.sign === c.sign);
13511
+ const \u540D\u524D = \u5411\u304D\u306E\u9806[\u9806].\u540D\u524D;
13512
+ if (c.amount === null || c.amount > \u672D\u306E\u6700\u5927\u79FB\u52D5) {
13513
+ \u7406\u7531.push({ \u9806, \u6587: `${\u540D\u524D}=\u4E0A\u9650 ${\u672D\u306E\u6700\u5927\u79FB\u52D5} \u3092\u8D8A\u3048\u308B` });
13514
+ continue;
13515
+ }
13516
+ const \u585E\u3050 = \u672D\u306E\u79FB\u52D5\u3092\u585E\u3050\u76F8\u624B\u3092\u63A2\u3059(\u5468\u308A, label, \u52D5\u304B\u3057\u305F\u7BB1(label, c.axis, c.sign, c.amount));
13517
+ if (!\u585E\u3050) return null;
13518
+ \u7406\u7531.push({ \u9806, \u6587: `${\u540D\u524D}=${\u585E\u3050.\u76F8\u624B} (${\u585E\u3050.\u524D.toFixed(0)}\u2192${\u585E\u3050.\u5F8C.toFixed(0)})` });
13519
+ }
13520
+ return `\u9003\u3052\u5834\u306A\u3057: ${\u7406\u7531.sort((a, b) => a.\u9806 - b.\u9806).map((r) => r.\u6587).join(" / ")}`;
13521
+ }
13522
+ function resolveLabelClearanceAfterPathPasses(edges, obstacles, maxIter = 8) {
13523
+ if (edges.length === 0) return edges;
13524
+ const labeledIds = new Set(
13525
+ edges.filter((e) => e.label?.trim() || e.sub?.trim()).map((e) => e.id)
13526
+ );
13527
+ if (labeledIds.size === 0) return edges;
13528
+ const \u7BB1\u305F\u3061 = obstacles.filter((o) => o.kind === "node" || o.kind === "lane-label");
13529
+ const edgeById = /* @__PURE__ */ new Map();
13530
+ for (const e of edges) edgeById.set(e.id, e);
13531
+ const \u6E2C\u308A\u65B9 = \u7DDA\u306E\u6E2C\u308A\u65B9\u3092\u4F5C\u308B();
13532
+ const { \u533A\u9593, \u9060\u3044 } = \u6E2C\u308A\u65B9;
13533
+ const \u6700\u5927\u79FB\u52D5 = \u672D\u306E\u6700\u5927\u79FB\u52D5;
13406
13534
  const shiftMap = /* @__PURE__ */ new Map();
13407
13535
  const getShift = (id) => shiftMap.get(id) ?? { dx: 0, dy: 0 };
13408
13536
  const labelBBoxes = () => {
@@ -13415,50 +13543,12 @@ function resolveLabelClearanceAfterPathPasses(edges, obstacles, maxIter = 8) {
13415
13543
  }
13416
13544
  return out;
13417
13545
  };
13418
- const \u96E2\u308C\u91CF = (a, b) => ({
13419
- x: Math.max(a.x - (b.x + b.w), b.x - (a.x + a.w)),
13420
- y: Math.max(a.y - (b.y + b.h), b.y - (a.y + a.h))
13421
- });
13422
- const \u52D5\u304B\u3057\u305F\u7BB1 = (box, axis, sign, amount) => ({
13423
- ...box,
13424
- x: box.x + (axis === "x" ? sign * amount : 0),
13425
- y: box.y + (axis === "y" ? sign * amount : 0)
13426
- });
13427
13546
  for (let iter = 0; iter < maxIter; iter += 1) {
13428
13547
  const labels = labelBBoxes();
13429
13548
  const \u672D\u306E\u8981\u6C42 = requiredNearClearance("edge-label", "edge-label");
13430
13549
  let \u52D5\u3044\u305F = false;
13431
13550
  const \u4ECA\u56DE\u52D5\u304B\u3057\u305F = /* @__PURE__ */ new Set();
13432
- const \u5B89\u5168\u304B = (label, \u884C\u304D\u5148) => {
13433
- for (const obs of \u7BB1\u305F\u3061) {
13434
- const \u524D = computeGap(label, obs);
13435
- const \u5F8C = computeGap(\u884C\u304D\u5148, obs);
13436
- if (\u5F8C < Math.min(\u524D, requiredNearClearance("edge-label", obs.kind))) return false;
13437
- }
13438
- for (const \u4ED6 of labels) {
13439
- if (\u4ED6.id === label.id) continue;
13440
- const \u524D = computeGap(label, \u4ED6);
13441
- const \u5F8C = computeGap(\u884C\u304D\u5148, \u4ED6);
13442
- if (\u5F8C < Math.min(\u524D, \u672D\u306E\u8981\u6C42)) return false;
13443
- }
13444
- const \u81EA\u5206 = edgeById.get(label.id);
13445
- const \u81EA\u5206\u306E\u533A\u9593 = \u81EA\u5206 ? \u533A\u9593(\u81EA\u5206.id, \u81EA\u5206.d) : [];
13446
- if (\u81EA\u5206\u306E\u533A\u9593.length > 0) {
13447
- const \u524D = measurePathLabelGapSegs(\u81EA\u5206\u306E\u533A\u9593, label);
13448
- const \u5F8C = measurePathLabelGapSegs(\u81EA\u5206\u306E\u533A\u9593, \u884C\u304D\u5148);
13449
- if (\u5F8C > Math.max(\u524D, DIST_LABEL_PATH_MAX)) return false;
13450
- }
13451
- for (const \u76F8\u624B of edges) {
13452
- if (\u76F8\u624B.id === label.id) continue;
13453
- if (\u9060\u3044(label, \u76F8\u624B.id, \u76F8\u624B.d, LABEL_TO_PATH_CLEARANCE) && \u9060\u3044(\u884C\u304D\u5148, \u76F8\u624B.id, \u76F8\u624B.d, LABEL_TO_PATH_CLEARANCE)) continue;
13454
- const segs = segmentsExcludingOwnPath(\u533A\u9593(\u76F8\u624B.id, \u76F8\u624B.d), \u81EA\u5206\u306E\u533A\u9593);
13455
- if (segs.length === 0) continue;
13456
- const \u524D = measurePathLabelGapSegs(segs, label);
13457
- const \u5F8C = measurePathLabelGapSegs(segs, \u884C\u304D\u5148);
13458
- if (\u5F8C < Math.min(\u524D, LABEL_TO_PATH_CLEARANCE)) return false;
13459
- }
13460
- return true;
13461
- };
13551
+ const \u5B89\u5168\u304B = (label, \u884C\u304D\u5148) => \u672D\u306E\u79FB\u52D5\u3092\u585E\u3050\u76F8\u624B\u3092\u63A2\u3059({ \u7BB1\u305F\u3061, labels, edges, edgeById, \u6E2C\u308A\u65B9 }, label, \u884C\u304D\u5148) === null;
13462
13552
  const \u9003\u304C\u3059 = (label, \u5019\u88DC) => {
13463
13553
  for (const c of \u5019\u88DC.slice().sort((a, b) => a.amount - b.amount)) {
13464
13554
  if (c.amount <= 0) continue;
@@ -13474,18 +13564,6 @@ function resolveLabelClearanceAfterPathPasses(edges, obstacles, maxIter = 8) {
13474
13564
  }
13475
13565
  return false;
13476
13566
  };
13477
- const \u77E9\u5F62\u306E\u5019\u88DC = (label, static\u7BB1, required) => {
13478
- const sep = \u96E2\u308C\u91CF(label, static\u7BB1);
13479
- const \u5411\u304D = (axis) => {
13480
- const a = axis === "x" ? label.x + label.w / 2 : label.y + label.h / 2;
13481
- const b = axis === "x" ? static\u7BB1.x + static\u7BB1.w / 2 : static\u7BB1.y + static\u7BB1.h / 2;
13482
- return a >= b ? 1 : -1;
13483
- };
13484
- return [
13485
- { axis: "x", sign: \u5411\u304D("x"), amount: required - sep.x + NEAR_MISS_MARGIN },
13486
- { axis: "y", sign: \u5411\u304D("y"), amount: required - sep.y + NEAR_MISS_MARGIN }
13487
- ];
13488
- };
13489
13567
  for (const label of labels) {
13490
13568
  if (\u4ECA\u56DE\u52D5\u304B\u3057\u305F.has(label.id)) continue;
13491
13569
  for (const obs of \u7BB1\u305F\u3061) {
@@ -13542,22 +13620,7 @@ function resolveLabelClearanceAfterPathPasses(edges, obstacles, maxIter = 8) {
13542
13620
  }
13543
13621
  }
13544
13622
  if (!\u8FD1\u3044\u70B9) continue;
13545
- const \u5FC5\u8981\u91CF = (axis, sign) => {
13546
- const \u6E80\u305F\u3059 = (\u91CF) => measurePathLabelGapSegs(segs, \u52D5\u304B\u3057\u305F\u7BB1(label, axis, sign, \u91CF)) >= LABEL_TO_PATH_CLEARANCE;
13547
- let lo = 0;
13548
- let hi = Math.max(4, LABEL_TO_PATH_CLEARANCE - gap);
13549
- while (!\u6E80\u305F\u3059(hi)) {
13550
- if (hi >= \u6700\u5927\u79FB\u52D5) return null;
13551
- lo = hi;
13552
- hi = Math.min(hi * 2, \u6700\u5927\u79FB\u52D5);
13553
- }
13554
- for (let k = 0; k < 12; k += 1) {
13555
- const mid = (lo + hi) / 2;
13556
- if (\u6E80\u305F\u3059(mid)) hi = mid;
13557
- else lo = mid;
13558
- }
13559
- return hi + NEAR_MISS_MARGIN;
13560
- };
13623
+ const \u5FC5\u8981\u91CF = (axis, sign) => \u7DDA\u304B\u3089\u96E2\u308C\u308B\u91CF(segs, label, gap, axis, sign);
13561
13624
  const dx = \u82AF.x - \u8FD1\u3044\u70B9.x;
13562
13625
  const dy = \u82AF.y - \u8FD1\u3044\u70B9.y;
13563
13626
  const \u5019\u88DC = [];
@@ -15989,9 +16052,15 @@ function visualValidateLaid(laid, diag, opts) {
15989
16052
  const counts = emptyCounts();
15990
16053
  const profile = opts?.profile ?? "production";
15991
16054
  const skipped = SKIPPED_AXES[profile];
15992
- const push = (axis, detail, severity = "error") => {
16055
+ const push = (axis, detail, severity = "error", reason) => {
15993
16056
  if (skipped.has(axis)) return;
15994
- violations.push({ axis, diagramId: safeDiagramId(diag), detail, severity });
16057
+ violations.push({
16058
+ axis,
16059
+ diagramId: safeDiagramId(diag),
16060
+ detail,
16061
+ severity,
16062
+ ...reason !== void 0 ? { reason } : {}
16063
+ });
15995
16064
  counts[axis]++;
15996
16065
  };
15997
16066
  return visualValidateInner(
@@ -16010,9 +16079,15 @@ function visualValidate(diag, opts) {
16010
16079
  const counts = emptyCounts();
16011
16080
  const profile = opts?.profile ?? "production";
16012
16081
  const skipped = SKIPPED_AXES[profile];
16013
- const push = (axis, detail, severity = "error") => {
16082
+ const push = (axis, detail, severity = "error", reason) => {
16014
16083
  if (skipped.has(axis)) return;
16015
- violations.push({ axis, diagramId: safeDiagramId(diag), detail, severity });
16084
+ violations.push({
16085
+ axis,
16086
+ diagramId: safeDiagramId(diag),
16087
+ detail,
16088
+ severity,
16089
+ ...reason !== void 0 ? { reason } : {}
16090
+ });
16016
16091
  counts[axis]++;
16017
16092
  };
16018
16093
  const diagProblems = findMalformedInput(void 0, diag).filter(
@@ -16349,10 +16424,19 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
16349
16424
  }
16350
16425
  }
16351
16426
  const nears = detectNearCollisions(bboxes, laid.edges);
16427
+ const \u672D\u306E\u969C\u5BB3\u7269 = bboxes.filter((b) => b.kind === "node" || b.kind === "lane-label");
16428
+ const \u8FBA\u306E\u9806 = new Map(laid.edges.map((e, i) => [e.id, i]));
16352
16429
  for (const n of nears) {
16430
+ const a\u306F\u672D = n.a.kind === "edge-label";
16431
+ const b\u306F\u672D = n.b.kind === "edge-label";
16432
+ const \u52D5\u304B\u3059 = a\u306F\u672D && b\u306F\u672D ? (\u8FBA\u306E\u9806.get(n.a.id) ?? 0) > (\u8FBA\u306E\u9806.get(n.b.id) ?? 0) ? n.a : n.b : a\u306F\u672D ? n.a : b\u306F\u672D ? n.b : null;
16433
+ const \u76F8\u624B = \u52D5\u304B\u3059 === n.a ? n.b : n.a;
16434
+ const reason = \u52D5\u304B\u3059 !== null ? \u672D\u304C\u52D5\u3051\u306A\u3044\u7406\u7531(\u52D5\u304B\u3059.id, \u76F8\u624B, laid.edges, \u672D\u306E\u969C\u5BB3\u7269) ?? void 0 : void 0;
16353
16435
  push(
16354
16436
  "clearance",
16355
- `${n.a.kind}:${n.a.id} \u2194 ${n.b.kind}:${n.b.id} gap=${n.gap.toFixed(1)}px (need ${n.required}px)`
16437
+ `${n.a.kind}:${n.a.id} \u2194 ${n.b.kind}:${n.b.id} gap=${n.gap.toFixed(1)}px (need ${n.required}px)`,
16438
+ "error",
16439
+ reason
16356
16440
  );
16357
16441
  }
16358
16442
  const PROXIMITY_WARN_THRESHOLD = DIST_LABEL_PATH_MAX;
@@ -21272,10 +21356,11 @@ function layoutWithValidation(diag, opts = {}) {
21272
21356
  }
21273
21357
  if (opts.emitConsole) {
21274
21358
  for (const v of report.violations) {
21359
+ const \u7406\u7531 = v.reason !== void 0 ? ` ${v.reason}` : "";
21275
21360
  if (v.severity === "error") {
21276
- console.error(`[cdl geometry ${v.axis}] ${v.detail} (diagram=${v.diagramId})`);
21361
+ console.error(`[cdl geometry ${v.axis}] ${v.detail} (diagram=${v.diagramId})${\u7406\u7531}`);
21277
21362
  } else {
21278
- console.warn(`[cdl geometry ${v.axis}] ${v.detail} (diagram=${v.diagramId})`);
21363
+ console.warn(`[cdl geometry ${v.axis}] ${v.detail} (diagram=${v.diagramId})${\u7406\u7531}`);
21279
21364
  }
21280
21365
  }
21281
21366
  }
@@ -22835,6 +22920,17 @@ function edgeHeadPaint(head, fill, color) {
22835
22920
  }
22836
22921
  return { fill: color, stroke: "none" };
22837
22922
  }
22923
+ var \u89D2\u62EC\u5F27\u306E\u9699\u9593 = 0.08;
22924
+ function \u7B49\u5E45\u306E\u5B57(text, fontSize) {
22925
+ if (typeof text !== "string" || !text.includes("[]")) return text;
22926
+ const \u584A = text.split("[]");
22927
+ const out = [];
22928
+ \u584A.forEach((s, i) => {
22929
+ if (i > 0) out.push("[", react.createElement("tspan", { key: i, dx: fontSize * \u89D2\u62EC\u5F27\u306E\u9699\u9593 }, "]"));
22930
+ if (s !== "") out.push(s);
22931
+ });
22932
+ return out;
22933
+ }
22838
22934
  function defaultEdgeWidth(active) {
22839
22935
  return active ? 2.5 : 1.25;
22840
22936
  }
@@ -23090,7 +23186,7 @@ function CdlEdgeLabelView({
23090
23186
  fill: active ? color : "var(--cdl-text-dim, #5a6270)",
23091
23187
  opacity: labelTextOpacity("sub"),
23092
23188
  style: { fontFamily: fontFamilyAttr("sub") },
23093
- children: edge.sub
23189
+ children: \u7B49\u5E45\u306E\u5B57(edge.sub, EDGE_LABEL_TEXT.sub.fontSize)
23094
23190
  }
23095
23191
  )
23096
23192
  ]
@@ -23170,7 +23266,7 @@ function ActorNode({ node, active, value }) {
23170
23266
  textAnchor: "end",
23171
23267
  fill: "var(--cdl-text, #1a1f2a)",
23172
23268
  style: { fontFamily: "'JetBrains Mono', monospace" },
23173
- children: value
23269
+ children: \u7B49\u5E45\u306E\u5B57(value, 42)
23174
23270
  }
23175
23271
  )
23176
23272
  ] });
@@ -23346,7 +23442,7 @@ function SequenceBoardNode({
23346
23442
  textAnchor: "middle",
23347
23443
  fill: "var(--cdl-text, #1a1f2a)",
23348
23444
  style: { fontFamily: "'JetBrains Mono', monospace" },
23349
- children: a.name
23445
+ children: \u7B49\u5E45\u306E\u5B57(a.name, SEQ_NAME)
23350
23446
  }
23351
23447
  ),
23352
23448
  a.subtitle && /* @__PURE__ */ jsxRuntime.jsx(
@@ -23536,7 +23632,7 @@ function EventNode({
23536
23632
  fill: "var(--cdl-text, #1a1f2a)",
23537
23633
  textAnchor: \u540D\u524D.anchor,
23538
23634
  style: { fontFamily: "'JetBrains Mono', monospace" },
23539
- children: node.title
23635
+ children: \u7B49\u5E45\u306E\u5B57(node.title, \u540D\u524D.size)
23540
23636
  }
23541
23637
  ),
23542
23638
  node.subtitle && /* @__PURE__ */ jsxRuntime.jsx(
@@ -23547,7 +23643,7 @@ function EventNode({
23547
23643
  fontSize: 21,
23548
23644
  fill: "var(--cdl-text-dim, #5a6270)",
23549
23645
  style: { fontFamily: "'JetBrains Mono', monospace" },
23550
- children: node.subtitle
23646
+ children: \u7B49\u5E45\u306E\u5B57(node.subtitle, 21)
23551
23647
  }
23552
23648
  )
23553
23649
  ] })
@@ -23596,7 +23692,7 @@ function FunctionNode({ node, active }) {
23596
23692
  fill: "var(--cdl-text, #1a1f2a)",
23597
23693
  textAnchor: \u540D\u524D.anchor,
23598
23694
  style: { fontFamily: "'JetBrains Mono', monospace" },
23599
- children: node.title
23695
+ children: \u7B49\u5E45\u306E\u5B57(node.title, \u540D\u524D.size)
23600
23696
  }
23601
23697
  ),
23602
23698
  node.subtitle && /* @__PURE__ */ jsxRuntime.jsx("text", { x: 26, y: 126 - \u305A\u3089\u3057, fontSize: 20, fill: "var(--cdl-text-dim, #5a6270)", children: node.subtitle })
@@ -23709,7 +23805,7 @@ function StorageNode({
23709
23805
  fill: "var(--cdl-text, #1a1f2a)",
23710
23806
  textAnchor: \u540D\u524D.anchor,
23711
23807
  style: { fontFamily: "'JetBrains Mono', monospace" },
23712
- children: node.title
23808
+ children: \u7B49\u5E45\u306E\u5B57(node.title, \u540D\u524D.size)
23713
23809
  }
23714
23810
  ),
23715
23811
  rows.length > 0 && !\u5370\u3067\u5206\u3051\u308B && /* @__PURE__ */ jsxRuntime.jsx(
@@ -23770,7 +23866,7 @@ function StorageNode({
23770
23866
  fontWeight: \u5370\u3067\u5206\u3051\u308B ? 500 : 600,
23771
23867
  fill: "var(--cdl-text, #1a1f2a)",
23772
23868
  style: { fontFamily: "'JetBrains Mono', monospace" },
23773
- children: s.left
23869
+ children: \u7B49\u5E45\u306E\u5B57(s.left, 26)
23774
23870
  }
23775
23871
  ),
23776
23872
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -23784,7 +23880,7 @@ function StorageNode({
23784
23880
  textAnchor: \u5370\u3067\u5206\u3051\u308B ? "end" : "start",
23785
23881
  fill: \u5370\u3067\u5206\u3051\u308B ? "var(--cdl-text-dim, #5a6270)" : highlightRows ? accent : "var(--cdl-text, #1a1f2a)",
23786
23882
  style: { fontFamily: "'JetBrains Mono', monospace" },
23787
- children: s.right
23883
+ children: \u7B49\u5E45\u306E\u5B57(s.right, \u5370\u3067\u5206\u3051\u308B ? ROW_TYPE_FONT : 26)
23788
23884
  }
23789
23885
  )
23790
23886
  ] }, idx);
@@ -24058,8 +24154,8 @@ function GenericNode({
24058
24154
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: style.icon, fill: style.eyebrowColor, opacity: 0.7, transform: "scale(1)" })
24059
24155
  ] }),
24060
24156
  node.eyebrow && /* @__PURE__ */ jsxRuntime.jsx("text", { x: textX, y: eyebrowY, fontSize: 17, fontWeight: 700, letterSpacing: 1.5, fill: paint.onSolid ? "var(--cdl-node-fill, #ffffff)" : style.eyebrowColor, textAnchor, dominantBaseline, children: node.eyebrow }),
24061
- /* @__PURE__ */ jsxRuntime.jsx("text", { "data-cdl-role": "node-label", x: textX, y: titleY, fontSize: 20, fontWeight: 700, fill: paint.onSolid ? "var(--cdl-node-fill, #ffffff)" : "var(--cdl-text, #1a1f2a)", textAnchor, dominantBaseline, style: node.kind === "function" || node.kind === "api" ? { fontFamily: "'JetBrains Mono', monospace" } : void 0, children: node.title }),
24062
- node.subtitle && /* @__PURE__ */ jsxRuntime.jsx("text", { x: textX, y: subtitleY, fontSize: 17, fill: paint.onSolid ? "var(--cdl-node-fill, #ffffff)" : "var(--cdl-text-dim, #5a6270)", textAnchor, dominantBaseline, style: { fontFamily: "'JetBrains Mono', monospace" }, children: node.subtitle }),
24157
+ /* @__PURE__ */ jsxRuntime.jsx("text", { "data-cdl-role": "node-label", x: textX, y: titleY, fontSize: 20, fontWeight: 700, fill: paint.onSolid ? "var(--cdl-node-fill, #ffffff)" : "var(--cdl-text, #1a1f2a)", textAnchor, dominantBaseline, style: node.kind === "function" || node.kind === "api" ? { fontFamily: "'JetBrains Mono', monospace" } : void 0, children: node.kind === "function" || node.kind === "api" ? \u7B49\u5E45\u306E\u5B57(node.title, 20) : node.title }),
24158
+ node.subtitle && /* @__PURE__ */ jsxRuntime.jsx("text", { x: textX, y: subtitleY, fontSize: 17, fill: paint.onSolid ? "var(--cdl-node-fill, #ffffff)" : "var(--cdl-text-dim, #5a6270)", textAnchor, dominantBaseline, style: { fontFamily: "'JetBrains Mono', monospace" }, children: \u7B49\u5E45\u306E\u5B57(node.subtitle, 17) }),
24063
24159
  resolvedValue && /* @__PURE__ */ jsxRuntime.jsx(
24064
24160
  "text",
24065
24161
  {
@@ -24070,7 +24166,7 @@ function GenericNode({
24070
24166
  textAnchor: "end",
24071
24167
  fill: "var(--cdl-text, #1a1f2a)",
24072
24168
  style: { fontFamily: "'JetBrains Mono', monospace" },
24073
- children: resolvedValue
24169
+ children: \u7B49\u5E45\u306E\u5B57(resolvedValue, 32)
24074
24170
  }
24075
24171
  ),
24076
24172
  node.rows && node.rows.length > 0 && (() => {
@@ -24095,7 +24191,7 @@ function GenericNode({
24095
24191
  textAnchor: "start",
24096
24192
  fill: "var(--cdl-text, #1a1f2a)",
24097
24193
  style: { fontFamily: "'JetBrains Mono', monospace" },
24098
- children: s.right
24194
+ children: \u7B49\u5E45\u306E\u5B57(s.right, 21)
24099
24195
  }
24100
24196
  )
24101
24197
  ] }, i)) });