@cardenelabs/cdl 0.49.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cardenelabs/cdl",
3
- "version": "0.49.0",
3
+ "version": "0.50.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",
@@ -1,3 +1,4 @@
1
+ import { 等幅の字 } from "../render/mono-text";
1
2
  import type { JSX } from "react";
2
3
  import type { LaidNode } from "../types";
3
4
  import { nodeAccent } from "./node-tone";
@@ -84,7 +85,7 @@ export function ActorNode({ node, active, value }: { node: LaidNode; active: boo
84
85
  fill="var(--cdl-text, #1a1f2a)"
85
86
  style={{ fontFamily: "'JetBrains Mono', monospace" }}
86
87
  >
87
- {value}
88
+ {等幅の字(value, 42)}
88
89
  </text>
89
90
  )}
90
91
  </g>
@@ -1,3 +1,4 @@
1
+ import { 等幅の字 } from "../render/mono-text";
1
2
  import type { JSX } from "react";
2
3
  import type { LaidNode } from "../types";
3
4
  import { nodeAccent } from "./node-tone";
@@ -63,7 +64,7 @@ export function EventNode({
63
64
  textAnchor={名前.anchor}
64
65
  style={{ fontFamily: "'JetBrains Mono', monospace" }}
65
66
  >
66
- {node.title}
67
+ {等幅の字(node.title, 名前.size)}
67
68
  </text>
68
69
  {node.subtitle && (
69
70
  <text
@@ -73,7 +74,7 @@ export function EventNode({
73
74
  fill="var(--cdl-text-dim, #5a6270)"
74
75
  style={{ fontFamily: "'JetBrains Mono', monospace" }}
75
76
  >
76
- {node.subtitle}
77
+ {等幅の字(node.subtitle, 21)}
77
78
  </text>
78
79
  )}
79
80
  </g>
@@ -1,3 +1,4 @@
1
+ import { 等幅の字 } from "../render/mono-text";
1
2
  import type { JSX } from "react";
2
3
  import type { LaidNode } from "../types";
3
4
  import { nodeAccent } from "./node-tone";
@@ -53,7 +54,7 @@ export function FunctionNode({ node, active }: { node: LaidNode; active: boolean
53
54
  textAnchor={名前.anchor}
54
55
  style={{ fontFamily: "'JetBrains Mono', monospace" }}
55
56
  >
56
- {node.title}
57
+ {等幅の字(node.title, 名前.size)}
57
58
  </text>
58
59
  {node.subtitle && (
59
60
  <text x={26} y={126 - ずらし} fontSize={20} fill="var(--cdl-text-dim, #5a6270)">
@@ -1,3 +1,4 @@
1
+ import { 等幅の字 } from "../render/mono-text";
1
2
  import type { JSX } from "react";
2
3
  import type { LaidNode, NodeKind } from "../types";
3
4
  import { toneColor } from "./node-tone";
@@ -423,11 +424,11 @@ export function GenericNode({
423
424
  </text>
424
425
  )}
425
426
  <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={textAnchor} dominantBaseline={dominantBaseline} style={node.kind === "function" || node.kind === "api" ? { fontFamily: "'JetBrains Mono', monospace" } : undefined}>
426
- {node.title}
427
+ {node.kind === "function" || node.kind === "api" ? 等幅の字(node.title, 20) : node.title}
427
428
  </text>
428
429
  {node.subtitle && (
429
430
  <text x={textX} y={subtitleY} fontSize={17} fill={paint.onSolid ? "var(--cdl-node-fill, #ffffff)" : "var(--cdl-text-dim, #5a6270)"} textAnchor={textAnchor} dominantBaseline={dominantBaseline} style={{ fontFamily: "'JetBrains Mono', monospace" }}>
430
- {node.subtitle}
431
+ {等幅の字(node.subtitle, 17)}
431
432
  </text>
432
433
  )}
433
434
  {resolvedValue && (
@@ -440,7 +441,7 @@ export function GenericNode({
440
441
  fill="var(--cdl-text, #1a1f2a)"
441
442
  style={{ fontFamily: "'JetBrains Mono', monospace" }}
442
443
  >
443
- {resolvedValue}
444
+ {等幅の字(resolvedValue, 32)}
444
445
  </text>
445
446
  )}
446
447
  {node.rows && node.rows.length > 0 && (() => {
@@ -473,7 +474,7 @@ export function GenericNode({
473
474
  fill="var(--cdl-text, #1a1f2a)"
474
475
  style={{ fontFamily: "'JetBrains Mono', monospace" }}
475
476
  >
476
- {s.right}
477
+ {等幅の字(s.right, 21)}
477
478
  </text>
478
479
  </g>
479
480
  ))}
@@ -1,3 +1,4 @@
1
+ import { 等幅の字 } from "../render/mono-text";
1
2
  import type { JSX } from "react";
2
3
  import type { LaidNode } from "../types";
3
4
  import { interpolate } from "../render/utils";
@@ -144,7 +145,7 @@ export function SequenceBoardNode({
144
145
  fill="var(--cdl-text, #1a1f2a)"
145
146
  style={{ fontFamily: "'JetBrains Mono', monospace" }}
146
147
  >
147
- {a.name}
148
+ {等幅の字(a.name, SEQ_NAME)}
148
149
  </text>
149
150
  {a.subtitle && (
150
151
  <text
@@ -1,3 +1,4 @@
1
+ import { 等幅の字 } from "../render/mono-text";
1
2
  import type { JSX } from "react";
2
3
  import type { LaidNode, RowMark } from "../types";
3
4
  import { nodeAccent } from "./node-tone";
@@ -233,7 +234,7 @@ export function StorageNode({
233
234
  textAnchor={名前.anchor}
234
235
  style={{ fontFamily: "'JetBrains Mono', monospace" }}
235
236
  >
236
- {node.title}
237
+ {等幅の字(node.title, 名前.size)}
237
238
  </text>
238
239
  {/*
239
240
  表の区切り線 2 本 (`#419`)。
@@ -323,7 +324,7 @@ export function StorageNode({
323
324
  fill="var(--cdl-text, #1a1f2a)"
324
325
  style={{ fontFamily: "'JetBrains Mono', monospace" }}
325
326
  >
326
- {s.left}
327
+ {等幅の字(s.left, 26)}
327
328
  </text>
328
329
  {/*
329
330
  型は **読み手が探すものではない**ので、右端で揃えて薄く引く。 名前の右に続けて
@@ -347,7 +348,7 @@ export function StorageNode({
347
348
  }
348
349
  style={{ fontFamily: "'JetBrains Mono', monospace" }}
349
350
  >
350
- {s.right}
351
+ {等幅の字(s.right, 印で分ける ? ROW_TYPE_FONT : 26)}
351
352
  </text>
352
353
  </g>
353
354
  );
@@ -1,3 +1,4 @@
1
+ import { 等幅の字 } from "./mono-text";
1
2
  import type { JSX } from "react";
2
3
  import { computeLabelBBoxWorld, hasRenderedLabel, LABEL_PILL_PAD_X } from "../layout/spec";
3
4
  import type { EdgeRole, LaidEdge, Tone } from "../types";
@@ -387,7 +388,7 @@ export function CdlEdgeLabelView({
387
388
  opacity={labelTextOpacity("sub")}
388
389
  style={{ fontFamily: fontFamilyAttr("sub") }}
389
390
  >
390
- {edge.sub}
391
+ {等幅の字(edge.sub, EDGE_LABEL_TEXT.sub.fontSize)}
391
392
  </text>
392
393
  )}
393
394
  </g>
@@ -0,0 +1,44 @@
1
+ /**
2
+ * 等幅の書体で描く文字の、 `[` と `]` の間にだけ隙間を足す (#817)。
3
+ *
4
+ * `JetBrains Mono` の `[` と `]` は横棒が字の枠いっぱいまで伸びている。 図を画面の幅に合わせて
5
+ * 縮めると (画面上 14px 前後)、 隣り合った 2 本の横棒がつながって `[]` が四角 1 つに見える
6
+ * (`string[]` が `string□` と読める)。 合字ではない = 合字を止めても見え方は変わらない。
7
+ *
8
+ * 隙間は `<tspan dx>` で足す。 文字は増やさないので `textContent` は元のまま (`string[]`) で、
9
+ * 文字を読む側 (検索 / 読み上げ / 写し取り) は変わらない。 `dx` は文字の塊を新しく始めないので、
10
+ * 右寄せ (`text-anchor: end`) も隙間を含めた全体に効く。
11
+ *
12
+ * `][` は横棒が外を向いていてつながらないので、 `[]` の組ごとに足せば足りる。
13
+ *
14
+ * **engine が等幅の書体で描く文字は全てここを通す**。 通していない箇所はソースの走査で落とす
15
+ * (`mono-bracket-gap.test.tsx`)。
16
+ */
17
+ import { createElement, type ReactNode } from "react";
18
+
19
+ /**
20
+ * 隙間の幅 (字の大きさに対する比)。
21
+ *
22
+ * 等倍で撮り比べて、 全ての字の間を 0.06 空けると 2 本の横棒が分かれて読めた。 図はそれより小さく
23
+ * 縮めて描かれることもあるので、 少し余裕を持たせる。 1 組あたり字幅の 1 割に満たず、 字の送り幅の
24
+ * 計算 (等幅を前提に文字数から桁の位置を決める) には入れない。
25
+ */
26
+ export const 角括弧の隙間 = 0.08;
27
+
28
+ /**
29
+ * 文字列の `[]` を `[` と、 前に隙間を持つ `]` に分けて返す。 `[]` を含まない文字と、 文字列でない
30
+ * 値 (数値 / 要素) はそのまま返す。
31
+ *
32
+ * @param text 描く文字
33
+ * @param fontSize その文字の大きさ (隙間はこれに比例する)
34
+ */
35
+ export function 等幅の字(text: ReactNode, fontSize: number): ReactNode {
36
+ if (typeof text !== "string" || !text.includes("[]")) return text;
37
+ const 塊 = text.split("[]");
38
+ const out: ReactNode[] = [];
39
+ 塊.forEach((s, i) => {
40
+ if (i > 0) out.push("[", createElement("tspan", { key: i, dx: fontSize * 角括弧の隙間 }, "]"));
41
+ if (s !== "") out.push(s);
42
+ });
43
+ return out;
44
+ }