@cardenelabs/cdl 0.6.1 → 0.9.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +401 -0
  2. package/SPEC.md +32 -17
  3. package/dist/index.cjs +820 -364
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +68 -14
  6. package/dist/index.d.ts +68 -14
  7. package/dist/index.js +820 -364
  8. package/dist/index.js.map +1 -1
  9. package/dist/react.cjs +692 -254
  10. package/dist/react.cjs.map +1 -1
  11. package/dist/react.d.cts +1 -1
  12. package/dist/react.d.ts +1 -1
  13. package/dist/react.js +692 -254
  14. package/dist/react.js.map +1 -1
  15. package/dist/{render-DquCvgOB.d.cts → render-hmFRAabt.d.cts} +33 -2
  16. package/dist/{render-DquCvgOB.d.ts → render-hmFRAabt.d.ts} +33 -2
  17. package/package.json +6 -3
  18. package/src/kinds/box-lines.ts +120 -0
  19. package/src/kinds/gantt.tsx +152 -24
  20. package/src/kinds/mind-map.tsx +77 -16
  21. package/src/kinds/quadrant.tsx +28 -2
  22. package/src/kinds/shape-blockchain.tsx +65 -12
  23. package/src/kinds/shape-region.tsx +152 -34
  24. package/src/kinds/tree.tsx +121 -24
  25. package/src/layout/collisions.ts +10 -2
  26. package/src/layout/footer-shape.ts +86 -24
  27. package/src/layout/lifeline.ts +80 -0
  28. package/src/layout/spec.ts +21 -2
  29. package/src/layout/text-width.ts +92 -4
  30. package/src/layout/viewbox.ts +0 -8
  31. package/src/layout.ts +8 -1
  32. package/src/presets.ts +120 -22
  33. package/src/render/header.tsx +3 -1
  34. package/src/render/nodes.tsx +6 -5
  35. package/src/render/payload-binding.ts +88 -3
  36. package/src/render/stage.tsx +17 -34
  37. package/src/render/template-fields.ts +212 -0
  38. package/src/render/utils.ts +32 -2
  39. package/src/render.tsx +2 -9
  40. package/src/types.ts +33 -2
  41. package/src/validate.ts +27 -9
  42. package/src/visual-validate.ts +34 -1
  43. package/src/layout/label-shift.ts +0 -28
package/CHANGELOG.md ADDED
@@ -0,0 +1,401 @@
1
+ # Changelog
2
+
3
+ CDL (Chainome Diagram Language) の主要変更履歴。
4
+ [Keep a Changelog](https://keepachangelog.com/ja/1.1.0/) format + [Semantic Versioning](https://semver.org/lang/ja/) 準拠。
5
+
6
+ ## [Unreleased]
7
+
8
+ 予定 ... feedback を反映した patch / minor。
9
+
10
+ ## [0.9.0] - 2026-08-20
11
+
12
+ `0.8.0` は tag を打った後 npm に公開されないまま 17 commit が載った。 同じ番号で公開すると
13
+ tag の中身と公開物が食い違うため、番号を進めて 1 回だけ公開する。 `0.8.0` は npm に存在
14
+ しない番号として残る。
15
+
16
+ ### Added
17
+
18
+ - **箱が狭くて描かれない文字を書き手に伝えるようにした** (#497)
19
+
20
+ 箱の幅に対して文字が長いと、描画側が黙って切り落とす。 書き手には図を見るまで伝わらない。
21
+ 検査の層で幅と文字数を突き合わせ、収まらない文字を知らせる。
22
+
23
+ - **工程表の横軸の範囲を書き手が宣言できるようにした** (#491)
24
+
25
+ 従来は帯の位置から自動で決めていたため、帯が 1 本しかない図では目盛りが 1 本に縮んだ。
26
+ `ganttAxisMax` を足し、有限の正の数だけを採る。 壊れた値では自動に落とす。
27
+
28
+ - **1 行で作る書き方の入口でも値を状態から取れるようにした** (#484)
29
+
30
+ 図表の中身の型は `{名前}` を受ける形で宣言されているのに、組み立ての入口は数と語しか
31
+ 受けなかった。 入口の型を中身に揃えた。
32
+
33
+ 併せて工程の帯の位置を整える処理を入れた。 始まりが負なら 0 に寄せ、終わりが始まりより
34
+ 手前なら始まりに揃える。 落とさず整えるのは、状態が動く途中で一瞬だけ逆転する形が
35
+ あるため (帯が消えるより潰れて見える方がよい)。
36
+
37
+ ### Fixed
38
+
39
+ - **字幅の見積りを実描画と突き合わせ、足りない分を直した** (#494)
40
+ - **小さい箱で絵に帯を譲り、補いの行を落とすようにした** (#493)
41
+ - **値の入れ物を継承なしに揃えた** (#490)
42
+
43
+ `{constructor}` のような名前が「値がある」 と読まれ、prototype の中身が図に出ていた。
44
+
45
+ - **下げた名札の座標を実際の描画に合わせた** (#489)
46
+ - **1 lane の名札の異常で図の全 lane から縦線が消えないようにした** (#488)
47
+ - **`{名前}` を読む欄と検査する欄を一致させた** (#487)
48
+
49
+ 読み手と書ける側で名前の字種の定義がずれると、定義はできるのにどの箱からも読めない
50
+ 名前ができる。 定義を 1 か所に集めた。
51
+
52
+ - **連鎖の箱が書き手の題と副題を読むようにした** (#486)
53
+ - **木と放射の箱に補足を描き、上の小ラベルを型から外した** (#485)
54
+ - **工程表の目盛りの裸の数字を消し、象限図の枠を名前の幅に合わせた** (#482)
55
+ - **下端の名札を位置でなく構造上の目印で判定するようにした** (#480)
56
+ - **変更履歴を公開物に入れ、版から commit を辿れるようにした** (#477)
57
+ - **実時間で測る検査を負荷に強くした** (#496)
58
+
59
+ ### Changed
60
+
61
+ - **`no-op` になっていた `label-shift.ts` を消した** (#498)
62
+ - **工程の帯の丸めを守る検査を足した** (#500)
63
+
64
+ 丸めは #484 で入っていたが、外して全 5286 件を回しても 0 件しか落ちなかった。
65
+ 幅の下限を `>= 0` から `> 0` に上げ、帯が消えた状態を「壊れていない」 と読まないようにした。
66
+
67
+ ## [0.8.0] - 2026-08-17
68
+
69
+ ### Added
70
+
71
+ - **`flow()` preset で矢印を宣言できるようにした** (#474)
72
+
73
+ `flow()` は矢印を `step()` の並び順から自動生成するだけで、呼び手が矢印を宣言する口が
74
+ 無かった。 そのため `a` から `c` へ直接繋ぎ `b` を経由しない図が作れなかった。
75
+
76
+ `FlowPreset.autoChain` (既定 `true`) と `FlowBuilder.edge()` を足した。
77
+
78
+ ```ts
79
+ flow({ id: "fl", topic: "T", autoChain: false })
80
+ .step({ id: "a", kind: "card", title: "A" })
81
+ .step({ id: "b", kind: "card", title: "B" })
82
+ .step({ id: "c", kind: "card", title: "C" })
83
+ .edge("a", "c", { label: "飛ばす" })
84
+ .build();
85
+ ```
86
+
87
+ `autoChain: false` にすると `step()` は node だけを置き、矢印は `edge()` で宣言する。
88
+ 枠 / 配置 / 段は preset のまま保たれる。
89
+
90
+ `edge()` は preset の既定の `tone` / `style` を引き継ぎ、第 3 引数で個別に上書きできる。
91
+ `edge()` で作った矢印も `build()` が作る段の点灯対象に載る (載せないと動きの中で光らず、
92
+ 自動生成分と見た目が揃わない)。
93
+
94
+ **`autoChain` の既定は `true` なので、既存の呼び出しは 1 行も変えずに同じ図になる**。
95
+ 既定を `false` に変える変異で既存の検査 4 件が落ちることを確認済。
96
+
97
+ ## [0.7.0] - 2026-08-17
98
+
99
+ ### Changed
100
+
101
+ - **木と放射の名前が状態を読むようになった** (#467)
102
+
103
+ `tree-hierarchy` と `mind-map` の名前 (木は `treeData[].title`、放射は `mindData.rootTitle` と
104
+ `branches[].title`) に `{名前}` を書くと、段ごとに解決するようになった。
105
+
106
+ この 2 種は「動かせる数を持たない」 という理由で解決層から外していた。 実際には
107
+ **この 2 種が持つのは数ではなく構造と名前** で、名前の側は動かせる。 利用側では
108
+ この 2 種だけが段を付けられず静止したまま残っていた。
109
+
110
+ **既存の図の見え方が変わる場合がある**。 木や放射の名前に `{...}` を含むテキストを
111
+ そのまま出していた図は、これまで書いた形のまま描かれていたが、今後は状態として解決を
112
+ 試みる。 解決できない場合は書いた形のまま残り、`data-cdl-unresolved` が付く。
113
+ 同じ性質の変更は図表 7 種で 0.6.0 に入っている。
114
+
115
+ 解決できない名前は **書いたまま残す**。 数の欄は既定値 (0 等) に落とせるが、名前は
116
+ 落とす先が無く、空にすると項目の存在まで図から消える。
117
+
118
+ 解決しない範囲が 2 つある。 親子の繋がり (`parent`) は状態で繋ぎ替えると木の形そのものが
119
+ 変わり、配置の計算と印の付け方が別問題になるため。 補足 (`subtitle`) はこの 2 種が
120
+ そもそも描いていないため = 解決だけ通すと、画面は何も変わらないのに解決できない時だけ
121
+ 印が付く状態になる (描く方を足すかは #471)。
122
+
123
+ ## [0.6.1] - 2026-08-16
124
+
125
+ ### Added
126
+
127
+ - **段ごとの実効値を出す 2 つを公開した** (#465)
128
+
129
+ `computeStateValues` (段と進みから状態の値を組み立てる) と `interpolate`
130
+ (`{名前}` を値で置き換える) を `index.ts` から輸出した。
131
+
132
+ 公開しない間、 利用者はこの 2 つに `src/render/utils` の相対 path で届くしかなかった。
133
+ `exports` は `.` と `./react` しか開いていないので package 経由では引けず、 隣に cdl を
134
+ checkout している前提の import になる。 実際 dragon の見本の検査がその形で、
135
+ **隣に cdl が無いと型検査も test も通らない**状態を作っていた (cardene777/dragon#1166)。
136
+
137
+ 自前で書き直す形も採れない。 `computeStateValues` は同じ段の中で `set` を順に当ててから
138
+ `tween` が上書きする順序を持ち、 組み直すと描画とずれる。 `interpolate` が受ける名前の
139
+ 字種は `template-name.ts` が 1 箇所で決めており、 別に書くと「読めるが書けない」 名前が
140
+ できる。
141
+
142
+ ## [0.6.0] - 2026-08-16
143
+
144
+ 図表が状態を読んで動くようになった版。 併せて動かせない種別 (放射状の図) を 1 つ落とした。
145
+
146
+ 0.5.0 からの破壊的変更は **放射状の図の削除 1 件だけ**。 見た目の主題 (`CdlTheme`) と
147
+ 検査軸 2 件の削除は 0.5.0 で既に出ており、 記録が漏れていたものを本版で `[0.5.0]` 節へ
148
+ 書き足した。
149
+
150
+ ### Added
151
+
152
+ - **図表 7 種の欄が `{signal}` を取れるようになった** (#451)
153
+
154
+ `chart-bar` / `chart-line` / `chart-pie` / `funnel-stages` / `gantt-timeline` の数の欄と、
155
+ `quadrant-matrix` / `journey-map` の語の欄で、 値の代わりに段の状態名を書けるようになった。
156
+ これまでは配列を受け取って一度描くだけで状態を読む経路が無く、 図表は永久に静止していた。
157
+
158
+ 解決は `render/payload-binding.ts` に集約し、 各 kind は描画の直前に 1 回呼ぶ。
159
+ 解決できない欄は **項目を落とさず** 既定値で描き、 `data-cdl-unresolved="true"` を付ける
160
+ (落とすと配列の長さが変わって図の形が別物になり、 どこが壊れたか読み取れなくなる)。
161
+
162
+ 数を直接書いた図の描画は変わらない。 解決層が配列を組み直さないため、 描くものも
163
+ 配列の同一性もそのまま。
164
+
165
+ `mind-map` / `tree-hierarchy` は動かせる数を持たないため配線していない。
166
+
167
+ - **他の値から決まる値を毎 frame 解く `derived` を足した** (#453)
168
+
169
+ `CdlDiagram` に `derived` を持たせ、 段の値を出した後に参照順で解いて `stateValues` に
170
+ 載せる。 毎 frame ここを通るので、 掛け算 / 割り算 / 比較 / `min` / `max` のような
171
+ 端点 2 点では表せない関係も、 段の補間の途中で正しい値になる。
172
+
173
+ 式は既存の `formula/` を使う。 波括弧で囲んだ名前 (`{waiting}`) は図の他の場所と同じ
174
+ 書き方で参照できる。 許可済の `Math` 関数は接頭辞なしでも書ける (`min(a, b)`)。
175
+
176
+ **名前に使えるのは英数字と `_` だけ** (`template-name.ts` の `TEMPLATE_NAME_CHARS` が
177
+ `\w+`)。 日本語の名前は `derived` の `id` に置くと `invalid-id` の通知が返り、
178
+ `{待ち}` のように参照しても `parse-error` になる。
179
+
180
+ 併せて 6 つを輸出した。 値を解く `applyDerivedValues` と、 段の値に重ねる
181
+ `withDerivedValues`、 型の `CdlDerivedValue` / `DerivedResult` / `DerivedNotice` /
182
+ `DerivedNoticeKind`。
183
+
184
+ **組み立て器からは宣言できない**。 `formulas` には `.formula(id, expression)` があるが、
185
+ `derived` に対応する method はまだ無く、 `CdlDiagram` を直接組む経路でしか渡せない。
186
+
187
+ ### Removed (破壊的変更)
188
+
189
+ - **放射状の図 (`mindMapRadial` / `mind-radial`) を削除した** (#460)
190
+
191
+ 中心から 45 度間隔で 8 方向へ枝を配る図で、 数を持たず構造だけを持つため段の値
192
+ (`{signal}`) を解けない「動かせない種別」 だった。 engine を「状態を読んで動く図」 に
193
+ 寄せる方針 (#451 / #453) の下で、 動かせないまま保守を続ける根拠が無くなった。
194
+
195
+ | 消えたもの | 代わりに使うもの |
196
+ |---|---|
197
+ | `mindMapRadial()` builder (`index.ts` から輸出) | `mindMap()`。 **同じ絵にはならない** (下記) |
198
+ | `MindMapRadialPreset` / `MindMapRadialBuilder` / `MindMapRadialBranch` 型 | `MindMapPreset` / `MindMapBuilder` / `MindBranch` |
199
+ | `NODE_KINDS` の `"mind-radial"` | `"mind-map"` |
200
+ | `CdlRole` の `"mind-radial-halo"` | 無し。 当てていた CSS は削除する |
201
+
202
+ **絵の形は変わる**。 `mind-radial` は第 1 階層を 45 度間隔の 8 方向へ放射状に置いたが、
203
+ `mind-map` は第 1 階層を左右 2 列に振り分けて縦に並べる (`computeMindMapLayout`)。
204
+ 8 方向の放射状という見た目自体に代わりは無い。
205
+
206
+ **書き換えは名前の置換では済まない**。 2 つの組み立て器は引数の形が違う。
207
+
208
+ | | `mindMapRadial` (0.5.0) | `mindMap` (0.6.0) |
209
+ |---|---|---|
210
+ | 中心の指定 | `centerTitle` (id は `centerId`、 既定 `"center"`) | `rootId` と `rootTitle` の 2 つが必須 |
211
+ | 距離の指定 | `radius` (既定 350) | 無し (canvas から導く) |
212
+ | 枝の親 | 省略可 (中心に繋がる) | `parent` が必須 |
213
+
214
+ したがって呼出は次のように書き換える。
215
+
216
+ ```ts
217
+ // 0.5.0
218
+ mindMapRadial({ id: "mr", topic: "...", centerTitle: "Product" })
219
+ .branch({ id: "users", title: "Users" })
220
+
221
+ // 0.6.0
222
+ mindMap({ id: "mr", topic: "...", rootId: "root", rootTitle: "Product" })
223
+ .branch({ id: "users", title: "Users", parent: "root" })
224
+ ```
225
+
226
+ 名前だけ置換すると型検査で落ちる (`'centerTitle' does not exist in type 'MindMapPreset'`
227
+ と `Property 'parent' is missing`)。 落ちるので黙って壊れることは無いが、 全ての呼出と
228
+ 全ての `.branch()` に手を入れる必要がある。
229
+
230
+ 枝の数の上限も外れる。 `mindMapRadial().branch()` は 9 本目で投げ、 描画も第 1 階層を
231
+ 8 本で切っていた。 `mindMap()` に上限は無く、 配置は再帰で降りる。 深さ数千段の payload を
232
+ 機械で作って渡すと `RangeError: Maximum call stack size exceeded` になる (実測 = 深さ
233
+ 1000 は 2.5ms で通り、 5000 で投げる)。 人が書く図では届かない深さだが、 生成した payload を
234
+ 流し込む場合は深さを見ておく。
235
+
236
+ `[data-cdl-role="mind-radial-halo"]` および `[data-cdl-role="mind-radial-edge"]` に
237
+ 当てていた CSS は、 一致する要素が無くなるため削除する。
238
+
239
+
240
+ ## [0.5.0] - 2026-06-28
241
+
242
+ 本節の `Removed (破壊的変更)` と `Changed` の後半 3 項目は **公開後に書き足した**。
243
+ 0.5.0 を公開した時点で CHANGELOG に記録し漏らしており、 0.6.0 を切る時に公開済の中身と
244
+ 突き合わせて気付いた (`npm pack @cardenelabs/cdl@0.5.0` を展開して確認)。 一度 0.6.0 の
245
+ 変更として書いたが、 実際には 0.5.0 で既に出ていたため本節へ移した。
246
+
247
+ ### Added
248
+
249
+ Initial OSS release.
250
+
251
+ - **12 preset** ... sequence / flow / swimlane / er / state / topology / solidity / gantt / class / pie / c4 / mind
252
+ - **29 NodeKind** ... actor / function / storage / event / service / database / cache / queue / wallet / validator / 他
253
+ - **8 EdgeStyle** ... solid / dotted / dashed / dotted-flow / 他
254
+ - **6 Tone** ... accent / teal / success / error / warning / info
255
+ - **phase / state / tween / set / badge** ... 時系列 animation を宣言的に
256
+ - **Text DSL v0.5** ... mermaid 感覚の 5 ブロック箇条書き DSL (parser + compiler、 JA / EN i18n)
257
+ - **Visual Editor** (`apps/playground`) ... GUI 編集 + live preview + SVG export
258
+ - **Catalog** ... 12 preset × animation の visual 一覧
259
+ - **Docs site** ... 全 16 概念 × JA / EN、 humans tab + LLM tab、 Diátaxis 準拠
260
+ - **Pagefind 全文検索** ... Cmd+K で全 docs 高速 lookup
261
+ - **React + Astro 両対応** ... static / SSR / hybrid どこでも動く
262
+ - **CdlDiagramThumbnail** ... thumbnail + viewport いっぱいのモーダル拡大
263
+ - **CdlDiagramView** ... phase autoplay / focusPhaseId / hideHeader / debug props
264
+ - **Performance optimization** ... spatial hash 採用、 1000 node でも 60ms 以下の layout
265
+ - **TypeScript strict 全面 ON** + zod runtime validation
266
+ - **OSS 公開準備** ... README / CONTRIBUTING / SECURITY / ISSUE_TEMPLATE / PR_TEMPLATE 整備
267
+ - **380 件のテスト** ... unit + integration + visual screenshot diff + e2e
268
+
269
+ ### Changed
270
+
271
+ - chainome monorepo から独立 OSS lib として分離 (旧 `chainome/packages/cdl` + `chainome/packages/anim` + `chainome/apps/web` の cdl 関連を移植)
272
+ - repo URL を `git@github.com:cardene777/cdl.git` に変更
273
+ - playground (旧 `apps/web`) を `apps/playground` に rename
274
+
275
+ - **`stateMachine` / `stateMachine2` の `stateWidth` が状態の箱の幅を指すようになった** (#357)
276
+
277
+ これまでは帯の幅にしか渡っておらず、 engine が帯を「箱の幅 320 + 余白 25 × 2 = 370」 まで広げ直すため、 **370 未満の指定は全て無視されていた** (260 / 300 / 340 のどれを指定しても図が 1 world も変わらない状態)。 option の名前が指すとおり箱の幅として扱うようにした。
278
+
279
+ 既定値は 360 → 320 (`kind: "card"` の既定幅) に変えている。 これにより **`stateWidth` を指定しない図の座標は従来と完全に一致する** (帯は 320 + 50 = 370 を宣言し、 engine の再拡張も 370 で一致するため)。
280
+
281
+ **320 以外を明示していた図は全て変わる**。 値の範囲で内訳が違う。
282
+
283
+ | 明示値 | 従来 | 今後 |
284
+ |---|---|---|
285
+ | 320 | 無視 (帯 370 / 箱 320) | 同じ (帯 370 / 箱 320) |
286
+ | 80-319 | 無視 (帯 370 / 箱 320) | 効く (箱が指定値まで狭まり図が縮む) |
287
+ | 321-370 | 無視 (帯 370 / 箱 320) | 効く (箱が指定値まで広がり図が伸びる) |
288
+ | 371 以上 | 帯の幅として効く (箱は 320 のまま) | 箱の幅として効く (帯は指定値 + 50) |
289
+
290
+ 370 以下は元から効いていなかったので、 今回初めて指定が反映される (option が名前どおりに働くようになった側)。 従来と同じ見た目に戻すなら `stateWidth: 320` を明示する。
291
+
292
+ 371 以上を指定していた図は意味が変わる。 従来の「箱 320 を広い帯に置く」 形は preset では表現できなくなるため、 その見た目が要る場合は低位 API (`diagram().lane().node()`) で帯と箱を個別に宣言する。 3 状態の実測 = `stateWidth: 400` で `viewBox.w` 1440 → 1605。
293
+
294
+ 併せて、 80 未満と有限でない値は例外を投げるようにした。 箱の幅として使う以上、 描画が壊れる値を黙って受け取らない。
295
+
296
+ - **`er` の `entityWidth` と `classDiagram` の `classWidth` が箱の幅を指すようになった** (#359)
297
+
298
+ #357 と同じ構造が 2 つ残っていた。 どちらも帯の幅にしか渡っておらず、 engine が帯を「箱の幅 400 + 余白 25 × 2 = 450」 まで広げ直すため、 **450 以下の指定は全て無視されていた** (200 / 300 / 450 のどれを指定しても図が 1 world も変わらない状態)。
299
+
300
+ 既定値はどちらも `kind: "storage"` の既定幅 (400) から導く。 帯は `400 + 50 = 450` を宣言する。
301
+
302
+ | preset | 従来の帯 | 今後の帯 | 既定の図 |
303
+ |---|---|---|---|
304
+ | `classDiagram` | 420 宣言 → engine が 450 に拡張 | 450 宣言 | 変わらない |
305
+ | `er` | 460 宣言 (engine の 450 を上回るのでそのまま) | 450 宣言 | **10 world 狭くなる** |
306
+
307
+ `er` だけ既定の見た目が変わる。 従来の 460 は `storage` の既定幅とも他の preset とも揃っていない値で、 doc には 360 と書かれていて実装 (460) とも食い違っていた。 箱は 400 のままなので、 変わるのは帯の左右の余白が 30 → 25 になる分だけ (他の preset は全て 25)。 従来と同じ幅に戻すなら `entityWidth: 410` を明示する。
308
+
309
+ 450 以下を明示していた図は全て変わる (今回初めて指定が反映される側)。 451 以上を指定していた図は意味が変わり、 従来の「箱 400 を広い帯に置く」 形は preset では表現できなくなる。 その見た目が要る場合は低位 API (`diagram().lane().node()`) で帯と箱を個別に宣言する。
310
+
311
+ 併せて、 80 未満と有限でない値は例外を投げるようにした。
312
+
313
+ ### Removed (破壊的変更)
314
+
315
+ - **見た目の主題 (`CdlTheme`) を型ごと削除した** (#426)
316
+
317
+ 主題は SVG の根に `data-cdl-theme` を出すだけの素通しの札で、 描画の判断には使っていなかった。
318
+ 唯一の利用者が主題という概念を廃止したため、 型と欄と属性の出力をまとめて外した。
319
+
320
+ | 消えたもの | 代わりに使うもの |
321
+ |---|---|
322
+ | `CdlTheme` 型 (`index.ts` / `builder.ts` から輸出) | 無し。 見た目は consumer 側の CSS が決める |
323
+ | `diagram(id, { theme })` の `theme` 欄 | 無し。 渡していた場合は削除する |
324
+ | `CdlDiagram.theme` / `LaidDiagram.theme` | 無し |
325
+ | SVG の根の `data-cdl-theme` 属性 | `[data-cdl-role="<role>"]` selector で見た目を当てる |
326
+
327
+ `[data-cdl-theme="x"] [data-cdl-role="y"]` の形で CSS を書いていた場合は、
328
+ 前半を外して `[data-cdl-role="y"]` にする。 明暗の切替は consumer 側の仕組み
329
+ (`html` の class 等) で行う。
330
+
331
+ - **`VisualAxis` から 2 軸を削除した** (#426)
332
+
333
+ | 消えた軸 | 理由 |
334
+ |---|---|
335
+ | `svg-filter-integrity` | 前提にしていた filter (`cdl-nm-raised-soft`) が既に存在せず、 何も検査していなかった |
336
+ | `neumorphism-shadow-budget` | 主題固有の影 (6 world) を前提とする軸で、 主題の廃止で根拠が消えた。 隣接の間隔は `node-vertical-clearance` (40 world) と near-collision (70 world) が引き続き見る |
337
+
338
+ 軸名を集計 / 比較している consumer は、 この 2 つを一覧から外す。
339
+
340
+ ## [0.4.0] - 2026-06-27
341
+
342
+ ### Added
343
+
344
+ - **Text DSL v0.4** ... 残 5 preset (flow / swimlane / er / state / topology) animation 拡張
345
+ - catalog の Text DSL demo page (`/catalog/text-dsl`) ... 6 preset × animation の visual 確認
346
+ - 全 docs code block への preview 強制 (48 件、 lint script による品質保証)
347
+ - integration test 21 件追加 (Permit / Topology / edge case / regression / 6 preset × animation)
348
+
349
+ ## [0.3.0] - 2026-06-27
350
+
351
+ ### Added
352
+
353
+ - **Text DSL v0.3** ... sequence preset で `アニメーション:` ブロック full compile
354
+ - DSL の `状態` / `ステップ` / `強調` / `遷移` / `切替` / `バッジ` / `説明` を実 phase / state / tween / set / activate / badge / body に注入
355
+ - highlight 解決 ... actor 名 → `header` + `footer` + `step box` を active 化、 `A→B` 矢印 → edge id を active 化
356
+ - アーキテクチャ ... animation あり時 builder 直接経路、 なし時 preset 経由 (v0.2 互換)
357
+ - test 6 件 (v0.3 機能)
358
+
359
+ ## [0.2.0] - 2026-06-27
360
+
361
+ ### Added
362
+
363
+ - **Text DSL v0.2** ... 6 preset 全対応 (sequence + flow + swimlane + er + state + topology)
364
+ - cardinality 自動解析 (1:1 / 1:N / N:M / 0..1 / 1..*)
365
+ - ER preset で entity 自動生成 + relation 自動 cardinality
366
+ - state preset で最初 actor = initial、 最後 = final 自動付与
367
+ - topology preset で 1 group 内 container 配置
368
+ - test 8 件 (5 preset 動作確認)
369
+
370
+ ## [0.1.0] - 2026-06-27
371
+
372
+ ### Added
373
+
374
+ - **Text DSL v0.1** ... 「タイトル / 種類 / 登場人物 / 流れ / アニメーション」 の 5 ブロック箇条書き DSL
375
+ - parser + compiler (sequence preset only) ... 行ベース parser + AST + LaidDiagram 変換
376
+ - 日本語 + 英語両対応 (キーワード i18n)
377
+ - 矢印正規化 (→ / -> / => / >>)
378
+ - duration 解析 (1.5 秒 / 1500ms / 2s)
379
+ - エラー親切 (行番号 + hint + 修正提案)
380
+ - LLM 生成ガイド + 5 few-shot 例
381
+ - ChatGPT/Claude/Cursor 即用 system prompt
382
+ - preview 強制 lint script (`pnpm lint:docs-preview`)
383
+ - text-dsl-spec.md + text-dsl-llm-guide.md (docs site 統合)
384
+ - test 11 件 (parse + compile + アニメーション parse)
385
+
386
+ ## 版と commit の対応
387
+
388
+ 各版の見出しから、 その版を公開した commit までの差分を辿れる。 `0.4.0` 以前はこの repo を
389
+ 切り出す前 (旧 monorepo) の版で、 対応する commit がこの repo に無いため link を持たない。
390
+
391
+ 最古の `0.5.0` だけ `/tree/` を指す (それ以前と比べる相手が無いため)。 `/releases/tag/` は
392
+ 使わない = annotated tag を push しても GitHub Release は作られず、 Release を作っていない版で
393
+ 行き止まりになる。
394
+
395
+ [Unreleased]: https://github.com/cardene777/cdl/compare/v0.9.0...HEAD
396
+ [0.9.0]: https://github.com/cardene777/cdl/compare/v0.8.0...v0.9.0
397
+ [0.8.0]: https://github.com/cardene777/cdl/compare/v0.7.0...v0.8.0
398
+ [0.7.0]: https://github.com/cardene777/cdl/compare/v0.6.1...v0.7.0
399
+ [0.6.1]: https://github.com/cardene777/cdl/compare/v0.6.0...v0.6.1
400
+ [0.6.0]: https://github.com/cardene777/cdl/compare/v0.5.0...v0.6.0
401
+ [0.5.0]: https://github.com/cardene777/cdl/tree/v0.5.0
package/SPEC.md CHANGED
@@ -144,9 +144,12 @@ phase が定義されると自動的に。
144
144
  6. **edge label** は path 中点から「path 進行方向の垂直方向」 に 50-80px 離して配置、 lane / node bbox との overlap を計算で避ける
145
145
  7. **viewBox** は cdl が auto 計算 (全 lane の右端 + 余白 80px、 全 node の下端 + 余白 80px)
146
146
 
147
- ## Routing v8 (fan-in / fan-out / label auto shift SSOT)
147
+ ## Routing v8-v10.1 (historical)
148
148
 
149
- 著者は座標 / offset / path 迂回を書かない。 以下 5 保証は全て engine が担う (`packages/cdl/src/layout/edges.ts` + `label-shift.ts` + `collisions.ts` 集約)。
149
+ CAR-430 より前の routing v8-v10.1 では、 著者が座標 / offset / path 迂回を書かず、
150
+ `packages/cdl/src/layout/edges.ts` + 旧 `label-shift.ts` + `collisions.ts` が以下の配置を担っていた。
151
+ 本節は係数と不具合の変遷を残す履歴資料であり、 **現行 pipeline の SSOT ではない**。
152
+ 現行の権限フローは後節の「Chain 伝搬 shift + spec 固定化 SSOT」を参照する。
150
153
 
151
154
  1. **fan-in 分散** ... 同 to node に集約する複数 edge を to 側 sidepoint offset で分散、 path 重複 0
152
155
  2. **fan-out 分散** ... 同 from node からの複数 edge を to の cy 順で offset 分散、 交差 0
@@ -171,15 +174,16 @@ border case sweep test (`dragon apps/playground/tests/visual/overlap-detector.sp
171
174
  10. **detour gap 拡張 (44 → 94、 +50)** ... label-shift v10 が detour path から NORMAL 100 world 上に label を置く挙動と組み合わせると、 obstacle.bottom + clearance 32 world では label bottom が obstacle と 24 world 割り込む (pattern-rollback e3 の label × commit 20 px² overlap の root cause、 cdl PR #58)。 gap +50 で label 位置が obstacle bottom から 66 world (DOM ~16 px) 離れる。
172
175
  11. **fan-in slot 別 detour Y 分散** ... 同 to node の複数 detour edge (pattern-rollback の e3 + e5 が両方 → db) が同 y 帯集約して label × label collision する問題を解消。 `slotFromCenter = Math.round(offset / fanGap)` で slot index を復元、 slot 0 起点で obstacle 側から離れる方向にのみ 0..fanGap の絶対値 shift。 上迂回 case は逆方向 (上方) にのみ shift、 detour Y 符号に合わせて分散方向を決定 (`edges.ts` `isDownDetour ? +detourYAdjustAbs : -detourYAdjustAbs` SSOT)。
173
176
 
174
- ### routing SSOT 前提 (壊れると再検証必要)
177
+ ### routing 実測の前提
175
178
 
176
- 以下の 3 前提を維持する限り上記 11 保証が有効:
179
+ 上記の旧 routing v8-v10.1 を評価した時点では、 以下の 3 前提を実測に使った。
177
180
 
178
181
  - **dragon CdlDiagramThumbnail の display 幅** ... 490 px 相当 (SVG viewBox 1820 world unit と scale 0.269 で対応)
179
182
  - **diagram viewBox 幅** ... 1500-2000 world unit 相当 (author lane 定数 SSOT の慣例値)
180
183
  - **font family** ... Inter / Newsreader (measureTextWidth の pt 想定と一致)
181
184
 
182
- これらが変更されたら `WORLD_SCALE = 4.0` (v8 の 3 番) と `TARGET_DIST = 100` (v10 の 9 番) の実測 SSOT を再測定して係数を再チューニングする (`edges.ts` v8 SSOT comment + `label-shift.ts` v10 SSOT comment 参照)。
185
+ これらが変更されたら、 現行値は `packages/cdl/src/layout/edges.ts` +
186
+ `packages/cdl/src/layout/spec.ts` + `packages/cdl/src/layout/clearance-constants.ts` を起点に再測定する。
183
187
 
184
188
  ## Chain 伝搬 shift + spec 固定化 SSOT (CAR-418 系)
185
189
 
@@ -194,32 +198,43 @@ layout constants は 2 種類の SSOT で管理する、 いずれも `packages/
194
198
  | **positive spec** | engine が満たすべき正しい配置目標値 | `visualValidateLaid` axes / dragon pixel-perfect gate | `SPEC_CLEARANCE_POLICY` |
195
199
  | **near-collision** | 「これ以下は誤読」 の下限 | `detectNearCollisions` (`collisions.ts`) | `NEAR_COLLISION_POLICY` |
196
200
 
197
- primitive 定数 (`CLEARANCE_NODE_LABEL` / `CLEARANCE_LANE_LABEL` / `CLEARANCE_LABEL_LABEL` / `CLEARANCE_PATH_LABEL` / `TARGET_LABEL_PATH_DIST` 等) は `packages/cdl/src/layout/clearance-constants.ts` に置き、 spec.ts / collisions.ts / label-shift.ts / edges.ts の全 downstream が import で参照する。 CAR-424 `edges.ts` / `label-shift.ts` の module-local 定数を全削除、 `clearance-constants.ts` を 1 箇所 SSOT に集約した。
201
+ primitive 定数 (`CLEARANCE_NODE_LABEL` / `CLEARANCE_LANE_LABEL` / `CLEARANCE_LABEL_LABEL` / `CLEARANCE_PATH_LABEL` / `TARGET_LABEL_PATH_DIST` 等) は `packages/cdl/src/layout/clearance-constants.ts` に置き、 spec.ts / collisions.ts / edges.ts の全 downstream が import で参照する。 CAR-424 で旧 `edges.ts` / `label-shift.ts` の module-local 定数を全削除、 `clearance-constants.ts` を 1 箇所 SSOT に集約した。
198
202
 
199
203
  ### 現行 pipeline と CAR-418 移行状態
200
204
 
201
- 現在 (2026-07-04) の `layout()` pipeline (`packages/cdl/src/layout.ts`) は以下 6 phase を走る。
205
+ 現在 (2026-08-19) の `layout()` pipeline (`packages/cdl/src/layout.ts`) は以下 7 phase を走る。
202
206
 
203
- 1. `layoutLanes` → `layoutNodes` → `expandLanesForNodes` (lane / node 静的配置)
204
- 2. `layoutEdges` (edge routing fan-in / fan-out offset 分散 + orthogonal routing + 水平大回り detour + midX/midY retreat)
207
+ 1. `layoutLanes` → `layoutNodes` → `expandLanesForNodes` → `expandLaneGapsForEdgeLabels` (lane / node 静的配置 + label 収納 gap 確保)
208
+ 2. `layoutEdges` (edge routing + 初期 label 位置を決定)
205
209
  3. `detectCollisions` → `resolveOverlaps` (node-node 後勝ち一発 shift)
206
- 4. `layoutEdges` (moved node で edge 再 route)
207
- 5. `shiftLabelsAwayFromNodes` (label auto shift 16 方向 × 26 段階 + 中央 anchor Tier)
208
- 6. `computeViewBox` (viewport 決定)
210
+ 4. node が動いた場合の `layoutEdges` 再 route
211
+ 5. `resolveEdgeLabelOverlapsWithChainAndPropagate` (edge label を起点に label / node / edge-path の chain 伝搬 shift を算出・反映。 lane-label obstacle として扱うが、 返却された lane-label shift は現行 `layout()` では未適用)
212
+ 6. `bowSharedStraightPaths` → `repositionParallelLabels` (共有直線 path を確定後、 parallel label の `labelY` を最終配置)
213
+ 7. `detectCollisions` / `detectNearCollisions` → `computeViewBox` (最終検証 + viewport 決定)
209
214
 
210
- CAR-421 `resolveOverlapsWithChain(nodes, minClearance, maxIter)` を新設し、 node-node overlap の chain 伝搬 shift を実装した (`packages/cdl/src/layout/collisions.ts`)。 単体 API として export 済、 実 pipeline `layout()` は現状 `resolveOverlaps` のまま (sequence preset の lifeline 等の既存 snapshot 保持のため opt-in で呼ぶ設計、 全 preset での有効化は将来 Issue で段階展開)。
215
+ label 位置は段階的に確定する。 `edges.ts routePath()` が初期位置を返し、 `layoutEdges`
216
+ author 指定 offset / margin と parallel / fan-in / fan-out label 分散を加えて暫定位置を決める。
217
+ 次に `resolveEdgeLabelOverlapsWithChainAndPropagate` が overlap / near-collision 発生時のみ
218
+ chain 伝搬で動かす。 node が chain shift された場合は `layoutEdges` を再実行して endpoint を追従させ、
219
+ 最後に `repositionParallelLabels` が共有 node pair の label を兄弟 path に合わせて置き直す。
220
+ 旧 `label-shift.ts` の 16 方向 × 26 段階探索は CAR-430 で削除済みで、 現行 pipeline には含まれない。
211
221
 
212
- edge 路線分散 (fan-in / fan-out offset) と label auto shift (16 方向 × 26 段階) は現在も稼働している。 これらを chain 伝搬に一本化する構想は CAR-418 で提示済だが、 label / edge の chain 伝搬 shift 実装は node-node の resolveOverlapsWithChain より複雑 (obstacle chain が edge path / label bbox / fan slot の 3 軸で干渉する) 段階的 PR で扱う (段階展開 SSOT は CAR-418 親 Issue)。
222
+ CAR-421 で新設した `resolveOverlapsWithChain(nodes, minClearance, maxIter)` は単体 API として残る。
223
+ 実 pipeline の node-node 解消は、 既存 snapshot との互換性のため引き続き `resolveOverlaps` が担う。
213
224
 
214
- ### CAR-424 の完了範囲 (二層 SSOT 集約 + SPEC 明文化)
225
+ ### CAR-424 の完了範囲 (履歴)
215
226
 
216
- CAR-424 は「PR 3 = 旧場当たり logic 除去 + SPEC.md 更新」 の scope だが、 現行 routing v8 / v10 系は border case sweep test (dragon overlap-detector) + 15+ preset の snapshot で品質保証されている。 場当たり logic の一括削除は「chain 伝搬 shift を label / edge にも展開」 が完了してからでないと preset 品質を落とすため、 本 PR では以下 3 点に scope を限定する。
227
+ CAR-424 時点では、 routing v8 / v10 系の一括削除を避け、 以下 3 点に scope を限定した。
228
+ 後続の CAR-429 / CAR-430 で edge path の sidepoint 分散と旧 label 探索の段階削除が完了しているため、
229
+ 以下は現行状態ではなく当時の完了範囲を示す。
217
230
 
218
231
  - **module-local 重複定数の集約** ... `edges.ts` `CLEARANCE_NODE_LABEL = 32` と `label-shift.ts` の 4 clearance 定数を `clearance-constants.ts` import に置換 (dedup)
219
232
  - **`CLEARANCE_POLICY` の SSOT 集約** ... `collisions.ts` module-local `CLEARANCE_POLICY` dict を `spec.ts` `NEAR_COLLISION_POLICY` に移管、 `collisions.ts requiredClearance` は `requiredNearClearance` に委譲する薄い adapter に縮小
220
233
  - **本 SPEC.md 「Chain 伝搬 shift + spec 固定化 SSOT」 セクション追加** ... 二層 SSOT (positive spec / near-collision) 分離、 現行 pipeline の CAR-418 移行状態、 CAR-424 完了範囲を明文化
221
234
 
222
- `edges.ts` fan-in / fan-out offset 分散 の削除 + `label-shift.ts` shift 探索 削除 は「chain 伝搬 shift を label / edge にも展開」 が別 Issue で完了してから段階削除、 現行の場当たり logic SSOT comment (`edges.ts` v8 SSOT + `label-shift.ts` v10 SSOT) は据え置き。
235
+ 当時は `edges.ts` fan-in / fan-out pathsidepoint offset 分散削除 + `label-shift.ts` shift 探索削除を
236
+ 後続 Issue に送った。 これらは CAR-429 / CAR-430 で完了済み。 label 自体の parallel / fan-in /
237
+ fan-out 分散は `layoutEdges` 内の暫定位置決定として現行でも稼働する。
223
238
 
224
239
  ### 参照
225
240