@cardenelabs/cdl 0.5.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/LICENSE +21 -0
- package/README.md +343 -0
- package/SPEC.md +374 -0
- package/dist/index.cjs +28085 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3415 -0
- package/dist/index.d.ts +3415 -0
- package/dist/index.js +27962 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +23043 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +2 -0
- package/dist/react.d.ts +2 -0
- package/dist/react.js +23041 -0
- package/dist/react.js.map +1 -0
- package/dist/render-C78lIXeC.d.cts +2449 -0
- package/dist/render-C78lIXeC.d.ts +2449 -0
- package/examples/quick-start.md +88 -0
- package/package.json +79 -0
- package/src/anim/core/easing.ts +77 -0
- package/src/anim/core/timeline.ts +335 -0
- package/src/anim/core/types.ts +42 -0
- package/src/anim/index.ts +20 -0
- package/src/anim/react/index.ts +3 -0
- package/src/anim/react/useReducedMotion.ts +27 -0
- package/src/anim/react/useTimeline.ts +48 -0
- package/src/assert-never.ts +16 -0
- package/src/author-intent-verify.ts +587 -0
- package/src/builder.ts +3740 -0
- package/src/compile.ts +12 -0
- package/src/dom-verify-core.ts +121 -0
- package/src/dom-verify-types.ts +21 -0
- package/src/dom-verify.ts +948 -0
- package/src/event-handler/index.ts +184 -0
- package/src/formula/ast.ts +46 -0
- package/src/formula/evaluator.ts +163 -0
- package/src/formula/formula-computeds.ts +83 -0
- package/src/formula/index.ts +5 -0
- package/src/formula/parser.ts +399 -0
- package/src/index.ts +284 -0
- package/src/input-signals.ts +74 -0
- package/src/kinds/actor.tsx +79 -0
- package/src/kinds/card.tsx +61 -0
- package/src/kinds/chart-bar.tsx +121 -0
- package/src/kinds/chart-line.tsx +163 -0
- package/src/kinds/chart-pie.tsx +107 -0
- package/src/kinds/compact-title.ts +164 -0
- package/src/kinds/dyn-shape.tsx +394 -0
- package/src/kinds/event.tsx +70 -0
- package/src/kinds/function.tsx +53 -0
- package/src/kinds/funnel.tsx +122 -0
- package/src/kinds/gantt.tsx +193 -0
- package/src/kinds/generic.tsx +368 -0
- package/src/kinds/mind-map.tsx +367 -0
- package/src/kinds/mind-radial.tsx +209 -0
- package/src/kinds/node-tone.ts +18 -0
- package/src/kinds/quadrant.tsx +164 -0
- package/src/kinds/row-align.ts +179 -0
- package/src/kinds/shape-basement.tsx +683 -0
- package/src/kinds/shape-blockchain.tsx +750 -0
- package/src/kinds/shape-commerce.tsx +553 -0
- package/src/kinds/shape-finance.tsx +706 -0
- package/src/kinds/shape-hardware.tsx +862 -0
- package/src/kinds/shape-people.tsx +439 -0
- package/src/kinds/shape-region.tsx +383 -0
- package/src/kinds/shape-software.tsx +859 -0
- package/src/kinds/storage.tsx +180 -0
- package/src/kinds/text-width.ts +73 -0
- package/src/kinds/tree.tsx +275 -0
- package/src/kinds/user-journey.tsx +240 -0
- package/src/label-text.ts +71 -0
- package/src/layout/clearance-constants.ts +47 -0
- package/src/layout/collisions.ts +2078 -0
- package/src/layout/edges.ts +2498 -0
- package/src/layout/footer-shape.ts +97 -0
- package/src/layout/geometry.ts +135 -0
- package/src/layout/label-shift.ts +28 -0
- package/src/layout/lanes.ts +328 -0
- package/src/layout/nodes.ts +190 -0
- package/src/layout/predict-bbox.ts +76 -0
- package/src/layout/px-projection.ts +176 -0
- package/src/layout/spec.ts +872 -0
- package/src/layout/text-width.ts +133 -0
- package/src/layout/tokens.ts +181 -0
- package/src/layout/viewbox.ts +47 -0
- package/src/layout-with-validation.ts +175 -0
- package/src/layout.ts +381 -0
- package/src/presets.ts +2108 -0
- package/src/reactive/batch.ts +48 -0
- package/src/reactive/computed.ts +85 -0
- package/src/reactive/effect.ts +145 -0
- package/src/reactive/index.ts +6 -0
- package/src/reactive/internal.ts +109 -0
- package/src/reactive/signal.ts +113 -0
- package/src/render/edges.tsx +318 -0
- package/src/render/header.tsx +146 -0
- package/src/render/interactive-panel.tsx +9620 -0
- package/src/render/nodes.tsx +319 -0
- package/src/render/stage.tsx +377 -0
- package/src/render/tone.ts +64 -0
- package/src/render/utils.ts +238 -0
- package/src/render.tsx +221 -0
- package/src/scroll-trigger/index.ts +109 -0
- package/src/scroll-trigger/progress.ts +49 -0
- package/src/thumbnail.tsx +114 -0
- package/src/types.ts +2371 -0
- package/src/validate.ts +268 -0
- package/src/visual-validate.ts +4381 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 cardene777
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
# @cardenelabs/cdl
|
|
2
|
+
|
|
3
|
+
> Declarative TypeScript DSL for animated React + SVG diagrams. UML / ER / state machine / topology / sequence / flow を 1 行で書く OSS library。
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@cardenelabs/cdl)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
## Documentation
|
|
9
|
+
|
|
10
|
+
| 目的 | リンク |
|
|
11
|
+
|---|---|
|
|
12
|
+
| **repo root** | [github.com/cardene777/cdl](https://github.com/cardene777/cdl) |
|
|
13
|
+
| **5 分で動かす** | [README quickstart](#quickstart) (本 file 下部) |
|
|
14
|
+
| **playground demo** | `pnpm dev` → http://localhost:4321 ([apps/playground](../../apps/playground/README.md)) |
|
|
15
|
+
| **全 API + preset 一覧** | playground `/docs/reference` |
|
|
16
|
+
| **Text DSL spec** | `apps/playground/src/content/cdl-docs/text-dsl-spec.md` |
|
|
17
|
+
| **LLM prompt guide** | `apps/playground/src/content/cdl-docs/text-dsl-llm-guide.md` |
|
|
18
|
+
| **contribute** | [CONTRIBUTING.md](../../CONTRIBUTING.md) |
|
|
19
|
+
|
|
20
|
+
## なぜ cdl
|
|
21
|
+
|
|
22
|
+
mermaid / PlantUML はテキストから静止画像を生成する。 cdl は **TypeScript → animated React + SVG component** で、 phase / state / tween / progress glow 等の動きを宣言的に書ける。
|
|
23
|
+
|
|
24
|
+
| 形式 | mermaid | cdl |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| sequence | 静止 | animated + phase 切替 |
|
|
27
|
+
| ER 図 | 静止 | animated + cardinality + sub label |
|
|
28
|
+
| state diagram | 静止 | animated + initial/final marker + guard |
|
|
29
|
+
| flow | 静止 | animated + dotted-flow 進行点 glow |
|
|
30
|
+
| 構成図 / deployment | 限定的 | animated + container group + connection |
|
|
31
|
+
| 自由レイアウト | 限定的 | lane + node + edge で自由構成 |
|
|
32
|
+
|
|
33
|
+
## Quickstart
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pnpm add @cardenelabs/cdl react react-dom
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### diagram declare
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { sequence } from "@cardenelabs/cdl";
|
|
43
|
+
|
|
44
|
+
export const authSeq = sequence({
|
|
45
|
+
id: "auth",
|
|
46
|
+
topic: "User Login",
|
|
47
|
+
actors: ["User", "API", "DB"],
|
|
48
|
+
})
|
|
49
|
+
.step({ from: "User", to: "API", label: "POST /login", sub: "email + password" })
|
|
50
|
+
.step({ from: "API", to: "DB", label: "SELECT credentials" })
|
|
51
|
+
.step({ from: "DB", to: "API", label: "rows", tone: "success", style: "dotted-flow" })
|
|
52
|
+
.step({ from: "API", to: "User", label: "200 OK", sub: "JWT token", tone: "success" })
|
|
53
|
+
.build();
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### React で render
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { CdlDiagramView } from "@cardenelabs/cdl";
|
|
60
|
+
import { authSeq } from "./auth-seq";
|
|
61
|
+
|
|
62
|
+
export function AuthSequenceDemo() {
|
|
63
|
+
return <CdlDiagramView diagram={authSeq} />;
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
これで UML sequence diagram が phase 切替 + state diff + 進行点 glow で animated に表示。
|
|
68
|
+
|
|
69
|
+
## 6 つの preset
|
|
70
|
+
|
|
71
|
+
低位 API (lane / node / edge 個別宣言) + 高位 preset (1 行で典型図生成)。
|
|
72
|
+
|
|
73
|
+
### swimlane
|
|
74
|
+
|
|
75
|
+
横並び 3 lane 自動配置 + slug 自動。
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
swimlane({ id, topic, lanes: ["送信元", "Contract", "出力"] })
|
|
79
|
+
.node("alice", { lane: "送信元", stack: 0, kind: "actor", title: "Alice" })
|
|
80
|
+
.node("fn", { lane: "Contract", stack: 0, kind: "function", title: "transfer(...)" })
|
|
81
|
+
.edge("alice", "fn", { id: "call", label: "call", tone: "accent", style: "dotted-flow" })
|
|
82
|
+
.build()
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### flow
|
|
86
|
+
|
|
87
|
+
1 lane 縦 stack、 前 step → 次 step 自動 edge。
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
flow({ id, topic, laneLabel: "Auth Flow", defaultTone: "teal" })
|
|
91
|
+
.step({ id: "user", kind: "person", title: "User" })
|
|
92
|
+
.step({ id: "api", kind: "api", title: "POST /login" }, "ログイン要求")
|
|
93
|
+
.step({ id: "db", kind: "database", title: "users 表" }, "credential 検証")
|
|
94
|
+
.build()
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### sequence
|
|
98
|
+
|
|
99
|
+
UML sequence diagram (actor lifeline + 時系列 message)。
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
sequence({ id, topic, actors: ["User", "API", "DB"] })
|
|
103
|
+
.step({ from: "User", to: "API", label: "POST /login" })
|
|
104
|
+
.step({ from: "API", to: "DB", label: "SELECT" })
|
|
105
|
+
.step({ from: "API", to: "User", label: "200 OK", tone: "success" })
|
|
106
|
+
.build()
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### topology
|
|
110
|
+
|
|
111
|
+
構成図 / deployment diagram (group + container + connection)。
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
topology({ id, topic })
|
|
115
|
+
.group("aws", { label: "AWS" })
|
|
116
|
+
.add({ id: "alb", kind: "service", title: "ALB" })
|
|
117
|
+
.add({ id: "ecs", kind: "service", title: "ECS Task" })
|
|
118
|
+
.add({ id: "rds", kind: "database", title: "RDS" })
|
|
119
|
+
.group("client", { label: "Client" })
|
|
120
|
+
.add({ id: "browser", kind: "frontend", title: "Browser" })
|
|
121
|
+
.connect("browser", "alb", { label: "HTTPS" })
|
|
122
|
+
.connect("ecs", "rds", { label: "TCP 5432", tone: "success" })
|
|
123
|
+
.build()
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### er
|
|
127
|
+
|
|
128
|
+
ER 図 (entity + cardinality)。
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
er({ id, topic })
|
|
132
|
+
.entity({ id: "user", title: "User", rows: ["id: PK", "email: string", "createdAt: timestamp"] })
|
|
133
|
+
.entity({ id: "order", title: "Order", rows: ["id: PK", "userId: FK", "total: number"] })
|
|
134
|
+
.relation({ from: "user", to: "order", cardinality: "1:N", label: "places" })
|
|
135
|
+
.build()
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
cardinality 6 種 ... `"1:1" | "1:N" | "N:1" | "N:M" | "0..1" | "1..*"`。
|
|
139
|
+
|
|
140
|
+
### stateMachine
|
|
141
|
+
|
|
142
|
+
FSM / workflow (state + transition trigger + guard)。
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
stateMachine({ id, topic })
|
|
146
|
+
.state({ id: "idle", title: "Idle", initial: true })
|
|
147
|
+
.state({ id: "loading", title: "Loading" })
|
|
148
|
+
.state({ id: "done", title: "Done", final: true })
|
|
149
|
+
.state({ id: "error", title: "Error" })
|
|
150
|
+
.transition({ from: "idle", to: "loading", trigger: "submit" })
|
|
151
|
+
.transition({ from: "loading", to: "done", trigger: "success", tone: "success" })
|
|
152
|
+
.transition({ from: "loading", to: "error", trigger: "fail", tone: "error" })
|
|
153
|
+
.transition({ from: "error", to: "idle", trigger: "retry", guard: "if attempts < 3" })
|
|
154
|
+
.build()
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## 低位 API
|
|
158
|
+
|
|
159
|
+
preset で表現しきれない自由レイアウトは低位 API で。
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
import { diagram } from "@cardenelabs/cdl";
|
|
163
|
+
|
|
164
|
+
export const custom = diagram("custom", { topic: "Custom" })
|
|
165
|
+
.lane("left", { x: 0, width: 400 })
|
|
166
|
+
.lane("right", { x: 500, width: 400 })
|
|
167
|
+
.node("a", { lane: "left", stack: 0, kind: "actor", title: "Alice" })
|
|
168
|
+
.node("b", { lane: "right", stack: 0, kind: "function", title: "Bob" })
|
|
169
|
+
.edge("a", "b", { id: "e", label: "msg", tone: "accent", style: "solid" })
|
|
170
|
+
.state("counter", { initial: 0 })
|
|
171
|
+
.phase("p1", { duration: 1500, title: "Phase 1", body: "tween counter" },
|
|
172
|
+
(p) => p.activate("a", "b", "e").tween("counter", 0, 100).badge("running"))
|
|
173
|
+
.build();
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## NodeKind 29 種
|
|
177
|
+
|
|
178
|
+
| 系統 | kinds |
|
|
179
|
+
|---|---|
|
|
180
|
+
| 基本 5 | `actor` / `function` / `storage` / `event` / `card` |
|
|
181
|
+
| 人系 5 | `person` / `user-group` / `admin` / `developer` / `external-user` |
|
|
182
|
+
| インフラ 6 | `database` / `cache` / `queue` / `message-bus` / `cloud` / `cdn` |
|
|
183
|
+
| アプリ系 6 | `service` / `api` / `frontend` / `backend` / `webhook` / `microservice` |
|
|
184
|
+
| blockchain 8 | `wallet` / `validator` / `miner` / `blockchain-node` / `mempool` / `block` / `bridge-node` / `relayer` |
|
|
185
|
+
| 暗号 / データ 4 | `signer` / `oracle` / `merkle-tree` / `decision` |
|
|
186
|
+
|
|
187
|
+
各 kind は shape / color / icon が異なる。 基本 5 は専用 component、 残り 24 種は `GenericNode` で汎用描画。
|
|
188
|
+
|
|
189
|
+
## EdgeStyle + Tone
|
|
190
|
+
|
|
191
|
+
| EdgeStyle | 動き |
|
|
192
|
+
|---|---|
|
|
193
|
+
| `solid` | 実線 + 矢頭 marker、 progress 連動で path が伸びる |
|
|
194
|
+
| `dotted-flow` | 点線 + 進行点 glow (3 重円) が path 上を流れる、 node 貫通自動判定 |
|
|
195
|
+
|
|
196
|
+
| Tone | 色 (hex) | 用途 |
|
|
197
|
+
|---|---|---|
|
|
198
|
+
| `accent` | `#c17f3e` | default |
|
|
199
|
+
| `teal` | `#4a8b7f` | 補助動作 |
|
|
200
|
+
| `success` | `#6b9e5a` | 成功 path |
|
|
201
|
+
| `error` | `#c15a4a` | 失敗 path |
|
|
202
|
+
| `warning` | `#c9a23e` | 警告 |
|
|
203
|
+
| `info` | `#5a8ec1` | 情報 |
|
|
204
|
+
|
|
205
|
+
## phase / state / tween / set / badge
|
|
206
|
+
|
|
207
|
+
phase 内で state を tween / set し、 badge を出す。
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
.state("amount", { initial: 0 })
|
|
211
|
+
.state("status", { initial: "idle" })
|
|
212
|
+
.phase("p1", { duration: 1800, title: "Phase 1", body: "tween + set" },
|
|
213
|
+
(p) => p
|
|
214
|
+
.activate("a", "b")
|
|
215
|
+
.tween("amount", 0, 100) // 数値の線形補間
|
|
216
|
+
.set("status", "running") // 文字列の即時切替
|
|
217
|
+
.badge("processing")) // header に badge 表示
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
state placeholder は node の `title` / `subtitle` / `eyebrow` / `value` 内で `{stateId}` 記法で参照。
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
.node("a", { lane: "l", stack: 0, kind: "function", title: "Process", subtitle: "status: {status}" })
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
phase 切替に連動して `status: idle` → `status: running` のように描画される。
|
|
227
|
+
|
|
228
|
+
## CdlDiagramView props
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
<CdlDiagramView
|
|
232
|
+
diagram={d}
|
|
233
|
+
hideHeader={false} // header (phase indicator + state diff) 表示
|
|
234
|
+
focusPhaseId="p1" // 特定 phase に固定 (autoplay は維持)
|
|
235
|
+
debug={false} // bbox + collision を半透明で重ね描き (開発用)
|
|
236
|
+
/>
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## 見た目を当てる (role selector)
|
|
240
|
+
|
|
241
|
+
cdl は形だけを描き、 色や影は持たない (geometry only、 style 不干渉、 CAR-643 SSOT)。
|
|
242
|
+
描かれる各部品には `data-cdl-role` が付くので、 consumer app 側が selector で見た目を当てる。
|
|
243
|
+
|
|
244
|
+
```css
|
|
245
|
+
[data-cdl-role="node-body"] {
|
|
246
|
+
fill: #ffffff;
|
|
247
|
+
stroke: #57534b;
|
|
248
|
+
stroke-width: 1.75;
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
明暗の切替は consumer 側の仕組み (`html` の class 等) で行う = cdl は明暗の概念を持たない。
|
|
253
|
+
|
|
254
|
+
**`CdlRole` 型は実装にある role の全部ではない**。 実装には 33 種の role があり、
|
|
255
|
+
型に載っているのは 13 種。 残り 20 種 (`chart-line` / `tree-edge` / `funnel-stage` /
|
|
256
|
+
`edge-glow` 等) は型を持たないが、 属性は付くので selector は書ける。
|
|
257
|
+
|
|
258
|
+
型の内外は「共通か kind 固有か」 では分かれていない (共通の描画で使う `edge-glow` が型の外に
|
|
259
|
+
あり、 放射状の図でしか使わない `mind-radial-halo` が型の中にある)。 **型に載っているかどうかは
|
|
260
|
+
selector を書けるかとは無関係**なので、 一覧が要る時は source を `data-cdl-role=` で検索する。
|
|
261
|
+
|
|
262
|
+
role が付かない小さな部品もある (kind が自前で描く目盛や軸など)。 それらは CSS 変数で色を渡す。
|
|
263
|
+
|
|
264
|
+
```css
|
|
265
|
+
:root {
|
|
266
|
+
--cdl-node-fill: #f2f1ec;
|
|
267
|
+
--cdl-text: #191714;
|
|
268
|
+
--cdl-tone-accent: #2c68ae;
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## CdlDiagramThumbnail
|
|
273
|
+
|
|
274
|
+
thumbnail として表示、 click で viewport いっぱい (94vw x 94vh) のモーダルで拡大。
|
|
275
|
+
|
|
276
|
+
```tsx
|
|
277
|
+
import { CdlDiagramThumbnail } from "@cardenelabs/cdl";
|
|
278
|
+
|
|
279
|
+
<CdlDiagramThumbnail diagram={d} hideHeader />
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
close は Escape / 背景クリック / × の 3 経路。
|
|
283
|
+
|
|
284
|
+
## Architecture
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
src/
|
|
288
|
+
├── builder.ts — DSL builder
|
|
289
|
+
├── compile.ts — DSL → CdlDiagram normalization
|
|
290
|
+
├── validate.ts — schema validation
|
|
291
|
+
├── layout/ — layout engine (6 file)
|
|
292
|
+
│ ├── tokens.ts — DESIGN TOKENS SSOT
|
|
293
|
+
│ ├── lanes.ts — lane 配置 + auto width
|
|
294
|
+
│ ├── nodes.ts — node cy/cx/w/h 確定
|
|
295
|
+
│ ├── edges.ts — orthogonal routing + label
|
|
296
|
+
│ ├── collisions.ts — bbox + clearance + Liang-Barsky
|
|
297
|
+
│ └── viewbox.ts — auto viewBox 計算
|
|
298
|
+
├── render/ — React + SVG (7 file)
|
|
299
|
+
│ ├── stage.tsx — SVG defs + 3 pass
|
|
300
|
+
│ ├── nodes.tsx — NodeKind 別 switch
|
|
301
|
+
│ ├── edges.tsx — solid / dotted-flow
|
|
302
|
+
│ ├── header.tsx — phase indicator + state diff
|
|
303
|
+
│ ├── utils.ts — interpolate / pathSubpath / shrinkPathEnd
|
|
304
|
+
│ └── tone.ts — TONE 6 色
|
|
305
|
+
├── kinds/ — 専用 component (actor/function/storage/event/card/generic)
|
|
306
|
+
├── presets.ts — 6 preset
|
|
307
|
+
├── thumbnail.tsx — モーダル拡大
|
|
308
|
+
└── types.ts — public types
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Testing
|
|
312
|
+
|
|
313
|
+
```sh
|
|
314
|
+
pnpm test
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
vitest で 36 test (builder / compile / layout / sequence preset / snapshot) を実行、 全 pass 確認。
|
|
318
|
+
|
|
319
|
+
## Performance baseline
|
|
320
|
+
|
|
321
|
+
`packages/cdl/test/bench.test.ts` の vitest bench で 5 case (small / medium / large / huge / animation-heavy) × 3 stage (parse / compile / layout) を計測する。
|
|
322
|
+
|
|
323
|
+
```sh
|
|
324
|
+
pnpm --filter @cardenelabs/cdl exec vitest bench --run
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
baseline (mean ms、 Apple Silicon / node 24)。
|
|
328
|
+
|
|
329
|
+
| case (node / edge / phase) | parse | compile | layout (旧) | layout (最適化後) |
|
|
330
|
+
| --- | --- | --- | --- | --- |
|
|
331
|
+
| small (10 / 5 / 0) | 0.002 | 0.020 | 0.260 | **0.192** |
|
|
332
|
+
| medium (100 / 50 / 5) | 0.022 | 1.488 | 25.014 | **0.807** |
|
|
333
|
+
| large (500 / 200 / 20) | 0.092 | 29.953 | 492.96 | **11.63** |
|
|
334
|
+
| huge (1000 / 500 / 50) | 0.200 | 129.88 | 2424.39 | **53.74** |
|
|
335
|
+
| animation-heavy (100 node / 100 phase / 50 tween) | 0.105 | 1.582 | 24.586 | **0.819** |
|
|
336
|
+
|
|
337
|
+
最適化内容 ... `detectCollisions` / `detectNearCollisions` を全 pair O(n²) から spatial hash (cell size 200px、 max clearance 70px margin) に変更。 巨大 bbox (edge-path 等) は fallback 経路で全件比較。 huge case で約 46x 高速化、 1000 node でも 60ms 以下で完了。
|
|
338
|
+
|
|
339
|
+
stage 内訳。 parse = `parseTextDslV05` (Text DSL → DslDocument)、 compile = `compileToCdl` (DslDocument → CdlDiagram)、 layout = `layout` (CdlDiagram → LaidDiagram)。 raw 出力は `.context/scratch/bench-baseline.{txt,json}` (vitest `--outputJson` 形式)。
|
|
340
|
+
|
|
341
|
+
## License
|
|
342
|
+
|
|
343
|
+
MIT
|