@cardenelabs/dragon 0.32.0 → 0.34.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cardenelabs/dragon",
3
- "version": "0.32.0",
3
+ "version": "0.34.0",
4
4
  "description": "Dragon — Mermaid 感覚で animated SVG を生成する Text DSL。 cdl engine を内部利用。",
5
5
  "license": "MIT",
6
6
  "author": "cardene777",
@@ -47,7 +47,7 @@
47
47
  },
48
48
  "sideEffects": false,
49
49
  "dependencies": {
50
- "@cardenelabs/cdl": "^0.139.0"
50
+ "@cardenelabs/cdl": "^0.140.0"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "react": "^19.0.0",
@@ -77,7 +77,7 @@ function cdl側のslug(s: string): string {
77
77
  *
78
78
  * | 図種 | `😀` だけを書いた時に付く id |
79
79
  * |---|---|
80
- * | `sequence` / `solidity` | 枠 `actor-0` (cdl の `sequence()`) |
80
+ * | `sequence` | 枠 `actor-0` (cdl の `sequence()`) |
81
81
  * | `swimlane` | 枠 `lane-0` (cdl の `swimlane()`) |
82
82
  * | 残る 5 図種 | 箱 `n` (dragon 側の逃げ先。 cdl の逃げ道を通らない) |
83
83
  *
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * | 経路 | 図種 | 起点 |
7
7
  * |---|---|---|
8
- * | 板の面 | `sequence` / `solidity` | #2358 |
8
+ * | 板の面 | `sequence` | #2358 |
9
9
  * | 木の図 | `tree` | #2360 |
10
10
  * | 値の図とじょうご | `pie` ほか 9 図種 + `funnel` | #2368 |
11
11
  * | ガントチャートと体験の地図と四象限 | `gantt` / `journey` / `quadrant` | #2370 |
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * | 経路 | 図種 | 起点 |
7
7
  * |---|---|---|
8
- * | 板の言づて | `sequence` / `solidity` | #2356 |
8
+ * | 板の言づて | `sequence` | #2356 |
9
9
  * | 骨格の図 | `tree` / `mind` | #2364 |
10
10
  * | ガントチャート | `gantt` | #2366 |
11
11
  *
@@ -5,23 +5,23 @@ import type { PresetType } from "../types";
5
5
  /**
6
6
  * 記法に書く種類を描画側の種類へ読み替える (#2030 で `compile.ts` から移した)。
7
7
  *
8
- * 記法は描画側に無い種類 (`contract` / `eoa` 等) を受け付けるため、渡す前に読み替える。
8
+ * 記法は描画側に無い種類 (`entity` / `state` 等) を受け付けるため、渡す前に読み替える。
9
9
  * 読み替えずに渡すと描画側が大きさを引けず、図の組み立てが落ちる。
10
10
  */
11
11
 
12
12
  /**
13
13
  * 記法だけが持つ種類を、描画できる種類へ読み替える (#1420)。
14
14
  *
15
- * 記法は `contract` / `eoa` のような **描画側に無い種類** を受け付ける
16
- * (`v05/parser.ts` の `DSL_ONLY_KINDS`)。 図種ごとの役割分け (`solidity` の縦列の並べ替え
17
- * など) に使うためで、記法としては正しい。
15
+ * 記法は `entity` / `state` のような **描画側に無い種類** を受け付ける
16
+ * (`v05/parser.ts` の `DSL_ONLY_KINDS`)。 図種ごとの役割分け (ER 図の実体など) に使うためで、
17
+ * 記法としては正しい。
18
18
  *
19
19
  * **そのまま描画側へ渡すと図の組み立てが落ちる**。 描画側は知らない種類の大きさを引けず、
20
20
  * `Cannot read properties of undefined (reading 'h')` で止まる (実測)。
21
21
  *
22
- * `solidity` と `er` は組み立ての中で別の種類に置き換えていたが、`flow` / `swimlane` /
23
- * `state` / `topology` は `a.kind` をそのまま渡していた。 記法が受ける値で図が出ない状態
24
- * だったので、渡す手前で必ず通す。
22
+ * `er` は組み立ての中で別の種類に置き換えていたが、`flow` / `swimlane` / `state` /
23
+ * `topology` は `a.kind` をそのまま渡していた。 記法が受ける値で図が出ない状態だったので、
24
+ * 渡す手前で必ず通す。
25
25
  *
26
26
  * ## 読み替え先
27
27
  *
@@ -29,9 +29,6 @@ import type { PresetType } from "../types";
29
29
  * |---|---|---|
30
30
  * | `entity` | `storage` | 表を持つ = ER 図の実体 |
31
31
  * | `state` | `card` | 状態は札で表す |
32
- * | `contract` / `proxy` / `library` / `interface` | `card` | 契約は札で表す (`solidity` の置き換え先に合わせた) |
33
- * | `eoa` | `person` | 人が持つ財布 |
34
- * | `multisig` | `signer` | 複数人で署名する (`solidity` の置き換え先に合わせた) |
35
32
  * | `loop` | `card` | 繰り返しは札で表す。 分かれ道の図では形に読み替わるのでここを通らない (#2523) |
36
33
  *
37
34
  * **表は `DSL_ONLY_KINDS` を鍵にして書く**。 種類を足した時に読み替え先が無いと
@@ -41,12 +38,6 @@ export const 記法だけの種類の読み替え: Readonly<Record<(typeof DSL_O
41
38
  {
42
39
  entity: "storage",
43
40
  state: "card",
44
- contract: "card",
45
- proxy: "card",
46
- library: "card",
47
- interface: "card",
48
- eoa: "person",
49
- multisig: "signer",
50
41
  loop: "card",
51
42
  };
52
43
 
@@ -11,7 +11,7 @@ import type { DslDocument, PresetType } from "../types";
11
11
  /**
12
12
  * 縦列を選べる図種 (#1263)。
13
13
  *
14
- * 縦列を **箱を並べるための入れ物** として使う図種だけを許す。 順序図と solidity は
14
+ * 縦列を **箱を並べるための入れ物** として使う図種だけを許す。 順序図は
15
15
  * 縦列がそのまま生命線として描かれる骨格なので許さない (#1248 の判断はこちらに当たる)。
16
16
  *
17
17
  * `er` は「1 縦列 1 箱」 が図の読み方そのもの (表が横に並ぶ) なので、2 つの箱を同じ縦列へ
@@ -102,7 +102,7 @@ export type CompileNotice = {
102
102
  // 出来事が指す相手が図に無い (#1393)。 書いた名前が本文のどこにも無い時に出す = 書き直せば直る
103
103
  | "event-target-missing"
104
104
  // 出来事が指す名前は本文に在るが、この図種はそれを箱 / 矢印にしない (#2336)。
105
- // 値を並べる図種は図全体で 1 つの箱になり、 順序図と solidity は 1 枚の板になる。
105
+ // 値を並べる図種は図全体で 1 つの箱になり、 順序図は 1 枚の板になる。
106
106
  // `event-target-missing` と分けるのは、こちらが **書き直しても直らない** 側だから
107
107
  | "event-target-not-honored"
108
108
  // 段の注目先に書いた名前は本文に在るが、この図種はそれを箱 / 矢印にしない (#2398)。
@@ -5,33 +5,28 @@ import type { DslDocument, PresetType } from "../types";
5
5
  *
6
6
  * ## 型ではなく語で持つ
7
7
  *
8
- * 並べ替えの鍵しか持たない図種 (`solidity`) が在り、独自の組み立てを 1 行も持たずに
9
- * 箱を種類で並べ替えてから順序図の組み立てをそのまま呼んでいた。
8
+ * 並べ替えの鍵しか持たない図種が在り、独自の組み立てを 1 行も持たずに箱を種類で並べ替えて
9
+ * から順序図の組み立てをそのまま呼んでいた。
10
10
  *
11
11
  * 型として持つと、振る舞いを書くたびに「順序図 または その型」 という条件を並べることになる。
12
12
  * 実際 `compile.ts` に 6 か所あり、**次に条件を足す人が片方を書き忘れれば黙って外れる**
13
13
  * 形になっていた。 差が並べ替えだけなら語で表す。
14
14
  *
15
- * ## 種類の順は 4 段
15
+ * ## 種類の順は 3 段
16
16
  *
17
- * 人 → 契約 → しまう場所 → 出来事 の順に置く。 元の実装が持っていた並びをそのまま移した。
17
+ * 人 → しまう場所 → 出来事 の順に置く。
18
18
  * **同じ段の中では書いた順のまま** = 比べる値が等しい時の並びは変わらない。
19
19
  *
20
+ * Solidity の図に向けた段 (契約) と行 (`eoa` / `multisig` / `wallet`) は外した (#2947)。
21
+ *
20
22
  * 表に無い種類は最後に置く。 知らない種類を先頭へ寄せると、書き手が種類を書き間違えた図で
21
23
  * 並びが大きく崩れて原因が読めない。
22
24
  */
23
25
  const 種類の段: Record<string, number> = {
24
- eoa: 0,
25
26
  actor: 0,
26
- multisig: 0,
27
27
  signer: 0,
28
- wallet: 0,
29
- contract: 1,
30
- proxy: 1,
31
- library: 1,
32
- interface: 1,
33
- storage: 2,
34
- event: 3,
28
+ storage: 1,
29
+ event: 2,
35
30
  };
36
31
 
37
32
  /** 表に無い種類を置く段。 どの段よりも後ろになる数にする */
package/src/compile.ts CHANGED
@@ -103,7 +103,6 @@ import {
103
103
  DIAGRAM_SHAPES,
104
104
  resolveShape,
105
105
  shapesForDiagramType,
106
- 意匠の円の区画の間,
107
106
  棒を描く節か,
108
107
  意匠の棒の角,
109
108
  type DslShape,
@@ -708,8 +707,6 @@ function 配色と縞を当てる(diagram: CdlDiagram, doc: DslDocument): void {
708
707
  if (配色 === undefined) return;
709
708
  diagram.palette = 配色;
710
709
  for (const node of diagram.nodes) {
711
- const 円の区画の間 = 意匠の円の区画の間(配色, node);
712
- if (円の区画の間 !== undefined) node.chartPieSliceGap = 円の区画の間;
713
710
  if (棒を描く節か(node)) {
714
711
  const 棒の角 = 意匠の棒の角(配色, node);
715
712
  if (棒の角 !== undefined) node.barCornerRadii = 棒の角;
@@ -1406,9 +1403,8 @@ function reportActorKindNotHonored(doc: DslDocument, onNotice?: (n: CompileNotic
1406
1403
  * 種類は板の絵には出ないが、並び順を書いた図では **面の並びを決めている**ので、
1407
1404
  * 書いた意味は figure に出ている。 落ちたと伝えると、正しく効いている指定に毎回鳴る。
1408
1405
  *
1409
- * 畳む前はこの判定を図種 (`solidity`) で行っていた。 型を畳んだので、同じことを
1410
- * 並び順が効いているかで見る = 古い名前で書いた図は読み替えでこの語が入るため、
1411
- * 鳴らないという振る舞いが前と変わらない。
1406
+ * 畳む前はこの判定を図種で行っていた。 型を畳んだので、同じことを並び順が効いているかで
1407
+ * 見る。
1412
1408
  */
1413
1409
  if (並び順が効くか(doc)) return;
1414
1410
  for (const a of doc.actors) {
package/src/focus.ts CHANGED
@@ -20,7 +20,7 @@ export type FocusEntry =
20
20
  /**
21
21
  * 矢印の形。 `->` の 2 文字か `→` の 1 文字だけを矢印と見なす。
22
22
  *
23
- * `-` 1 文字を矢印に含めてはいけない。 名前に `-` を使う箱 (`api-gateway` / `shape-api-gateway`)
23
+ * `-` 1 文字を矢印に含めてはいけない。 名前に `-` を使う箱 (`api-gateway` / `shape-code-block`)
24
24
  * が矢印として読まれる。
25
25
  */
26
26
  const ARROW = /^(.+?)\s*(?:->|→)\s*(.+)$/;
@@ -90,6 +90,7 @@ import {
90
90
  } from "./keywords";
91
91
  // 区画の語の表 (#2667)。 記法と同じ表から直す = 同じ区画を 2 通りで呼ばない
92
92
  import { 区画 } from "./compile/word-state";
93
+ import { 外した図種の知らせ, 外した種類, 外した種類の知らせ } from "./v05/removed-syntax";
93
94
  // 行頭の印の古い語の読み替え (#2782)。 記法と同じ表を通す = JSON だけ古い語が印を持たない
94
95
  // 形にならない
95
96
  import { 行頭の語へ読み替える } from "./compile/row-marks";
@@ -139,7 +140,7 @@ import {
139
140
  } from "./relative-pos";
140
141
 
141
142
  /** 古い綴りで書いた図種 (#2655 / #2657)。 受ける値は `TYPE_ALIASES` が SSOT */
142
- type 図種の別名 = "solidity" | DslShape;
143
+ type 図種の別名 = DslShape;
143
144
 
144
145
  /**
145
146
  * LLM 向け JSON DSL の入力 shape。 YAML DSL と 1:1 対応、 top-level は flat な object。
@@ -150,8 +151,9 @@ export interface DragonJson {
150
151
  /**
151
152
  * preset type (必須)。 受け付ける値は `PRESET_TYPES` と `TYPE_ALIASES` が SSOT。
152
153
  *
153
- * 別名 (#2655 / #2657) は読み取りで図種と語の 2 つに開く = `solidity` と書いた JSON は
154
- * 順序図 + 種類で並べ替え、`pie` と書いた JSON は 数を描く図 + 円の形 として読まれる。
154
+ * 別名 (#2655 / #2657) は読み取りで図種と語の 2 つに開く = `pie` と書いた JSON は
155
+ * 数を描く図 + 円の形 として読まれる。 外した図種 (`solidity`) は置き換え先を誤りとして返す
156
+ * (#2947、`v05/removed-syntax.ts`)。
155
157
  */
156
158
  type: PresetType | 図種の別名;
157
159
  /** 円グラフの見せ方。 */
@@ -1621,7 +1623,13 @@ function 値を検査(
1621
1623
  });
1622
1624
  }
1623
1625
  return;
1624
- case "必須の図種":
1626
+ case "必須の図種": {
1627
+ // 外した図種は置き換え先を示す (#2947)。 「使える図種の一覧」 では書き換え先が分からない
1628
+ const 外した = typeof v === "string" ? 外した図種の知らせ(v) : undefined;
1629
+ if (外した !== undefined) {
1630
+ errors.push({ path, message: `${名前} "${String(v)}" was removed`, hint: 外した.hint });
1631
+ return;
1632
+ }
1625
1633
  if (
1626
1634
  typeof v !== "string" ||
1627
1635
  !(VALID_PRESETS.includes(v as PresetType) || VALID_ALIASES.includes(v))
@@ -1633,6 +1641,7 @@ function 値を検査(
1633
1641
  });
1634
1642
  }
1635
1643
  return;
1644
+ }
1636
1645
  case "object":
1637
1646
  case "並び":
1638
1647
  case "必須の並び":
@@ -1779,7 +1788,8 @@ function validateRelativeAnchors(actors: readonly unknown[], errors: JsonDslErro
1779
1788
  */
1780
1789
  function 見本の名前か(kind: unknown): boolean {
1781
1790
  if (typeof kind !== "string" || kind.length === 0) return false;
1782
- return kind !== "actor" && !VALID_KIND_SET.has(kind);
1791
+ // 外した種類は見本の名前として扱わない (#2947)。 置き換え先の知らせだけを出す
1792
+ return kind !== "actor" && !外した種類.has(kind) && !VALID_KIND_SET.has(kind);
1783
1793
  }
1784
1794
 
1785
1795
  /**
@@ -3361,6 +3371,11 @@ function validateJson(
3361
3371
  }
3362
3372
  const ao = a as Record<string, unknown>;
3363
3373
  checkUnknownKeys(ao, "actor", `$.actors[${i}]`, errors);
3374
+ // 外した種類は置き換え先を示す (#2947)。 記法と同じ表を引く
3375
+ const 外した = typeof ao.kind === "string" ? 外した種類の知らせ(ao.kind) : undefined;
3376
+ if (外した !== undefined) {
3377
+ errors.push({ path: `$.actors[${i}].kind`, message: `kind "${String(ao.kind)}" was removed`, hint: 外した.hint });
3378
+ }
3364
3379
  // 値そのものの型は表が見る (#1304)。 `kind` は見本 (parts) の名前も受けるため
3365
3380
  // 非空の文字列までしか縛らない (CAR-1657 の unified syntax)
3366
3381
  表で検査(ao, "actor", `$.actors[${i}]`, "actor", errors);
@@ -3818,17 +3833,20 @@ export function jsonToDoc(json: DragonJson, 行の表?: 書いた行の表): Dsl
3818
3833
  }
3819
3834
  // CAR-1657 = kind が既存 NodeKind に無い値なら parts identifier 候補、 partId に格納
3820
3835
  const kindStr = a.kind ?? "actor";
3821
- const isPart = kindStr !== "actor" && !VALID_KIND_SET.has(kindStr);
3836
+ const isPart = 見本の名前か(kindStr);
3837
+ // 外した種類 (#2947) は検査が誤りとして返す。 検査を通さずに呼ばれても描けない種類を
3838
+ // 描画側へ渡さないよう、書かなかった箱と同じ扱いにする
3839
+ const 外した = 外した種類.has(kindStr);
3822
3840
  // 色は記法と同じ振り分けを通す (#1294)。 `#` で始まれば色番号、それ以外は色の名前。
3823
3841
  // 別々に書くと、同じ値が入口によって色番号にも色名にもなる
3824
3842
  const 色 = a.color !== undefined ? splitColorValue(a.color) : {};
3825
3843
  const 書いた座標 = a.at ?? a.点の位置;
3826
3844
  return {
3827
3845
  name: a.name,
3828
- kind: isPart ? "actor" : resolveNodeKind(kindStr),
3846
+ kind: isPart || 外した ? "actor" : resolveNodeKind(kindStr),
3829
3847
  // parts 候補は `kind` を `actor` に倒して `partId` へ退避するため、 名札に載せる種類としては
3830
3848
  // 「書かなかった」 と同じ扱いにする (#1058)
3831
- kindWritten: a.kind !== undefined && !isPart,
3849
+ kindWritten: a.kind !== undefined && !isPart && !外した,
3832
3850
  subtitle: a.subtitle,
3833
3851
  kindForm: isPart ? undefined : a.kindForm,
3834
3852
  icon: isPart ? undefined : a.icon,
@@ -4138,7 +4156,6 @@ export function jsonToDoc(json: DragonJson, 行の表?: 書いた行の表): Dsl
4138
4156
  ...(json.ganttSize !== undefined ? { ganttSize: json.ganttSize } : {}),
4139
4157
  ...(json.quadrantLabelPosition !== undefined ? { quadrantLabelPosition: json.quadrantLabelPosition } : {}),
4140
4158
  ...(json.quadrantSize !== undefined ? { quadrantSize: json.quadrantSize } : {}),
4141
- ...(別名?.order !== undefined ? { order: 別名.order, orderPos: 位置("type") } : {}),
4142
4159
  ...(別名?.shape !== undefined ? { shape: 別名.shape, shapePos: 位置("type") } : {}),
4143
4160
  // 前後の空白を落としてから見る。 記法側 (`v05/parser.ts`) が `trim()` してから
4144
4161
  // 空かどうかを判定するため、 揃えないと **空白だけの値で入口ごとに図が変わる**
package/src/keywords.ts CHANGED
@@ -57,9 +57,8 @@ export function resolveDirection(s: string): DslDirection | null {
57
57
  *
58
58
  * 書かなければ **書いた順** のまま。 `種類` と書くと箱の種類で並べ替えてから置く。
59
59
  *
60
- * これは図の型として持っていた差を語に出したもの。 並べ替えの鍵しか持たない型
61
- * (`solidity`) が在り、`compile.ts` は「順序図 または その型」 という条件を 6 か所で
62
- * 書いていた。 **型が 1 つ増えるたびに条件を 2 つ並べる形**になるので、差が並べ替えだけなら
60
+ * これは図の型として持っていた差を語に出したもの。 並べ替えの鍵しか持たない型が在り、
61
+ * `compile.ts` は「順序図 または その型」 という条件を 6 か所で書いていた。 **型が 1 つ増えるたびに条件を 2 つ並べる形**になるので、差が並べ替えだけなら
63
62
  * 型ではなく語で表す。
64
63
  */
65
64
  export const ORDERS = ["種類"] as const;
@@ -238,12 +237,16 @@ export function 意匠の字の測り方(_theme: DslTheme): "widest" {
238
237
  return "widest";
239
238
  }
240
239
 
241
- /** 意匠と節から、見本に合わせた円の区画間の弧の長さを引く (#2871)。 */
240
+ /**
241
+ * 意匠と節から円の区画間の弧の長さを引く (#2871 / #2926)。
242
+ *
243
+ * 区画の形を意匠で変えないため値は返さない。公開済みの関数なので互換の窓口だけを残す。
244
+ */
242
245
  export function 意匠の円の区画の間(
243
- theme: DslTheme,
244
- node: Pick<CdlNode, "kind">,
245
- ): number | undefined {
246
- return theme === "neon" && node.kind === "chart-pie" ? 3 : undefined;
246
+ _theme: DslTheme,
247
+ _node: Pick<CdlNode, "kind">,
248
+ ): undefined {
249
+ return undefined;
247
250
  }
248
251
 
249
252
  /** `barCornerRadii` が効く棒を描く節か。 */
@@ -29,7 +29,6 @@
29
29
  "swimlane",
30
30
  "record",
31
31
  "topology",
32
- "solidity",
33
32
  "gantt",
34
33
  "chart",
35
34
  "pie",
@@ -48,7 +47,7 @@
48
47
  "c4",
49
48
  "mind"
50
49
  ],
51
- "description": "図の種類。 型ごとに actors の書き方が違う。 [関係を描く] sequence (時系列の呼び出し) / flow (処理の流れ) / flowchart (分かれ道と判断を含む手順) / swimlane (責務ごとの流れ) / record (箱が行を持ち関係を持つ図。 表のつながり、移り変わり、UML クラス関係にも使う) / topology (network) / c4 (architecture) / mind (発想の枝分かれ) は actors に名前を並べ flow に矢印を書く。 [値を描く] chart (数の並び) は actors に `- 名前: \"45\"` の形で数を書き、 shape で形を選ぶ (pie = 割合 / bar = 棒の高さ / line = 線の高さで書いた順に並ぶ / gauge = 合計を半円で示す / radial = 弧の長さで比べる / stat = 値 1 つを大きく示す / waffle = 割合を 100 個の印で示す / stacked = 内訳を帯で示す / slope = 2 時点を直線でつなぎ増減と順位の入れ替わりを示す)。 shape が stat と stacked と slope の時は `- 名前: { value: \"320\", previous: \"280\" }` の形で前の時点の値も書ける。 funnel (段ごとに減る数) も同じ形。 [語を描く] journey (体験の起伏) は `- 登録: \"不満\"` の形で 最高 / 満足 / 普通 / 不満 / 怒り のどれかを書く。 quadrant (2 軸の仕分け) は `- 重複削除: \"左上\"` の形で 左上 / 右上 / 左下 / 右下 のどれかを書く。 [時期を描く] gantt (工程の並び) は `- 設計: \"1月\"` の形で始まりの時期を書き、 flow の矢印で前後関係を書く。 [親子を描く] tree (親子の入れ子) は actors に名前を並べ flow の矢印で親子を書く (矢印の先が子)。 [古い綴り] solidity は sequence と order: kind の組、 pie / bar / line / gauge / radial / stat / waffle / stacked / slope は chart と同じ綴りの shape の組と同じ扱いになる"
50
+ "description": "図の種類。 型ごとに actors の書き方が違う。 [関係を描く] sequence (時系列の呼び出し) / flow (処理の流れ) / flowchart (分かれ道と判断を含む手順) / swimlane (責務ごとの流れ) / record (箱が行を持ち関係を持つ図。 表のつながり、移り変わり、UML クラス関係にも使う) / topology (network) / c4 (architecture) / mind (発想の枝分かれ) は actors に名前を並べ flow に矢印を書く。 [値を描く] chart (数の並び) は actors に `- 名前: \"45\"` の形で数を書き、 shape で形を選ぶ (pie = 割合 / bar = 棒の高さ / line = 線の高さで書いた順に並ぶ / gauge = 合計を半円で示す / radial = 弧の長さで比べる / stat = 値 1 つを大きく示す / waffle = 割合を 100 個の印で示す / stacked = 内訳を帯で示す / slope = 2 時点を直線でつなぎ増減と順位の入れ替わりを示す)。 shape が stat と stacked と slope の時は `- 名前: { value: \"320\", previous: \"280\" }` の形で前の時点の値も書ける。 funnel (段ごとに減る数) も同じ形。 [語を描く] journey (体験の起伏) は `- 登録: \"不満\"` の形で 最高 / 満足 / 普通 / 不満 / 怒り のどれかを書く。 quadrant (2 軸の仕分け) は `- 重複削除: \"左上\"` の形で 左上 / 右上 / 左下 / 右下 のどれかを書く。 [時期を描く] gantt (工程の並び) は `- 設計: \"1月\"` の形で始まりの時期を書き、 flow の矢印で前後関係を書く。 [親子を描く] tree (親子の入れ子) は actors に名前を並べ flow の矢印で親子を書く (矢印の先が子)。 [古い綴り] pie / bar / line / gauge / radial / stat / waffle / stacked / slope は chart と同じ綴りの shape の組と同じ扱いになる"
52
51
  },
53
52
  "form": {
54
53
  "type": "string",
@@ -410,7 +409,7 @@
410
409
  },
411
410
  "kind": {
412
411
  "type": "string",
413
- "description": "node kind。 shape-* を指定して 49 shape 中から選ぶ。 例: 'shape-wallet' / 'shape-smart-contract' / 'shape-cloud' / 'shape-file' / 'actor' (default) / 'function' / 'storage' / 'event' 等。 種別に無い名前は部品の名前として部品の一覧 (partsCatalog) から引き、一覧にも無ければ種別を書かなかった箱になる。 部品を持つ一覧を渡した時は知らせを出し、綴りの近い名前を案内する。"
412
+ "description": "node kind。 shape-* を指定すると基本の形 (箱の形そのものを描く) と汎用の挿絵 (窓 / 端末 / コードの札 / 携帯 / サーバーの棚) から選べる。 例: 'shape-cloud' / 'shape-file' / 'shape-window' / 'actor' (default) / 'function' / 'storage' / 'event' 等。 種別に無い名前は部品の名前として部品の一覧 (partsCatalog) から引き、一覧にも無ければ種別を書かなかった箱になる。 部品を持つ一覧を渡した時は知らせを出し、綴りの近い名前を案内する。"
414
413
  },
415
414
  "subtitle": {
416
415
  "type": "string",
package/src/types.ts CHANGED
@@ -10,8 +10,8 @@ import type { DslDiagramShape, DslDirection, DslOrder, DslTheme } from "./keywor
10
10
  /**
11
11
  * 記法が書ける箱の種類 (#1420)。
12
12
  *
13
- * 描画できる種類 (`NodeKind`) に、**記法だけが持つ種類** (`contract` / `eoa` など) を足す。
14
- * 後者は図種ごとの役割分け (`solidity` の縦列の並べ替えなど) に使い、描画側へ渡す手前で
13
+ * 描画できる種類 (`NodeKind`) に、**記法だけが持つ種類** (`entity` / `state` など) を足す。
14
+ * 後者は図種ごとの役割分け (ER 図の実体など) に使い、描画側へ渡す手前で
15
15
  * `compile.ts` の `描ける種別` が読み替える。
16
16
  *
17
17
  * `NodeKind` だけに縛っていた間、記法が受ける値を型が表せていなかった。
@@ -371,8 +371,8 @@ export type DslDocument = {
371
371
  * 効くのは順序図だけで、他の図種は並び方そのものが読み方を担うため書いても効かない
372
372
  * (知らせを出す)。
373
373
  *
374
- * 並べ替えの鍵しか持たない図種 (`solidity`) を畳んだ先。 読み取りの入口で
375
- * 順序図 + この語 に読み替えるので、古い名前で書いた記法はそのまま動く。
374
+ * 並べ替えの鍵しか持たない図種を畳んだ先。 その図種 (`solidity`) は特定の技術に向けた
375
+ * 名前なので外した (#2947)。
376
376
  */
377
377
  order?: DslOrder;
378
378
  /** `order:` を書いた行。 効かない時の知らせで、書いた場所を指すために持つ */
package/src/v05/parser.ts CHANGED
@@ -84,6 +84,7 @@ import {
84
84
  resolveLegendMark,
85
85
  } from "../keywords";
86
86
  import { 区画 } from "../compile/word-state";
87
+ import { 外した図種の知らせ, 外した種類の知らせ } from "./removed-syntax";
87
88
  // 行頭の印の古い語の読み替え (#2782)。 印を作る側と同じ file が表を持つ = 縦に並べた形と
88
89
  // 中括弧の形と JSON の 3 経路が同じ表を通る
89
90
  import { 行頭の語へ読み替える } from "../compile/row-marks";
@@ -609,25 +610,23 @@ export const PRESET_TYPES: ReadonlySet<PresetType> = new Set([
609
610
  * 図種の別名 (#2655 / #2657)。
610
611
  *
611
612
  * **差が語 1 つしかない図種を、畳んだ先の型とその語に読み替える**。
613
+ * 数を描く 9 つは `chart` + `shape: <綴り>` に読み替える = 同じ組み立て関数に渡す文字列 2 つ
614
+ * しか違わない。
612
615
  *
613
- * | 古い綴り | 読み替え先 | 差 |
614
- * |---|---|---|
615
- * | `solidity` | `sequence` + `order: 種類` | 箱を種類で並べ替えるだけで、独自の組み立てを持たない |
616
- * | 数を描く 9 つ | `chart` + `shape: <綴り>` | 同じ組み立て関数に渡す文字列 2 つしか違わない |
617
- *
618
- * 型として持つと、同じ扱いをする条件と表が型の数だけ増える。 `solidity` は
619
- * 「順序図 または その型」 という条件を 12 か所に増やし、数を描く 9 つは 4 つの表に
616
+ * 型として持つと、同じ扱いをする条件と表が型の数だけ増える。 数を描く 9 つは 4 つの表に
620
617
  * 同じ値の行を 9 行ずつ並べていた (足す人が 1 か所書き忘れると黙って外れる)。
621
618
  *
619
+ * `solidity` も `sequence` + `order: 種類` への別名だったが、特定の技術に向けた図種なので
620
+ * 外した (#2947)。 書いた人には `removed-syntax.ts` の表が置き換え先を返す。
621
+ *
622
622
  * **読み替えは読み取りの入口 1 か所に閉じる**。 ここを通った後は古い綴りが
623
623
  * どこにも残らないので、組み立て側は畳んだ先の型として 1 通りに扱える。
624
624
  *
625
625
  * 古い名前で書いた記法はそのまま動く = 別名を消すのは別の回にする。
626
626
  */
627
- type 読み替え先 = { type: PresetType; order?: DslOrder; shape?: DslShape };
627
+ type 読み替え先 = { type: PresetType; shape?: DslShape };
628
628
 
629
629
  export const TYPE_ALIASES: ReadonlyMap<string, 読み替え先> = new Map<string, 読み替え先>([
630
- ["solidity", { type: "sequence", order: "種類" }],
631
630
  ...SHAPES.map((s): [string, 読み替え先] => [s, { type: "chart", shape: s }]),
632
631
  ]);
633
632
 
@@ -645,8 +644,8 @@ const NODE_KIND_DEFAULT: NodeKind = "actor";
645
644
  /**
646
645
  * 記法だけが持つ種類。 描画側には無いが、 図種ごとの組み立てで意味を持つ。
647
646
  *
648
- * `contract` / `eoa` / `multisig` / `proxy` / `library` / `interface` は Solidity 図の
649
- * 役割分けに、 `entity` / `state` は ER 図と状態遷移図に使う。
647
+ * `entity` / `state` は ER 図と状態遷移図に使う。 Solidity の図の役割分け
648
+ * (`contract` / `eoa` など) は外した (#2947、置き換え先は `removed-syntax.ts`)。
650
649
  *
651
650
  * **描画側へ渡す前に必ず読み替える** (`compile.ts` の `描ける種別`)。 読み替えを通さずに渡すと
652
651
  * 図の組み立てが落ちる = 描画側は知らない種類の大きさを引けない (#1420 で実測、
@@ -655,12 +654,6 @@ const NODE_KIND_DEFAULT: NodeKind = "actor";
655
654
  export const DSL_ONLY_KINDS = [
656
655
  "entity",
657
656
  "state",
658
- "contract",
659
- "eoa",
660
- "multisig",
661
- "proxy",
662
- "library",
663
- "interface",
664
657
  // 繰り返しの箱 (#2523)。 描画側は分かれ道の図の形としてだけ持ち、種類としては持たないため
665
658
  // ここに置く。 分かれ道の図では形に読み替わり (`compile/flowchart.ts`)、それ以外の図種では
666
659
  // `記法だけの種類の読み替え` が札に落とす
@@ -671,24 +664,17 @@ export const DSL_ONLY_KINDS = [
671
664
  export type DslOnlyKind = (typeof DSL_ONLY_KINDS)[number];
672
665
 
673
666
  /**
674
- * AWS などの固有名を、 同じ役割を表す汎用の種類に読み替える表。
667
+ * 一般の語を、 同じ役割を表す描画側の種類に読み替える表。
675
668
  *
676
- * これらは記法が受け付けるのに描画側に無く、 書くと「kind "alb" は未対応」 とエラーになって
677
- * いた。 受け付けるのをやめると今度は部品名として扱われ「そんな部品はない」 と出る。 どちらも
678
- * 書いた人が困るだけなので、 意味の近い種類に読み替えて実際に図が出るようにする。
669
+ * これらは記法が受け付けるのに描画側に無く、 受け付けるのをやめると部品名として扱われ
670
+ * 「そんな部品はない」 と出る。 書いた人が困るだけなので、 意味の近い種類に読み替えて
671
+ * 実際に図が出るようにする。
679
672
  *
680
- * 読み替え先が重なるものがある (`iam` と `kms` は権限と鍵を守る役、 `s3` と `secret` は
681
- * 保管する役)。 見た目が同じになるが、 役割が同じなので嘘にはならない。
673
+ * AWS の名前 (`alb` / `lambda` / `s3` など) もここで読み替えていたが、特定の会社の語なので
674
+ * 外した (#2947、置き換え先は `removed-syntax.ts`)。 残る 4 つは特定の会社の語ではない。
682
675
  */
683
676
  const INFRA_KIND_ALIAS: Record<string, NodeKind> = {
684
- alb: "shape-api-gateway", // 入口で振り分ける
685
677
  browser: "frontend", // 画面側
686
- ecs: "microservice", // コンテナ群
687
- iam: "admin", // 権限を守る
688
- kms: "admin", // 鍵を守る
689
- lambda: "function", // 呼ぶと動く
690
- rds: "database", // 表を持つ
691
- s3: "storage", // 置き場
692
678
  secret: "storage", // 機密の置き場
693
679
  user: "person", // 人
694
680
  container: "service", // 動かす単位 (C4 の container)
@@ -1505,13 +1491,15 @@ export function parseTextDslV05(src: string): V05ParseResult {
1505
1491
  // **別名を先に引く** (#2655)。 引けたら図種と並び順の 2 つに開いて、以降は
1506
1492
  // その語が 1 か所も残らないようにする
1507
1493
  const 別名 = TYPE_ALIASES.get(v);
1508
- if (別名 !== undefined) {
1494
+ const 外した = 外した図種の知らせ(v);
1495
+ if (外した !== undefined) {
1496
+ // 外した図種は置き換え先を示す (#2947)。 「図種が読めません」 では書き換え先が分からない
1497
+ errors.push({ line: line.no, ...外した });
1498
+ // 図種は置き換え先の順序図として読み進める。 空のままにすると「type が書かれていません」
1499
+ // が重なり、書いたのに書いていないと言われる
1500
+ type = "sequence";
1501
+ } else if (別名 !== undefined) {
1509
1502
  type = 別名.type;
1510
- // 書き手が語も書いていればそちらが勝つ = 別名は既定を入れるだけ
1511
- if (order === null && 別名.order !== undefined) {
1512
- order = 別名.order;
1513
- orderLine = line.no;
1514
- }
1515
1503
  if (別名.shape !== undefined) {
1516
1504
  aliasShape = 別名.shape;
1517
1505
  aliasShapeLine = line.no;
@@ -3981,6 +3969,19 @@ function reportV04Kind(kindRaw: string, line: number, errors: DslError[]): void
3981
3969
  });
3982
3970
  }
3983
3971
 
3972
+ /**
3973
+ * 外した箱の種類を書いた時に置き換え先を知らせる (#2947)。 知らせたら真を返す。
3974
+ *
3975
+ * 真を返した種類は見本 (parts) の名前として扱わない。 扱うと「そんな部品は無い」 が重なって
3976
+ * 出て、置き換え先の知らせが埋もれる。
3977
+ */
3978
+ function reportRemovedKind(kindRaw: string, line: number, errors: DslError[]): boolean {
3979
+ const 知らせ = 外した種類の知らせ(kindRaw);
3980
+ if (知らせ === undefined) return false;
3981
+ errors.push({ line, ...知らせ });
3982
+ return true;
3983
+ }
3984
+
3984
3985
  /** `色` / `color` のどちらでも書ける。 */
3985
3986
  const COLOR_KEYS = new Set(["色", "color", "tone"]);
3986
3987
 
@@ -4089,11 +4090,12 @@ function applyContinuationLines(actor: DslActor, rest: Line[], errors: DslError[
4089
4090
  case "種類": {
4090
4091
  const k = stripQuotes(raw).toLowerCase();
4091
4092
  reportV04Kind(k, ln.no, errors);
4092
- const isPart = k !== "" && !NODE_KIND_VALID.has(k);
4093
- out.kind = isPart ? NODE_KIND_DEFAULT : resolveNodeKind(k);
4093
+ const 外した = reportRemovedKind(k, ln.no, errors);
4094
+ const isPart = k !== "" && !外した && !NODE_KIND_VALID.has(k);
4095
+ out.kind = isPart || 外した ? NODE_KIND_DEFAULT : resolveNodeKind(k);
4094
4096
  // parts 候補は `kind` を既定に倒して `partId` へ退避するため、 名札に載せる種類としては
4095
4097
  // 「書かなかった」 と同じ扱いにする (#1058)
4096
- out.kindWritten = k !== "" && !isPart;
4098
+ out.kindWritten = k !== "" && !isPart && !外した;
4097
4099
  out.partId = isPart ? k : undefined;
4098
4100
  break;
4099
4101
  }
@@ -5256,9 +5258,10 @@ function parseActor(line: Line, errors: DslError[]): DslActor | null {
5256
5258
  // 縦書きでは通り中括弧では落ちる
5257
5259
  const opts = 中括弧の別名を寄せる(parseInlineMapping(mapMatch.inner));
5258
5260
  const kindRaw = (opts.kind ?? "").toLowerCase();
5261
+ const 外した = reportRemovedKind(kindRaw, line.no, errors);
5259
5262
  // CAR-1657 = kind が既存 NODE_KIND_VALID に無い場合 parts identifier 候補として partId に格納、
5260
5263
  // kind は actor default fallback。 compile 側 partsCatalog lookup で解決する。
5261
- const isPart = kindRaw !== "" && !NODE_KIND_VALID.has(kindRaw);
5264
+ const isPart = kindRaw !== "" && !外した && !NODE_KIND_VALID.has(kindRaw);
5262
5265
  // 倍率はパーツにしか効かない。 書いたのに効かない状態を黙って作らない (#1026)。
5263
5266
  // 値が空の形でも名前を残すため、`opts` ではなく中身から直接拾う
5264
5267
  const inlineScale = resolveScale(writtenScaleFields(mapMatch.inner), line.no, errors);
@@ -5323,7 +5326,7 @@ function parseActor(line: Line, errors: DslError[]): DslActor | null {
5323
5326
  kind,
5324
5327
  // parts 候補は `kind` を既定に倒して `partId` へ退避するため、 名札に載せる種類としては
5325
5328
  // 「書かなかった」 と同じ扱いにする (#1058)
5326
- kindWritten: kindRaw !== "" && !isPart,
5329
+ kindWritten: kindRaw !== "" && !isPart && !外した,
5327
5330
  subtitle: opts.subtitle,
5328
5331
  kindForm: 閉じた箱の値("kindForm", KIND_FORM_VALUES),
5329
5332
  icon: 閉じた箱の値("icon", CDL_ICON_VALUES),
@@ -5435,7 +5438,8 @@ function parseActor(line: Line, errors: DslError[]): DslActor | null {
5435
5438
  const v = classifyValues(splitValues(rest), line.no, errors);
5436
5439
 
5437
5440
  // CAR-1657 = short form (`arc1: arc-gauge`) でも parts kind 対応、 未知 kind は partId 経路
5438
- const isPart = v.kind !== "" && !NODE_KIND_VALID.has(v.kind);
5441
+ const 外した = reportRemovedKind(v.kind, line.no, errors);
5442
+ const isPart = v.kind !== "" && !外した && !NODE_KIND_VALID.has(v.kind);
5439
5443
  reportV04Kind(v.kind, line.no, errors);
5440
5444
  // 倍率はパーツにしか効かない (#1026)
5441
5445
  reportScaleOnNonPart(isPart, v.scaleKeys?.[0], line.no, errors);
@@ -5447,7 +5451,7 @@ function parseActor(line: Line, errors: DslError[]): DslActor | null {
5447
5451
  kind,
5448
5452
  // parts 候補は `kind` を既定に倒して `partId` へ退避するため、 名札に載せる種類としては
5449
5453
  // 「書かなかった」 と同じ扱いにする (#1058)
5450
- kindWritten: v.kind !== "" && !isPart,
5454
+ kindWritten: v.kind !== "" && !isPart && !外した,
5451
5455
  // parts では `tone` を状態の上書きとして扱うため、 色として渡さない
5452
5456
  tone: isPart ? undefined : v.tone,
5453
5457
  subtitle: v.subtitle,