@cardenelabs/dragon 0.7.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 +173 -0
- package/dist/index.cjs +4916 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1451 -0
- package/dist/index.d.ts +1451 -0
- package/dist/index.js +4870 -0
- package/dist/index.js.map +1 -0
- package/examples/quick-start.md +142 -0
- package/package.json +79 -0
- package/src/canvas-bounds.ts +52 -0
- package/src/color.ts +172 -0
- package/src/compile.ts +3739 -0
- package/src/focus.ts +46 -0
- package/src/index.ts +226 -0
- package/src/input-size.ts +154 -0
- package/src/json-parser.ts +434 -0
- package/src/keywords.ts +114 -0
- package/src/notation-lint.ts +304 -0
- package/src/parser.ts +354 -0
- package/src/relative-pos.ts +182 -0
- package/src/schema.ts +24 -0
- package/src/schemas/diagram.json +133 -0
- package/src/types.ts +294 -0
- package/src/v05/index.ts +9 -0
- package/src/v05/parser.ts +1678 -0
- package/src/write-position.ts +270 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,1451 @@
|
|
|
1
|
+
import { NodeKind, Tone, EdgeStyle, CdlDiagram, LaidDiagram } from '@cardenelabs/cdl';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 位置を他の要素からの相対で書くための解決。
|
|
5
|
+
*
|
|
6
|
+
* `位置: Web の右 200` のように、 座標の代わりに「誰の」「どちら側に」「どれだけ離して」 を書く。
|
|
7
|
+
* 書く人も LLM も座標を知らないので、 数値を当てさせない形を用意する。
|
|
8
|
+
*
|
|
9
|
+
* 解決結果は絶対座標 (`posX` / `posY`) で、 座標を直接書いた時と同じ経路を通る。
|
|
10
|
+
* 書き方が増えるだけで、 効き方は変わらない。
|
|
11
|
+
*
|
|
12
|
+
* 座標を決める場所が組み立て側 (`compile.ts`) と画面側 (playground の `overlay-dsl.ts`) の
|
|
13
|
+
* 2 つあるため、 解決の規則は本 file に 1 つだけ置いて両方から呼ぶ。 片方だけ直すと画面が
|
|
14
|
+
* 直らない事故を、 規則を共有することで構造的に防ぐ。
|
|
15
|
+
*/
|
|
16
|
+
/** 基準からどちら側に置くか。 */
|
|
17
|
+
type RelativeDirection = "right" | "left" | "above" | "below";
|
|
18
|
+
/** 相対で書かれた位置の指定。 */
|
|
19
|
+
type RelativePos = {
|
|
20
|
+
/** 基準にする相手の名前。 `actors:` に書かれた名前をそのまま持つ。 */
|
|
21
|
+
anchor: string;
|
|
22
|
+
dir: RelativeDirection;
|
|
23
|
+
/** 相手との間隔。 書かなかった時は `RELATIVE_GAP_DEFAULT`。 */
|
|
24
|
+
gap?: number;
|
|
25
|
+
};
|
|
26
|
+
/** 位置を決めるのに必要な、 基準の中心と大きさ。 */
|
|
27
|
+
type AnchorBox = {
|
|
28
|
+
cx: number;
|
|
29
|
+
cy: number;
|
|
30
|
+
w: number;
|
|
31
|
+
h: number;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* 間隔を書かなかった時の既定値。
|
|
35
|
+
*
|
|
36
|
+
* 8 図種 × 4 向きで間隔を変えながら、 cdl が出す近すぎ系の指摘の数を数えて決めた。
|
|
37
|
+
* 100 で 17 件、 130 で 10 件、 140 で 4 件と減り、 160 で 2 件に落ちて以降は変わらない。
|
|
38
|
+
* 残る 2 件は間隔と無関係な指摘なので、 減らなくなる 160 を既定にする。
|
|
39
|
+
*
|
|
40
|
+
* 自動配置が空ける隙間も実測では縦 100 / 横 256-406 で、 160 はその間に収まる。
|
|
41
|
+
* 隣に置いたと読める近さと、 詰まって見えない広さの両方を満たす。
|
|
42
|
+
*/
|
|
43
|
+
declare const RELATIVE_GAP_DEFAULT = 160;
|
|
44
|
+
/**
|
|
45
|
+
* `位置:` に書かれた値を相対指定として読む。 相対の形でなければ null。
|
|
46
|
+
*
|
|
47
|
+
* 座標の形 (`300,200`) は呼ぶ側が先に判定する。 ここは相対だけを見る。
|
|
48
|
+
*/
|
|
49
|
+
declare function parseRelativePos(raw: string): RelativePos | null;
|
|
50
|
+
/**
|
|
51
|
+
* 相対指定を絶対座標に直す。
|
|
52
|
+
*
|
|
53
|
+
* `posX` / `posY` は箱の中心。 間隔は箱の縁と縁の間の距離として扱う。 中心間の距離にすると、
|
|
54
|
+
* 大きさの違う箱を並べた時に見た目の隙間が揃わない。
|
|
55
|
+
*/
|
|
56
|
+
declare function resolveRelativePos(rel: RelativePos, anchor: AnchorBox, target: {
|
|
57
|
+
w: number;
|
|
58
|
+
h: number;
|
|
59
|
+
}): {
|
|
60
|
+
posX: number;
|
|
61
|
+
posY: number;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* 相対指定を解く順番を決める。
|
|
65
|
+
*
|
|
66
|
+
* 基準にした相手がまた相対で書かれていることがある (`B は A の右`、 `C は B の右`)。
|
|
67
|
+
* 先に相手が決まっていないと座標を出せないので、 依存の浅い順に並べ替える。
|
|
68
|
+
*
|
|
69
|
+
* 輪になっている分 (`A は B の右`、 `B は A の右`) は解けないため、 順番からは外して
|
|
70
|
+
* 名前だけを返す。 呼ぶ側が誤りとして扱う。
|
|
71
|
+
*/
|
|
72
|
+
declare function orderByDependency(items: ReadonlyArray<{
|
|
73
|
+
name: string;
|
|
74
|
+
rel?: RelativePos;
|
|
75
|
+
}>): {
|
|
76
|
+
order: string[];
|
|
77
|
+
cyclic: string[];
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Text DSL の AST 型定義
|
|
82
|
+
* docs/cdl/text-dsl-spec.md の文法を AST に変換した中間表現
|
|
83
|
+
*/
|
|
84
|
+
|
|
85
|
+
type PresetType = "sequence" | "flow" | "swimlane" | "er" | "state" | "topology" | "solidity" | "gantt" | "class" | "pie" | "c4" | "mind";
|
|
86
|
+
type Position = {
|
|
87
|
+
line: number;
|
|
88
|
+
column?: number;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* canvas pivot (CAR-1693 Phase 1) の DSL 表面 `pos: {x, y}` を保持する型。
|
|
92
|
+
* auto layout の compute value からの offset (dx, dy) を表す。 element の `layoutPos:` が
|
|
93
|
+
* undefined なら auto layout の値をそのまま採用 (catalog 100+ backward compat)、 set 済なら
|
|
94
|
+
* Phase 2 の applyPosOffset pass が offset として適用する。
|
|
95
|
+
*
|
|
96
|
+
* naming = DSL 表面 syntax は user 提案 wording (`pos:`) を維持、 内部 AST は既存 `pos: Position`
|
|
97
|
+
* (source line/column) との collision 回避のため `layoutPos:` に rename する 2 層設計。
|
|
98
|
+
*/
|
|
99
|
+
type LayoutPos = {
|
|
100
|
+
x: number;
|
|
101
|
+
y: number;
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* diagram-level layout mode (CAR-1693 Phase 1)。 未指定は "auto" default で catalog 100+ は
|
|
105
|
+
* byte-identical 動作。 "manual" は Phase 4 で drag interaction が「auto layout を skip して
|
|
106
|
+
* pos: 値をそのまま採用する」 mode として使う予定。
|
|
107
|
+
*/
|
|
108
|
+
type LayoutMode = "auto" | "manual";
|
|
109
|
+
/** トップレベル AST */
|
|
110
|
+
type DslDocument = {
|
|
111
|
+
title: string;
|
|
112
|
+
type: PresetType;
|
|
113
|
+
actors: DslActor[];
|
|
114
|
+
flow: DslStep[];
|
|
115
|
+
animate?: DslAnimate;
|
|
116
|
+
/** v0.5+ 拡張 ... viewport / lanes / groups */
|
|
117
|
+
viewport?: DslViewport;
|
|
118
|
+
lanes?: Record<string, DslLane>;
|
|
119
|
+
groups?: Record<string, DslGroup>;
|
|
120
|
+
/**
|
|
121
|
+
* canvas pivot (CAR-1693 Phase 1) diagram-level layout mode。 未指定は "auto" default で
|
|
122
|
+
* catalog 100+ backward compat。 "manual" は Phase 4 で drag → pos: 保存の完全 manual mode。
|
|
123
|
+
*/
|
|
124
|
+
layout?: LayoutMode;
|
|
125
|
+
pos: Position;
|
|
126
|
+
};
|
|
127
|
+
/** 登場人物 (v0.5+ ... inline option 拡張) */
|
|
128
|
+
type DslActor = {
|
|
129
|
+
name: string;
|
|
130
|
+
kind: NodeKind;
|
|
131
|
+
/**
|
|
132
|
+
* 著者が種類を書いたか。 書かなかった時 `kind` には既定の `actor` が入るため、
|
|
133
|
+
* `kind` の値だけでは「書いた `actor`」 と「書かなかった」 を区別できない。
|
|
134
|
+
*
|
|
135
|
+
* 順序図の名札は小型の箱 (`h: 72`) で作られる。 描画側は `card` に小型用の分岐を持つが
|
|
136
|
+
* `actor` には無く、 名札の文字が箱の下端をはみ出す。 書いた時だけ種類を名札に載せ、
|
|
137
|
+
* 書かなかった時は小型に耐える形のまま残すために、 この 2 つを区別する (#1058)。
|
|
138
|
+
*/
|
|
139
|
+
kindWritten?: boolean;
|
|
140
|
+
/** v0.5+ inline option */
|
|
141
|
+
subtitle?: string;
|
|
142
|
+
eyebrow?: string;
|
|
143
|
+
value?: string;
|
|
144
|
+
rows?: string[];
|
|
145
|
+
lane?: string;
|
|
146
|
+
stack?: number;
|
|
147
|
+
initial?: boolean;
|
|
148
|
+
final?: boolean;
|
|
149
|
+
/**
|
|
150
|
+
* 箱の色。 未指定なら種類ごとの既定色。
|
|
151
|
+
*
|
|
152
|
+
* 矢印 (`DslStep.tone`) と同じ名前と別名を受け付ける (`成功` / `success` 等)。
|
|
153
|
+
* 効く種類は cdl 側の 26 種で、 それ以外は指定しても色が変わらない。
|
|
154
|
+
*/
|
|
155
|
+
tone?: Tone;
|
|
156
|
+
/**
|
|
157
|
+
* CAR-1657 parts unified syntax = kind が既存 NODE_KIND_VALID に無い値 (parts identifier 候補)
|
|
158
|
+
* だった時、 parser は partId に格納して compile 側に委譲する。 compile 時に partsCatalog から
|
|
159
|
+
* 対応する CdlDiagram を lookup + merge する経路。 partId set 時は kind = "actor" (default) fallback。
|
|
160
|
+
*/
|
|
161
|
+
partId?: string;
|
|
162
|
+
/**
|
|
163
|
+
* `色:` に色番号を書いた時の値。 どの状態に入れるかは組み立て時に決める。
|
|
164
|
+
*
|
|
165
|
+
* 色を保持する状態の名前はパーツごとに違う (`bg` / `stFill` / `gFill` / `hue` など 17 種)。
|
|
166
|
+
* 解析の時点ではパーツの定義を知らないため、 名前を決めずに持っておく。
|
|
167
|
+
*/
|
|
168
|
+
colorHex?: string;
|
|
169
|
+
/**
|
|
170
|
+
* parts state override (partId set 時のみ有効)。 kind + 既存 reserved fields を除いた
|
|
171
|
+
* inline option の残り (`v: 50` / `count: 100` 等) を state 名 → initial 値 map として保持。
|
|
172
|
+
* compile 時に parts.states[i].initial を上書きする。
|
|
173
|
+
*/
|
|
174
|
+
stateOverride?: Record<string, number | string | boolean>;
|
|
175
|
+
/**
|
|
176
|
+
* canvas pivot 新 spec (dragon canvas pivot spec §layout-role-conversion)。
|
|
177
|
+
* user drag / resize で明示的に固定した絶対座標 / サイズ。 4 field set 済なら CDL layout が
|
|
178
|
+
* 該当 actor 由来 lane / node の位置計算を skip、 posX / posY / posW / posH をそのまま採用する。
|
|
179
|
+
* 未指定なら従来の auto layout (catalog 100+ backward compat 保証)。
|
|
180
|
+
*/
|
|
181
|
+
posX?: number;
|
|
182
|
+
posY?: number;
|
|
183
|
+
posW?: number;
|
|
184
|
+
posH?: number;
|
|
185
|
+
/**
|
|
186
|
+
* 見本を何倍で描くか (`倍率: 2` / `scale: 2`、 #1026)。 partId set 時のみ有効。
|
|
187
|
+
*
|
|
188
|
+
* `大きさ:` (`posW` / `posH`) とは掛け合わさる。 画面側も同じ意味で読むため、
|
|
189
|
+
* `scale` は状態の名前としては使えない (予約語)。 状態を上書きしたい時は
|
|
190
|
+
* `state: { scale: 2 }` と明示するか、別の名前を使う。
|
|
191
|
+
*/
|
|
192
|
+
scale?: number;
|
|
193
|
+
/**
|
|
194
|
+
* 倍率として書かれた項目名 (`scale` / `倍率`、 #1026)。
|
|
195
|
+
*
|
|
196
|
+
* 値が読めない形 (`scale: x`) と書いていない形を見分けるために持つ。 見本が同じ名前の
|
|
197
|
+
* 状態を持つ時の知らせ (`scale-reserved`) が、値の読めなさに左右されないようにする。
|
|
198
|
+
*/
|
|
199
|
+
scaleKeys?: string[];
|
|
200
|
+
/**
|
|
201
|
+
* 位置を他の要素からの相対で書いた時の指定 (`位置: Web の右 200`)。
|
|
202
|
+
*
|
|
203
|
+
* 組み立ての段階で 1 度配置を計算し、 基準の実座標から `posX` / `posY` に直す。 解決後は
|
|
204
|
+
* 座標を直接書いた時と同じ経路を通るため、 効き方は書き方によって変わらない。
|
|
205
|
+
*/
|
|
206
|
+
posRel?: RelativePos;
|
|
207
|
+
/**
|
|
208
|
+
* canvas pivot UX 修正 (B1 individual node isolation)。 actor 1 件が生成する複数 sub-node
|
|
209
|
+
* (sequence の header / spacer / footer / s{N} 等) の中で「特定 sub-node だけを固定 / resize」
|
|
210
|
+
* するための nested override map。 key = sub-node id 相当の short key (`header` / `footer` /
|
|
211
|
+
* `spacer` / `s0` 等)、 value = posX/Y/W/H の 4 field。 compile 側は対応 CDL node に単独反映、
|
|
212
|
+
* 同 actor の他 sub-node は影響を受けない (lane 全体 posX とは独立経路)。
|
|
213
|
+
*/
|
|
214
|
+
nodes?: Record<string, DslActorNodeOverride>;
|
|
215
|
+
/**
|
|
216
|
+
* canvas pivot (CAR-1693 Phase 1) DSL 表面 `pos: {x, y}` 由来の layout offset。 未指定は auto
|
|
217
|
+
* layout の compute value そのまま (backward compat)、 set 済なら Phase 2 の applyPosOffset で
|
|
218
|
+
* (auto x + layoutPos.x, auto y + layoutPos.y) に shift される。 既存 posX/posY (絶対座標) は
|
|
219
|
+
* 別 mechanism で、 layoutPos は auto layout からの nudge (dx, dy)。
|
|
220
|
+
*/
|
|
221
|
+
layoutPos?: LayoutPos;
|
|
222
|
+
pos: Position;
|
|
223
|
+
};
|
|
224
|
+
/**
|
|
225
|
+
* canvas pivot UX 修正 (B1) = actor 内 sub-node 単位で「絶対座標 / サイズ」 を固定するための
|
|
226
|
+
* override 値。 全 field optional、 posX / posY が両方 set 済なら CDL 側で該当 sub-node の
|
|
227
|
+
* auto layout を skip、 明示座標をそのまま採用する。 posW / posH は width / height の上書き。
|
|
228
|
+
*/
|
|
229
|
+
type DslActorNodeOverride = {
|
|
230
|
+
posX?: number;
|
|
231
|
+
posY?: number;
|
|
232
|
+
posW?: number;
|
|
233
|
+
posH?: number;
|
|
234
|
+
};
|
|
235
|
+
/** 流れ (1 行 = 1 step) (v0.5+ ... inline option 拡張) */
|
|
236
|
+
type DslStep = {
|
|
237
|
+
no: number;
|
|
238
|
+
from: string;
|
|
239
|
+
to: string;
|
|
240
|
+
label: string;
|
|
241
|
+
sub?: string;
|
|
242
|
+
tone?: Tone;
|
|
243
|
+
style?: EdgeStyle;
|
|
244
|
+
/** v0.5+ inline option */
|
|
245
|
+
guard?: string;
|
|
246
|
+
cardinality?: string;
|
|
247
|
+
labelOffsetX?: number;
|
|
248
|
+
labelOffsetY?: number;
|
|
249
|
+
/**
|
|
250
|
+
* canvas pivot (CAR-1693 Phase 1) DSL 表面 `pos: {x, y}` 由来の layout offset。 step の edge
|
|
251
|
+
* label 位置を auto layout compute から (dx, dy) shift する。 未指定は auto、 set 済は Phase 2 で適用。
|
|
252
|
+
*/
|
|
253
|
+
layoutPos?: LayoutPos;
|
|
254
|
+
pos: Position;
|
|
255
|
+
};
|
|
256
|
+
/** lane 宣言 (v0.5+ top-level lanes section) */
|
|
257
|
+
type DslLane = {
|
|
258
|
+
id: string;
|
|
259
|
+
x?: number;
|
|
260
|
+
width?: number;
|
|
261
|
+
label?: string;
|
|
262
|
+
contain?: boolean;
|
|
263
|
+
lifeline?: boolean;
|
|
264
|
+
/**
|
|
265
|
+
* canvas pivot (CAR-1693 Phase 1) DSL 表面 `pos: {x, y}` 由来の layout offset。 lane の x 座標を
|
|
266
|
+
* auto layout compute から (dx, dy) shift する。 未指定は auto、 set 済は Phase 2 で適用。
|
|
267
|
+
*/
|
|
268
|
+
layoutPos?: LayoutPos;
|
|
269
|
+
pos: Position;
|
|
270
|
+
};
|
|
271
|
+
/** group 宣言 (v0.5+ top-level groups section、 topology preset 専用) */
|
|
272
|
+
type DslGroup = {
|
|
273
|
+
id: string;
|
|
274
|
+
label?: string;
|
|
275
|
+
lanes: string[];
|
|
276
|
+
pos: Position;
|
|
277
|
+
};
|
|
278
|
+
/** viewport 全体仕様 (v0.5+ top-level viewport section) */
|
|
279
|
+
type DslViewport = {
|
|
280
|
+
width?: number;
|
|
281
|
+
height?: number;
|
|
282
|
+
/**
|
|
283
|
+
* 図全体の倍率 (default 1)。 箱 / 文字 / 線 / 間隔のすべてが等比で拡大縮小される。
|
|
284
|
+
*
|
|
285
|
+
* `laneWidth` / `laneGap` / `nodeGap` は **間隔だけ**を動かすため、 箱の大きさは変わらず
|
|
286
|
+
* 図に占める割合はむしろ下がる。 本 field は cdl 側で座標系ごと拡大するので、
|
|
287
|
+
* 見た目の比率が完全に保たれる (SVG user unit 固定の font-size も追従する)。
|
|
288
|
+
*/
|
|
289
|
+
scale?: number;
|
|
290
|
+
laneWidth?: number;
|
|
291
|
+
/** 全体 default gap (互換維持、 個別 laneGap / nodeGap / labelMargin の fallback) */
|
|
292
|
+
gap?: number;
|
|
293
|
+
/** lanes 間 horizontal gap */
|
|
294
|
+
laneGap?: number;
|
|
295
|
+
/** nodes 間 vertical gap within lane */
|
|
296
|
+
nodeGap?: number;
|
|
297
|
+
/** edge label 周辺余白 */
|
|
298
|
+
labelMargin?: number;
|
|
299
|
+
pos: Position;
|
|
300
|
+
};
|
|
301
|
+
/** アニメーション ブロック */
|
|
302
|
+
type DslAnimate = {
|
|
303
|
+
states: DslState[];
|
|
304
|
+
phases: DslPhase[];
|
|
305
|
+
pos: Position;
|
|
306
|
+
};
|
|
307
|
+
/** 状態宣言 */
|
|
308
|
+
type DslState = {
|
|
309
|
+
name: string;
|
|
310
|
+
initial: number | string;
|
|
311
|
+
pos: Position;
|
|
312
|
+
};
|
|
313
|
+
/** ステップ (phase) */
|
|
314
|
+
type DslPhase = {
|
|
315
|
+
name: string;
|
|
316
|
+
durationMs: number;
|
|
317
|
+
highlight?: string[];
|
|
318
|
+
tweens?: DslTween[];
|
|
319
|
+
sets?: DslSet[];
|
|
320
|
+
body?: string;
|
|
321
|
+
badge?: string;
|
|
322
|
+
pos: Position;
|
|
323
|
+
};
|
|
324
|
+
/** state lerp (遷移) */
|
|
325
|
+
type DslTween = {
|
|
326
|
+
state: string;
|
|
327
|
+
from: number;
|
|
328
|
+
to: number;
|
|
329
|
+
pos: Position;
|
|
330
|
+
};
|
|
331
|
+
/** state 即時遷移 (切替) */
|
|
332
|
+
type DslSet = {
|
|
333
|
+
state: string;
|
|
334
|
+
value: string | number;
|
|
335
|
+
pos: Position;
|
|
336
|
+
};
|
|
337
|
+
/** Parser error (行番号付き) */
|
|
338
|
+
type DslError = {
|
|
339
|
+
line: number;
|
|
340
|
+
message: string;
|
|
341
|
+
hint?: string;
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Text DSL parser
|
|
346
|
+
* 入力: docs/cdl/text-dsl-spec.md 準拠の箇条書きテキスト
|
|
347
|
+
* 出力: DslDocument AST or DslError[]
|
|
348
|
+
*/
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Parser 本体
|
|
352
|
+
*/
|
|
353
|
+
type ParseResult = {
|
|
354
|
+
ok: true;
|
|
355
|
+
doc: DslDocument;
|
|
356
|
+
} | {
|
|
357
|
+
ok: false;
|
|
358
|
+
errors: DslError[];
|
|
359
|
+
};
|
|
360
|
+
declare function parseTextDsl(src: string): ParseResult;
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* AST (DslDocument) → 既存 preset API 経由 → LaidDiagram
|
|
364
|
+
*
|
|
365
|
+
* v0.3 ... アニメーション ブロック full compile 対応 (sequence preset のみ、 他 preset は v0.4 で順次)
|
|
366
|
+
* - state / tween / set / highlight / badge / body を実 phase に注入
|
|
367
|
+
* - アニメーション ありなら builder 直接経路 ... preset の標準 phase を置換
|
|
368
|
+
* - アニメーション なしは v0.2 と同じく preset 経由
|
|
369
|
+
*
|
|
370
|
+
* v0.2 ... 6 preset 全対応 (sequence / flow / swimlane / er / state / topology)
|
|
371
|
+
*/
|
|
372
|
+
|
|
373
|
+
interface CompileToCdlOpts {
|
|
374
|
+
/**
|
|
375
|
+
* CAR-1657 = parts identifier lookup catalog、 caller (CdlEditor / test) が inject。
|
|
376
|
+
* DslActor.partId が set された actor を検出したら partsCatalog[partId] から CdlDiagram を
|
|
377
|
+
* lookup + mergePartIntoDiagram で target に統合。 未渡し時は parts kind actor を skip + warn。
|
|
378
|
+
*/
|
|
379
|
+
partsCatalog?: Record<string, CdlDiagram>;
|
|
380
|
+
/**
|
|
381
|
+
* 組み立ての途中で分かった「書いたのに効かなかったこと」 の受け取り口。
|
|
382
|
+
*
|
|
383
|
+
* 図は出せるので誤りにはしないが、 黙って捨てると書いた人が理由を追えない。 editor は
|
|
384
|
+
* これを受けて画面に出す。 判定は組み立て側だけが持ち、 画面側は表示に徹する。
|
|
385
|
+
*/
|
|
386
|
+
onNotice?: (notice: CompileNotice) => void;
|
|
387
|
+
/**
|
|
388
|
+
* edge が DSL のどの行から来たかの受け取り口 (#998)。
|
|
389
|
+
*
|
|
390
|
+
* preset によっては書いた step と生成される edge が一致しない (`type: flow` は actor を鎖状に
|
|
391
|
+
* 繋ぐため `a -> c` と書いても `a -> b` になる)。 edge を起点に本文の行を直す機能は、 この
|
|
392
|
+
* 対応が無いと別の行を書き換える。
|
|
393
|
+
*
|
|
394
|
+
* **対応が取れない edge については呼ばれない**。 「対応が無い」 と「行 0」 を区別するため。
|
|
395
|
+
*/
|
|
396
|
+
onEdgeSource?: (edgeId: string, line: number) => void;
|
|
397
|
+
}
|
|
398
|
+
/** 図は出せるが書いた通りにならなかった、 という知らせ。 */
|
|
399
|
+
type CompileNotice = {
|
|
400
|
+
kind: "relative-position-ignored" | "focus-target-missing" | "state-override-rejected" | "external-paint-dropped" | "part-not-drawn" | "scale-reserved";
|
|
401
|
+
/** 対象の名前。 光らせる相手なら書かれた指定そのまま */
|
|
402
|
+
actor: string;
|
|
403
|
+
/** 書かれていた行 */
|
|
404
|
+
line: number;
|
|
405
|
+
message: string;
|
|
406
|
+
hint?: string;
|
|
407
|
+
};
|
|
408
|
+
declare function compileToCdl(doc: DslDocument, opts?: CompileToCdlOpts): CdlDiagram;
|
|
409
|
+
/**
|
|
410
|
+
* 登場人物ごとの、 図の上での中心と大きさを測る。
|
|
411
|
+
*
|
|
412
|
+
* 対応付けは箱に表示される名前で行う。 id を使わない理由は `applyNodeTones` と同じで、
|
|
413
|
+
* slug の作り方が dragon と cdl で違うため記号を含む名前で一致しない。
|
|
414
|
+
*
|
|
415
|
+
* 1 人が複数の箱に分かれる図種 (順序図の上端 / 下端) では、 全部を囲む矩形を返す。
|
|
416
|
+
* 箱として現れない登場人物は縦列の矩形で代用する。
|
|
417
|
+
*/
|
|
418
|
+
declare function measureActorBoxes(diagram: CdlDiagram,
|
|
419
|
+
/**
|
|
420
|
+
* 配置まで済ませた図。 渡すとここでは測り直さない (#1006)。
|
|
421
|
+
*
|
|
422
|
+
* 呼出側が既に組み立てているなら、 ここで `layout` を呼ぶと同じ図の配置を 2 度計算する。
|
|
423
|
+
* 図の規模に比例して重く、 辺 500 本で約 300ms (実測)。
|
|
424
|
+
* 渡す時は `diagram` と対にする = 別の図の配置を渡すと、 測る位置がずれる。
|
|
425
|
+
*/
|
|
426
|
+
laidHint?: LaidDiagram): Map<string, AnchorBox>;
|
|
427
|
+
/**
|
|
428
|
+
* この図を取り込んでよいか (#1015)。
|
|
429
|
+
*
|
|
430
|
+
* 見るのは **要素数が上限 (`MAX_INPUT_ELEMENTS`) を超えていないこと** だけ。
|
|
431
|
+
* 超えた図を取り込むと、既定の 400x200 の枠を確保した場所に中身が全て展開される。
|
|
432
|
+
* 上限を置いた意図 (大きすぎる入力で止まらないようにする) も達成されない。
|
|
433
|
+
*
|
|
434
|
+
* **配置計算が通るかは見ない**。 取り込みは lane を張り替えるため、単体では配置計算が
|
|
435
|
+
* 通らない図でも取り込みは成功する (実測 = 存在しない lane を指す箱を持つ見本が、
|
|
436
|
+
* 取り込み後は正しい lane に載った)。 配置計算で弾くと、動いている本文が描けなくなる。
|
|
437
|
+
*/
|
|
438
|
+
declare function partIsMeasurable(part: CdlDiagram): boolean;
|
|
439
|
+
/**
|
|
440
|
+
* 倍率の上限 (#1020)。
|
|
441
|
+
*
|
|
442
|
+
* 図枠は数百 world 単位なので、1000 倍で数十万になる。 これを超える倍率は画面上で意味を持たず、
|
|
443
|
+
* 掛けた先が非有限になる危険だけが残る。
|
|
444
|
+
*/
|
|
445
|
+
declare const MAX_PART_SCALE = 1000;
|
|
446
|
+
/**
|
|
447
|
+
* 本文に書かれた倍率を、描ける値に直す (#1020 / #1026)。
|
|
448
|
+
*
|
|
449
|
+
* 記法は `倍率: -2` も `倍率: 0` も、桁が溢れて `Infinity` になる値も書ける。 置き場所と
|
|
450
|
+
* 描画で別々に直すと、同じ見本が「置き場所は等倍・画面では消える」 状態になる (実測 =
|
|
451
|
+
* `scale: 0` が等倍の場所を占めるのに画面には出なかった)。 読んだ時点で直す。
|
|
452
|
+
*
|
|
453
|
+
* **画面側と組み立て側の両方から呼ぶ**。 別々に持つと、同じ本文が経路で別の絵になる (#1026)。
|
|
454
|
+
*/
|
|
455
|
+
declare function normalizePartScale(value: number): number;
|
|
456
|
+
/**
|
|
457
|
+
* `大きさ:` と `倍率:` を合成した最終の伸縮率 (#1026)。
|
|
458
|
+
*
|
|
459
|
+
* **上限は合成した後に 1 度だけ掛ける**。 率ごとに掛けると、`大きさ:` 由来 1000 倍と
|
|
460
|
+
* `倍率: 2` で合わせて 2000 倍になり、1 度だけ掛ける経路 (1000 倍) と食い違う (実測)。
|
|
461
|
+
*
|
|
462
|
+
* 基準は `大きさ:` と同じ物差し (縦列の外接矩形と段の送り幅)。 図枠を基準にすると、
|
|
463
|
+
* 図枠と外接矩形の差のぶんだけ余分に掛かる (実測 = 3 倍と書いて 4.0875 倍になった)。
|
|
464
|
+
*
|
|
465
|
+
* 画面側 (重ねて描く時の `transform`) と組み立て側 (取り込む時の伸縮) が同じ値を使う。
|
|
466
|
+
*/
|
|
467
|
+
declare function partScaleFactor(part: CdlDiagram, posW: number | undefined, posH: number | undefined, scale: number | undefined): {
|
|
468
|
+
x: number;
|
|
469
|
+
y: number;
|
|
470
|
+
};
|
|
471
|
+
/**
|
|
472
|
+
* 見本 1 件の狙いの大きさ (#1026)。
|
|
473
|
+
*
|
|
474
|
+
* 合成した率を基準に掛けて返す。 取り込み側はこの値から自分で率を出し直すため、
|
|
475
|
+
* ここで上限を掛けておかないと「見積りは上限どまり・実体は青天井」 になる (実測 =
|
|
476
|
+
* 見積り 1000 倍に対して実体 10000 倍)。
|
|
477
|
+
*
|
|
478
|
+
* 何も書かれていない辺は「狙いなし」 のまま返す。 基準の値を入れると、取り込み側が
|
|
479
|
+
* 自前で測る外接矩形との差だけ伸縮が掛かってしまう。
|
|
480
|
+
*/
|
|
481
|
+
declare function partTargetSize(part: CdlDiagram, posW: number | undefined, posH: number | undefined, scale: number | undefined): {
|
|
482
|
+
w: number | undefined;
|
|
483
|
+
h: number | undefined;
|
|
484
|
+
};
|
|
485
|
+
/**
|
|
486
|
+
* `大きさ:` を書いた時に、見本を何倍にするか (#1018)。
|
|
487
|
+
*
|
|
488
|
+
* 横は縦列の幅、縦は段の数から出す。 どちらも書かなければ 1 倍。
|
|
489
|
+
*
|
|
490
|
+
* **縦は「書いた高さにする」 ではなく「段の送り幅の合計に対する倍率」**。 `大きさ: 2000,300` を
|
|
491
|
+
* 1 段の見本に書くと、横は 2000 になるが縦は 300 ではなく 409 になる (段の送り幅 220 に対して
|
|
492
|
+
* 300 なので 1.36 倍、それが箱の高さ 300 に掛かる)。 意図した仕様かは怪しいが、既に本文が
|
|
493
|
+
* この前提で書かれているため変えない。 画面側も同じ規則で拡大する。
|
|
494
|
+
*
|
|
495
|
+
* 組み立て側 (`partExtent`) と画面側 (playground) の両方から呼ぶ。 別々に持つと、`大きさ:` を
|
|
496
|
+
* 書いた見本だけ経路で大きさが変わる。
|
|
497
|
+
*/
|
|
498
|
+
declare function partTargetScale(part: CdlDiagram, targetW?: number, targetH?: number): {
|
|
499
|
+
x: number;
|
|
500
|
+
y: number;
|
|
501
|
+
};
|
|
502
|
+
/**
|
|
503
|
+
* パーツ 1 個が実際に描かれる大きさ (#937)。
|
|
504
|
+
*
|
|
505
|
+
* 図枠 (`viewBox`) を返す。 箱の外接矩形 (`partVisualSize`) ではない。 2 つは別物で、
|
|
506
|
+
* 実測では図枠 525x520 に対し箱 380x400 と余白の分だけ違う。 SVG は図枠を基準に
|
|
507
|
+
* `preserveAspectRatio` で収めるため、 箱の値を渡すと縮んで描いた大きさと食い違う
|
|
508
|
+
* (実測 = achievement が箱の値で描くと約 275x275 になった)。
|
|
509
|
+
*
|
|
510
|
+
* 箱を持たないパーツ (実体が操作パネルの部品である 17 件) でも図枠は出る。 箱だけを見ると
|
|
511
|
+
* 1x1 になり、 その値で描くと潰れる。
|
|
512
|
+
*
|
|
513
|
+
* ただし **図枠は場所を確保するだけで、図の中に何か描かれることは保証しない**。 上の 17 件は
|
|
514
|
+
* 図の中に描く部品を持たず、重ねても図には出ない (`partDrawsInDiagram`、#1017)。
|
|
515
|
+
*
|
|
516
|
+
* 画面が描く大きさと、 組み立て側の格子が確保する場所の両方がこれを見る。 別々の物差しを
|
|
517
|
+
* 持っていた頃は、 同じ本文でも通った経路でパーツの位置が変わっていた (#937)。
|
|
518
|
+
*
|
|
519
|
+
* 組み立てに失敗する図では、 既定の大きさに落とす (呼出側は catalog を渡すので通常起きない)。
|
|
520
|
+
*/
|
|
521
|
+
declare function partRenderSize(part: CdlDiagram): {
|
|
522
|
+
w: number;
|
|
523
|
+
h: number;
|
|
524
|
+
};
|
|
525
|
+
/**
|
|
526
|
+
* この見本が、図の中に描かれる部品を持っているか (#1017)。
|
|
527
|
+
*
|
|
528
|
+
* 見本の中には実体が **操作パネルの部品** (`readouts`) だけのものがある。 配置計算も描画も
|
|
529
|
+
* `readouts` を図の中では扱わないため、図として重ねても何も出ない。 位置決めのための
|
|
530
|
+
* 1x1 の箱が 1 つあるだけになる。
|
|
531
|
+
*
|
|
532
|
+
* catalog 80 件を測ると、この 2 群は `readouts` の有無で完全に分かれた。
|
|
533
|
+
* `readouts` を持つ 17 件は箱と図枠の面積比が全件 0.0000 (箱は 1x1)、
|
|
534
|
+
* 持たない 63 件は最小でも 0.1877。 境目に入る件は無い。
|
|
535
|
+
*
|
|
536
|
+
* 判定は面積の閾値ではなく **`readouts` を持ち、かつ箱が図枠に対して極小** の 2 条件で行う。
|
|
537
|
+
* 閾値だけで見ると、小さい箱を意図して置いた見本を巻き込む。 `readouts` だけで見ると、
|
|
538
|
+
* 箱も実体も両方持つ見本 (現状 0 件だが作れる) を誤って弾く。
|
|
539
|
+
*
|
|
540
|
+
* 測れない図では「持っている」 側に倒す。 弾く側に倒すと、測れないだけの見本が使えなくなる。
|
|
541
|
+
*/
|
|
542
|
+
declare function partDrawsInDiagram(part: CdlDiagram): boolean;
|
|
543
|
+
/**
|
|
544
|
+
* 図枠の中で、 箱の外接矩形がどこにどれだけの大きさで描かれるか (#1014)。
|
|
545
|
+
*
|
|
546
|
+
* `left` / `top` は図枠の左上からの余白、 `w` / `h` は箱の大きさ。 図枠は 1 対 1 で描かれるので、
|
|
547
|
+
* 画面上の箱の位置は「図枠の左上 + `left`/`top`」 になる。
|
|
548
|
+
*
|
|
549
|
+
* 相対で書いた位置 (`位置: Web の右 200`) の間隔は、 見えている箱の縁から測る。 図枠の縁で
|
|
550
|
+
* 測ると余白のぶんだけ広がる (実測 = 200 と書いて画面では 260 空いた)。 画面側が間隔を解く時に
|
|
551
|
+
* 図枠ではなくこちらを使うことで、 組み立て側と同じ間隔になる。
|
|
552
|
+
*
|
|
553
|
+
* 測れない図では図枠と同じ大きさ・余白 0 を返す。 箱を持たない図でも同じで、 図枠がそのまま
|
|
554
|
+
* 箱として扱われる。
|
|
555
|
+
*/
|
|
556
|
+
declare function partBoxInFrame(part: CdlDiagram): {
|
|
557
|
+
w: number;
|
|
558
|
+
h: number;
|
|
559
|
+
left: number;
|
|
560
|
+
top: number;
|
|
561
|
+
};
|
|
562
|
+
/**
|
|
563
|
+
* パーツ 1 個の箱の外接矩形。
|
|
564
|
+
*
|
|
565
|
+
* 図枠 (`partRenderSize`) とは別で、 余白を含まない。 相対指定を解く時の「縁からの距離」 に使う。
|
|
566
|
+
*/
|
|
567
|
+
declare function partVisualSize(part: CdlDiagram, targetW?: number, targetH?: number): {
|
|
568
|
+
w: number;
|
|
569
|
+
h: number;
|
|
570
|
+
};
|
|
571
|
+
/**
|
|
572
|
+
* 位置を書かなかったパーツを格子に並べた時の、 矩形の中心。
|
|
573
|
+
*
|
|
574
|
+
* 組み立て側 (`mergePartsFromActors`) と画面側 (playground の overlay) の両方から呼ぶ。
|
|
575
|
+
* 別々に計算すると、 同じ本文でも経路によってパーツの位置が変わる。
|
|
576
|
+
*
|
|
577
|
+
* 列の送り幅は並べる全パーツの最大幅で揃える。 個々の幅で送ると、 幅の違うパーツが混ざった時に
|
|
578
|
+
* 隣と重なる (実測 = 400 の次に 200 を置くと 280 重なった)。 段の高さも段内の最大高で揃える。
|
|
579
|
+
* 縦は自分の高さの半分だけ段の上端から下げて、 段内で上端を揃える。
|
|
580
|
+
*
|
|
581
|
+
* @param baseNodeCount パーツ以外の箱の数。 既存の図の下から並べ始めるために使う
|
|
582
|
+
*/
|
|
583
|
+
declare function partsGridCenters(baseNodeCount: number, items: ReadonlyArray<{
|
|
584
|
+
id: string;
|
|
585
|
+
w: number;
|
|
586
|
+
h: number;
|
|
587
|
+
}>): Map<string, {
|
|
588
|
+
cx: number;
|
|
589
|
+
cy: number;
|
|
590
|
+
}>;
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Text DSL v0.5 parser
|
|
594
|
+
*
|
|
595
|
+
* 設計方針:
|
|
596
|
+
* - keyword は英語のみ (title / type / actors / flow / states / animation / step / focus / tween / set / badge)
|
|
597
|
+
* - 値の日本語は quote 必須 (`title: "API call"` / `step: "request" 1.5s`)
|
|
598
|
+
* - YAML 風 + 短縮 keyword + 箇条書き構造
|
|
599
|
+
* - Mermaid 知ってる人にもゼロ学習、 非エンジニアにも直感的
|
|
600
|
+
*
|
|
601
|
+
* syntax 例:
|
|
602
|
+
*
|
|
603
|
+
* title: "API call"
|
|
604
|
+
* type: sequence
|
|
605
|
+
*
|
|
606
|
+
* actors:
|
|
607
|
+
* - Client
|
|
608
|
+
* - API: function
|
|
609
|
+
* - DB
|
|
610
|
+
*
|
|
611
|
+
* flow:
|
|
612
|
+
* - Client -> API: "GET /items"
|
|
613
|
+
* - API -> DB: "SELECT" (success)
|
|
614
|
+
*
|
|
615
|
+
* states:
|
|
616
|
+
* request_count: 0
|
|
617
|
+
* row_count: 0
|
|
618
|
+
*
|
|
619
|
+
* animation:
|
|
620
|
+
* - step: "request" 1.5s
|
|
621
|
+
* focus: [Client, API]
|
|
622
|
+
* tween:
|
|
623
|
+
* request_count: 0 -> 1
|
|
624
|
+
* badge: "request"
|
|
625
|
+
*
|
|
626
|
+
* - step: "query" 1.5s
|
|
627
|
+
* focus: [API, DB]
|
|
628
|
+
* tween:
|
|
629
|
+
* row_count: 0 -> 20
|
|
630
|
+
* badge: "query"
|
|
631
|
+
*
|
|
632
|
+
* 出力は v0.4 と同じ DslDocument。 既存 compile.ts で CdlDiagram に変換できる。
|
|
633
|
+
*/
|
|
634
|
+
|
|
635
|
+
type V05ParseResult = {
|
|
636
|
+
ok: true;
|
|
637
|
+
doc: DslDocument;
|
|
638
|
+
} | {
|
|
639
|
+
ok: false;
|
|
640
|
+
errors: DslError[];
|
|
641
|
+
};
|
|
642
|
+
/** 受け付ける図種。 記法一覧はここを見る。 */
|
|
643
|
+
declare const PRESET_TYPES: ReadonlySet<PresetType>;
|
|
644
|
+
/**
|
|
645
|
+
* 受け付ける箱の種類。 描画できる種類 (cdl の `NODE_KINDS`) に、 記法だけが持つ種類を足す。
|
|
646
|
+
*
|
|
647
|
+
* 以前は手書きの 31 種だった。 描画できる 90 種のうち 78 種が記法から書けず、 部品名として
|
|
648
|
+
* 扱われて「そんな部品は無い」 と警告が出るだけだった。 描画側を出所に加えることで
|
|
649
|
+
* 「描画できるものは書ける」 が成立する。
|
|
650
|
+
*/
|
|
651
|
+
/**
|
|
652
|
+
* 記法が受理する種類の全体。 これに載っていない種類は見本 (パーツ) の候補になる。
|
|
653
|
+
*
|
|
654
|
+
* 画面側が「本文が見本を使っているか」 を判定するのに使う (#1022)。 手書きの一覧を
|
|
655
|
+
* 別に持つと、種類が増えた時にそちらだけ取り残されて余分な読み込みが起きる。
|
|
656
|
+
*/
|
|
657
|
+
declare const NODE_KIND_VALID: ReadonlySet<string>;
|
|
658
|
+
declare function parseTextDslV05(src: string): V05ParseResult;
|
|
659
|
+
/**
|
|
660
|
+
* 対応する引用符だけを外す。
|
|
661
|
+
*
|
|
662
|
+
* 先頭と末尾を別々に外すと、対応しない形 (`'300,200"`) が中身だけ取り出せてしまう。
|
|
663
|
+
* 画面側も同じ関数を使う (#1028) = 別々に持つと、片方だけが読める本文ができる。
|
|
664
|
+
*/
|
|
665
|
+
declare function stripQuotes(s: string): string;
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* Text DSL i18n キーワード一覧
|
|
669
|
+
* 日本語 / 英語両対応 (大文字小文字無視)
|
|
670
|
+
*/
|
|
671
|
+
|
|
672
|
+
/** NodeKind 別名 (日本語 → English) */
|
|
673
|
+
declare const NODE_KIND_ALIAS: Record<string, NodeKind>;
|
|
674
|
+
/** Tone 別名 */
|
|
675
|
+
declare const TONE_ALIAS: Record<string, Tone>;
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* Notation lint (author 向け修正システム)。
|
|
679
|
+
*
|
|
680
|
+
* cdl / dragon 記法で書かれた CdlDiagram を rule-based に検査し、
|
|
681
|
+
* 「もっと良い書き方」 を suggestion として返す純粋関数。 LLM 不要、 rule のみ。
|
|
682
|
+
*
|
|
683
|
+
* 検知システム (`check:cdl` / `check:dragon` / `check:kind`) は開発陣向けで
|
|
684
|
+
* 「実装バグ」 を検出するが、 本 notation-lint は **author 向け** で
|
|
685
|
+
* 「書き方の癖 / 冗長表現 / 未定義参照 / 空 payload」 等を検出する。
|
|
686
|
+
*
|
|
687
|
+
* 使い方:
|
|
688
|
+
* import { lintDiagram } from "@cardenelabs/dragon";
|
|
689
|
+
* const report = lintDiagram(diagram);
|
|
690
|
+
* // report.issues[] = LintIssue[]
|
|
691
|
+
* // report.fixed = LintIssue[] のうち自動修正で解消される件
|
|
692
|
+
* // report.autoFix(diagram) = 修正済 CdlDiagram
|
|
693
|
+
*
|
|
694
|
+
* CLI:
|
|
695
|
+
* pnpm dragon-lint apps/playground-spa/src/topics/catalog/presets.cdl.ts
|
|
696
|
+
*/
|
|
697
|
+
|
|
698
|
+
type LintSeverity = "warn" | "info";
|
|
699
|
+
type LintIssue = {
|
|
700
|
+
/** rule 識別子 */
|
|
701
|
+
rule: string;
|
|
702
|
+
severity: LintSeverity;
|
|
703
|
+
/** 該当対象 (node id / edge id / diagram id) */
|
|
704
|
+
target: string;
|
|
705
|
+
/** 人間向けメッセージ */
|
|
706
|
+
message: string;
|
|
707
|
+
/** 修正案 (自動修正可能なら適用後の値、 手動修正必要なら null) */
|
|
708
|
+
suggestion?: string;
|
|
709
|
+
/** autoFix() が本 issue を自動解消できるか */
|
|
710
|
+
autoFixable: boolean;
|
|
711
|
+
};
|
|
712
|
+
type LintReport = {
|
|
713
|
+
diagramId: string;
|
|
714
|
+
issues: LintIssue[];
|
|
715
|
+
/** autoFix() が実際に解消できる issue の数 */
|
|
716
|
+
autoFixableCount: number;
|
|
717
|
+
};
|
|
718
|
+
/**
|
|
719
|
+
* 検査対象 diagram の全 rule を実行し LintReport を返す。
|
|
720
|
+
* 全 rule は純粋 (副作用なし / LLM 呼び出しなし)。
|
|
721
|
+
*/
|
|
722
|
+
declare function lintDiagram(d: CdlDiagram): LintReport;
|
|
723
|
+
/**
|
|
724
|
+
* lintDiagram で detected な issue のうち autoFixable=true のものを機械的に適用して
|
|
725
|
+
* 修正済 CdlDiagram を返す。 手動修正必要な issue は残る (次回 lint 時に再検出)。
|
|
726
|
+
*/
|
|
727
|
+
declare function autoFix(d: CdlDiagram): CdlDiagram;
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* canvas pivot 新 spec 図境界計算 helper (dragon canvas pivot spec §diagram-boundary)。
|
|
731
|
+
*
|
|
732
|
+
* 図の bounding box (点線四角) を「構成パーツの外接矩形 + 余白」 で計算する SSOT。
|
|
733
|
+
* CDL の layout() を呼んで LaidDiagram.viewBox から外接矩形を取得し、 spec 準拠の 20px 余白を加える。
|
|
734
|
+
*
|
|
735
|
+
* 用途:
|
|
736
|
+
* - dragon editor で drag 中の overlay が「図の中」 に入ったか判定 (spec §4 自動調整発動)
|
|
737
|
+
* - dragon renderer で図 hover 時に dashed rect を描画 (spec 項目 4 の視覚 UI)
|
|
738
|
+
* - PR-B 以降で drag / resize / snap 判定の base rect として参照
|
|
739
|
+
*/
|
|
740
|
+
|
|
741
|
+
/** 図境界の padding (SVG unit)、 spec §diagram-boundary で 20 と定めた */
|
|
742
|
+
declare const DIAGRAM_BOUNDARY_PADDING = 20;
|
|
743
|
+
type DiagramBoundingBox = {
|
|
744
|
+
x: number;
|
|
745
|
+
y: number;
|
|
746
|
+
width: number;
|
|
747
|
+
height: number;
|
|
748
|
+
};
|
|
749
|
+
/**
|
|
750
|
+
* CdlDiagram の外接矩形 + 20px 余白を計算する。
|
|
751
|
+
* layout() が返す LaidDiagram.viewBox は既に全 element を包む rect (右端 +80 / 下端 +80 の CDL 既定余白付き)。
|
|
752
|
+
* それにさらに spec 準拠の 20px を加えて figure 判定 buffer とする。
|
|
753
|
+
*/
|
|
754
|
+
declare function computeDiagramBoundingBox(diag: CdlDiagram): DiagramBoundingBox;
|
|
755
|
+
/**
|
|
756
|
+
* bbox 同士の重なり判定 (dragon canvas pivot spec §4 図内 drag 判定 SSOT)。
|
|
757
|
+
* user 明示 「1 部でも重なれば中」 = 交差面積 > 0 を判定。
|
|
758
|
+
*/
|
|
759
|
+
declare function rectsOverlap(a: DiagramBoundingBox, b: DiagramBoundingBox): boolean;
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* 光らせる相手 (`focus:`) の書き方を読む。
|
|
763
|
+
*
|
|
764
|
+
* 書き方は 2 通り。 箱の名前 1 つか、 矢印 (`A -> B`) で 2 者を指す形。
|
|
765
|
+
*
|
|
766
|
+
* 読み方をここに 1 つだけ置く。 id の形は図種で違う (順序図は縦列の上端 / 下端 / 手順箱、
|
|
767
|
+
* 流れ図は箱 1 個) ため id への解決は図種ごとに残すが、 「どちらの書き方か」 の判断を
|
|
768
|
+
* 図種ごとに持つと、 同じ記述が図種によって別の意味になる。
|
|
769
|
+
*
|
|
770
|
+
* 以前は図種ごとに判定していて、 順序図と汎用の 2 経路が `-` 1 文字を矢印と見なしていた。
|
|
771
|
+
* その結果 `api-gateway` のような名前が「api から gateway への矢印」 と読まれ、 順序図では
|
|
772
|
+
* 光らず、 流れ図では名前に部分一致した別の矢印が光っていた (実測)。
|
|
773
|
+
*/
|
|
774
|
+
/** 光らせる相手の指定。 */
|
|
775
|
+
type FocusEntry = {
|
|
776
|
+
kind: "edge";
|
|
777
|
+
from: string;
|
|
778
|
+
to: string;
|
|
779
|
+
} | {
|
|
780
|
+
kind: "node";
|
|
781
|
+
name: string;
|
|
782
|
+
};
|
|
783
|
+
/**
|
|
784
|
+
* 書かれた 1 件を読む。
|
|
785
|
+
*
|
|
786
|
+
* 矢印の両側は 1 文字以上を要求するので、 片側だけの形 (`-> API` / `API ->`) は矢印に
|
|
787
|
+
* ならず名前として読まれる。
|
|
788
|
+
*
|
|
789
|
+
* `knownNames` に一致する名前は矢印より先に名前として読む。 引用符付きで矢印を含む名前
|
|
790
|
+
* (`"A -> B"`) を書いた箱は実在し得るので、 常に矢印と読むと光らせられない (実測 = 名前が
|
|
791
|
+
* 一致する箱があるのに何も光らず、 「矢印が流れにありません」 と誤報した)。
|
|
792
|
+
*
|
|
793
|
+
* @param knownNames 実在する箱の名前。 渡さない場合は書き方だけで判断する
|
|
794
|
+
*/
|
|
795
|
+
declare function parseFocusEntry(raw: string, knownNames?: ReadonlySet<string>): FocusEntry;
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* 登場人物 1 人の位置を DSL 本文に書き込む。
|
|
799
|
+
*
|
|
800
|
+
* editor の画面で見えている座標を、 そのまま記法に落とすために使う。 書く人は図を見ながら
|
|
801
|
+
* 数値を決められないので、 今の位置を出発点として渡す経路が要る。
|
|
802
|
+
*
|
|
803
|
+
* 記法を知っているのは本 package なので、 本文の書き換えもここに置く。 画面側に置くと
|
|
804
|
+
* 記法が増えた時に画面側だけが取り残される。
|
|
805
|
+
*
|
|
806
|
+
* 書き方は 4 通りあり、 元の形を保ったまま位置だけを差し替える。 形を勝手に揃えると、
|
|
807
|
+
* 書いた人の見た目が変わって差分が読めなくなる。
|
|
808
|
+
*/
|
|
809
|
+
/** 位置の書き込み結果。 対象が見つからなければ null。 */
|
|
810
|
+
declare function writeActorPosition(src: string, actorName: string, posX: number, posY: number): string | null;
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* 色として読める値かの判定と、 図から外部参照を落とす処理 (#1004)。
|
|
814
|
+
*
|
|
815
|
+
* 図の中の文字列は最終的に SVG の属性になる。 色を塗る位置 (`fill` / `stroke` 等) に
|
|
816
|
+
* `url(https://example.invalid/x)` が入ると、 図を開いた人の環境からその URL へ要求が飛ぶ。
|
|
817
|
+
* 書き出した SVG を配布しても同じことが起きる。
|
|
818
|
+
*
|
|
819
|
+
* 入口は 1 つではない (状態の上書き / phase の `set` / 画面が直接書く背景色 / 埋め込んだ JSON)。
|
|
820
|
+
* 入口ごとに塞ぐと 1 つ見落とした時に穴が残るため、 **組み立ての最後に図全体を走査する**
|
|
821
|
+
* 出口の検査を置く。 入口側の判定 (`isColorValue`) は「正しい図を保つ」 ため、
|
|
822
|
+
* 出口の検査 (`stripExternalPaint`) は「漏れを塞ぐ」 ための二重の構えになっている。
|
|
823
|
+
*/
|
|
824
|
+
/**
|
|
825
|
+
* 色として読める値か。
|
|
826
|
+
*
|
|
827
|
+
* 状態の値は node の `fill` にそのまま入る。 そのため「色の状態を探す」 判定と
|
|
828
|
+
* 「上書きを受け入れるか」 の判定は同じ物差しでなければならない。 別々に持つと、
|
|
829
|
+
* 片方だけ直した時に片方が通してしまう。
|
|
830
|
+
*
|
|
831
|
+
* 通すのは 16 進の 3 形 (`#rgb` / `#rrggbb` / `#rrggbbaa`) と、 標準の色名。
|
|
832
|
+
* 桁数を絞るのは、 `#1234` のような半端な形を色として扱うと描画側の解釈に委ねる範囲が
|
|
833
|
+
* 広がるため。 見本のすべての色が 3 形に収まることは `parts-color-hex-format.test.ts` が検査している。
|
|
834
|
+
*
|
|
835
|
+
* `rgb(...)` / `hsl(...)` は通さない。 括弧を含む形を許すと、 括弧の中身を見る判定が要る。
|
|
836
|
+
* 見本のどのパーツも使っておらず、 通す理由が無い。
|
|
837
|
+
*/
|
|
838
|
+
declare function isColorValue(v: unknown): v is string;
|
|
839
|
+
/**
|
|
840
|
+
* 図の外側を指す値か。
|
|
841
|
+
*
|
|
842
|
+
* SVG の `url(...)` は図の中の定義 (`url(#gradient-1)`) も指せる。 これは正当な用途なので、
|
|
843
|
+
* 括弧の中が `#` で始まる形だけを残し、 それ以外を外向きとみなす。
|
|
844
|
+
*
|
|
845
|
+
* 空白と大文字小文字は無視する。 `URL( https://... )` のような書き方で判定を抜けられないため。
|
|
846
|
+
*/
|
|
847
|
+
declare function pointsOutside(v: unknown): boolean;
|
|
848
|
+
/** 落とした場所と値。 呼出側が書いた人に知らせるために使う */
|
|
849
|
+
type StrippedPaint = {
|
|
850
|
+
path: string;
|
|
851
|
+
value: string;
|
|
852
|
+
};
|
|
853
|
+
/**
|
|
854
|
+
* 図の中から、 色を塗る位置に入った外部参照を落とす。
|
|
855
|
+
*
|
|
856
|
+
* 対象は 2 種類ある。
|
|
857
|
+
*
|
|
858
|
+
* - 色を塗る key (`fill` / `stroke` / `bg` 等) の値
|
|
859
|
+
* - 状態の値 (`states[].initial` と、 phase が状態へ入れる値)。 状態は `{名前}` の形で
|
|
860
|
+
* `fill` に差し込まれるため、 色を塗る位置に届く
|
|
861
|
+
*
|
|
862
|
+
* 説明文 (`title` / `subtitle` / `value` / `rows`) は対象外。 文字として出るだけで
|
|
863
|
+
* 属性にはならないため、 URL を書く正当な用途を壊さない。
|
|
864
|
+
*
|
|
865
|
+
* 図を直接書き換える (返り値ではなく引数を変える)。 組み立ての最後に 1 度だけ呼ぶ前提。
|
|
866
|
+
*/
|
|
867
|
+
declare function stripExternalPaint(diagram: unknown): StrippedPaint[];
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* 図を組み立てる前に、 大きすぎる入力を止める (#1005)。
|
|
871
|
+
*
|
|
872
|
+
* 組み立てにかかる時間は要素数の 2 乗で伸びる。 実測 (要素だけを並べた形)。
|
|
873
|
+
*
|
|
874
|
+
* | 要素 | 組み立て |
|
|
875
|
+
* |---|---|
|
|
876
|
+
* | 1,000 | 104ms |
|
|
877
|
+
* | 2,000 | 346ms |
|
|
878
|
+
* | 5,000 | 1,647ms |
|
|
879
|
+
* | 10,000 | 7,622ms |
|
|
880
|
+
*
|
|
881
|
+
* 待機 (500ms) の後に同じ流れの中で走るため、 この間 editor は操作を受け付けない。
|
|
882
|
+
* 貼ってしまうと tab を閉じるまで戻らない。
|
|
883
|
+
*
|
|
884
|
+
* 見本 (catalog) は 1 図あたり平均 4 要素、 最も多い file でも平均 7 要素。 実用の規模と
|
|
885
|
+
* 1 秒の境界 (約 3,000 要素) は桁が 2-3 つ違うため、 上限を置いても正当な図には当たらない。
|
|
886
|
+
*
|
|
887
|
+
* 既にある `dom-complexity-budget` (400 要素) とは別物。 あちらは組み立てた**後**に
|
|
888
|
+
* 「見やすさ」 の観点で警告を出すだけで、 組み立て自体は走る。 こちらは組み立てる**前**に
|
|
889
|
+
* 「固まらない」 ために止める。 400-2,000 の範囲は従来どおり警告が出て図も描ける。
|
|
890
|
+
*/
|
|
891
|
+
/** 組み立てを止める要素数。 1 秒を明確に下回る水準に置く (2,000 要素で約 350ms) */
|
|
892
|
+
declare const MAX_INPUT_ELEMENTS = 2000;
|
|
893
|
+
/**
|
|
894
|
+
* 組み立てを止める本文の大きさ (byte)。
|
|
895
|
+
*
|
|
896
|
+
* 要素数だけでは、 1 要素に極端に長い文字列を持つ形を捉えられない。 読み取り自体は速い
|
|
897
|
+
* (10,000 要素 98,936 byte で 2ms) ので、 実用の余裕を大きく取って置く。
|
|
898
|
+
*/
|
|
899
|
+
declare const MAX_INPUT_BYTES: number;
|
|
900
|
+
/** 数えた結果。 超過した時に何がどれだけ超えたかを画面に出すために使う */
|
|
901
|
+
interface InputSize {
|
|
902
|
+
elements: number;
|
|
903
|
+
bytes: number;
|
|
904
|
+
}
|
|
905
|
+
/**
|
|
906
|
+
* 記法の解析結果から要素数を数える。
|
|
907
|
+
*
|
|
908
|
+
* 数えるのは組み立ての重さに効くもの = 要素 / 流れ / 段 / 状態 / 段組み。
|
|
909
|
+
* 図の題名や表示の設定は数に入れない (何件あっても重さが変わらない)。
|
|
910
|
+
*
|
|
911
|
+
* **段の中身 (光らせる相手 / 遷移 / 即時変更) も数える**。 段の数だけを見ると、
|
|
912
|
+
* 1 段に 1,000 件の相手を書いた形が 1 件として通る。 実測ではこの形が組み立ての中で
|
|
913
|
+
* 約 100 万件に展開され、 呼び出しの深さが上限を超えて落ちた。
|
|
914
|
+
*/
|
|
915
|
+
declare function countDocElements(doc: DslDocument): number;
|
|
916
|
+
/**
|
|
917
|
+
* 組み立て済みの図から要素数を数える。
|
|
918
|
+
*
|
|
919
|
+
* 記法を通らない入口 (本文に埋め込んだ図の定義) 用。 解析結果が無いため、 図の側で数える。
|
|
920
|
+
*
|
|
921
|
+
* **段の中身と読み取り部品も数える**。 段を 1 件として数えるだけだと、段の中に 10,000 件の
|
|
922
|
+
* 光らせる指定を持つ図が「1 要素」 と判定されて素通りする (実測)。 記法側の数え方
|
|
923
|
+
* (`countDocElements`) は段の中身を足しているので、こちらも揃える。
|
|
924
|
+
*/
|
|
925
|
+
declare function countDiagramElements(diagram: {
|
|
926
|
+
nodes?: unknown[];
|
|
927
|
+
edges?: unknown[];
|
|
928
|
+
lanes?: unknown[];
|
|
929
|
+
states?: unknown[];
|
|
930
|
+
phases?: unknown[];
|
|
931
|
+
readouts?: unknown[];
|
|
932
|
+
inputs?: unknown[];
|
|
933
|
+
formulas?: unknown[];
|
|
934
|
+
scrollTriggers?: unknown[];
|
|
935
|
+
eventBindings?: unknown[];
|
|
936
|
+
}): number;
|
|
937
|
+
/** 本文の大きさを byte で数える (文字数ではなく実際の大きさ) */
|
|
938
|
+
declare function countBytes(src: string): number;
|
|
939
|
+
/**
|
|
940
|
+
* 大きすぎる入力なら、 その旨を伝える文を返す。 収まっていれば `null`。
|
|
941
|
+
*
|
|
942
|
+
* 投げるのではなく文を返すのは、 呼出側が「誤りとして表示する」 か「別の扱いにする」 かを
|
|
943
|
+
* 選べるようにするため。
|
|
944
|
+
*
|
|
945
|
+
* `bytes` に 0 を渡すと大きさの検査を飛ばす (要素数だけを見たい合流点で使う)。
|
|
946
|
+
*/
|
|
947
|
+
declare function describeOversize(size: InputSize): string | null;
|
|
948
|
+
/**
|
|
949
|
+
* 本文が大きすぎるなら、 その旨を伝える文を返す。 収まっていれば `null`。
|
|
950
|
+
*
|
|
951
|
+
* **読み取る前に呼ぶ**。 要素数の上限は読み取った後にしか分からないため、 巨大な本文を
|
|
952
|
+
* 渡された時の読み取り自体 (11.9MB で記憶 200MB) を防げない。
|
|
953
|
+
*/
|
|
954
|
+
declare function describeOversizeSource(src: string): string | null;
|
|
955
|
+
|
|
956
|
+
/**
|
|
957
|
+
* LLM 向け JSON DSL parser。
|
|
958
|
+
*
|
|
959
|
+
* dragon の YAML DSL と 1:1 対応する JSON 記法を提供する。
|
|
960
|
+
* LLM (Anthropic Claude / OpenAI GPT) が structured output (tool call / response_format)
|
|
961
|
+
* で確実に生成できるよう、 flat な object array を優先した shape になっている。
|
|
962
|
+
*
|
|
963
|
+
* 使い方 (LLM):
|
|
964
|
+
* 1. `packages/dragon/schemas/diagram.json` の JSON Schema を LLM の tool schema に注入
|
|
965
|
+
* 2. LLM が JSON を返す
|
|
966
|
+
* 3. `jsonToDiagram(json)` で CdlDiagram に変換
|
|
967
|
+
* 4. validation error は throw、 retry loop で LLM に修正させる
|
|
968
|
+
*
|
|
969
|
+
* YAML との対応:
|
|
970
|
+
* YAML `title: "..."` ⇔ JSON `{title: "..."}`
|
|
971
|
+
* YAML `actors: [A, B: kind]` ⇔ JSON `{actors: [{name: "A"}, {name: "B", kind: "storage"}]}`
|
|
972
|
+
* YAML `flow: [- A -> B: "label"]` ⇔ JSON `{flow: [{from: "A", to: "B", label: "label"}]}`
|
|
973
|
+
* YAML `animation: [step: "..."]` ⇔ JSON `{animation: [{step: "...", duration: 1.4, focus: [...]}]}`
|
|
974
|
+
*/
|
|
975
|
+
|
|
976
|
+
/**
|
|
977
|
+
* LLM 向け JSON DSL の入力 shape。 YAML DSL と 1:1 対応、 top-level は flat な object。
|
|
978
|
+
*/
|
|
979
|
+
interface DragonJson {
|
|
980
|
+
/** 図の title (必須) */
|
|
981
|
+
title: string;
|
|
982
|
+
/** preset type (必須): sequence / flow / swimlane / er / state / topology / solidity / gantt / class / pie / c4 / mind */
|
|
983
|
+
type: PresetType;
|
|
984
|
+
/** 登場人物 (必須): 文字列 or { name, kind, ... } object */
|
|
985
|
+
actors: (string | JsonActor)[];
|
|
986
|
+
/** flow step 配列 (必須): { from, to, label, ... } */
|
|
987
|
+
flow: JsonStep[];
|
|
988
|
+
/** animation phase 配列 (optional) */
|
|
989
|
+
animation?: JsonPhase[];
|
|
990
|
+
/** viewport (optional): 全体 canvas size / gap */
|
|
991
|
+
viewport?: {
|
|
992
|
+
width?: number;
|
|
993
|
+
height?: number;
|
|
994
|
+
laneWidth?: number;
|
|
995
|
+
gap?: number;
|
|
996
|
+
laneGap?: number;
|
|
997
|
+
nodeGap?: number;
|
|
998
|
+
labelMargin?: number;
|
|
999
|
+
};
|
|
1000
|
+
/** lanes (optional): topology / swimlane preset で使う lane 宣言 */
|
|
1001
|
+
lanes?: Record<string, {
|
|
1002
|
+
x?: number;
|
|
1003
|
+
width?: number;
|
|
1004
|
+
label?: string;
|
|
1005
|
+
contain?: boolean;
|
|
1006
|
+
lifeline?: boolean;
|
|
1007
|
+
/**
|
|
1008
|
+
* canvas pivot (CAR-1693 Phase 1) DSL 表面 `pos: {x, y}` = auto layout offset。 未指定は
|
|
1009
|
+
* backward compat、 set 済は Phase 2 の applyPosOffset で lane 位置を shift する。
|
|
1010
|
+
*/
|
|
1011
|
+
pos?: LayoutPos;
|
|
1012
|
+
}>;
|
|
1013
|
+
/** groups (optional): topology preset で使う group 宣言 */
|
|
1014
|
+
groups?: Record<string, {
|
|
1015
|
+
label?: string;
|
|
1016
|
+
lanes: string[];
|
|
1017
|
+
}>;
|
|
1018
|
+
/**
|
|
1019
|
+
* canvas pivot (CAR-1693 Phase 1) diagram-level layout mode。 "auto" (default) は catalog 100+
|
|
1020
|
+
* backward compat、 "manual" は Phase 4 で drag → pos: 保存の完全 manual mode として使う予定。
|
|
1021
|
+
*/
|
|
1022
|
+
layout?: LayoutMode;
|
|
1023
|
+
}
|
|
1024
|
+
interface JsonActor {
|
|
1025
|
+
name: string;
|
|
1026
|
+
/**
|
|
1027
|
+
* CAR-1657 unified syntax = 既存 NodeKind (28 個) に加えて parts identifier (arc-gauge 等) を
|
|
1028
|
+
* accept する。 未知 kind 値は parts 候補として partId に格納、 compile 側 partsCatalog で解決。
|
|
1029
|
+
* LLM structured output の typing 制約を緩めるため union に string 追加。
|
|
1030
|
+
* `string & {}` = NodeKind の候補を IDE 補完で提示しつつ任意 string も許容する idiom。
|
|
1031
|
+
* 素の `NodeKind | string` は no-redundant-type-constituents に抵触し補完も潰れる (#865)。
|
|
1032
|
+
*/
|
|
1033
|
+
kind?: NodeKind | (string & {});
|
|
1034
|
+
subtitle?: string;
|
|
1035
|
+
eyebrow?: string;
|
|
1036
|
+
value?: string;
|
|
1037
|
+
rows?: string[];
|
|
1038
|
+
lane?: string;
|
|
1039
|
+
stack?: number;
|
|
1040
|
+
initial?: boolean;
|
|
1041
|
+
final?: boolean;
|
|
1042
|
+
/**
|
|
1043
|
+
* canvas pivot (CAR-1693 Phase 1) DSL 表面 `pos: {x, y}` = auto layout offset。 未指定は
|
|
1044
|
+
* backward compat、 set 済は Phase 2 の applyPosOffset で actor 由来 lane / node の位置を shift。
|
|
1045
|
+
*/
|
|
1046
|
+
pos?: LayoutPos;
|
|
1047
|
+
/**
|
|
1048
|
+
* CAR-1657 parts state override (kind = parts identifier 時のみ有効)。
|
|
1049
|
+
* LLM JSON DSL では nested 明示 = `{ "state": { "v": 50 } }` が natural、 human 側の
|
|
1050
|
+
* inline 拡散 pattern (`- arc1: { kind: arc-gauge, v: 50 }`) とは記述形式が分岐する
|
|
1051
|
+
* (spec § 2.3 分岐設計、 human = YAML 手書き最適 / LLM = JSON structured 最適)。
|
|
1052
|
+
*/
|
|
1053
|
+
state?: Record<string, number | string | boolean>;
|
|
1054
|
+
}
|
|
1055
|
+
interface JsonStep {
|
|
1056
|
+
from: string;
|
|
1057
|
+
to: string;
|
|
1058
|
+
label: string;
|
|
1059
|
+
sub?: string;
|
|
1060
|
+
tone?: Tone;
|
|
1061
|
+
style?: EdgeStyle;
|
|
1062
|
+
guard?: string;
|
|
1063
|
+
cardinality?: string;
|
|
1064
|
+
labelOffsetX?: number;
|
|
1065
|
+
labelOffsetY?: number;
|
|
1066
|
+
/**
|
|
1067
|
+
* canvas pivot (CAR-1693 Phase 1) DSL 表面 `pos: {x, y}` = edge label offset。 未指定は
|
|
1068
|
+
* backward compat、 set 済は Phase 2 の applyPosOffset で edge label 位置を shift する。
|
|
1069
|
+
*/
|
|
1070
|
+
pos?: LayoutPos;
|
|
1071
|
+
}
|
|
1072
|
+
interface JsonPhase {
|
|
1073
|
+
/** phase name (必須) */
|
|
1074
|
+
step: string;
|
|
1075
|
+
/** duration in seconds (default 1.4) */
|
|
1076
|
+
duration?: number;
|
|
1077
|
+
/** highlight 対象 (actor name / edge "A -> B") */
|
|
1078
|
+
focus?: string[];
|
|
1079
|
+
/** body 説明文 */
|
|
1080
|
+
body?: string;
|
|
1081
|
+
/** badge label */
|
|
1082
|
+
badge?: string;
|
|
1083
|
+
}
|
|
1084
|
+
/**
|
|
1085
|
+
* JSON DSL error。 line 概念がないため、 field path (JSON pointer style) で位置を示す。
|
|
1086
|
+
*/
|
|
1087
|
+
interface JsonDslError {
|
|
1088
|
+
path: string;
|
|
1089
|
+
message: string;
|
|
1090
|
+
hint?: string;
|
|
1091
|
+
}
|
|
1092
|
+
/**
|
|
1093
|
+
* LLM 向け JSON DSL の parse + compile 一発変換。
|
|
1094
|
+
*
|
|
1095
|
+
* @param json - DragonJson shape の object (parsed JSON、 not string)
|
|
1096
|
+
* @returns CdlDiagram (@cardenelabs/cdl の CdlDiagramView 等に渡せる)
|
|
1097
|
+
* @throws Error - validation error + hint 付きの詳細メッセージ、 LLM に retry させるための情報を含む
|
|
1098
|
+
*
|
|
1099
|
+
* @example
|
|
1100
|
+
* const diagram = jsonToDiagram({
|
|
1101
|
+
* title: "ログインAPI",
|
|
1102
|
+
* type: "sequence",
|
|
1103
|
+
* actors: ["User", "API", { name: "DB", kind: "storage" }],
|
|
1104
|
+
* flow: [
|
|
1105
|
+
* { from: "User", to: "API", label: "login" },
|
|
1106
|
+
* { from: "API", to: "DB", label: "SELECT" },
|
|
1107
|
+
* ],
|
|
1108
|
+
* animation: [
|
|
1109
|
+
* { step: "call", duration: 1.4, focus: ["User", "API"] },
|
|
1110
|
+
* ],
|
|
1111
|
+
* });
|
|
1112
|
+
*/
|
|
1113
|
+
declare function jsonToDiagram(json: unknown, opts?: {
|
|
1114
|
+
partsCatalog?: Record<string, CdlDiagram>;
|
|
1115
|
+
}): CdlDiagram;
|
|
1116
|
+
/**
|
|
1117
|
+
* JSON DSL を validate だけ実施 (compile しない)。 error 詳細を配列で取得したい場合に使う。
|
|
1118
|
+
* LLM の structured output の retry loop で、 error path を prompt に注入する用途。
|
|
1119
|
+
*/
|
|
1120
|
+
declare function validateDragonJson(json: unknown): {
|
|
1121
|
+
ok: true;
|
|
1122
|
+
data: DragonJson;
|
|
1123
|
+
} | {
|
|
1124
|
+
ok: false;
|
|
1125
|
+
errors: JsonDslError[];
|
|
1126
|
+
};
|
|
1127
|
+
|
|
1128
|
+
/**
|
|
1129
|
+
* JSON Schema を TypeScript から使えるように export。
|
|
1130
|
+
*
|
|
1131
|
+
* 使い方 (LLM 呼出):
|
|
1132
|
+
* import Anthropic from "@anthropic-ai/sdk";
|
|
1133
|
+
* import { diagramJsonSchema, jsonToDiagram } from "@cardenelabs/dragon";
|
|
1134
|
+
* const client = new Anthropic();
|
|
1135
|
+
* const res = await client.messages.create({
|
|
1136
|
+
* model: "claude-sonnet-5",
|
|
1137
|
+
* max_tokens: 4096,
|
|
1138
|
+
* tools: [{ name: "create_diagram", description: "...", input_schema: diagramJsonSchema }],
|
|
1139
|
+
* messages: [{ role: "user", content: "..." }],
|
|
1140
|
+
* });
|
|
1141
|
+
* const diagram = jsonToDiagram(res.content[0].input);
|
|
1142
|
+
*
|
|
1143
|
+
* schema JSON は `packages/dragon/schemas/diagram.json` が SSOT、 本 file は import して再 export するだけ。
|
|
1144
|
+
*/
|
|
1145
|
+
/**
|
|
1146
|
+
* Dragon DSL JSON Schema (Draft 7)。 Anthropic / OpenAI の tool schema にそのまま注入可能。
|
|
1147
|
+
*/
|
|
1148
|
+
declare const diagramJsonSchema: {
|
|
1149
|
+
$schema: string;
|
|
1150
|
+
$id: string;
|
|
1151
|
+
title: string;
|
|
1152
|
+
description: string;
|
|
1153
|
+
type: string;
|
|
1154
|
+
required: string[];
|
|
1155
|
+
additionalProperties: boolean;
|
|
1156
|
+
properties: {
|
|
1157
|
+
title: {
|
|
1158
|
+
type: string;
|
|
1159
|
+
minLength: number;
|
|
1160
|
+
description: string;
|
|
1161
|
+
};
|
|
1162
|
+
type: {
|
|
1163
|
+
type: string;
|
|
1164
|
+
enum: string[];
|
|
1165
|
+
description: string;
|
|
1166
|
+
};
|
|
1167
|
+
actors: {
|
|
1168
|
+
type: string;
|
|
1169
|
+
minItems: number;
|
|
1170
|
+
description: string;
|
|
1171
|
+
items: {
|
|
1172
|
+
oneOf: ({
|
|
1173
|
+
type: string;
|
|
1174
|
+
description: string;
|
|
1175
|
+
required?: undefined;
|
|
1176
|
+
additionalProperties?: undefined;
|
|
1177
|
+
properties?: undefined;
|
|
1178
|
+
} | {
|
|
1179
|
+
type: string;
|
|
1180
|
+
required: string[];
|
|
1181
|
+
additionalProperties: boolean;
|
|
1182
|
+
properties: {
|
|
1183
|
+
name: {
|
|
1184
|
+
type: string;
|
|
1185
|
+
minLength: number;
|
|
1186
|
+
description: string;
|
|
1187
|
+
};
|
|
1188
|
+
kind: {
|
|
1189
|
+
type: string;
|
|
1190
|
+
description: string;
|
|
1191
|
+
};
|
|
1192
|
+
subtitle: {
|
|
1193
|
+
type: string;
|
|
1194
|
+
description: string;
|
|
1195
|
+
};
|
|
1196
|
+
eyebrow: {
|
|
1197
|
+
type: string;
|
|
1198
|
+
description: string;
|
|
1199
|
+
};
|
|
1200
|
+
value: {
|
|
1201
|
+
type: string;
|
|
1202
|
+
description: string;
|
|
1203
|
+
};
|
|
1204
|
+
rows: {
|
|
1205
|
+
type: string;
|
|
1206
|
+
items: {
|
|
1207
|
+
type: string;
|
|
1208
|
+
};
|
|
1209
|
+
description: string;
|
|
1210
|
+
};
|
|
1211
|
+
lane: {
|
|
1212
|
+
type: string;
|
|
1213
|
+
description: string;
|
|
1214
|
+
};
|
|
1215
|
+
stack: {
|
|
1216
|
+
type: string;
|
|
1217
|
+
minimum: number;
|
|
1218
|
+
description: string;
|
|
1219
|
+
};
|
|
1220
|
+
initial: {
|
|
1221
|
+
type: string;
|
|
1222
|
+
description: string;
|
|
1223
|
+
};
|
|
1224
|
+
final: {
|
|
1225
|
+
type: string;
|
|
1226
|
+
description: string;
|
|
1227
|
+
};
|
|
1228
|
+
};
|
|
1229
|
+
description?: undefined;
|
|
1230
|
+
})[];
|
|
1231
|
+
};
|
|
1232
|
+
};
|
|
1233
|
+
flow: {
|
|
1234
|
+
type: string;
|
|
1235
|
+
description: string;
|
|
1236
|
+
items: {
|
|
1237
|
+
type: string;
|
|
1238
|
+
required: string[];
|
|
1239
|
+
additionalProperties: boolean;
|
|
1240
|
+
properties: {
|
|
1241
|
+
from: {
|
|
1242
|
+
type: string;
|
|
1243
|
+
description: string;
|
|
1244
|
+
};
|
|
1245
|
+
to: {
|
|
1246
|
+
type: string;
|
|
1247
|
+
description: string;
|
|
1248
|
+
};
|
|
1249
|
+
label: {
|
|
1250
|
+
type: string;
|
|
1251
|
+
description: string;
|
|
1252
|
+
};
|
|
1253
|
+
sub: {
|
|
1254
|
+
type: string;
|
|
1255
|
+
description: string;
|
|
1256
|
+
};
|
|
1257
|
+
tone: {
|
|
1258
|
+
type: string;
|
|
1259
|
+
enum: string[];
|
|
1260
|
+
description: string;
|
|
1261
|
+
};
|
|
1262
|
+
style: {
|
|
1263
|
+
type: string;
|
|
1264
|
+
enum: string[];
|
|
1265
|
+
description: string;
|
|
1266
|
+
};
|
|
1267
|
+
guard: {
|
|
1268
|
+
type: string;
|
|
1269
|
+
description: string;
|
|
1270
|
+
};
|
|
1271
|
+
cardinality: {
|
|
1272
|
+
type: string;
|
|
1273
|
+
description: string;
|
|
1274
|
+
};
|
|
1275
|
+
labelOffsetX: {
|
|
1276
|
+
type: string;
|
|
1277
|
+
description: string;
|
|
1278
|
+
};
|
|
1279
|
+
labelOffsetY: {
|
|
1280
|
+
type: string;
|
|
1281
|
+
description: string;
|
|
1282
|
+
};
|
|
1283
|
+
};
|
|
1284
|
+
};
|
|
1285
|
+
};
|
|
1286
|
+
animation: {
|
|
1287
|
+
type: string;
|
|
1288
|
+
description: string;
|
|
1289
|
+
items: {
|
|
1290
|
+
type: string;
|
|
1291
|
+
required: string[];
|
|
1292
|
+
additionalProperties: boolean;
|
|
1293
|
+
properties: {
|
|
1294
|
+
step: {
|
|
1295
|
+
type: string;
|
|
1296
|
+
minLength: number;
|
|
1297
|
+
description: string;
|
|
1298
|
+
};
|
|
1299
|
+
duration: {
|
|
1300
|
+
type: string;
|
|
1301
|
+
minimum: number;
|
|
1302
|
+
description: string;
|
|
1303
|
+
};
|
|
1304
|
+
focus: {
|
|
1305
|
+
type: string;
|
|
1306
|
+
items: {
|
|
1307
|
+
type: string;
|
|
1308
|
+
};
|
|
1309
|
+
description: string;
|
|
1310
|
+
};
|
|
1311
|
+
body: {
|
|
1312
|
+
type: string;
|
|
1313
|
+
description: string;
|
|
1314
|
+
};
|
|
1315
|
+
badge: {
|
|
1316
|
+
type: string;
|
|
1317
|
+
description: string;
|
|
1318
|
+
};
|
|
1319
|
+
};
|
|
1320
|
+
};
|
|
1321
|
+
};
|
|
1322
|
+
viewport: {
|
|
1323
|
+
type: string;
|
|
1324
|
+
description: string;
|
|
1325
|
+
additionalProperties: boolean;
|
|
1326
|
+
properties: {
|
|
1327
|
+
width: {
|
|
1328
|
+
type: string;
|
|
1329
|
+
minimum: number;
|
|
1330
|
+
};
|
|
1331
|
+
height: {
|
|
1332
|
+
type: string;
|
|
1333
|
+
minimum: number;
|
|
1334
|
+
};
|
|
1335
|
+
laneWidth: {
|
|
1336
|
+
type: string;
|
|
1337
|
+
minimum: number;
|
|
1338
|
+
};
|
|
1339
|
+
gap: {
|
|
1340
|
+
type: string;
|
|
1341
|
+
minimum: number;
|
|
1342
|
+
};
|
|
1343
|
+
laneGap: {
|
|
1344
|
+
type: string;
|
|
1345
|
+
minimum: number;
|
|
1346
|
+
};
|
|
1347
|
+
nodeGap: {
|
|
1348
|
+
type: string;
|
|
1349
|
+
minimum: number;
|
|
1350
|
+
};
|
|
1351
|
+
labelMargin: {
|
|
1352
|
+
type: string;
|
|
1353
|
+
minimum: number;
|
|
1354
|
+
};
|
|
1355
|
+
};
|
|
1356
|
+
};
|
|
1357
|
+
lanes: {
|
|
1358
|
+
type: string;
|
|
1359
|
+
description: string;
|
|
1360
|
+
additionalProperties: {
|
|
1361
|
+
type: string;
|
|
1362
|
+
additionalProperties: boolean;
|
|
1363
|
+
properties: {
|
|
1364
|
+
x: {
|
|
1365
|
+
type: string;
|
|
1366
|
+
};
|
|
1367
|
+
width: {
|
|
1368
|
+
type: string;
|
|
1369
|
+
minimum: number;
|
|
1370
|
+
};
|
|
1371
|
+
label: {
|
|
1372
|
+
type: string;
|
|
1373
|
+
};
|
|
1374
|
+
contain: {
|
|
1375
|
+
type: string;
|
|
1376
|
+
};
|
|
1377
|
+
lifeline: {
|
|
1378
|
+
type: string;
|
|
1379
|
+
};
|
|
1380
|
+
};
|
|
1381
|
+
};
|
|
1382
|
+
};
|
|
1383
|
+
groups: {
|
|
1384
|
+
type: string;
|
|
1385
|
+
description: string;
|
|
1386
|
+
additionalProperties: {
|
|
1387
|
+
type: string;
|
|
1388
|
+
required: string[];
|
|
1389
|
+
additionalProperties: boolean;
|
|
1390
|
+
properties: {
|
|
1391
|
+
label: {
|
|
1392
|
+
type: string;
|
|
1393
|
+
};
|
|
1394
|
+
lanes: {
|
|
1395
|
+
type: string;
|
|
1396
|
+
items: {
|
|
1397
|
+
type: string;
|
|
1398
|
+
};
|
|
1399
|
+
minItems: number;
|
|
1400
|
+
};
|
|
1401
|
+
};
|
|
1402
|
+
};
|
|
1403
|
+
};
|
|
1404
|
+
};
|
|
1405
|
+
};
|
|
1406
|
+
|
|
1407
|
+
/**
|
|
1408
|
+
* Dragon — Text DSL public API
|
|
1409
|
+
*
|
|
1410
|
+
* Mermaid 感覚で animated SVG を生成する Text DSL。 cdl engine を呼出して CdlDiagram を返す。
|
|
1411
|
+
*
|
|
1412
|
+
* 使い方:
|
|
1413
|
+
* const diagram = textDslToDiagram(source);
|
|
1414
|
+
* // diagram は @cardenelabs/cdl の CdlDiagram、 そのまま CdlDiagramView 等に渡せる
|
|
1415
|
+
*/
|
|
1416
|
+
|
|
1417
|
+
/**
|
|
1418
|
+
* CAR-1657 = compile 時 parts identifier lookup 用 catalog。
|
|
1419
|
+
* caller (CdlEditor 等) が loadPartsItems() の結果を Record<partId, CdlDiagram> で inject。
|
|
1420
|
+
* 未渡し時 partId set actor は「未解決」 として skip + console.warn (diagram render は継続)。
|
|
1421
|
+
*/
|
|
1422
|
+
interface CompileOpts {
|
|
1423
|
+
partsCatalog?: Record<string, CdlDiagram>;
|
|
1424
|
+
/**
|
|
1425
|
+
* 図は出せるが書いた通りにならなかったことの受け取り口 (`位置: Web の下` が順序図で
|
|
1426
|
+
* 効かない等)。 判定は組み立て側が持ち、 呼出側は受け取って表示するだけにする。
|
|
1427
|
+
*/
|
|
1428
|
+
onNotice?: (notice: CompileNotice) => void;
|
|
1429
|
+
/**
|
|
1430
|
+
* edge が DSL のどの行から来たかの受け取り口 (#998)。
|
|
1431
|
+
*
|
|
1432
|
+
* preset によっては書いた step と生成される edge が一致しない (`type: flow` は actor を鎖状に
|
|
1433
|
+
* 繋ぐため `a -> c` と書いても `a -> b` になる)。 edge を起点に本文の行を直す機能 (自動修正の
|
|
1434
|
+
* 書き戻し等) は、 この対応が無いと別の行を書き換える。
|
|
1435
|
+
*
|
|
1436
|
+
* **対応が取れない edge については呼ばれない**。 「対応が無い」 と「行 0」 を区別するため。
|
|
1437
|
+
*/
|
|
1438
|
+
onEdgeSource?: (edgeId: string, line: number) => void;
|
|
1439
|
+
}
|
|
1440
|
+
/**
|
|
1441
|
+
* Dragon DSL から CdlDiagram に一発変換。 v0.5 (英語 keyword) / v0.4 (日本語 keyword) を auto-detect。
|
|
1442
|
+
*
|
|
1443
|
+
* 判定 ... src 内に v0.5 専用 syntax (`animation:` block / `- A -> B` flow / `step: "..."` ) を含むなら v0.5、
|
|
1444
|
+
* 含まなければ v0.4 (deprecated、 console.warn を出す)。
|
|
1445
|
+
*
|
|
1446
|
+
* エラー時は throw、 詳細を取りたい場合は parseTextDslV05 / parseTextDsl を直接呼ぶ。
|
|
1447
|
+
* opts.partsCatalog を渡すと CAR-1657 parts kind (arc-gauge 等) の actor が merge 展開される。
|
|
1448
|
+
*/
|
|
1449
|
+
declare function textDslToDiagram(src: string, opts?: CompileOpts): CdlDiagram;
|
|
1450
|
+
|
|
1451
|
+
export { type AnchorBox, type CompileNotice, type CompileOpts, DIAGRAM_BOUNDARY_PADDING, type DiagramBoundingBox, type DragonJson, type DslActor, type DslAnimate, type DslDocument, type DslError, type DslGroup, type DslLane, type DslPhase, type DslSet, type DslState, type DslStep, type DslTween, type DslViewport, type FocusEntry, type InputSize, type JsonActor, type JsonDslError, type JsonPhase, type JsonStep, type LayoutMode, type LayoutPos, type LintIssue, type LintReport, type LintSeverity, MAX_INPUT_BYTES, MAX_INPUT_ELEMENTS, MAX_PART_SCALE, NODE_KIND_ALIAS, NODE_KIND_VALID, PRESET_TYPES, type PresetType, RELATIVE_GAP_DEFAULT, type RelativeDirection, type RelativePos, TONE_ALIAS, autoFix, compileToCdl, computeDiagramBoundingBox, countBytes, countDiagramElements, countDocElements, describeOversize, describeOversizeSource, diagramJsonSchema, isColorValue, jsonToDiagram, lintDiagram, measureActorBoxes, normalizePartScale, orderByDependency, parseFocusEntry, parseRelativePos, parseTextDsl, parseTextDslV05, partBoxInFrame, partDrawsInDiagram, partIsMeasurable, partRenderSize, partScaleFactor, partTargetScale, partTargetSize, partVisualSize, partsGridCenters, pointsOutside, rectsOverlap, resolveRelativePos, stripExternalPaint, stripQuotes, textDslToDiagram, validateDragonJson, writeActorPosition };
|