@cardenelabs/cdl 0.117.0 → 0.119.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cardenelabs/cdl",
3
- "version": "0.117.0",
3
+ "version": "0.119.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",
@@ -8,6 +8,8 @@ import {
8
8
  ROW_PITCH_STORAGE,
9
9
  ROW_TOP_STORAGE,
10
10
  STORAGE_ROW_DIVIDER_Y,
11
+ STORAGE_SUBTITLE_BASELINE,
12
+ STORAGE_SUBTITLE_FONT,
11
13
  STORAGE_TITLE_BASELINE,
12
14
  STORAGE_TITLE_FONT,
13
15
  SUBTITLE_ROW_SHIFT,
@@ -49,10 +51,13 @@ const ROW_GLYPH_RISE = 8;
49
51
  /**
50
52
  * 題の下に置く呼び名の baseline (#578)。
51
53
  *
52
- * 題 (78) と 1 行目 (130) の間。 印で分ける箱では区切り線を引かないので、その分の余白が空く。
54
+ * 題 (86) と 1 行目 (130) の間。 印で分ける箱では区切り線を引かないので、その分の余白が空く。
53
55
  * ER の表名や状態の名前は識別子なので、その下に日本語の呼び名を薄く添える。
56
+ *
57
+ * **値は `layout/spec.ts` が持つ** (#974)。 高さを出す側が同じ値を読むため、
58
+ * ここで別に持つと片方だけ動いて箱の下が空く。
54
59
  */
55
- const SUBTITLE_BASELINE = 118;
60
+ const SUBTITLE_BASELINE = STORAGE_SUBTITLE_BASELINE;
56
61
 
57
62
  /**
58
63
  * 縞を敷く最少の行数 (#627)。
@@ -63,8 +68,13 @@ const SUBTITLE_BASELINE = 118;
63
68
  */
64
69
  const STRIPE_MIN_ROWS = 2;
65
70
 
66
- /** 呼び名の級。 行の名前 (26) より小さく、型 (24) と同じ */
67
- const SUBTITLE_FONT = 20;
71
+ /**
72
+ * 呼び名の級。 行の名前 (26) より小さく、型 (24) と同じ。
73
+ *
74
+ * **値は `layout/spec.ts` が持つ** (#974)。 高さを出す側が字形の深さをこの級から
75
+ * 見込むため、ここで別に持つと片方だけ動く。
76
+ */
77
+ const SUBTITLE_FONT = STORAGE_SUBTITLE_FONT;
68
78
 
69
79
  /** 主キーの下線を名前の baseline からどれだけ下に引くか */
70
80
  const UNDERLINE_DROP = 7;
@@ -17,21 +17,40 @@
17
17
  * 使う。 弦の向きを使うと、大きく膨らむ曲線で線が端へ入ってくる向きと別の向きが出る。
18
18
  */
19
19
  import { EDGE_LABEL_TEXT } from "../label-text";
20
+ import { EDGE_HEAD_MARKER_SIZE } from "../types";
20
21
  import { extractPathSegments } from "./collisions";
21
22
  import { hasRenderedLabel } from "./spec";
22
23
  import { measureTextWidth } from "./text-width";
23
24
 
25
+ /** 端の印と端の字の間に空ける余白 (world)。 線に沿う向きと直角の向きで同じ値を使う */
26
+ export const 端の字と印の余白 = 8;
27
+
28
+ /** 端の印が線の芯から左右へ張り出す長さ (world)。 印の縦の半分 */
29
+ export const 端の印の張り出し = EDGE_HEAD_MARKER_SIZE.既定 / 2;
30
+
24
31
  /**
25
32
  * 端から字までの、線に沿った距離 (world)。
26
33
  *
27
- * 端の印の長さの最大 (光っている時の 14、 `render/stage.tsx` の marker の大きさ) に隙間 8 を足す。
34
+ * 端の印の長さの最大 (光っている時の大きさ) に余白を足す。
28
35
  * 印を持たない端 (菱が出どころ側にある「集約」 「コンポジション」 の行き先) でも同じ距離にする = 端ごとに
29
36
  * 距離が変わると、図の中で多重度の位置が揃わない。
37
+ *
38
+ * **この値は箱と箱の間隔にも入る** (`端の字に要る線の長さ` を `layout/nodes.ts` が引く)。
39
+ * 変えると図の高さが動くので、印との重なりは直角の向き (`端の字と線の隙間`) で解く。
30
40
  */
31
- export const 端の字を戻す距離 = 22;
41
+ export const 端の字を戻す距離 = EDGE_HEAD_MARKER_SIZE.既定 + 端の字と印の余白;
32
42
 
33
- /** 線と字の間の隙間 (world) */
34
- export const 端の字と線の隙間 = 8;
43
+ /**
44
+ * 線と字の間の隙間 (world)。 線の芯から字の箱までを測る。
45
+ *
46
+ * **印の張り出しに余白を足す** (#984)。 印は線に沿う向きだけでなく直角の向きにも広がり、
47
+ * 菱と三角は線の芯から 7 ある。 隙間を 8 にしていた頃は印の縁と字の箱が 1 しか空かず、
48
+ * 端の数が印に貼り付いて読めた (見本帳のクラス図の集約とコンポジションの両方で出た)。
49
+ *
50
+ * 余白は `端の字を戻す距離` が印の長さに足しているものと同じ値にする = 線に沿う向きと
51
+ * 直角の向きで、印から字までの空き方が揃う。
52
+ */
53
+ export const 端の字と線の隙間 = 端の印の張り出し + 端の字と印の余白;
35
54
 
36
55
  /** 端の字の大きさ。 札の下の行と同じ等幅の字 = 多重度を札に入れていた頃と同じ見え方 */
37
56
  export const 端の字の大きさ = EDGE_LABEL_TEXT.sub.fontSize;
@@ -9,6 +9,7 @@ import {
9
9
  requiredVerticalLabelGap,
10
10
  SUBTITLE_ROW_SHIFT,
11
11
  中身から出す高さ,
12
+ 呼び名で伸びる量,
12
13
  目印なしの繰り上げ,
13
14
  } from "./spec";
14
15
  import { DEFAULT_NODE_GAP, HEADER_RESERVE, LANE_TOP_PAD, NODE_SIZE, STACK_GAP } from "./tokens";
@@ -47,7 +48,11 @@ function autoStorageHeight(
47
48
  const 呼び名の分 = n.subtitle ? SUBTITLE_ROW_SHIFT : 0;
48
49
  // 小見出しを書かない形では字を上へ繰り上げるので、その分だけ箱も低くする (#589)
49
50
  const 繰り上げ = n.eyebrow ? 0 : 目印なしの繰り上げ("storage");
50
- if (!n.rows || n.rows.length === 0) return 115 + 呼び名の分 - 繰り上げ;
51
+ // 行を持たない箱は **下げる相手が居ない** ので、行の下げ幅ではなく字の塊が下に伸びる分を
52
+ // 足す (#974)。 46 を足していた間は上 17 に対し下 39 と、下だけ 22 空いていた
53
+ if (!n.rows || n.rows.length === 0) {
54
+ return 115 + (n.subtitle ? 呼び名で伸びる量 : 0) - 繰り上げ;
55
+ }
51
56
  const 必要 = requiredRowsHeight("storage", n.rows.length) ?? defaultH;
52
57
  // 行頭の印を持つ箱は **中身の足し算だけ** で高さを決める (#578)。 下限を残すと、行が
53
58
  // 1 つしか無い箱が 4 行の箱と同じ高さになり、下が空いたまま並ぶ。
@@ -658,6 +658,16 @@ export const STORAGE_TITLE_FONT = 34;
658
658
  */
659
659
  export const SUBTITLE_ROW_SHIFT = 46;
660
660
 
661
+ /**
662
+ * `kinds/storage.tsx` の呼び名 (subtitle) の baseline (#578)。
663
+ *
664
+ * 題 (86) と 1 行目 (130) の間に置く。 描き手が字を置く位置で、高さの計算もここを読む。
665
+ */
666
+ export const STORAGE_SUBTITLE_BASELINE = 118;
667
+
668
+ /** `kinds/storage.tsx` の呼び名の字の大きさ。 題 (34) より小さくして題を先に読ませる */
669
+ export const STORAGE_SUBTITLE_FONT = 20;
670
+
661
671
  /**
662
672
  * `storage` の名前と列の間に引く区切り線の Y。
663
673
  *
@@ -701,6 +711,22 @@ export const ROW_GLYPH_DEPTH_RATIO = 0.4;
701
711
  export const TITLE_ROW_MIN_GAP =
702
712
  GENERIC_TITLE_FONT * ROW_GLYPH_DEPTH_RATIO + ROW_FONT_GENERIC * GLYPH_CAP_RATIO;
703
713
 
714
+ /**
715
+ * 行を持たない `storage` に呼び名を書いた時、箱がどれだけ高くなるか (#974)。
716
+ *
717
+ * **`SUBTITLE_ROW_SHIFT` を流用しない**。 あちらは行の群を下げる幅で、下げる相手が
718
+ * 居ない箱に足すと下だけ空く (実測で上 17 に対し下 39、許容は 7)。
719
+ *
720
+ * 足すべきなのは **字の塊の下端が下がる分** になる。 下端は題の字形の底から呼び名の
721
+ * 字形の底へ移るので、baseline の差に字形の深さの差を足す。 呼び名の方が字が小さいぶん
722
+ * 深さは浅く、差は引き算になる。
723
+ */
724
+ export const 呼び名で伸びる量 = Math.round(
725
+ STORAGE_SUBTITLE_BASELINE -
726
+ STORAGE_TITLE_BASELINE +
727
+ (STORAGE_SUBTITLE_FONT - STORAGE_TITLE_FONT) * ROW_GLYPH_DEPTH_RATIO,
728
+ );
729
+
704
730
  /**
705
731
  * 最終行の baseline から下に、 字形が枠に触れないために要ると **見込む** 量。
706
732
  *
@@ -7,6 +7,7 @@ import { buildDiagramAltText, isRenderedNode } from "../layout/spec";
7
7
  import {
8
8
  EDGE_HEADS,
9
9
  EDGE_HEAD_FILLS,
10
+ EDGE_HEAD_MARKER_SIZE,
10
11
  EDGE_HEAD_FILL_DEFAULT,
11
12
  EDGE_REVEAL_DEFAULT,
12
13
  RELATION_FOCUS_DEFAULT,
@@ -238,8 +239,8 @@ export function CdlStage({
238
239
  return Object.entries(TONE).flatMap(([tone, color]) =>
239
240
  (
240
241
  [
241
- [false, 14],
242
- [true, 10],
242
+ [false, EDGE_HEAD_MARKER_SIZE.既定],
243
+ [true, EDGE_HEAD_MARKER_SIZE.小],
243
244
  ] as const
244
245
  ).flatMap(([small, size]) =>
245
246
  EDGE_HEADS.flatMap((head) =>
package/src/types.ts CHANGED
@@ -282,6 +282,17 @@ export const EDGE_HEAD_FILL_DEFAULT: EdgeHeadFill = "solid";
282
282
  /** 塗り方の全種。 marker の定義と検査の走査がこの並びを引く */
283
283
  export const EDGE_HEAD_FILLS: readonly EdgeHeadFill[] = ["solid", "hollow"];
284
284
 
285
+ /**
286
+ * 端の印の大きさ (world)。 `markerHeight` そのもので、形の枠の縦 10 に掛かる倍率ではない。
287
+ *
288
+ * `render/stage.tsx` が marker を定義する時と、`layout/head-label.ts` が端の字を印から
289
+ * 離す時の 2 箇所が引く。 片方に数を直に書くと、印を大きくした時に字だけが元の位置に残る
290
+ * (#984 では印の縦を見ずに字を置いており、菱の縁と字の間が 1 しか空いていなかった)。
291
+ *
292
+ * 縦は形によらず この値。 横だけが形の枠の縦横比で伸びる (`EDGE_HEAD_SHAPE.w / .h`)。
293
+ */
294
+ export const EDGE_HEAD_MARKER_SIZE = { 既定: 14, 小: 10 } as const;
295
+
285
296
  /** 矢印をいつ出すか (#582)。 `CdlDiagram.edgeReveal` が取る値と 1 対 1 */
286
297
  export type EdgeReveal = "phase" | "all";
287
298