@cardenelabs/dragon 0.8.0 → 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.
- package/README.md +8 -4
- package/dist/index.cjs +6378 -5214
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +340 -8
- package/dist/index.d.ts +340 -8
- package/dist/index.js +6374 -5215
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/compile.ts +65 -1
- package/src/index.ts +26 -15
- package/src/json-parser.ts +928 -99
- package/src/schemas/diagram.json +368 -44
- package/src/tokenize.ts +289 -0
- package/src/types.ts +19 -0
- package/src/v05/parser.ts +670 -138
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cardenelabs/dragon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Dragon — Mermaid 感覚で animated SVG を生成する Text DSL。 cdl engine を内部利用。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "cardene777",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"prepublishOnly": "pnpm run typecheck && pnpm run test && pnpm run build"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@cardenelabs/cdl": "^0.
|
|
59
|
+
"@cardenelabs/cdl": "^0.11.0"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
62
|
"react": "^19.0.0",
|
package/src/compile.ts
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
applyDerivedValues, parseFormula,
|
|
18
18
|
} from "@cardenelabs/cdl";
|
|
19
19
|
import { parseFocusEntry } from "./focus";
|
|
20
|
+
import { DRAW_TARGETS } from "./v05/parser";
|
|
20
21
|
import { isColorValue, stripExternalPaint } from "./color";
|
|
21
22
|
import {
|
|
22
23
|
MAX_INPUT_ELEMENTS,
|
|
@@ -91,7 +92,11 @@ export type CompileNotice = {
|
|
|
91
92
|
// 最上位に `eyebrow:` を書いたが、 箱ごとに分かれる図種で相手が決まらなかった (#1247)
|
|
92
93
|
| "eyebrow-not-honored"
|
|
93
94
|
// 静止した `type: flow` で、書いた矢印の端が使われなかった (#1269)
|
|
94
|
-
| "flow-endpoint-not-honored"
|
|
95
|
+
| "flow-endpoint-not-honored"
|
|
96
|
+
// 起点から描く動きを持たない図種で段に `draw:` を書いた (#1312)
|
|
97
|
+
| "draw-not-honored"
|
|
98
|
+
// `draw:` の語がその図種と食い違う (`type: bar` に `draw: pie`、 #1314)
|
|
99
|
+
| "draw-target-mismatch";
|
|
95
100
|
/** 対象の名前。 光らせる相手なら書かれた指定そのまま */
|
|
96
101
|
actor: string;
|
|
97
102
|
/** 書かれていた行 */
|
|
@@ -212,6 +217,7 @@ export function compileToCdl(doc: DslDocument, opts?: CompileToCdlOpts): CdlDiag
|
|
|
212
217
|
reportFlowEndpointNotHonored(doc, 分けた.元の名前, opts?.onNotice);
|
|
213
218
|
reportLaneNotHonored(書いたまま, opts?.onNotice);
|
|
214
219
|
reportDocEyebrowNotHonored(書いたまま, opts?.onNotice);
|
|
220
|
+
reportDrawNotHonored(書いたまま, opts?.onNotice);
|
|
215
221
|
reportChartFieldsNotHonored(書いたまま, opts?.onNotice);
|
|
216
222
|
reportAxesNotHonored(書いたまま, opts?.onNotice);
|
|
217
223
|
// `位置: Web の右` を実際の配置から絶対座標に直す。 以降は座標を直接書いた時と同じ経路
|
|
@@ -553,6 +559,52 @@ function reportDocEyebrowNotHonored(doc: DslDocument, onNotice?: (n: CompileNoti
|
|
|
553
559
|
});
|
|
554
560
|
}
|
|
555
561
|
|
|
562
|
+
/**
|
|
563
|
+
* 左から描く動きを持たない図種で段に `draw:` を書いた時に伝える (#1312)。
|
|
564
|
+
*
|
|
565
|
+
* 描く動きを持つのは今のところ折れ線だけ。 他の図種では書いても何も起きないため、
|
|
566
|
+
* 黙って捨てると「書いたのに伸びない」 が手掛かりなしで起きる。
|
|
567
|
+
*
|
|
568
|
+
* 段ごとに知らせる = 5 段のうち 1 段だけに書いた形で、どの段が効いていないかを読めるようにする。
|
|
569
|
+
*/
|
|
570
|
+
function reportDrawNotHonored(doc: DslDocument, onNotice?: (n: CompileNotice) => void): void {
|
|
571
|
+
if (!onNotice) return;
|
|
572
|
+
for (const phase of doc.animate?.phases ?? []) {
|
|
573
|
+
if (phase.draw === undefined) continue;
|
|
574
|
+
// 段の `pos` は `- step:` の行を指す。 書いた行に辿り着けるよう `drawPos` を優先する
|
|
575
|
+
const line = phase.drawPos?.line ?? phase.pos?.line ?? 0;
|
|
576
|
+
if (!DRAWABLE_DOC_TYPES.has(doc.type)) {
|
|
577
|
+
onNotice({
|
|
578
|
+
kind: "draw-not-honored",
|
|
579
|
+
actor: phase.name,
|
|
580
|
+
line,
|
|
581
|
+
message: `段 "${phase.name}" に書いた draw は効きません (type: ${doc.type} は起点から描く動きを持ちません)`,
|
|
582
|
+
hint: `draw が効くのは type: ${[...DRAWABLE_DOC_TYPES].join(" / ")} です`,
|
|
583
|
+
});
|
|
584
|
+
continue;
|
|
585
|
+
}
|
|
586
|
+
// 語が別の図種を指している形 (#1314)。 図は描けるので誤りにはしない
|
|
587
|
+
const 語の図種 = DRAW_TARGETS.get(phase.draw);
|
|
588
|
+
if (語の図種 !== undefined && 語の図種 !== doc.type) {
|
|
589
|
+
onNotice({
|
|
590
|
+
kind: "draw-target-mismatch",
|
|
591
|
+
actor: phase.name,
|
|
592
|
+
line,
|
|
593
|
+
message: `段 "${phase.name}" の draw: ${phase.draw} は type: ${doc.type} では効きません (${phase.draw} は type: ${語の図種} の図に書きます)`,
|
|
594
|
+
hint: `この図では draw: ${doc.type} と書いてください`,
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* 段の `draw:` が効く図種 (#1312 / #1314)。
|
|
602
|
+
*
|
|
603
|
+
* **語と図種の対応表から導く** (`DRAW_TARGETS`)。 一覧を写すと、語を足した時に片方だけ
|
|
604
|
+
* 古いまま残る。 描画側 (`cdl` の `CdlPhase.draw`) が対応する 3 種と一致する。
|
|
605
|
+
*/
|
|
606
|
+
const DRAWABLE_DOC_TYPES: ReadonlySet<PresetType> = new Set<PresetType>(DRAW_TARGETS.values());
|
|
607
|
+
|
|
556
608
|
/**
|
|
557
609
|
* 縦列を選べる図種で、一部の箱だけが縦列を書いた時に伝える (#1263)。
|
|
558
610
|
*
|
|
@@ -5563,12 +5615,24 @@ function injectPhasesFallback(diagram: CdlDiagram, doc: DslDocument): void {
|
|
|
5563
5615
|
// phase 注入。 CdlPhase.tweens[].stateId / sets[].stateId で state 参照 (state ではない)。
|
|
5564
5616
|
for (const p of doc.animate.phases) {
|
|
5565
5617
|
const activateIds: string[] = [...resolveIds(p.highlight ?? [])];
|
|
5618
|
+
// `draw: line` を描画側の欄へ写す (#1312)。 相手は 1 箱で図全体を描く種別の箱で、
|
|
5619
|
+
// 折れ線は必ずこの形になるため名前を書かせずに引ける。
|
|
5620
|
+
//
|
|
5621
|
+
// **`activate` と兼ねない**。 描画側は焦点と別集合で持つ (`cdl#512`) = 焦点が当たり
|
|
5622
|
+
// 続ける図で毎段引き直しになるため。 書いた段だけが欄を持つ
|
|
5623
|
+
const drawIds =
|
|
5624
|
+
p.draw !== undefined &&
|
|
5625
|
+
DRAW_TARGETS.get(p.draw) === doc.type &&
|
|
5626
|
+
singleBoxNode !== undefined
|
|
5627
|
+
? [singleBoxNode.id]
|
|
5628
|
+
: [];
|
|
5566
5629
|
diagram.phases.push({
|
|
5567
5630
|
id: slugify(p.name) || p.name,
|
|
5568
5631
|
duration: p.durationMs,
|
|
5569
5632
|
title: p.name,
|
|
5570
5633
|
body: p.body ?? "",
|
|
5571
5634
|
activate: activateIds,
|
|
5635
|
+
...(drawIds.length > 0 ? { draw: drawIds } : {}),
|
|
5572
5636
|
tweens: (p.tweens ?? []).map((t) => ({ stateId: t.state, from: t.from, to: t.to })),
|
|
5573
5637
|
sets: (p.sets ?? []).map((s) => ({ stateId: s.state, value: s.value })),
|
|
5574
5638
|
...(p.badge ? { badge: p.badge } : {}),
|
package/src/index.ts
CHANGED
|
@@ -13,16 +13,12 @@ export { compileToCdl } from "./compile";
|
|
|
13
13
|
export type { CompileNotice } from "./compile";
|
|
14
14
|
export { parseTextDslV05 } from "./v05";
|
|
15
15
|
// 記法一覧が「実際に受け付ける値」 を実装から引くための公開。 手書きすると説明と実装がずれる。
|
|
16
|
-
export { PRESET_TYPES, TOP_LEVEL_KEYS } from "./v05/parser";
|
|
16
|
+
export { DRAW_TARGETS, DRAW_WORDS, PRESET_TYPES, TOP_LEVEL_KEYS } from "./v05/parser";
|
|
17
17
|
export { TONE_ALIAS, NODE_KIND_ALIAS } from "./keywords";
|
|
18
18
|
export { lintDiagram, autoFix } from "./notation-lint";
|
|
19
19
|
export type { LintIssue, LintReport, LintSeverity } from "./notation-lint";
|
|
20
20
|
// canvas pivot 新 spec 図境界計算 helper (§diagram-boundary SSOT)
|
|
21
|
-
export {
|
|
22
|
-
computeDiagramBoundingBox,
|
|
23
|
-
rectsOverlap,
|
|
24
|
-
DIAGRAM_BOUNDARY_PADDING,
|
|
25
|
-
} from "./canvas-bounds";
|
|
21
|
+
export { computeDiagramBoundingBox, rectsOverlap, DIAGRAM_BOUNDARY_PADDING } from "./canvas-bounds";
|
|
26
22
|
export type { DiagramBoundingBox } from "./canvas-bounds";
|
|
27
23
|
// 位置を相対で書くための解決。 組み立て側と画面側の両方が同じ規則を使うために公開する。
|
|
28
24
|
export {
|
|
@@ -78,6 +74,10 @@ export { isColorValue, pointsOutside, stripExternalPaint } from "./color";
|
|
|
78
74
|
// 別々に持つと、片方だけが読める本文ができる (実測 = `位置: '300,200"` が
|
|
79
75
|
// 画面側では座標 300 として通り、組み立て側では読めない値として知らせが出た)
|
|
80
76
|
export { stripQuotes } from "./v05/parser";
|
|
77
|
+
|
|
78
|
+
// 画面で色分けするための分解器 (#1310)。 色は持たず、種類名と位置だけを返す
|
|
79
|
+
export { 記法を分解する, JSONを分解する, 区間に広げる } from "./tokenize";
|
|
80
|
+
export type { トークン, トークンの種類 } from "./tokenize";
|
|
81
81
|
// 大きすぎる入力を組み立てる前に止める上限 (#1005)。 画面側も同じ物差しで事前に知らせられるよう公開する。
|
|
82
82
|
export {
|
|
83
83
|
MAX_INPUT_ELEMENTS,
|
|
@@ -96,6 +96,8 @@ export { diagramJsonSchema } from "./schema";
|
|
|
96
96
|
export type {
|
|
97
97
|
DragonJson,
|
|
98
98
|
JsonActor,
|
|
99
|
+
JsonActorNodeOverride,
|
|
100
|
+
JsonAxes,
|
|
99
101
|
JsonStep,
|
|
100
102
|
JsonPhase,
|
|
101
103
|
JsonDslError,
|
|
@@ -204,15 +206,24 @@ function isV05Source(src: string): boolean {
|
|
|
204
206
|
// 判定不足。 v0.4-specific syntax (`step "..." Xs` = colon なし step / `^\d+\.\s+` = 番号 flow) を
|
|
205
207
|
// negative marker に追加。
|
|
206
208
|
const V04_KEYWORDS = [
|
|
207
|
-
// Japanese v0.4 専用 keyword (v0.5 は英語のみ)
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
209
|
+
// Japanese v0.4 専用 keyword (v0.5 は英語のみ)。
|
|
210
|
+
//
|
|
211
|
+
// **字下げした行には当てない** (#1300)。 v0.4 の見出しは行頭に書くが、v0.5 の縦書き形は
|
|
212
|
+
// 必ず字下げする。 同じ語が「v0.4 の見出し」 と「v0.5 の箱の欄 / 見本の状態名」 の両方で
|
|
213
|
+
// 使われるため、`\s*` を許すと **正しい v0.5 の本文が旧 parser へ回る**。
|
|
214
|
+
//
|
|
215
|
+
// 実測 = `種類:` を箱の欄として縦に書いた本文と、見本の状態名が下の 7 語のいずれかである
|
|
216
|
+
// 本文が、いずれも v0.4 として読まれて別の行を指す誤りを返していた。
|
|
217
|
+
/^タイトル\s*[::]/, // title (JA)
|
|
218
|
+
/^種類\s*[::]/, // type (JA)
|
|
219
|
+
/^登場人物\s*[::]/, // actors (JA)
|
|
220
|
+
/^流れ\s*[::]/, // flow (JA)
|
|
221
|
+
/^アニメーション\s*[::]/, // animation (JA)
|
|
222
|
+
/^動作\s*[::]/, // step (JA)
|
|
223
|
+
/^状態\s*[::]/, // state (JA)
|
|
224
|
+
// 鉤括弧が続く形は v0.5 に無い (状態名は `ステップ: 5` の形しか取れない) ため、
|
|
225
|
+
// 字下げを許しても v0.5 と衝突しない。 v0.4 では `アニメーション:` の下に字下げして書く
|
|
226
|
+
/^\s*ステップ\s*[「『]/, // step (JA)
|
|
216
227
|
// v0.4 English-specific syntax = colon なし step (v0.5 は step: 必須)
|
|
217
228
|
/^\s*step\s+"[^"]+"\s+[\d.]+\s*s\b/,
|
|
218
229
|
/^\s*step\s+'[^']+'\s+[\d.]+\s*s\b/,
|