@cardenelabs/dragon 0.18.2 → 0.19.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 +3 -0
- package/dist/index.cjs +690 -148
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +53 -1
- package/dist/index.d.ts +53 -1
- package/dist/index.js +690 -148
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/compile.ts +87 -9
- package/src/json-parser.ts +38 -0
- package/src/keywords.ts +33 -0
- package/src/schemas/diagram.json +586 -140
- package/src/types.ts +12 -1
- package/src/v05/parser.ts +76 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cardenelabs/dragon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "Dragon — Mermaid 感覚で animated SVG を生成する Text DSL。 cdl engine を内部利用。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "cardene777",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"prepublishOnly": "pnpm run typecheck && pnpm run test && pnpm run build"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@cardenelabs/cdl": "^0.
|
|
60
|
+
"@cardenelabs/cdl": "^0.25.0"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
63
|
"react": "^19.0.0",
|
package/src/compile.ts
CHANGED
|
@@ -544,9 +544,75 @@ export function compileToCdl(doc: DslDocument, opts?: CompileToCdlOpts): CdlDiag
|
|
|
544
544
|
// 作り替えた名前を表示だけ戻す (#1220)。 **図への追加を全て終えた後**に戻す = 途中で戻すと、
|
|
545
545
|
// 後続の処理が名前で引く時に作り替え前と後が混ざる
|
|
546
546
|
restoreActorNames(merged, 分けた.元の名前, 作り替えた対象);
|
|
547
|
+
// 配色と行の縞は **図への追加を全て終えた後**に当てる (#1553)。 図種ごとの組み立ては
|
|
548
|
+
// 20 か所以上あり、そのどれに足しても残りが取り残される
|
|
549
|
+
配色と縞を当てる(merged, doc);
|
|
550
|
+
静止した図の焦点を外す(merged, doc);
|
|
547
551
|
return merged;
|
|
548
552
|
}
|
|
549
553
|
|
|
554
|
+
/**
|
|
555
|
+
* 段を書かない図では、どの箱も「いま」 にしない (#1557)。
|
|
556
|
+
*
|
|
557
|
+
* ## 何が起きていたか
|
|
558
|
+
*
|
|
559
|
+
* `animation:` を書かない図でも段は 1 つ作られる。 作るのは 2 経路あり、cdl の組み立て器
|
|
560
|
+
* (`er()` / `flow()` / `topology()` 等) が図種ごとに 1 段を作る経路と、どちらも作らない図種に
|
|
561
|
+
* dragon が 1 段を足す経路 (`injectStaticPhase`)。 どちらも **全ての箱と矢印を段に載せる**。
|
|
562
|
+
*
|
|
563
|
+
* 描画側は段に載った箱を「いま」 として描く (枠を主役色にして太くする)。 その結果、静止した図は
|
|
564
|
+
* 全ての箱が「いま」 になり、止まっている箱の枠が 1 度も出ない (実測 = ER 図 3 箱 / 流れ図 2 箱)。
|
|
565
|
+
*
|
|
566
|
+
* 全部を強調するのと何も強調しないのは、どちらも「区別が無い」 状態。 後者の方が落ち着いて読める。
|
|
567
|
+
*
|
|
568
|
+
* ## 矢印は段に載せたまま置く
|
|
569
|
+
*
|
|
570
|
+
* 描画側の既定 (`edgeReveal: "phase"`) は「段が名指しする矢印は、その段が来るまで描かない」。
|
|
571
|
+
* 矢印まで外すと、静止した図から線が 1 本も出なくなる。
|
|
572
|
+
*
|
|
573
|
+
* ## 判定は書いた内容で決める
|
|
574
|
+
*
|
|
575
|
+
* 「段に全ての箱が載っている図」 を目印にしない = 書き手が 1 段だけ書いて全部を焦点にした図と
|
|
576
|
+
* 見分けが付かない。 見るのは `animation:` を書いたかどうかで、これは書き手が段のために書く値。
|
|
577
|
+
*/
|
|
578
|
+
function 静止した図の焦点を外す(diagram: CdlDiagram, doc: DslDocument): void {
|
|
579
|
+
if ((doc.animate?.phases.length ?? 0) > 0) return;
|
|
580
|
+
const 箱 = new Set(diagram.nodes.map((n) => n.id));
|
|
581
|
+
for (const phase of diagram.phases) {
|
|
582
|
+
phase.activate = phase.activate.filter((id) => !箱.has(id));
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* 図の配色と、表の箱の行の縞を当てる (#1553)。
|
|
588
|
+
*
|
|
589
|
+
* ## 配色
|
|
590
|
+
*
|
|
591
|
+
* cdl は色を持たない。 名前だけを `data-cdl-palette` として markup に出し、消費側
|
|
592
|
+
* (`cdl-theme.css`) が名前を見て 7 つの口 (台 / 行の面 / 縞 / 枠 / 字 / 型名 / 線) に色を当てる。
|
|
593
|
+
*
|
|
594
|
+
* ER 図は書かなくても `kinari` (生成りに茶) になる。 ER 図は小さい字が密に並ぶので、他の図種と
|
|
595
|
+
* 同じ色みだと行を追えない = 既定を持たせて「作れば必ずその色みになる」 形にする。
|
|
596
|
+
* 書き手が `palette:` を書いた時はそちらが勝つ。
|
|
597
|
+
*
|
|
598
|
+
* ## 行の縞
|
|
599
|
+
*
|
|
600
|
+
* cdl の `er()` 組み立て器は縞を既定で敷くが、**動きを持つ ER 図はその経路を通らない**
|
|
601
|
+
* (`compileGenericWithAnimate` が箱を直に組む)。 同じ図が動きの有無で縞を持ったり持たなかったり
|
|
602
|
+
* しないよう、出口で揃える。
|
|
603
|
+
*
|
|
604
|
+
* 縞を描くのは表の箱 (`storage`) だけ。 他の種別の箱に書いても描画側が読まないので、
|
|
605
|
+
* ここで対象を絞って「書いたのに出ない」 欄を残さない。
|
|
606
|
+
*/
|
|
607
|
+
function 配色と縞を当てる(diagram: CdlDiagram, doc: DslDocument): void {
|
|
608
|
+
const 配色 = doc.palette ?? (doc.type === "er" ? "kinari" : undefined);
|
|
609
|
+
if (配色 !== undefined) diagram.palette = 配色;
|
|
610
|
+
if (doc.type !== "er") return;
|
|
611
|
+
for (const node of diagram.nodes) {
|
|
612
|
+
if (node.kind === "storage") node.rowStripe = true;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
550
616
|
/**
|
|
551
617
|
* readout の配色配列から外部参照を落とす (#1374)。
|
|
552
618
|
*
|
|
@@ -599,11 +665,15 @@ function materializeStates(diagram: CdlDiagram, doc: DslDocument): void {
|
|
|
599
665
|
* 描画側は段が 1 件以上あることを要求する。 一方で段を作るかどうかは種類ごとにばらけており、
|
|
600
666
|
* `animation:` を書かない図は 12 種のうち 6 種だけが描かれ、 残り 6 種は弾かれていた。
|
|
601
667
|
*
|
|
602
|
-
* ##
|
|
668
|
+
* ## 空の段にはしない
|
|
669
|
+
*
|
|
670
|
+
* 描画側の既定 (`edgeReveal: "phase"`) は「段が名指しする矢印は、その段が来るまで描かない」。
|
|
671
|
+
* 空の段を入れると、静止した図から線が 1 本も出ない。
|
|
603
672
|
*
|
|
604
|
-
*
|
|
605
|
-
*
|
|
606
|
-
*
|
|
673
|
+
* **箱は段に載せた後で外す** (#1557)。 ここで載せるのは矢印を描かせるためで、箱まで
|
|
674
|
+
* 「いま」 のままにすると静止した図の全ての箱が主役色の枠になる。 外すのは出口の
|
|
675
|
+
* `静止した図の焦点を外す` が 1 か所で行う = 段を作る経路は cdl の組み立て器にもあり、
|
|
676
|
+
* ここだけ直しても図種によって残る。
|
|
607
677
|
*
|
|
608
678
|
* ## 既に段がある図には触らない
|
|
609
679
|
*
|
|
@@ -3436,6 +3506,10 @@ function 矢印へ書き写す(target: CdlEdge, s: DslStep, doc: DslDocument): v
|
|
|
3436
3506
|
if (s.tailHead !== undefined) target.tailHead = s.tailHead;
|
|
3437
3507
|
if (s.headFill !== undefined) target.headFill = s.headFill;
|
|
3438
3508
|
if (s.tailHeadFill !== undefined) target.tailHeadFill = s.tailHeadFill;
|
|
3509
|
+
// 辺の役目と名前の下地 (cdl#618)。 主となる道を朱で引き、丸い下地を外せる。
|
|
3510
|
+
// 書かない辺には値を入れない = 既存の図が変わらない
|
|
3511
|
+
if (s.role !== undefined) target.role = s.role;
|
|
3512
|
+
if (s.labelPlate !== undefined) target.labelPlate = s.labelPlate;
|
|
3439
3513
|
if (s.labelOffsetX !== undefined) target.labelOffsetX = s.labelOffsetX;
|
|
3440
3514
|
if (s.labelOffsetY !== undefined) target.labelOffsetY = s.labelOffsetY;
|
|
3441
3515
|
if (s.overlay !== undefined) target.overlay = s.overlay;
|
|
@@ -5443,9 +5517,13 @@ function 行を組み立て器が持つ(type: DslDocument["type"]): boolean {
|
|
|
5443
5517
|
/**
|
|
5444
5518
|
* 行と印を組む (#1466)。 群の分け方は図の種類が決める。
|
|
5445
5519
|
*
|
|
5446
|
-
* ER は
|
|
5447
|
-
* 記法に空の行を書かせないのは、`rows` が空の要素を捨てるため = 書いても消える。
|
|
5520
|
+
* ER は **鍵の群を上にまとめる** (組み立て器 `er()` と同じ形)。
|
|
5448
5521
|
* 状態遷移は群を分けないので、書いた並びのまま。
|
|
5522
|
+
*
|
|
5523
|
+
* **空の行では開けない** (cdl `#606`)。 群の区切りは行頭の印が持っている = ER は鍵の名前に
|
|
5524
|
+
* 下線が付く。 空の行はその 2 つ目の手掛かりで、代わりに行の間隔を不揃いにしていた
|
|
5525
|
+
* (鍵と値を持つ箱だけ境目が広がる)。 組み立て器が cdl 0.23.0 で空の行をやめたので、
|
|
5526
|
+
* こちらも同時にやめる = 片方だけ残ると記法と図の照合が落ちる。
|
|
5449
5527
|
*/
|
|
5450
5528
|
function 行と印を組む(
|
|
5451
5529
|
type: DslDocument["type"],
|
|
@@ -5460,10 +5538,10 @@ function 行と印を組む(
|
|
|
5460
5538
|
const 鍵: number[] = [];
|
|
5461
5539
|
const 値: number[] = [];
|
|
5462
5540
|
rows.forEach((_, i) => ((印[i]?.underline === true ? 鍵 : 値).push(i)));
|
|
5463
|
-
const 並び =
|
|
5541
|
+
const 並び = [...鍵, ...値];
|
|
5464
5542
|
return {
|
|
5465
|
-
rows: 並び.map((i) =>
|
|
5466
|
-
rowMarks: 並び.map((i) =>
|
|
5543
|
+
rows: 並び.map((i) => rows[i] ?? ""),
|
|
5544
|
+
rowMarks: 並び.map((i) => 印[i] ?? null),
|
|
5467
5545
|
};
|
|
5468
5546
|
}
|
|
5469
5547
|
|
package/src/json-parser.ts
CHANGED
|
@@ -36,6 +36,10 @@ import {
|
|
|
36
36
|
EVENT_KINDS,
|
|
37
37
|
type 図形の定義,
|
|
38
38
|
} from "./v05/parser";
|
|
39
|
+
// 図の配色 (#1553)。 記法の読み手と同じ解決を通す = 別名 (`生成り` / `青磁`) の受け方が
|
|
40
|
+
// 記法と JSON でずれない
|
|
41
|
+
import { resolvePalette } from "./keywords";
|
|
42
|
+
import type { DslPalette } from "./keywords";
|
|
39
43
|
import type { CompileToCdlOpts } from "./compile";
|
|
40
44
|
import type {
|
|
41
45
|
CdlDiagram,
|
|
@@ -189,6 +193,13 @@ export interface DragonJson {
|
|
|
189
193
|
reveal?: EdgeReveal;
|
|
190
194
|
/** 図の並ぶ向き (#1494)。 記法の最上位 `direction:` と同じ。 JSON は英語の語で書く */
|
|
191
195
|
direction?: "vertical" | "horizontal";
|
|
196
|
+
/**
|
|
197
|
+
* 図の配色 (#1553)。 記法の最上位 `palette:` と同じ。
|
|
198
|
+
*
|
|
199
|
+
* 名前だけを図に載せる = cdl は色を持たず、値は `cdl-theme.css` が決める。
|
|
200
|
+
* ER 図は書かなくても `kinari` になる。
|
|
201
|
+
*/
|
|
202
|
+
palette?: DslPalette;
|
|
192
203
|
}
|
|
193
204
|
|
|
194
205
|
export interface JsonActor {
|
|
@@ -347,6 +358,14 @@ export interface JsonStep {
|
|
|
347
358
|
tailHead?: EdgeHead;
|
|
348
359
|
headFill?: EdgeHeadFill;
|
|
349
360
|
tailHeadFill?: EdgeHeadFill;
|
|
361
|
+
/**
|
|
362
|
+
* 辺の役目 (cdl#618)。 記法の `{ role: main }` と同じ。
|
|
363
|
+
*
|
|
364
|
+
* `main` を書いた辺だけ「いま」 の色で引く。 主となる 1 本 (または 1 続き) にだけ書く。
|
|
365
|
+
*/
|
|
366
|
+
role?: "main";
|
|
367
|
+
/** 名前の下地を敷くか (cdl#618)。 記法の `{ labelPlate: false }` と同じ。 既定は敷く */
|
|
368
|
+
labelPlate?: boolean;
|
|
350
369
|
/** クラス図の関係の語 (#1466)。 書くと端の形 / 塗り / 線種がまとめて決まる */
|
|
351
370
|
relation?: ClassRelationType;
|
|
352
371
|
/** 順序図の言づての種類 (#1466)。 `call` / `return` / `fire` */
|
|
@@ -491,6 +510,8 @@ export const ACCEPTED_KEYS = {
|
|
|
491
510
|
"reveal",
|
|
492
511
|
// 図の並ぶ向き (#1494)
|
|
493
512
|
"direction",
|
|
513
|
+
// 図の配色 (#1553)
|
|
514
|
+
"palette",
|
|
494
515
|
],
|
|
495
516
|
actor: [
|
|
496
517
|
"name",
|
|
@@ -548,6 +569,9 @@ export const ACCEPTED_KEYS = {
|
|
|
548
569
|
"headFill",
|
|
549
570
|
"tailHeadFill",
|
|
550
571
|
"relation",
|
|
572
|
+
// 辺の役目と名前の下地 (cdl#618)
|
|
573
|
+
"role",
|
|
574
|
+
"labelPlate",
|
|
551
575
|
"kind",
|
|
552
576
|
"tone",
|
|
553
577
|
"style",
|
|
@@ -649,6 +673,8 @@ export const 欄の型表 = {
|
|
|
649
673
|
reveal: "非空の文字列",
|
|
650
674
|
// 図の並ぶ向き (#1494)
|
|
651
675
|
direction: "非空の文字列",
|
|
676
|
+
// 図の配色 (#1553)
|
|
677
|
+
palette: "非空の文字列",
|
|
652
678
|
},
|
|
653
679
|
actor: {
|
|
654
680
|
name: "必須の非空文字列",
|
|
@@ -704,6 +730,9 @@ export const 欄の型表 = {
|
|
|
704
730
|
headFill: "非空の文字列",
|
|
705
731
|
tailHeadFill: "非空の文字列",
|
|
706
732
|
relation: "非空の文字列",
|
|
733
|
+
// 辺の役目と名前の下地 (cdl#618)
|
|
734
|
+
role: "非空の文字列",
|
|
735
|
+
labelPlate: "真偽",
|
|
707
736
|
kind: "非空の文字列",
|
|
708
737
|
tone: "色",
|
|
709
738
|
style: "線種",
|
|
@@ -2348,6 +2377,9 @@ export function jsonToDoc(json: DragonJson): DslDocument {
|
|
|
2348
2377
|
pos: p0,
|
|
2349
2378
|
};
|
|
2350
2379
|
});
|
|
2380
|
+
// 図の配色 (#1553)。 解くのは 1 度だけにする
|
|
2381
|
+
const 配色 = json.palette === undefined ? null : resolvePalette(json.palette);
|
|
2382
|
+
|
|
2351
2383
|
const flow: DslStep[] = json.flow.map((s, i) => ({
|
|
2352
2384
|
no: i + 1,
|
|
2353
2385
|
from: s.from,
|
|
@@ -2362,6 +2394,9 @@ export function jsonToDoc(json: DragonJson): DslDocument {
|
|
|
2362
2394
|
headFill: s.headFill,
|
|
2363
2395
|
tailHeadFill: s.tailHeadFill,
|
|
2364
2396
|
relation: s.relation,
|
|
2397
|
+
// 辺の役目と名前の下地 (cdl#618)
|
|
2398
|
+
role: s.role,
|
|
2399
|
+
labelPlate: s.labelPlate,
|
|
2365
2400
|
msgKind: s.kind,
|
|
2366
2401
|
// 箱と同じ読み替えを通す (#1304)。 通さないと `tone: "成功"` が色名として解決されないまま
|
|
2367
2402
|
// 図に届き、同じ値が箱では色になり矢印では色にならない
|
|
@@ -2502,6 +2537,9 @@ export function jsonToDoc(json: DragonJson): DslDocument {
|
|
|
2502
2537
|
reveal: json.reveal,
|
|
2503
2538
|
// 図の並ぶ向き (#1494)。 JSON は英語で書くので、記法と同じ語に直してから渡す
|
|
2504
2539
|
...(json.direction !== undefined ? { direction: json.direction === "horizontal" ? ("横" as const) : ("縦" as const) } : {}),
|
|
2540
|
+
// 図の配色 (#1553)。 記法と同じ解決を通す = 別名 (`生成り` / `青磁`) の受け方がずれない。
|
|
2541
|
+
// 読めない語は渡さない = 上流の型検査が語を絞っているので、ここに来るのは書き間違いだけ
|
|
2542
|
+
...(配色 !== null ? { palette: 配色 } : {}),
|
|
2505
2543
|
pos: p0,
|
|
2506
2544
|
};
|
|
2507
2545
|
}
|
package/src/keywords.ts
CHANGED
|
@@ -45,6 +45,39 @@ export function resolveDirection(s: string): DslDirection | null {
|
|
|
45
45
|
return Object.hasOwn(DIRECTION_ALIAS, k) ? DIRECTION_ALIAS[k]! : null;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* 図の配色 (`palette:`、 #1553)。
|
|
50
|
+
*
|
|
51
|
+
* cdl は色を持たない (形だけを描く)。 名前を `data-cdl-palette` として markup に出すので、
|
|
52
|
+
* dragon の `cdl-theme.css` がその名前を見て 7 つの口 (台 / 行の面 / 縞 / 枠 / 字 / 型名 / 線)
|
|
53
|
+
* に色を当てる。
|
|
54
|
+
*
|
|
55
|
+
* **名前を自由文字列にしない**。 書き間違えると既定の色みのまま出るので、書き手には
|
|
56
|
+
* 「効かない」 としか見えない。 語を絞れば読めない語をその場で知らせられる。
|
|
57
|
+
*/
|
|
58
|
+
export const PALETTES = ["kinari", "celadon"] as const;
|
|
59
|
+
export type DslPalette = (typeof PALETTES)[number];
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 配色の別名。 向きと同じく日本語と英語の両方で書ける。
|
|
63
|
+
*
|
|
64
|
+
* `kinari` = 生成りに茶 (ER 図の既定)、 `celadon` = 青磁に墨。
|
|
65
|
+
*/
|
|
66
|
+
export const PALETTE_ALIAS: Record<string, DslPalette> = {
|
|
67
|
+
kinari: "kinari",
|
|
68
|
+
celadon: "celadon",
|
|
69
|
+
生成り: "kinari",
|
|
70
|
+
生成りに茶: "kinari",
|
|
71
|
+
青磁: "celadon",
|
|
72
|
+
青磁に墨: "celadon",
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/** 書いた配色を正規の語に直す。 読めない語は `null`。 */
|
|
76
|
+
export function resolvePalette(s: string): DslPalette | null {
|
|
77
|
+
const k = s.trim().toLowerCase();
|
|
78
|
+
return Object.hasOwn(PALETTE_ALIAS, k) ? PALETTE_ALIAS[k]! : null;
|
|
79
|
+
}
|
|
80
|
+
|
|
48
81
|
/** NodeKind 別名 (日本語 → English) */
|
|
49
82
|
export const NODE_KIND_ALIAS: Record<string, NodeKind> = {
|
|
50
83
|
// 日本語
|