@cardenelabs/cdl 0.44.0 → 0.45.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 +31 -1
- package/dist/index.cjs +51 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.js +51 -16
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +31 -15
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +31 -15
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/visual-validate.ts +104 -30
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cardenelabs/cdl",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.45.0",
|
|
4
4
|
"description": "CDL (Chainome Diagram Language). Mermaid-like declarative DSL that compiles to animated SVG diagrams. Built for blockchain / Solidity flows, generic enough for sequence / flow / state / ER / topology diagrams.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "cardene777",
|
package/src/index.ts
CHANGED
package/src/visual-validate.ts
CHANGED
|
@@ -412,10 +412,65 @@ const SKIPPED_AXES: Readonly<Record<ValidationProfile, ReadonlySet<VisualAxis>>>
|
|
|
412
412
|
catalog: new Set<VisualAxis>(["seo-metadata-quality", "structured-data-extraction"]),
|
|
413
413
|
};
|
|
414
414
|
|
|
415
|
+
/**
|
|
416
|
+
* 図を描く器 (px)。 軸 23 `responsive-viewport` が画面上の字の大きさを出す時に使う。
|
|
417
|
+
*
|
|
418
|
+
* **高さは省ける**。 幅にだけ合わせて縦は巻き取る器があるため = 0 や無限大で表すと
|
|
419
|
+
* 「上限が無い」 と「潰れている」 が同じ値になる (`rules/quality.md § 判定できなかったことを
|
|
420
|
+
* 値に潰さない` と同じ形)。
|
|
421
|
+
*/
|
|
422
|
+
export interface ReferenceContainer {
|
|
423
|
+
/** 器の幅 (px)。 正の有限値。 */
|
|
424
|
+
readonly width: number;
|
|
425
|
+
/** 器の高さ (px)。 正の有限値。 **上限が無い器では省く**。 */
|
|
426
|
+
readonly height?: number;
|
|
427
|
+
}
|
|
428
|
+
|
|
415
429
|
/** 検査の設定。 */
|
|
416
430
|
export interface ValidateOptions {
|
|
417
431
|
/** 検査の用途。 既定は `production` (全ての軸を見る)。 */
|
|
418
432
|
profile?: ValidationProfile;
|
|
433
|
+
/**
|
|
434
|
+
* 軸 23 `responsive-viewport` が基準にする器。
|
|
435
|
+
*
|
|
436
|
+
* 既定は下流の見本帳の拡大表示を画面で測った値 (1150 × 630px)。
|
|
437
|
+
* 実際の器は呼び出し側が決めるものなので、別の見せ方を測る時はここで渡す。
|
|
438
|
+
*/
|
|
439
|
+
container?: ReferenceContainer;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/** 既定の器。 下流の見本帳の拡大表示を画面で測った値から導く (`#793` / `#797`)。 */
|
|
443
|
+
const 既定の器: Required<Pick<ReferenceContainer, "width">> & { height: number } = {
|
|
444
|
+
/**
|
|
445
|
+
* 拡大表示の枠は `min(1200px, 94vw)` で、中身は 1px の縁と 24px の余白の内側に描かれる。
|
|
446
|
+
* 画面が 1280px 以上なら 1200 が効くので、そこから縁 2 枚と余白 2 枚を引く。
|
|
447
|
+
*/
|
|
448
|
+
width: 1200 - 1 * 2 - 24 * 2,
|
|
449
|
+
/** 同じ拡大表示の高さの頭打ち (`90vh − 180px`) を、基準の画面の高さ 900px で評価した値。 */
|
|
450
|
+
height: 900 * 0.9 - 180,
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* 渡された器を検査して確定させる。 **入口で 1 度だけ呼ぶ** = 軸 23 の中で投げると
|
|
455
|
+
* 図ごとに投げることになり、どの呼び出しが誤っていたかが読みにくい。
|
|
456
|
+
*
|
|
457
|
+
* 壊れた寸法は既定に落とさず投げる。 落とすと、誤った値を渡した呼び出し側が
|
|
458
|
+
* 「効いている」 と読める。
|
|
459
|
+
*/
|
|
460
|
+
function 器を確かめる(c: ReferenceContainer | undefined): {
|
|
461
|
+
幅: number;
|
|
462
|
+
高さ: number | undefined;
|
|
463
|
+
} {
|
|
464
|
+
if (c === undefined) return { 幅: 既定の器.width, 高さ: 既定の器.height };
|
|
465
|
+
if (!(c.width > 0) || !Number.isFinite(c.width)) {
|
|
466
|
+
throw new Error(`container.width が描画不能 (正の有限値である必要がある): ${c.width}`);
|
|
467
|
+
}
|
|
468
|
+
if (c.height !== undefined && (!(c.height > 0) || !Number.isFinite(c.height))) {
|
|
469
|
+
throw new Error(
|
|
470
|
+
`container.height が描画不能 (正の有限値で渡すか、上限が無いなら省く): ${c.height}`,
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
return { 幅: c.width, 高さ: c.height };
|
|
419
474
|
}
|
|
420
475
|
|
|
421
476
|
export interface VisualValidationReport {
|
|
@@ -1401,7 +1456,16 @@ export function visualValidateLaid(
|
|
|
1401
1456
|
counts[axis]++;
|
|
1402
1457
|
};
|
|
1403
1458
|
|
|
1404
|
-
return visualValidateInner(
|
|
1459
|
+
return visualValidateInner(
|
|
1460
|
+
laid,
|
|
1461
|
+
diag,
|
|
1462
|
+
violations,
|
|
1463
|
+
counts,
|
|
1464
|
+
push,
|
|
1465
|
+
profile,
|
|
1466
|
+
[...skipped],
|
|
1467
|
+
器を確かめる(opts?.container),
|
|
1468
|
+
);
|
|
1405
1469
|
}
|
|
1406
1470
|
|
|
1407
1471
|
/**
|
|
@@ -1456,7 +1520,16 @@ export function visualValidate(diag: CdlDiagram, opts?: ValidateOptions): Visual
|
|
|
1456
1520
|
console.warn = origWarn;
|
|
1457
1521
|
}
|
|
1458
1522
|
|
|
1459
|
-
return visualValidateInner(
|
|
1523
|
+
return visualValidateInner(
|
|
1524
|
+
laid,
|
|
1525
|
+
safeDiag,
|
|
1526
|
+
violations,
|
|
1527
|
+
counts,
|
|
1528
|
+
push,
|
|
1529
|
+
profile,
|
|
1530
|
+
[...skipped],
|
|
1531
|
+
器を確かめる(opts?.container),
|
|
1532
|
+
);
|
|
1460
1533
|
}
|
|
1461
1534
|
|
|
1462
1535
|
/**
|
|
@@ -1782,6 +1855,8 @@ function visualValidateInner(
|
|
|
1782
1855
|
push: (axis: VisualAxis, detail: string, severity?: "error" | "warn") => void,
|
|
1783
1856
|
profile: ValidationProfile,
|
|
1784
1857
|
skippedAxes: VisualAxis[],
|
|
1858
|
+
/** 軸 23 が基準にする器。 入口で確かめ済 (`器を確かめる`)。 高さ `undefined` は上限なし。 */
|
|
1859
|
+
器: { 幅: number; 高さ: number | undefined },
|
|
1785
1860
|
): VisualValidationReport {
|
|
1786
1861
|
// 層 1 = 入口の検査 (top-level の配列 13 個と `viewBox`)。 壊れている箇所を報告してから、
|
|
1787
1862
|
// 検査が反復できる形に差し替える。
|
|
@@ -1801,7 +1876,7 @@ function visualValidateInner(
|
|
|
1801
1876
|
// 途中までに見つけた違反は `violations` に積まれているので保持される。 例外を投げた軸より
|
|
1802
1877
|
// 後ろの軸は走らない = 「検査できなかった」 ことを報告に出す。
|
|
1803
1878
|
try {
|
|
1804
|
-
return runAxes(laid, diag, violations, counts, push, profile, skippedAxes);
|
|
1879
|
+
return runAxes(laid, diag, violations, counts, push, profile, skippedAxes, 器);
|
|
1805
1880
|
} catch (err) {
|
|
1806
1881
|
// 入口が既に破綻を見つけていたなら入力側、 何も見つけていなければ検査側の欠陥。
|
|
1807
1882
|
// 直す先が違うので軸を分ける。 まとめると「入力が悪い」 と誤読して本 file の bug を
|
|
@@ -1837,6 +1912,8 @@ function runAxes(
|
|
|
1837
1912
|
push: (axis: VisualAxis, detail: string, severity?: "error" | "warn") => void,
|
|
1838
1913
|
profile: ValidationProfile,
|
|
1839
1914
|
skippedAxes: VisualAxis[],
|
|
1915
|
+
/** 軸 23 が基準にする器。 入口で確かめ済 (`器を確かめる`)。 高さ `undefined` は上限なし。 */
|
|
1916
|
+
器: { 幅: number; 高さ: number | undefined },
|
|
1840
1917
|
): VisualValidationReport {
|
|
1841
1918
|
// ───────────────────────────────────────────────────────────
|
|
1842
1919
|
// Axis 1: node-visibility (bbox 面積 / 最小寸法)
|
|
@@ -3079,33 +3156,18 @@ function runAxes(
|
|
|
3079
3156
|
// ───────────────────────────────────────────────────────────
|
|
3080
3157
|
//
|
|
3081
3158
|
/**
|
|
3082
|
-
*
|
|
3159
|
+
* 判定に使う器 (px)。 **呼び出し側が `ValidateOptions.container` で渡す** (`#797`)。
|
|
3083
3160
|
*
|
|
3084
|
-
*
|
|
3085
|
-
*
|
|
3086
|
-
*
|
|
3087
|
-
*
|
|
3088
|
-
* **実際の器は呼び出し側が決める**。 engine はそれを知らないので、 判定の基準として
|
|
3089
|
-
* 1 つ選ぶ。 選んだ値そのものが閾値の意味を決めるため、 定数として出す。
|
|
3090
|
-
*/
|
|
3091
|
-
const RESPONSIVE_REF_FRAME_W_PX = 1200;
|
|
3092
|
-
const RESPONSIVE_REF_FRAME_BORDER_PX = 1;
|
|
3093
|
-
const RESPONSIVE_REF_FRAME_PAD_PX = 24;
|
|
3094
|
-
const RESPONSIVE_REF_CONTAINER_W_PX =
|
|
3095
|
-
RESPONSIVE_REF_FRAME_W_PX - RESPONSIVE_REF_FRAME_BORDER_PX * 2 - RESPONSIVE_REF_FRAME_PAD_PX * 2;
|
|
3096
|
-
/**
|
|
3097
|
-
* 判定に使う器の高さ (px)。 同じ拡大表示の高さの頭打ち (`90vh − 180px`) を、
|
|
3098
|
-
* 基準の画面の高さ 900px で評価した値。
|
|
3161
|
+
* 実際の器は見せ方ごとに違う (拡大表示は 1150 × 630px、 一覧に並べた時の枠は
|
|
3162
|
+
* 幅 874px で高さの頭打ちが無い)。 engine はどちらで見られるかを知らないので、
|
|
3163
|
+
* 渡されなければ拡大表示の値を既定にする (`既定の器`)。
|
|
3099
3164
|
*
|
|
3100
|
-
*
|
|
3101
|
-
*
|
|
3102
|
-
*
|
|
3165
|
+
* **高さは省ける**。 図は `preserveAspectRatio="xMidYMid meet"` で器に収まるよう中で縮むため、
|
|
3166
|
+
* 高さの上限がある器では縦が倍率を決めうる (画面での実測 28 回のうち 27 回は縦が効いていた、
|
|
3167
|
+
* `#793`)。 縦に巻き取る器ではその制約が無いので、 高さを見ない。
|
|
3103
3168
|
*/
|
|
3104
|
-
const
|
|
3105
|
-
const
|
|
3106
|
-
const RESPONSIVE_REF_CHROME_H_PX = 180;
|
|
3107
|
-
const RESPONSIVE_REF_CONTAINER_H_PX =
|
|
3108
|
-
RESPONSIVE_REF_VIEWPORT_H_PX * RESPONSIVE_REF_FRAME_H_RATIO - RESPONSIVE_REF_CHROME_H_PX;
|
|
3169
|
+
const RESPONSIVE_REF_CONTAINER_W_PX = 器.幅;
|
|
3170
|
+
const RESPONSIVE_REF_CONTAINER_H_PX = 器.高さ;
|
|
3109
3171
|
/**
|
|
3110
3172
|
* 画面上で読めると見なす文字の下限 (px)。
|
|
3111
3173
|
*
|
|
@@ -3136,7 +3198,12 @@ function runAxes(
|
|
|
3136
3198
|
} else {
|
|
3137
3199
|
// 器に収めた時に効く倍率。 `xMidYMid meet` は縦横の小さい方に合わせる。
|
|
3138
3200
|
const 横の倍率 = RESPONSIVE_REF_CONTAINER_W_PX / vbResp.w;
|
|
3139
|
-
|
|
3201
|
+
// **高さの上限が無い器では縦を見ない**。 0 や巨大な数で表すと「上限なし」 と
|
|
3202
|
+
// 「潰れている」 が同じ値になるため、 `undefined` のまま `Infinity` に落とす。
|
|
3203
|
+
const 縦の倍率 =
|
|
3204
|
+
RESPONSIVE_REF_CONTAINER_H_PX === undefined
|
|
3205
|
+
? Number.POSITIVE_INFINITY
|
|
3206
|
+
: RESPONSIVE_REF_CONTAINER_H_PX / vbResp.h;
|
|
3140
3207
|
const 倍率 = Math.min(横の倍率, 縦の倍率);
|
|
3141
3208
|
const 画面上の字 = RESPONSIVE_BASE_FONT_WORLD * 倍率;
|
|
3142
3209
|
if (画面上の字 < RESPONSIVE_MIN_ON_SCREEN_FONT_PX) {
|
|
@@ -3144,12 +3211,16 @@ function runAxes(
|
|
|
3144
3211
|
// (実測 = 1255×1700 の図は幅を半分にしても縦が効いたまま)。
|
|
3145
3212
|
const 効く辺 = 横の倍率 <= 縦の倍率 ? "横" : "縦";
|
|
3146
3213
|
const 収まる寸法 =
|
|
3147
|
-
効く辺 === "横"
|
|
3214
|
+
効く辺 === "横" || RESPONSIVE_REF_CONTAINER_H_PX === undefined
|
|
3148
3215
|
? `幅 ${((RESPONSIVE_REF_CONTAINER_W_PX * RESPONSIVE_BASE_FONT_WORLD) / RESPONSIVE_MIN_ON_SCREEN_FONT_PX).toFixed(0)} 以下`
|
|
3149
3216
|
: `高さ ${((RESPONSIVE_REF_CONTAINER_H_PX * RESPONSIVE_BASE_FONT_WORLD) / RESPONSIVE_MIN_ON_SCREEN_FONT_PX).toFixed(0)} 以下`;
|
|
3217
|
+
const 器の書き方 =
|
|
3218
|
+
RESPONSIVE_REF_CONTAINER_H_PX === undefined
|
|
3219
|
+
? `器 幅 ${RESPONSIVE_REF_CONTAINER_W_PX}px (高さの上限なし)`
|
|
3220
|
+
: `器 ${RESPONSIVE_REF_CONTAINER_W_PX}×${RESPONSIVE_REF_CONTAINER_H_PX}px`;
|
|
3150
3221
|
push(
|
|
3151
3222
|
"responsive-viewport",
|
|
3152
|
-
`viewBox ${vbResp.w}×${vbResp.h}
|
|
3223
|
+
`viewBox ${vbResp.w}×${vbResp.h} は${器の書き方} で ` +
|
|
3153
3224
|
`${倍率.toFixed(3)} 倍に縮み、 箱の題が ${画面上の字.toFixed(1)}px になる ` +
|
|
3154
3225
|
`(下限 ${RESPONSIVE_MIN_ON_SCREEN_FONT_PX}px、 倍率を決めたのは ${効く辺}、 ${収まる寸法}にすると届く)`,
|
|
3155
3226
|
"warn",
|
|
@@ -4305,6 +4376,9 @@ export interface SweepReport {
|
|
|
4305
4376
|
}
|
|
4306
4377
|
|
|
4307
4378
|
export function visualValidateAll(diagrams: CdlDiagram[], opts?: ValidateOptions): SweepReport {
|
|
4379
|
+
// **図を 1 枚も持たない呼び出しでも器を確かめる**。 各図の `visualValidate` に任せると、
|
|
4380
|
+
// 図が 0 枚の掃き出しでは壊れた器が黙って通る (`#797`)。
|
|
4381
|
+
器を確かめる(opts?.container);
|
|
4308
4382
|
// Axis 52 用 = 各 diagram の validate 実行時間 (ms) を計測。 performance budget 超過検知。
|
|
4309
4383
|
const durations: number[] = [];
|
|
4310
4384
|
const reports = diagrams.map((d) => {
|