@cardenelabs/cdl 0.106.0 → 0.108.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,80 @@ CDL (Chainome Diagram Language) の主要変更履歴。
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.108.0] - 2026-09-30
9
+
10
+ ### Fixed
11
+
12
+ - **絵の中に置く題が、読めない大きさまで縮むのを止めた** (#953)
13
+
14
+ 絵の中に字を置く 34 種 (`shape-person` / `shape-bank` / `shape-file` 等) は、題が箱の幅に
15
+ 収まらない時に字を小さくして収める。 **この縮めに下限が無かった**。
16
+ 幅 300 の箱に 120 字の題を渡すと `shape-person` は 2.4px で描く = 点にしか見えない。
17
+
18
+ 同じ engine でも箱の種別 (`actor` / `card` / `event` / `function` / `storage`) は
19
+ `kinds/compact-title.ts` の `fitTextSize` が 11px で縮めるのをやめる。 絵の中の字だけが
20
+ 下限を持たなかった。 検査の側は 0.107.0 (#951) で挙げられるようになっていたが、
21
+ 描く側には止める仕組みが無かった。
22
+
23
+ 幅で縮める倍率を読める下限 (11px) で止め、**止めた行は入るところまでで切って `…` を付ける**。
24
+ 切る形を採ったのは、箱の中に収める決まり (#433) を全種別の検査が見ているため。
25
+ 横へ出す形も採れるが、120 字を 11px で描くと 1400px になり隣の箱まで覆う。
26
+ `kinds/box-lines.ts` の `幅に収める` が #534 で決めた形と同じになる。
27
+
28
+ 2 つの場合は下限を当てない。
29
+
30
+ | 場合 | 理由 |
31
+ |---|---|
32
+ | 素の大きさが下限以下 | 当てると幅の縮めが 1 度も効かず、横へ大きく出る |
33
+ | `…` すら入らない幅 | 切ると名前が 1 字も残らない = 読めない大きさより悪い |
34
+
35
+ 高さで決まる字の大きさ (`labelPlan` の下限 9) は変えていない。 縦にはみ出すと絵と重なり、
36
+ 字も絵もどちらも読めなくなる。
37
+
38
+ 焼き付けた見た目の記録は 1 件も動いていない。
39
+
40
+ ## [0.107.0] - 2026-09-30
41
+
42
+ ### Fixed
43
+
44
+ - **収まっている題を「はみ出す」 と判定するのをやめた** (#951)
45
+
46
+ 軸 3 (`text-readability`) の見積りが、実際に描く形と 2 点で違っていた。
47
+
48
+ 第一に、字の幅の表が **組み方のための上振れ値** だった。 箱の大きさと線の置き場を決める
49
+ 側は狭く見積もると字が枠から出るため、表は広い側へ寄せてある。 同じ値で「はみ出すか」 を
50
+ 判定すると、収まっている題まで挙がる。
51
+
52
+ 見本帳の題 407 か所を `getComputedTextLength()` で測ると、上振れは字種で分かれた。
53
+
54
+ | 字種 | 件数 | 見積り / 実描画 |
55
+ |---|---|---|
56
+ | 和文だけ | 247 | 1.080 倍 (例外なし) |
57
+ | 欧文だけ | 119 | 1.16 から 1.82 倍 (中央 1.27 倍) |
58
+ | 混在 | 41 | 1.09 から 1.35 倍 |
59
+
60
+ 第二に、**描く側は箱に収まるまで字を小さくする**。 `actor` / `card` / `event` / `function` /
61
+ `storage` は読める下限 11px まで 1 ずつ落とし、絵の中に字を置く 34 種は下限なく縮める。
62
+ 軸 3 は種別ごとの最大値で見積もっていたので、縮めて収めた題まで挙がっていた。
63
+
64
+ 2 点を直した。
65
+
66
+ | 直した所 | 内容 |
67
+ |---|---|
68
+ | `measureTextWidth` | `bound: "drawn"` を足し、字種ごとに上振れを割り戻す。 既定 (`layout`) は変えない |
69
+ | 軸 3 | 縮める種別は「読める下限を割るか」、縮めない種別は「箱の幅を超えるか」 を見る |
70
+
71
+ **組み方の見積りは 1 つも変えていない**。 箱の大きさと線の置き場は従来どおりで、
72
+ 焼き付けた見た目も動かない。
73
+
74
+ 検知力は下げていない。 縮める種別では、下限 11px まで落としても収まらない題を挙げる
75
+ (`storage` の箱 400px に全角 40 字を書くと挙がる)。 絵の中に字を置く 34 種では、
76
+ 下限を割る大きさまで縮む題を挙げる = 直す前は「はみ出す」 という当たらない理由で
77
+ 挙げていたものを、実際に起きること (読めない大きさになる) に付け替えた。
78
+
79
+ 引く側は cardene777/dragon#2701 で 9 枚が受け入れ一覧に載っていた。 本版でその 9 枚が
80
+ 挙がらなくなる。
81
+
8
82
  ## [0.106.0] - 2026-09-30
9
83
 
10
84
  ### Fixed
@@ -4285,7 +4359,9 @@ Initial OSS release.
4285
4359
  使わない = annotated tag を push しても GitHub Release は作られず、 Release を作っていない版で
4286
4360
  行き止まりになる。
4287
4361
 
4288
- [Unreleased]: https://github.com/cardene777/cdl/compare/v0.106.0...HEAD
4362
+ [Unreleased]: https://github.com/cardene777/cdl/compare/v0.108.0...HEAD
4363
+ [0.108.0]: https://github.com/cardene777/cdl/compare/v0.107.0...v0.108.0
4364
+ [0.107.0]: https://github.com/cardene777/cdl/compare/v0.106.0...v0.107.0
4289
4365
  [0.106.0]: https://github.com/cardene777/cdl/compare/v0.105.0...v0.106.0
4290
4366
  [0.105.0]: https://github.com/cardene777/cdl/compare/v0.104.0...v0.105.0
4291
4367
  [0.104.0]: https://github.com/cardene777/cdl/compare/v0.103.0...v0.104.0
package/dist/index.cjs CHANGED
@@ -12241,6 +12241,11 @@ function isHalfwidthKana(code) {
12241
12241
  }
12242
12242
  var EMOJI_ADVANCE_EM = 1.05;
12243
12243
  var MONO_EMOJI_ADVANCE_EM = 1.16;
12244
+ var DRAWN_CJK_RATIO = 1.08;
12245
+ var DRAWN_ASCII_RATIO = 1.16;
12246
+ function isAscii(code) {
12247
+ return code < 128;
12248
+ }
12244
12249
  var WIDE_SYMBOL_ADVANCE_EM = 0.95;
12245
12250
  function isEmoji(code) {
12246
12251
  return code >= 126976 && code <= 129791 || // 絵文字の主要面
@@ -12279,29 +12284,31 @@ function measureTextWidth(text, opts = {}) {
12279
12284
  const fontSize = opts.fontSize ?? 22;
12280
12285
  const letterSpacing = opts.letterSpacing ?? 0;
12281
12286
  const fontFamily = opts.fontFamily ?? "sans";
12287
+ const bound = opts.bound ?? "layout";
12282
12288
  let advanceEmSum = 0;
12283
12289
  let charCount = 0;
12284
12290
  const \u6587\u5B57\u5217 = CLUSTER_JOINER_RE.test(text) ? segmentGraphemes(text) : [...text];
12285
12291
  for (const ch of \u6587\u5B57\u5217) {
12286
12292
  charCount++;
12287
12293
  const code = ch.codePointAt(0) ?? 0;
12294
+ const \u5272\u308A\u623B\u3057 = bound === "drawn" && !isEmojiGrapheme(ch, code) ? isAscii(code) ? DRAWN_ASCII_RATIO : isCJK(code) ? DRAWN_CJK_RATIO : 1 : 1;
12288
12295
  if (isEmojiGrapheme(ch, code)) {
12289
12296
  advanceEmSum += fontFamily === "mono" ? MONO_EMOJI_ADVANCE_EM : EMOJI_ADVANCE_EM;
12290
12297
  continue;
12291
12298
  }
12292
12299
  if (fontFamily === "mono") {
12293
- advanceEmSum += isCJK(code) ? 1.08 : JETBRAINS_MONO_ADVANCE_EM;
12300
+ advanceEmSum += (isCJK(code) ? 1.08 : JETBRAINS_MONO_ADVANCE_EM) / \u5272\u308A\u623B\u3057;
12294
12301
  continue;
12295
12302
  }
12296
12303
  if (isCJK(code)) {
12297
- advanceEmSum += 1.08;
12304
+ advanceEmSum += 1.08 / \u5272\u308A\u623B\u3057;
12298
12305
  continue;
12299
12306
  }
12300
12307
  const table = ch.length === 1 ? INTER_BOLD_ADVANCE_EM[ch] : void 0;
12301
- advanceEmSum += table !== void 0 ? table : defaultAdvanceEm(ch, code);
12308
+ advanceEmSum += (table !== void 0 ? table : defaultAdvanceEm(ch, code)) / \u5272\u308A\u623B\u3057;
12302
12309
  }
12303
12310
  const w = advanceEmSum * fontSize + letterSpacing * charCount;
12304
- return Math.max(w, fontSize * 1.2);
12311
+ return bound === "drawn" ? w : Math.max(w, fontSize * 1.2);
12305
12312
  }
12306
12313
  function \u53CE\u3081\u308B\u500D\u7387(text, opts, \u5E45) {
12307
12314
  if (!(\u5E45 > 0) || !(opts.fontSize > 0)) return 1;
@@ -12442,6 +12449,51 @@ function titleFontSize(kind) {
12442
12449
  return TITLE_FONT_SIZE.get(kind ?? "") ?? TITLE_FONT_SIZE_DEFAULT;
12443
12450
  }
12444
12451
  var TITLE_BOX_PADDING = 52;
12452
+ var KINDS_SCALING_TITLE_WHEN_LOW = /* @__PURE__ */ new Set(["actor", "event", "function", "storage"]);
12453
+ var KINDS_SCALING_TITLE_ALWAYS = /* @__PURE__ */ new Set([
12454
+ "card",
12455
+ "shape-file",
12456
+ "shape-folder",
12457
+ "shape-cloud",
12458
+ "shape-cylinder",
12459
+ "shape-hexagon",
12460
+ "shape-diamond",
12461
+ "shape-stack",
12462
+ "shape-person",
12463
+ "shape-server-rack",
12464
+ "shape-network-node",
12465
+ "shape-mobile-device",
12466
+ "shape-satellite",
12467
+ "shape-smart-contract",
12468
+ "shape-rpc-node",
12469
+ "shape-wallet",
12470
+ "shape-nft",
12471
+ "shape-token",
12472
+ "shape-blockchain",
12473
+ "shape-bitcoin-chain",
12474
+ "shape-ethereum-chain",
12475
+ "shape-blockchain-node",
12476
+ "shape-bank",
12477
+ "shape-trust-bank",
12478
+ "shape-payment-provider",
12479
+ "shape-credit-card",
12480
+ "shape-brokerage",
12481
+ "shape-exchange",
12482
+ "shape-atm",
12483
+ "shape-website",
12484
+ "shape-storefront",
12485
+ "shape-warehouse",
12486
+ "shape-online-shop",
12487
+ "shape-cdn-edge",
12488
+ "shape-api-gateway"
12489
+ ]);
12490
+ var COMPACT_TITLE_MAX_H = 100;
12491
+ function titleScalesToFit(kind, h) {
12492
+ const k = kind ?? "";
12493
+ if (KINDS_SCALING_TITLE_ALWAYS.has(k)) return true;
12494
+ return KINDS_SCALING_TITLE_WHEN_LOW.has(k) && h < COMPACT_TITLE_MAX_H;
12495
+ }
12496
+ var MIN_TITLE_FONT_SIZE = 11;
12445
12497
  var KINDS_DRAWN_BY_GENERIC = [
12446
12498
  "person",
12447
12499
  "user-group",
@@ -14649,6 +14701,14 @@ function \u5E45\u306E\u500D\u7387(text, size, letterSpacing, \u5E45) {
14649
14701
  const \u5B9F\u5E45 = textWidth(text, size, letterSpacing);
14650
14702
  return \u5B9F\u5E45 > \u5E45 ? \u5E45 / \u5B9F\u5E45 : 1;
14651
14703
  }
14704
+ function \u8AAD\u3081\u308B\u4E0B\u9650\u306E\u500D\u7387(\u5927\u304D\u3055) {
14705
+ return \u5927\u304D\u3055 > MIN_TITLE_FONT_SIZE ? MIN_TITLE_FONT_SIZE / \u5927\u304D\u3055 : 0;
14706
+ }
14707
+ function \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(\u984C, \u5927\u304D\u3055, \u5B57\u9593, \u5E45\u4E0A\u9650, \u6E2C\u308B) {
14708
+ const \u4E0B\u9650 = \u8AAD\u3081\u308B\u4E0B\u9650\u306E\u500D\u7387(\u5927\u304D\u3055);
14709
+ if (!(\u4E0B\u9650 > 0) || !(\u5E45\u4E0A\u9650 > 0)) return 0;
14710
+ return \u5E45\u3067\u5207\u308B(\u984C, \u5927\u304D\u3055 * \u4E0B\u9650, \u5E45\u4E0A\u9650, (u, f) => \u6E2C\u308B(u, f, \u5B57\u9593 * \u4E0B\u9650)) === "" ? 0 : \u4E0B\u9650;
14711
+ }
14652
14712
  var TITLE_MAX = 18;
14653
14713
  var TITLE_MIN = 9;
14654
14714
  var TITLE_RATIO = 0.17;
@@ -14808,16 +14868,19 @@ function bodyBand(node, opt) {
14808
14868
  const h = Math.max(0, \u7BB1h - \u7E26\u4F59\u767D * ky);
14809
14869
  return { x, y, w, h, cx: x + w / 2, cy: y + h / 2, \u53F3: x + w, \u5E95: y + h };
14810
14870
  }
14811
- function fitLabel(band, block, pos) {
14871
+ function fitLabel(band, block, pos, \u6A2A\u306E\u4E0B\u9650 = 0) {
14812
14872
  const \u7E26 = block.\u4E0A + block.\u4E0B;
14813
14873
  const \u6A2A = Math.max(0, block.\u5E45);
14814
14874
  if (!(\u7E26 > 0)) return { k: 1, x: pos.x, y: pos.y };
14815
14875
  if (!(band.h > 0) || !(band.w > 0)) return { k: 0, x: band.x + band.w / 2, y: band.y };
14816
- const k = Math.min(1, band.h / \u7E26, \u6A2A > 0 ? band.w / \u6A2A : 1);
14876
+ const \u6A2A\u3067 = \u6A2A > 0 ? Math.max(band.w / \u6A2A, \u6A2A\u306E\u4E0B\u9650) : 1;
14877
+ const k = Math.min(1, band.h / \u7E26, \u6A2A\u3067);
14817
14878
  const \u534A = \u6A2A * k / 2;
14818
14879
  return {
14819
14880
  k,
14820
- x: Math.max(band.x + \u534A, Math.min(pos.x, band.x + band.w - \u534A)),
14881
+ // 下限で止めた塊は帯より広い。 その時は帯の中央に置いて左右へ均等に出す =
14882
+ // 寄せの式をそのまま当てると片側だけに出る (`compact-title.ts` と同じ判断)
14883
+ x: \u534A * 2 > band.w ? band.x + band.w / 2 : Math.max(band.x + \u534A, Math.min(pos.x, band.x + band.w - \u534A)),
14821
14884
  y: Math.max(band.y + block.\u4E0A * k, Math.min(pos.y, band.y + band.h - block.\u4E0B * k))
14822
14885
  };
14823
14886
  }
@@ -17225,12 +17288,23 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
17225
17288
  if (!isRenderedNode(n)) continue;
17226
17289
  const titleTrimmed = n.title?.trim() ?? "";
17227
17290
  if (!titleTrimmed) continue;
17228
- const expectedW = measureTextWidth(titleTrimmed, { fontSize: titleFontSize(n.kind) }) + (drawsTitleOutsideBox(n.kind) ? 0 : TITLE_BOX_PADDING);
17229
- if (expectedW > n.w + 8) {
17291
+ const \u4F59\u767D = drawsTitleOutsideBox(n.kind) ? 0 : TITLE_BOX_PADDING;
17292
+ const \u4F7F\u3048\u308B\u5E452 = n.w - \u4F59\u767D;
17293
+ const \u5B9F\u5E45 = measureTextWidth(titleTrimmed, { fontSize: titleFontSize(n.kind), bound: "drawn" });
17294
+ if (titleScalesToFit(n.kind, n.h)) {
17295
+ const \u7E2E\u3081\u305F\u5927\u304D\u3055 = \u5B9F\u5E45 > 0 ? titleFontSize(n.kind) * Math.min(1, \u4F7F\u3048\u308B\u5E452 / \u5B9F\u5E45) : titleFontSize(n.kind);
17296
+ if (\u7E2E\u3081\u305F\u5927\u304D\u3055 < MIN_TITLE_FONT_SIZE) {
17297
+ push(
17298
+ "text-readability",
17299
+ `node "${n.id}" title "${n.title}" \u304C node \u5E45 ${n.w}px \u306B\u53CE\u307E\u3089\u305A\u3001\u8AAD\u3081\u308B\u4E0B\u9650 ${MIN_TITLE_FONT_SIZE}px \u3092\u5272\u308B (\u7E2E\u3081\u3066 ${\u7E2E\u3081\u305F\u5927\u304D\u3055.toFixed(1)}px)`,
17300
+ "warn"
17301
+ );
17302
+ }
17303
+ } else if (\u5B9F\u5E45 > \u4F7F\u3048\u308B\u5E452 + 8) {
17230
17304
  push(
17231
17305
  "text-readability",
17232
17306
  // 字ごとの実幅は小数になるので、読む人に出す時だけ丸める (判定は丸めない)
17233
- `node "${n.id}" title "${n.title}" \u304C node \u5E45 ${n.w}px \u3092\u8D85\u904E\u3059\u308B\u53EF\u80FD\u6027 (\u671F\u5F85 ${Math.round(expectedW)}px)`,
17307
+ `node "${n.id}" title "${n.title}" \u304C node \u5E45 ${n.w}px \u3092\u8D85\u904E\u3059\u308B\u53EF\u80FD\u6027 (\u671F\u5F85 ${Math.round(\u5B9F\u5E45 + \u4F59\u767D)}px)`,
17234
17308
  "warn"
17235
17309
  );
17236
17310
  }
@@ -28646,13 +28720,15 @@ function labelBlock(node, pos, size, band) {
28646
28720
  node.eyebrow ? textWidth(node.eyebrow, EYEBROW_SIZE2, EYEBROW_TRACKING) : 0,
28647
28721
  node.subtitle ? textWidth(node.subtitle, SUB_SIZE) : 0
28648
28722
  );
28649
- const { k, x, y: baseline } = fitLabel(band, { \u4E0A, \u4E0B, \u5E45 }, pos);
28723
+ const \u4E0B\u9650 = \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(node.title ?? "", size, 0, band.w, textWidth);
28724
+ const { k, x, y: baseline } = fitLabel(band, { \u4E0A, \u4E0B, \u5E45 }, pos, \u4E0B\u9650);
28650
28725
  return { k, x, baseline, \u4E0A\u7AEF: baseline - \u4E0A * k, \u4E0B\u7AEF: baseline + \u4E0B * k };
28651
28726
  }
28652
28727
  function commonLabel(node, pos, size, band) {
28653
28728
  const \u584A = labelBlock(node, pos, size, band);
28654
28729
  const k = \u584A.k;
28655
28730
  const x = \u584A.x;
28731
+ const \u5207\u308B = (t, \u5927\u304D\u3055, \u5B57\u9593 = 0) => \u5E45\u3067\u5207\u308B(t, \u5927\u304D\u3055 * k, band.w, (u, f) => textWidth(u, f, \u5B57\u9593 * k));
28656
28732
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
28657
28733
  node.eyebrow && /* @__PURE__ */ jsxRuntime.jsx(
28658
28734
  "text",
@@ -28664,7 +28740,7 @@ function commonLabel(node, pos, size, band) {
28664
28740
  letterSpacing: EYEBROW_TRACKING * k,
28665
28741
  textAnchor: "middle",
28666
28742
  fill: "var(--cdl-tone-accent, #2d6a8f)",
28667
- children: node.eyebrow
28743
+ children: \u5207\u308B(node.eyebrow, EYEBROW_SIZE2, EYEBROW_TRACKING)
28668
28744
  }
28669
28745
  ),
28670
28746
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -28677,7 +28753,7 @@ function commonLabel(node, pos, size, band) {
28677
28753
  fontWeight: 700,
28678
28754
  textAnchor: "middle",
28679
28755
  fill: "var(--cdl-text, #1a1f2a)",
28680
- children: node.title
28756
+ children: \u5207\u308B(node.title ?? "", size)
28681
28757
  }
28682
28758
  ),
28683
28759
  node.subtitle && /* @__PURE__ */ jsxRuntime.jsx(
@@ -28688,7 +28764,7 @@ function commonLabel(node, pos, size, band) {
28688
28764
  fontSize: SUB_SIZE * k,
28689
28765
  textAnchor: "middle",
28690
28766
  fill: "var(--cdl-text-dim, #5a6270)",
28691
- children: node.subtitle
28767
+ children: \u5207\u308B(node.subtitle, SUB_SIZE)
28692
28768
  }
28693
28769
  )
28694
28770
  ] });
@@ -29023,7 +29099,9 @@ function planLabel(node, cx, \u5E45\u4E0A\u9650, plan) {
29023
29099
  node.eyebrow && plan.\u80A9\u66F8 ? textWidth(node.eyebrow, plan.\u80A9\u66F8.size, EYEBROW_TRACKING) : 0,
29024
29100
  node.subtitle && plan.\u8AAC\u660E ? textWidth(node.subtitle, plan.\u8AAC\u660E.size) : 0
29025
29101
  );
29026
- const k = \u5E45 > 0 && \u5E45\u4E0A\u9650 > 0 ? Math.min(1, \u5E45\u4E0A\u9650 / \u5E45) : 1;
29102
+ const \u4E0B\u9650 = \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(node.title ?? "", plan.\u540D\u524D.size, 0, \u5E45\u4E0A\u9650, textWidth);
29103
+ const k = \u5E45 > 0 && \u5E45\u4E0A\u9650 > 0 ? Math.min(1, Math.max(\u5E45\u4E0A\u9650 / \u5E45, \u4E0B\u9650)) : 1;
29104
+ const \u5207\u308B = (t, \u5927\u304D\u3055, \u5B57\u9593 = 0) => \u5E45\u3067\u5207\u308B(t, \u5927\u304D\u3055 * k, \u5E45\u4E0A\u9650, (u, f) => textWidth(u, f, \u5B57\u9593 * k));
29027
29105
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
29028
29106
  node.eyebrow && plan.\u80A9\u66F8 && /* @__PURE__ */ jsxRuntime.jsx(
29029
29107
  "text",
@@ -29035,7 +29113,7 @@ function planLabel(node, cx, \u5E45\u4E0A\u9650, plan) {
29035
29113
  letterSpacing: EYEBROW_TRACKING * k,
29036
29114
  textAnchor: "middle",
29037
29115
  fill: "var(--cdl-tone-accent, #2d6a8f)",
29038
- children: node.eyebrow
29116
+ children: \u5207\u308B(node.eyebrow, plan.\u80A9\u66F8.size, EYEBROW_TRACKING)
29039
29117
  }
29040
29118
  ),
29041
29119
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -29048,7 +29126,7 @@ function planLabel(node, cx, \u5E45\u4E0A\u9650, plan) {
29048
29126
  fontWeight: 700,
29049
29127
  textAnchor: "middle",
29050
29128
  fill: "var(--cdl-text, #1a1f2a)",
29051
- children: node.title
29129
+ children: \u5207\u308B(node.title ?? "", plan.\u540D\u524D.size)
29052
29130
  }
29053
29131
  ),
29054
29132
  node.subtitle && plan.\u8AAC\u660E && /* @__PURE__ */ jsxRuntime.jsx(
@@ -29059,7 +29137,7 @@ function planLabel(node, cx, \u5E45\u4E0A\u9650, plan) {
29059
29137
  fontSize: plan.\u8AAC\u660E.size * k,
29060
29138
  textAnchor: "middle",
29061
29139
  fill: "var(--cdl-text-dim, #5a6270)",
29062
- children: node.subtitle
29140
+ children: \u5207\u308B(node.subtitle, plan.\u8AAC\u660E.size)
29063
29141
  }
29064
29142
  )
29065
29143
  ] });
@@ -29982,17 +30060,19 @@ var externalLabel = (node, cx, bottomY) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRu
29982
30060
  var LABEL_EYEBROW_SPACING = 2;
29983
30061
  function \u5E45\u306B\u53CE\u3081\u308B2(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45) {
29984
30062
  const \u5E45 = textWidth(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593);
29985
- const \u500D\u7387 = \u5E45 > 0 && \u7BB1\u5E45 > 0 ? Math.min(1, \u7BB1\u5E45 / \u5E45) : 1;
29986
- return { size: \u5927\u304D\u3055 * \u500D\u7387, spacing: \u5B57\u9593 * \u500D\u7387 };
30063
+ const \u500D\u7387 = \u5E45 > 0 && \u7BB1\u5E45 > 0 ? Math.min(1, Math.max(\u7BB1\u5E45 / \u5E45, \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, textWidth))) : 1;
30064
+ const size = \u5927\u304D\u3055 * \u500D\u7387;
30065
+ const spacing = \u5B57\u9593 * \u500D\u7387;
30066
+ return { size, spacing, text: \u5E45\u3067\u5207\u308B(\u6587\u5B57\u5217, size, \u7BB1\u5E45, (u, f) => textWidth(u, f, spacing)) };
29987
30067
  }
29988
30068
  function bottomLabel(node, cx, plan) {
29989
30069
  const \u80A9 = \u5E45\u306B\u53CE\u3081\u308B2(node.eyebrow ?? "", plan.\u80A9\u66F8?.size ?? 0, LABEL_EYEBROW_SPACING, node.w);
29990
30070
  const \u540D = \u5E45\u306B\u53CE\u3081\u308B2(node.title ?? "", plan.\u540D\u524D.size, 0, node.w);
29991
30071
  const \u8AAC = \u5E45\u306B\u53CE\u3081\u308B2(node.subtitle ?? "", plan.\u8AAC\u660E?.size ?? 0, 0, node.w);
29992
30072
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
29993
- node.eyebrow && plan.\u80A9\u66F8 && /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: plan.\u80A9\u66F8.y, fontSize: \u80A9.size, fontWeight: 700, letterSpacing: \u80A9.spacing, textAnchor: "middle", fill: "var(--cdl-tone-accent, #2d6a8f)", children: node.eyebrow }),
29994
- /* @__PURE__ */ jsxRuntime.jsx("text", { "data-cdl-role": "node-label", x: cx, y: plan.\u540D\u524D.y, fontSize: \u540D.size, fontWeight: 700, textAnchor: "middle", fill: "var(--cdl-text, #1a1f2a)", children: node.title }),
29995
- node.subtitle && plan.\u8AAC\u660E && /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: plan.\u8AAC\u660E.y, fontSize: \u8AAC.size, textAnchor: "middle", fill: "var(--cdl-text-dim, #5a6270)", children: node.subtitle })
30073
+ node.eyebrow && plan.\u80A9\u66F8 && /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: plan.\u80A9\u66F8.y, fontSize: \u80A9.size, fontWeight: 700, letterSpacing: \u80A9.spacing, textAnchor: "middle", fill: "var(--cdl-tone-accent, #2d6a8f)", children: \u80A9.text }),
30074
+ /* @__PURE__ */ jsxRuntime.jsx("text", { "data-cdl-role": "node-label", x: cx, y: plan.\u540D\u524D.y, fontSize: \u540D.size, fontWeight: 700, textAnchor: "middle", fill: "var(--cdl-text, #1a1f2a)", children: \u540D.text }),
30075
+ node.subtitle && plan.\u8AAC\u660E && /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: plan.\u8AAC\u660E.y, fontSize: \u8AAC.size, textAnchor: "middle", fill: "var(--cdl-text-dim, #5a6270)", children: \u8AAC.text })
29996
30076
  ] });
29997
30077
  }
29998
30078
  var RACK_SLOT_TOP = 20;
@@ -30787,13 +30867,22 @@ function blockchainNodeExtent(strokeWidth) {
30787
30867
  return { \u4E0A: \u7E26, \u4E0B: \u7E26, \u5DE6: \u6A2A, \u53F3: \u6A2A };
30788
30868
  }
30789
30869
  function bottomLabel2(node, cx, plan) {
30790
- const \u80A9\u66F8\u500D\u7387 = node.eyebrow && plan.\u80A9\u66F8 ? \u5E45\u306E\u500D\u7387(node.eyebrow, plan.\u80A9\u66F8.size, 2, node.w) : 1;
30791
- const \u540D\u524D\u500D\u7387 = \u5E45\u306E\u500D\u7387(node.title, plan.\u540D\u524D.size, 0, node.w);
30792
- const \u8AAC\u660E\u500D\u7387 = node.subtitle && plan.\u8AAC\u660E ? \u5E45\u306E\u500D\u7387(node.subtitle, plan.\u8AAC\u660E.size, 0, node.w) : 1;
30870
+ const \u53CE\u3081\u308B = (t, \u5927\u304D\u3055, \u5B57\u9593) => {
30871
+ const \u6E2C\u308B = (u, f, ls) => \u5B57\u306E\u5E45(u, f) + ls * [...u].length;
30872
+ const \u500D\u7387 = Math.max(\u5E45\u306E\u500D\u7387(t, \u5927\u304D\u3055, \u5B57\u9593, node.w), \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(t, \u5927\u304D\u3055, \u5B57\u9593, node.w, \u6E2C\u308B));
30873
+ const size = \u5927\u304D\u3055 * \u500D\u7387;
30874
+ return { \u500D\u7387, text: \u5E45\u3067\u5207\u308B(t, size, node.w, (u, f) => \u5B57\u306E\u5E45(u, f) + \u5B57\u9593 * \u500D\u7387 * [...u].length) };
30875
+ };
30876
+ const \u80A9 = node.eyebrow && plan.\u80A9\u66F8 ? \u53CE\u3081\u308B(node.eyebrow, plan.\u80A9\u66F8.size, 2) : { \u500D\u7387: 1, text: node.eyebrow ?? "" };
30877
+ const \u540D = \u53CE\u3081\u308B(node.title ?? "", plan.\u540D\u524D.size, 0);
30878
+ const \u8AAC = node.subtitle && plan.\u8AAC\u660E ? \u53CE\u3081\u308B(node.subtitle, plan.\u8AAC\u660E.size, 0) : { \u500D\u7387: 1, text: node.subtitle ?? "" };
30879
+ const \u80A9\u66F8\u500D\u7387 = \u80A9.\u500D\u7387;
30880
+ const \u540D\u524D\u500D\u7387 = \u540D.\u500D\u7387;
30881
+ const \u8AAC\u660E\u500D\u7387 = \u8AAC.\u500D\u7387;
30793
30882
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
30794
- node.eyebrow && plan.\u80A9\u66F8 && /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: plan.\u80A9\u66F8.y, fontSize: plan.\u80A9\u66F8.size * \u80A9\u66F8\u500D\u7387, fontWeight: 700, letterSpacing: 2 * \u80A9\u66F8\u500D\u7387, textAnchor: "middle", fill: "var(--cdl-tone-accent, #2d6a8f)", children: node.eyebrow }),
30795
- /* @__PURE__ */ jsxRuntime.jsx("text", { "data-cdl-role": "node-label", x: cx, y: plan.\u540D\u524D.y, fontSize: plan.\u540D\u524D.size * \u540D\u524D\u500D\u7387, fontWeight: 700, textAnchor: "middle", fill: "var(--cdl-text, #1a1f2a)", children: node.title }),
30796
- node.subtitle && plan.\u8AAC\u660E && /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: plan.\u8AAC\u660E.y, fontSize: plan.\u8AAC\u660E.size * \u8AAC\u660E\u500D\u7387, textAnchor: "middle", fill: "var(--cdl-text-dim, #5a6270)", children: node.subtitle })
30883
+ node.eyebrow && plan.\u80A9\u66F8 && /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: plan.\u80A9\u66F8.y, fontSize: plan.\u80A9\u66F8.size * \u80A9\u66F8\u500D\u7387, fontWeight: 700, letterSpacing: 2 * \u80A9\u66F8\u500D\u7387, textAnchor: "middle", fill: "var(--cdl-tone-accent, #2d6a8f)", children: \u80A9.text }),
30884
+ /* @__PURE__ */ jsxRuntime.jsx("text", { "data-cdl-role": "node-label", x: cx, y: plan.\u540D\u524D.y, fontSize: plan.\u540D\u524D.size * \u540D\u524D\u500D\u7387, fontWeight: 700, textAnchor: "middle", fill: "var(--cdl-text, #1a1f2a)", children: \u540D.text }),
30885
+ node.subtitle && plan.\u8AAC\u660E && /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: plan.\u8AAC\u660E.y, fontSize: plan.\u8AAC\u660E.size * \u8AAC\u660E\u500D\u7387, textAnchor: "middle", fill: "var(--cdl-text-dim, #5a6270)", children: \u8AAC.text })
30797
30886
  ] });
30798
30887
  }
30799
30888
  function EthereumDiamond({ cx, cy, h, colors }) {
@@ -31402,17 +31491,19 @@ function \u5B57\u5E45(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593) {
31402
31491
  }
31403
31492
  function \u5E45\u306B\u53CE\u3081\u308B3(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45) {
31404
31493
  const \u5E45 = \u5B57\u5E45(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593);
31405
- const \u500D\u7387 = \u5E45 > 0 && \u7BB1\u5E45 > 0 ? Math.min(1, \u7BB1\u5E45 / \u5E45) : 1;
31406
- return { size: \u5927\u304D\u3055 * \u500D\u7387, spacing: \u5B57\u9593 * \u500D\u7387 };
31494
+ const \u500D\u7387 = \u5E45 > 0 && \u7BB1\u5E45 > 0 ? Math.min(1, Math.max(\u7BB1\u5E45 / \u5E45, \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u5B57\u5E45))) : 1;
31495
+ const size = \u5927\u304D\u3055 * \u500D\u7387;
31496
+ const spacing = \u5B57\u9593 * \u500D\u7387;
31497
+ return { size, spacing, text: \u5E45\u3067\u5207\u308B(\u6587\u5B57\u5217, size, \u7BB1\u5E45, (u, f) => \u5B57\u5E45(u, f, spacing)) };
31407
31498
  }
31408
31499
  function bottomLabel3(node, cx, plan) {
31409
31500
  const \u80A9 = \u5E45\u306B\u53CE\u3081\u308B3(node.eyebrow ?? "", plan.\u80A9\u66F8?.size ?? 0, LABEL_EYEBROW_SPACING2, node.w);
31410
31501
  const \u540D = \u5E45\u306B\u53CE\u3081\u308B3(node.title ?? "", plan.\u540D\u524D.size, 0, node.w);
31411
31502
  const \u8AAC = \u5E45\u306B\u53CE\u3081\u308B3(node.subtitle ?? "", plan.\u8AAC\u660E?.size ?? 0, 0, node.w);
31412
31503
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
31413
- node.eyebrow && plan.\u80A9\u66F8 && /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: plan.\u80A9\u66F8.y, fontSize: \u80A9.size, fontWeight: 700, letterSpacing: \u80A9.spacing, textAnchor: "middle", fill: "var(--cdl-tone-accent, #2d6a8f)", children: node.eyebrow }),
31414
- /* @__PURE__ */ jsxRuntime.jsx("text", { "data-cdl-role": "node-label", x: cx, y: plan.\u540D\u524D.y, fontSize: \u540D.size, fontWeight: 700, textAnchor: "middle", fill: "var(--cdl-text, #1a1f2a)", children: node.title }),
31415
- node.subtitle && plan.\u8AAC\u660E && /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: plan.\u8AAC\u660E.y, fontSize: \u8AAC.size, textAnchor: "middle", fill: "var(--cdl-text-dim, #5a6270)", children: node.subtitle })
31504
+ node.eyebrow && plan.\u80A9\u66F8 && /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: plan.\u80A9\u66F8.y, fontSize: \u80A9.size, fontWeight: 700, letterSpacing: \u80A9.spacing, textAnchor: "middle", fill: "var(--cdl-tone-accent, #2d6a8f)", children: \u80A9.text }),
31505
+ /* @__PURE__ */ jsxRuntime.jsx("text", { "data-cdl-role": "node-label", x: cx, y: plan.\u540D\u524D.y, fontSize: \u540D.size, fontWeight: 700, textAnchor: "middle", fill: "var(--cdl-text, #1a1f2a)", children: \u540D.text }),
31506
+ node.subtitle && plan.\u8AAC\u660E && /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: plan.\u8AAC\u660E.y, fontSize: \u8AAC.size, textAnchor: "middle", fill: "var(--cdl-text-dim, #5a6270)", children: \u8AAC.text })
31416
31507
  ] });
31417
31508
  }
31418
31509
  var BANK_PEDIMENT_H = 44;
@@ -31885,17 +31976,19 @@ function \u5B57\u5E452(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593) {
31885
31976
  }
31886
31977
  function \u5E45\u306B\u53CE\u3081\u308B4(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45) {
31887
31978
  const \u5E45 = \u5B57\u5E452(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593);
31888
- const \u500D\u7387 = \u5E45 > 0 && \u7BB1\u5E45 > 0 ? Math.min(1, \u7BB1\u5E45 / \u5E45) : 1;
31889
- return { size: \u5927\u304D\u3055 * \u500D\u7387, spacing: \u5B57\u9593 * \u500D\u7387 };
31979
+ const \u500D\u7387 = \u5E45 > 0 && \u7BB1\u5E45 > 0 ? Math.min(1, Math.max(\u7BB1\u5E45 / \u5E45, \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u5B57\u5E452))) : 1;
31980
+ const size = \u5927\u304D\u3055 * \u500D\u7387;
31981
+ const spacing = \u5B57\u9593 * \u500D\u7387;
31982
+ return { size, spacing, text: \u5E45\u3067\u5207\u308B(\u6587\u5B57\u5217, size, \u7BB1\u5E45, (u, f) => \u5B57\u5E452(u, f, spacing)) };
31890
31983
  }
31891
31984
  function bottomLabel4(node, cx, plan) {
31892
31985
  const \u80A9 = \u5E45\u306B\u53CE\u3081\u308B4(node.eyebrow ?? "", plan.\u80A9\u66F8?.size ?? 0, LABEL_EYEBROW_SPACING3, node.w);
31893
31986
  const \u540D = \u5E45\u306B\u53CE\u3081\u308B4(node.title ?? "", plan.\u540D\u524D.size, 0, node.w);
31894
31987
  const \u8AAC = \u5E45\u306B\u53CE\u3081\u308B4(node.subtitle ?? "", plan.\u8AAC\u660E?.size ?? 0, 0, node.w);
31895
31988
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
31896
- node.eyebrow && plan.\u80A9\u66F8 && /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: plan.\u80A9\u66F8.y, fontSize: \u80A9.size, fontWeight: 700, letterSpacing: \u80A9.spacing, textAnchor: "middle", fill: "var(--cdl-tone-accent, #2d6a8f)", children: node.eyebrow }),
31897
- /* @__PURE__ */ jsxRuntime.jsx("text", { "data-cdl-role": "node-label", x: cx, y: plan.\u540D\u524D.y, fontSize: \u540D.size, fontWeight: 700, textAnchor: "middle", fill: "var(--cdl-text, #1a1f2a)", children: node.title }),
31898
- node.subtitle && plan.\u8AAC\u660E && /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: plan.\u8AAC\u660E.y, fontSize: \u8AAC.size, textAnchor: "middle", fill: "var(--cdl-text-dim, #5a6270)", children: node.subtitle })
31989
+ node.eyebrow && plan.\u80A9\u66F8 && /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: plan.\u80A9\u66F8.y, fontSize: \u80A9.size, fontWeight: 700, letterSpacing: \u80A9.spacing, textAnchor: "middle", fill: "var(--cdl-tone-accent, #2d6a8f)", children: \u80A9.text }),
31990
+ /* @__PURE__ */ jsxRuntime.jsx("text", { "data-cdl-role": "node-label", x: cx, y: plan.\u540D\u524D.y, fontSize: \u540D.size, fontWeight: 700, textAnchor: "middle", fill: "var(--cdl-text, #1a1f2a)", children: \u540D.text }),
31991
+ node.subtitle && plan.\u8AAC\u660E && /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: plan.\u8AAC\u660E.y, fontSize: \u8AAC.size, textAnchor: "middle", fill: "var(--cdl-text-dim, #5a6270)", children: \u8AAC.text })
31899
31992
  ] });
31900
31993
  }
31901
31994
  var DROP_SHADOW_D = 4;