@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/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,173 @@
|
|
|
1
|
+
# @cardenelabs/dragon
|
|
2
|
+
|
|
3
|
+
Dragon は [@cardenelabs/cdl](https://www.npmjs.com/package/@cardenelabs/cdl) engine の上に乗る、 Mermaid 感覚の Text DSL。
|
|
4
|
+
箇条書きで書ける宣言的 syntax から animated SVG diagram を生成する。
|
|
5
|
+
|
|
6
|
+
## Why Dragon
|
|
7
|
+
|
|
8
|
+
Mermaid は静的、 cdl 直書きは TypeScript builder が必要。
|
|
9
|
+
Dragon は両者の中間 ... Mermaid に似た短文 syntax で書きつつ、 cdl の animation engine 上で動く。
|
|
10
|
+
|
|
11
|
+
- Mermaid 風 syntax (1 行 = 1 step、 `A -> B` 矢印、 box-drawing 不要)
|
|
12
|
+
- Mermaid にない animation (state tween / phase highlight / badge)
|
|
13
|
+
- 出力は cdl の `CdlDiagram`、 そのまま `CdlDiagramView` 等に渡せる
|
|
14
|
+
- engine 部 (layout / render / animation) は cdl に委譲、 dragon は parser + compiler に専念
|
|
15
|
+
|
|
16
|
+
## Quickstart
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @cardenelabs/dragon @cardenelabs/cdl
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { textDslToDiagram } from "@cardenelabs/dragon";
|
|
24
|
+
import { CdlDiagramView } from "@cardenelabs/cdl/react";
|
|
25
|
+
|
|
26
|
+
const diagram = textDslToDiagram(`
|
|
27
|
+
title: "送金フロー"
|
|
28
|
+
type: sequence
|
|
29
|
+
|
|
30
|
+
actors:
|
|
31
|
+
- Alice
|
|
32
|
+
- Vault: storage
|
|
33
|
+
- Bob
|
|
34
|
+
|
|
35
|
+
flow:
|
|
36
|
+
- Alice -> Vault: "deposit"
|
|
37
|
+
- Vault -> Bob: "send" (success)
|
|
38
|
+
`);
|
|
39
|
+
|
|
40
|
+
// React で render
|
|
41
|
+
<CdlDiagramView diagram={diagram} />
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## API
|
|
45
|
+
|
|
46
|
+
**Text DSL (人向け YAML)**
|
|
47
|
+
- `textDslToDiagram(src: string): CdlDiagram` ... 一発変換 (v0.4 / v0.5 auto-detect、 recommended entry)
|
|
48
|
+
- `parseTextDslV05(src: string): V05ParseResult` ... v0.5 parser を直接呼出 (error 詳細取得)
|
|
49
|
+
- `compileToCdl(doc: DslDocument): CdlDiagram` ... AST → CdlDiagram
|
|
50
|
+
|
|
51
|
+
**JSON DSL (LLM 向け)**
|
|
52
|
+
- `jsonToDiagram(json: unknown): CdlDiagram` ... JSON DSL → CdlDiagram、 validation error は throw
|
|
53
|
+
- `validateDragonJson(json: unknown): { ok, data | errors }` ... compile なしで validation のみ
|
|
54
|
+
- `diagramJsonSchema` ... JSON Schema (Draft 7)、 LLM の tool schema にそのまま注入可能
|
|
55
|
+
|
|
56
|
+
**Deprecated (2026-12-31 削除予定)**
|
|
57
|
+
- `parseTextDsl(src: string): ParseResult` ... v0.4 parser、 `textDslToDiagram` に移行推奨
|
|
58
|
+
|
|
59
|
+
## LLM 向け JSON DSL
|
|
60
|
+
|
|
61
|
+
LLM (Anthropic Claude / OpenAI GPT) が structured output で確実に diagram を生成できるよう、 YAML DSL と 1:1 対応する JSON 記法を提供する。
|
|
62
|
+
|
|
63
|
+
### 最小 example
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import { jsonToDiagram } from "@cardenelabs/dragon";
|
|
67
|
+
import { CdlDiagramView } from "@cardenelabs/cdl/react";
|
|
68
|
+
|
|
69
|
+
const diagram = jsonToDiagram({
|
|
70
|
+
title: "ログインAPI",
|
|
71
|
+
type: "sequence",
|
|
72
|
+
actors: ["ユーザー", "API", "DB"],
|
|
73
|
+
flow: [
|
|
74
|
+
{ from: "ユーザー", to: "API", label: "ログイン要求" },
|
|
75
|
+
{ from: "API", to: "DB", label: "ユーザー検索" },
|
|
76
|
+
{ from: "DB", to: "API", label: "結果", tone: "success" },
|
|
77
|
+
{ from: "API", to: "ユーザー", label: "認証成功", tone: "success" },
|
|
78
|
+
],
|
|
79
|
+
animation: [
|
|
80
|
+
{ step: "call", duration: 1.4, focus: ["ユーザー", "API"] },
|
|
81
|
+
{ step: "query", duration: 1.4, focus: ["API", "DB"] },
|
|
82
|
+
{ step: "return", duration: 1.4, focus: ["DB", "API"] },
|
|
83
|
+
{ step: "ok", duration: 1.4, focus: ["API", "ユーザー"] },
|
|
84
|
+
],
|
|
85
|
+
});
|
|
86
|
+
// <CdlDiagramView diagram={diagram} />
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Anthropic Claude で LLM に書かせる example
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
93
|
+
import { jsonToDiagram, diagramJsonSchema, validateDragonJson } from "@cardenelabs/dragon";
|
|
94
|
+
|
|
95
|
+
const client = new Anthropic();
|
|
96
|
+
|
|
97
|
+
async function generateDiagramFromLLM(userRequest: string, maxRetry = 3) {
|
|
98
|
+
const messages: Anthropic.MessageParam[] = [{ role: "user", content: userRequest }];
|
|
99
|
+
for (let attempt = 0; attempt < maxRetry; attempt++) {
|
|
100
|
+
const res = await client.messages.create({
|
|
101
|
+
model: "claude-sonnet-5",
|
|
102
|
+
max_tokens: 4096,
|
|
103
|
+
tools: [{
|
|
104
|
+
name: "create_diagram",
|
|
105
|
+
description: "Create an animated diagram from user's request using Dragon DSL.",
|
|
106
|
+
input_schema: diagramJsonSchema,
|
|
107
|
+
}],
|
|
108
|
+
tool_choice: { type: "tool", name: "create_diagram" },
|
|
109
|
+
messages,
|
|
110
|
+
});
|
|
111
|
+
const toolUse = res.content.find((c) => c.type === "tool_use");
|
|
112
|
+
if (!toolUse || toolUse.type !== "tool_use") throw new Error("no tool_use in LLM response");
|
|
113
|
+
const validation = validateDragonJson(toolUse.input);
|
|
114
|
+
if (validation.ok) {
|
|
115
|
+
return jsonToDiagram(validation.data);
|
|
116
|
+
}
|
|
117
|
+
// retry loop = error path を prompt に注入して LLM に修正させる
|
|
118
|
+
const errorSummary = validation.errors.map((e) => ` ${e.path}: ${e.message}`).join("\n");
|
|
119
|
+
messages.push({ role: "assistant", content: res.content });
|
|
120
|
+
messages.push({
|
|
121
|
+
role: "user",
|
|
122
|
+
content: `The diagram JSON has validation errors:\n${errorSummary}\nPlease fix and retry.`,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
throw new Error(`LLM failed to generate valid diagram after ${maxRetry} attempts`);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// 使用例
|
|
129
|
+
const diagram = await generateDiagramFromLLM(
|
|
130
|
+
"ユーザーが API 経由で DB に検索をかけて結果を受け取るシーケンス図を作って"
|
|
131
|
+
);
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### OpenAI GPT で structured output に使う場合
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
import OpenAI from "openai";
|
|
138
|
+
import { jsonToDiagram, diagramJsonSchema } from "@cardenelabs/dragon";
|
|
139
|
+
|
|
140
|
+
const client = new OpenAI();
|
|
141
|
+
const res = await client.chat.completions.create({
|
|
142
|
+
model: "gpt-4o-2024-08-06",
|
|
143
|
+
messages: [{ role: "user", content: "..." }],
|
|
144
|
+
response_format: {
|
|
145
|
+
type: "json_schema",
|
|
146
|
+
json_schema: { name: "diagram", strict: true, schema: diagramJsonSchema },
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
const json = JSON.parse(res.choices[0].message.content!);
|
|
150
|
+
const diagram = jsonToDiagram(json);
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### JSON Schema の場所
|
|
154
|
+
|
|
155
|
+
- SSOT = `packages/dragon/src/schemas/diagram.json`
|
|
156
|
+
- npm 経由取得 = `@cardenelabs/dragon/schemas/diagram.json` (package.json exports)
|
|
157
|
+
- TypeScript import = `import { diagramJsonSchema } from "@cardenelabs/dragon"`
|
|
158
|
+
|
|
159
|
+
### YAML と JSON の 1:1 対応
|
|
160
|
+
|
|
161
|
+
同じ図を両方の記法で書ける。 人 → YAML、 LLM → JSON が推奨だが、 混在可能。
|
|
162
|
+
|
|
163
|
+
| YAML | JSON |
|
|
164
|
+
|---|---|
|
|
165
|
+
| `title: "..."` | `{title: "..."}` |
|
|
166
|
+
| `actors: [A, B: kind]` | `{actors: [{name: "A"}, {name: "B", kind: "storage"}]}` |
|
|
167
|
+
| `- A -> B: "label"` | `{from: "A", to: "B", label: "label"}` |
|
|
168
|
+
| `step: "..." 1.4s` | `{step: "...", duration: 1.4}` |
|
|
169
|
+
| `focus: [A, B]` | `{focus: ["A", "B"]}` |
|
|
170
|
+
|
|
171
|
+
## License
|
|
172
|
+
|
|
173
|
+
MIT
|