@cardenelabs/cdl 0.44.0 → 0.46.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,59 @@ CDL (Chainome Diagram Language) の主要変更履歴。
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.46.0] - 2026-09-11
9
+
10
+ ### Fixed
11
+
12
+ - **上向きに曲がる線の角に突起が出るのを直した** (#801)
13
+
14
+ 縦の対の辺 (`fromSide` と `toSide` が上下) は、角を「手前 14 で直線を止め、弧で 14 先へ
15
+ 抜ける」 形で丸める。 その手前と先を上下に固定していたため、**相手が上にある辺**
16
+ (`fromSide === "top"`) では直線が角を 14 通り過ぎ、弧が戻る形になっていた。
17
+ 戻りが画面上の突起として見える。
18
+
19
+ 見本帳 `class-complex-demo` の実物で並べると差が読める。
20
+
21
+ ```
22
+ 正しい (下向き) 壊れていた (上向き)
23
+ L 903 1244 <- 角の 14 手前 L 1613 1244 <- 角を 14 通り過ぎている
24
+ Q 903 1258, 917 1258 Q 1613 1258, 1627 1258
25
+ ```
26
+
27
+ 角の丸めを **進む向き** から決めるようにした。 同じ誤りは `CAR-482` が別の分岐で
28
+ 1 度直しており、本件はその時に見落とされた 2 つ目の分岐。
29
+
30
+ 下向きの辺 (`fromSide === "bottom"`) の `d` は 1 文字も変わらない。
31
+
32
+ ## [0.45.0] - 2026-09-11
33
+
34
+ ### Added
35
+
36
+ - **読みにくさを測る器を呼び出し側から渡せるようにした** (軸 23 `responsive-viewport`、#797)
37
+
38
+ `visualValidate` / `visualValidateLaid` / `visualValidateAll` に `container` を足した。
39
+
40
+ ```ts
41
+ visualValidate(diagram, { container: { width: 874 } });
42
+ ```
43
+
44
+ 軸 23 は `#793` から器に収めた倍率で読みにくさを判定するが、その器を engine が
45
+ 1150 × 630px に決め打っていた。 これは下流の見本帳の **拡大表示** を画面で実測した値で、
46
+ 同じ見本帳でも一覧に並べた時の枠は幅 874px、縦は巻き取るので上限が無い。
47
+ 器が違えば同じ図でも読めるかどうかが変わるため、決め打つと片方の見せ方が測れないまま残る。
48
+
49
+ **高さは省ける**。 省いた器では縦を見ない = 0 や無限大で表すと「上限が無い」 と
50
+ 「潰れている」 が同じ値になる。 省いた時の文面は `器 幅 874px (高さの上限なし)` になり、
51
+ 効いた辺は必ず横、届く寸法も幅で出す。
52
+
53
+ **壊れた寸法は既定に落とさず例外にする**。 落とすと、誤った値を渡した呼び出し側が
54
+ 「効いている」 と読む。 0 / 負値 / `NaN` / 無限大が対象で、判定は **図ごとではなく入口で
55
+ 1 度だけ**行う (図ごとに投げると、器の誤りが図の破綻に紛れてどちらを直すか読めない)。
56
+ 図を 1 枚も渡さない掃き出しでも確かめる。
57
+
58
+ `container` を渡さない呼び出しは今までどおり拡大表示の器 (1150 × 630px) で判定する。
59
+ 文面も 1 文字も変えていない。
60
+
8
61
  ## [0.44.0] - 2026-09-10
9
62
 
10
63
  ### Fixed
@@ -2267,7 +2320,9 @@ Initial OSS release.
2267
2320
  使わない = annotated tag を push しても GitHub Release は作られず、 Release を作っていない版で
2268
2321
  行き止まりになる。
2269
2322
 
2270
- [Unreleased]: https://github.com/cardene777/cdl/compare/v0.44.0...HEAD
2323
+ [Unreleased]: https://github.com/cardene777/cdl/compare/v0.46.0...HEAD
2324
+ [0.46.0]: https://github.com/cardene777/cdl/compare/v0.45.0...v0.46.0
2325
+ [0.45.0]: https://github.com/cardene777/cdl/compare/v0.44.0...v0.45.0
2271
2326
  [0.44.0]: https://github.com/cardene777/cdl/compare/v0.43.0...v0.44.0
2272
2327
  [0.43.0]: https://github.com/cardene777/cdl/compare/v0.42.0...v0.43.0
2273
2328
  [0.42.0]: https://github.com/cardene777/cdl/compare/v0.41.1...v0.42.0
package/dist/index.cjs CHANGED
@@ -15500,6 +15500,27 @@ var SKIPPED_AXES = {
15500
15500
  production: /* @__PURE__ */ new Set(),
15501
15501
  catalog: /* @__PURE__ */ new Set(["seo-metadata-quality", "structured-data-extraction"])
15502
15502
  };
15503
+ var \u65E2\u5B9A\u306E\u5668 = {
15504
+ /**
15505
+ * 拡大表示の枠は `min(1200px, 94vw)` で、中身は 1px の縁と 24px の余白の内側に描かれる。
15506
+ * 画面が 1280px 以上なら 1200 が効くので、そこから縁 2 枚と余白 2 枚を引く。
15507
+ */
15508
+ width: 1200 - 1 * 2 - 24 * 2,
15509
+ /** 同じ拡大表示の高さの頭打ち (`90vh − 180px`) を、基準の画面の高さ 900px で評価した値。 */
15510
+ height: 900 * 0.9 - 180
15511
+ };
15512
+ function \u5668\u3092\u78BA\u304B\u3081\u308B(c) {
15513
+ if (c === void 0) return { \u5E45: \u65E2\u5B9A\u306E\u5668.width, \u9AD8\u3055: \u65E2\u5B9A\u306E\u5668.height };
15514
+ if (!(c.width > 0) || !Number.isFinite(c.width)) {
15515
+ throw new Error(`container.width \u304C\u63CF\u753B\u4E0D\u80FD (\u6B63\u306E\u6709\u9650\u5024\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308B): ${c.width}`);
15516
+ }
15517
+ if (c.height !== void 0 && (!(c.height > 0) || !Number.isFinite(c.height))) {
15518
+ throw new Error(
15519
+ `container.height \u304C\u63CF\u753B\u4E0D\u80FD (\u6B63\u306E\u6709\u9650\u5024\u3067\u6E21\u3059\u304B\u3001\u4E0A\u9650\u304C\u7121\u3044\u306A\u3089\u7701\u304F): ${c.height}`
15520
+ );
15521
+ }
15522
+ return { \u5E45: c.width, \u9AD8\u3055: c.height };
15523
+ }
15503
15524
  var MIN_NODE_W = 80;
15504
15525
  var MIN_NODE_H = 40;
15505
15526
  var ROW_FORMAT = /^[^:]+:\s*.+$/;
@@ -15971,7 +15992,16 @@ function visualValidateLaid(laid, diag, opts) {
15971
15992
  violations.push({ axis, diagramId: safeDiagramId(diag), detail, severity });
15972
15993
  counts[axis]++;
15973
15994
  };
15974
- return visualValidateInner(laid, diag, violations, counts, push, profile, [...skipped]);
15995
+ return visualValidateInner(
15996
+ laid,
15997
+ diag,
15998
+ violations,
15999
+ counts,
16000
+ push,
16001
+ profile,
16002
+ [...skipped],
16003
+ \u5668\u3092\u78BA\u304B\u3081\u308B(opts?.container)
16004
+ );
15975
16005
  }
15976
16006
  function visualValidate(diag, opts) {
15977
16007
  const violations = [];
@@ -16008,7 +16038,16 @@ function visualValidate(diag, opts) {
16008
16038
  } finally {
16009
16039
  console.warn = origWarn;
16010
16040
  }
16011
- return visualValidateInner(laid, safeDiag, violations, counts, push, profile, [...skipped]);
16041
+ return visualValidateInner(
16042
+ laid,
16043
+ safeDiag,
16044
+ violations,
16045
+ counts,
16046
+ push,
16047
+ profile,
16048
+ [...skipped],
16049
+ \u5668\u3092\u78BA\u304B\u3081\u308B(opts?.container)
16050
+ );
16012
16051
  }
16013
16052
  var VALIDATED_ARRAY_FIELDS = [
16014
16053
  ["laid", "lanes"],
@@ -16208,7 +16247,7 @@ function normalizeForValidation(value, problems, owner) {
16208
16247
  }
16209
16248
  return next;
16210
16249
  }
16211
- function visualValidateInner(laid, diag, violations, counts, push, profile, skippedAxes) {
16250
+ function visualValidateInner(laid, diag, violations, counts, push, profile, skippedAxes, \u5668) {
16212
16251
  const problems = findMalformedInput(laid, diag);
16213
16252
  for (const p of problems) push("malformed-input", p.detail, "error");
16214
16253
  if (problems.length > 0) {
@@ -16216,7 +16255,7 @@ function visualValidateInner(laid, diag, violations, counts, push, profile, skip
16216
16255
  diag = normalizeForValidation(diag, problems, "diag");
16217
16256
  }
16218
16257
  try {
16219
- return runAxes(laid, diag, violations, counts, push, profile, skippedAxes);
16258
+ return runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5668);
16220
16259
  } catch (err) {
16221
16260
  const known = counts["malformed-input"] > 0;
16222
16261
  const axis = known ? "malformed-input" : "validation-interrupted";
@@ -16229,7 +16268,7 @@ function visualValidateInner(laid, diag, violations, counts, push, profile, skip
16229
16268
  return { diagramId: safeDiagramId(diag), ok: false, violations, counts, profile, skippedAxes };
16230
16269
  }
16231
16270
  }
16232
- function runAxes(laid, diag, violations, counts, push, profile, skippedAxes) {
16271
+ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5668) {
16233
16272
  const LIFELINE_W_THRESHOLD = 8;
16234
16273
  for (const n of laid.nodes) {
16235
16274
  if (n.w < LIFELINE_W_THRESHOLD) continue;
@@ -16929,14 +16968,8 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes) {
16929
16968
  } catch {
16930
16969
  }
16931
16970
  }
16932
- const RESPONSIVE_REF_FRAME_W_PX = 1200;
16933
- const RESPONSIVE_REF_FRAME_BORDER_PX = 1;
16934
- const RESPONSIVE_REF_FRAME_PAD_PX = 24;
16935
- const RESPONSIVE_REF_CONTAINER_W_PX = RESPONSIVE_REF_FRAME_W_PX - RESPONSIVE_REF_FRAME_BORDER_PX * 2 - RESPONSIVE_REF_FRAME_PAD_PX * 2;
16936
- const RESPONSIVE_REF_VIEWPORT_H_PX = 900;
16937
- const RESPONSIVE_REF_FRAME_H_RATIO = 0.9;
16938
- const RESPONSIVE_REF_CHROME_H_PX = 180;
16939
- const RESPONSIVE_REF_CONTAINER_H_PX = RESPONSIVE_REF_VIEWPORT_H_PX * RESPONSIVE_REF_FRAME_H_RATIO - RESPONSIVE_REF_CHROME_H_PX;
16971
+ const RESPONSIVE_REF_CONTAINER_W_PX = \u5668.\u5E45;
16972
+ const RESPONSIVE_REF_CONTAINER_H_PX = \u5668.\u9AD8\u3055;
16940
16973
  const RESPONSIVE_MIN_ON_SCREEN_FONT_PX = 12;
16941
16974
  const RESPONSIVE_BASE_FONT_WORLD = 22;
16942
16975
  const vbResp = laid.viewBox;
@@ -16948,15 +16981,16 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes) {
16948
16981
  );
16949
16982
  } else {
16950
16983
  const \u6A2A\u306E\u500D\u7387 = RESPONSIVE_REF_CONTAINER_W_PX / vbResp.w;
16951
- const \u7E26\u306E\u500D\u7387 = RESPONSIVE_REF_CONTAINER_H_PX / vbResp.h;
16984
+ const \u7E26\u306E\u500D\u7387 = RESPONSIVE_REF_CONTAINER_H_PX === void 0 ? Number.POSITIVE_INFINITY : RESPONSIVE_REF_CONTAINER_H_PX / vbResp.h;
16952
16985
  const \u500D\u7387 = Math.min(\u6A2A\u306E\u500D\u7387, \u7E26\u306E\u500D\u7387);
16953
16986
  const \u753B\u9762\u4E0A\u306E\u5B57 = RESPONSIVE_BASE_FONT_WORLD * \u500D\u7387;
16954
16987
  if (\u753B\u9762\u4E0A\u306E\u5B57 < RESPONSIVE_MIN_ON_SCREEN_FONT_PX) {
16955
16988
  const \u52B9\u304F\u8FBA = \u6A2A\u306E\u500D\u7387 <= \u7E26\u306E\u500D\u7387 ? "\u6A2A" : "\u7E26";
16956
- const \u53CE\u307E\u308B\u5BF8\u6CD5 = \u52B9\u304F\u8FBA === "\u6A2A" ? `\u5E45 ${(RESPONSIVE_REF_CONTAINER_W_PX * RESPONSIVE_BASE_FONT_WORLD / RESPONSIVE_MIN_ON_SCREEN_FONT_PX).toFixed(0)} \u4EE5\u4E0B` : `\u9AD8\u3055 ${(RESPONSIVE_REF_CONTAINER_H_PX * RESPONSIVE_BASE_FONT_WORLD / RESPONSIVE_MIN_ON_SCREEN_FONT_PX).toFixed(0)} \u4EE5\u4E0B`;
16989
+ const \u53CE\u307E\u308B\u5BF8\u6CD5 = \u52B9\u304F\u8FBA === "\u6A2A" || RESPONSIVE_REF_CONTAINER_H_PX === void 0 ? `\u5E45 ${(RESPONSIVE_REF_CONTAINER_W_PX * RESPONSIVE_BASE_FONT_WORLD / RESPONSIVE_MIN_ON_SCREEN_FONT_PX).toFixed(0)} \u4EE5\u4E0B` : `\u9AD8\u3055 ${(RESPONSIVE_REF_CONTAINER_H_PX * RESPONSIVE_BASE_FONT_WORLD / RESPONSIVE_MIN_ON_SCREEN_FONT_PX).toFixed(0)} \u4EE5\u4E0B`;
16990
+ const \u5668\u306E\u66F8\u304D\u65B9 = RESPONSIVE_REF_CONTAINER_H_PX === void 0 ? `\u5668 \u5E45 ${RESPONSIVE_REF_CONTAINER_W_PX}px (\u9AD8\u3055\u306E\u4E0A\u9650\u306A\u3057)` : `\u5668 ${RESPONSIVE_REF_CONTAINER_W_PX}\xD7${RESPONSIVE_REF_CONTAINER_H_PX}px`;
16957
16991
  push(
16958
16992
  "responsive-viewport",
16959
- `viewBox ${vbResp.w}\xD7${vbResp.h} \u306F\u5668 ${RESPONSIVE_REF_CONTAINER_W_PX}\xD7${RESPONSIVE_REF_CONTAINER_H_PX}px \u3067 ${\u500D\u7387.toFixed(3)} \u500D\u306B\u7E2E\u307F\u3001 \u7BB1\u306E\u984C\u304C ${\u753B\u9762\u4E0A\u306E\u5B57.toFixed(1)}px \u306B\u306A\u308B (\u4E0B\u9650 ${RESPONSIVE_MIN_ON_SCREEN_FONT_PX}px\u3001 \u500D\u7387\u3092\u6C7A\u3081\u305F\u306E\u306F ${\u52B9\u304F\u8FBA}\u3001 ${\u53CE\u307E\u308B\u5BF8\u6CD5}\u306B\u3059\u308B\u3068\u5C4A\u304F)`,
16993
+ `viewBox ${vbResp.w}\xD7${vbResp.h} \u306F${\u5668\u306E\u66F8\u304D\u65B9} \u3067 ${\u500D\u7387.toFixed(3)} \u500D\u306B\u7E2E\u307F\u3001 \u7BB1\u306E\u984C\u304C ${\u753B\u9762\u4E0A\u306E\u5B57.toFixed(1)}px \u306B\u306A\u308B (\u4E0B\u9650 ${RESPONSIVE_MIN_ON_SCREEN_FONT_PX}px\u3001 \u500D\u7387\u3092\u6C7A\u3081\u305F\u306E\u306F ${\u52B9\u304F\u8FBA}\u3001 ${\u53CE\u307E\u308B\u5BF8\u6CD5}\u306B\u3059\u308B\u3068\u5C4A\u304F)`,
16960
16994
  "warn"
16961
16995
  );
16962
16996
  }
@@ -17661,6 +17695,7 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes) {
17661
17695
  };
17662
17696
  }
17663
17697
  function visualValidateAll(diagrams, opts) {
17698
+ \u5668\u3092\u78BA\u304B\u3081\u308B(opts?.container);
17664
17699
  const durations = [];
17665
17700
  const reports = diagrams.map((d) => {
17666
17701
  const start = Date.now();
@@ -18147,6 +18182,9 @@ var LANE_PAD_MIN = 25;
18147
18182
  // src/layout/edges.ts
18148
18183
  var VERTICAL_DETOUR_GAP = 50;
18149
18184
  var VERTICAL_DETOUR_CORNER = 14;
18185
+ function verticalCornerDir(from, to) {
18186
+ return to < from ? -1 : 1;
18187
+ }
18150
18188
  var VERTICAL_DETOUR_EXIT = 45;
18151
18189
  function nearestBoxDistance(anchorX, dir, verticalTop, verticalBottom, boxes) {
18152
18190
  let nearest = Infinity;
@@ -19328,12 +19366,14 @@ function routePath(from, to, fromSide, toSide, obstacles = [], detourSide, _from
19328
19366
  midY2 = retreatBelowMidBlockers(midY2);
19329
19367
  const corner = 14;
19330
19368
  const labelY = midY2 - labelInit;
19369
+ const \u7E26\u306E\u5411\u304DA = verticalCornerDir(A.y, midY2);
19370
+ const \u7E26\u306E\u5411\u304DB = verticalCornerDir(midY2, B.y);
19331
19371
  return {
19332
19372
  d: `M ${A.x} ${A.y}
19333
- L ${A.x} ${midY2 - corner}
19373
+ L ${A.x} ${midY2 - \u7E26\u306E\u5411\u304DA * corner}
19334
19374
  Q ${A.x} ${midY2}, ${A.x + xDir * corner} ${midY2}
19335
19375
  L ${B.x - xDir * corner} ${midY2}
19336
- Q ${B.x} ${midY2}, ${B.x} ${midY2 + corner}
19376
+ Q ${B.x} ${midY2}, ${B.x} ${midY2 + \u7E26\u306E\u5411\u304DB * corner}
19337
19377
  L ${B.x} ${B.y}`,
19338
19378
  labelX: (A.x + B.x) / 2,
19339
19379
  labelY,