@cardenelabs/dragon 0.34.0 → 0.35.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.
Files changed (127) hide show
  1. package/README.md +39 -720
  2. package/dist/cli.cjs +4529 -0
  3. package/dist/cli.cjs.map +1 -0
  4. package/dist/cli.js +4523 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/export.cjs +3912 -0
  7. package/dist/export.cjs.map +1 -0
  8. package/dist/export.d.cts +36 -0
  9. package/dist/export.d.ts +36 -0
  10. package/dist/export.js +3907 -0
  11. package/dist/export.js.map +1 -0
  12. package/dist/fonts.cjs +7 -0
  13. package/dist/fonts.cjs.map +1 -0
  14. package/dist/fonts.js +4 -0
  15. package/dist/fonts.js.map +1 -0
  16. package/dist/index.cjs +4105 -20356
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +227 -5522
  19. package/dist/index.d.ts +227 -5522
  20. package/dist/index.js +4091 -20283
  21. package/dist/index.js.map +1 -1
  22. package/dist/player.global.js +2 -0
  23. package/dist/schema-BBWfniwH.d.cts +112 -0
  24. package/dist/schema-BBWfniwH.d.ts +112 -0
  25. package/package.json +39 -24
  26. package/src/cli.ts +237 -0
  27. package/src/export/capture.ts +277 -0
  28. package/src/export/fonts.ts +68 -0
  29. package/src/export/html.ts +32 -0
  30. package/src/export/index.ts +146 -0
  31. package/src/field-messages.ts +104 -0
  32. package/src/figure-text.ts +42 -0
  33. package/src/index.ts +30 -283
  34. package/src/layout/architecture.ts +381 -0
  35. package/src/layout/measure.ts +21 -0
  36. package/src/layout/scene.ts +353 -0
  37. package/src/layout/sequence.ts +189 -0
  38. package/src/load-fonts.ts +8 -0
  39. package/src/look/fonts.ts +33 -0
  40. package/src/look/palettes.json +209 -0
  41. package/src/look/values.ts +155 -0
  42. package/src/markdown.ts +35 -0
  43. package/src/messages.ts +122 -0
  44. package/src/parser.ts +342 -310
  45. package/src/player-global.ts +4 -0
  46. package/src/player.ts +271 -0
  47. package/src/printer.ts +76 -0
  48. package/src/render/icons.ts +41 -0
  49. package/src/render/motion.ts +106 -0
  50. package/src/render/parts.ts +279 -0
  51. package/src/render/svg.ts +341 -0
  52. package/src/schema.ts +161 -16
  53. package/src/schemas/diagram.schema.json +150 -0
  54. package/src/schemas/validate-diagram.d.ts +12 -0
  55. package/src/schemas/validate-diagram.js +8 -0
  56. package/src/timeline.ts +166 -0
  57. package/src/tokenize.ts +20 -281
  58. package/src/version.ts +55 -0
  59. package/src/view.ts +16 -0
  60. package/src/words.ts +79 -0
  61. package/examples/quick-start.md +0 -142
  62. package/src/canvas-bounds.ts +0 -52
  63. package/src/color.ts +0 -197
  64. package/src/compile/actor-ids.ts +0 -297
  65. package/src/compile/actor-option-notice.ts +0 -379
  66. package/src/compile/actors.ts +0 -103
  67. package/src/compile/c4.ts +0 -74
  68. package/src/compile/chain.ts +0 -93
  69. package/src/compile/chart-fields.ts +0 -193
  70. package/src/compile/deep-rewrite.ts +0 -30
  71. package/src/compile/derived-source.ts +0 -18
  72. package/src/compile/direction.ts +0 -102
  73. package/src/compile/edge-option-notice.ts +0 -112
  74. package/src/compile/er-relation.ts +0 -200
  75. package/src/compile/flow.ts +0 -54
  76. package/src/compile/flowchart.ts +0 -344
  77. package/src/compile/funnel.ts +0 -87
  78. package/src/compile/gantt.ts +0 -337
  79. package/src/compile/generic.ts +0 -696
  80. package/src/compile/hierarchy.ts +0 -92
  81. package/src/compile/journey.ts +0 -93
  82. package/src/compile/kinds.ts +0 -139
  83. package/src/compile/lanes.ts +0 -138
  84. package/src/compile/metro.ts +0 -271
  85. package/src/compile/mind.ts +0 -393
  86. package/src/compile/node-title.ts +0 -24
  87. package/src/compile/notice.ts +0 -141
  88. package/src/compile/order.ts +0 -57
  89. package/src/compile/parts-lookup.ts +0 -17
  90. package/src/compile/parts.ts +0 -2709
  91. package/src/compile/placement-apply.ts +0 -689
  92. package/src/compile/placement.ts +0 -15
  93. package/src/compile/quadrant.ts +0 -265
  94. package/src/compile/record.ts +0 -75
  95. package/src/compile/row-marks.ts +0 -128
  96. package/src/compile/rows.ts +0 -40
  97. package/src/compile/sequence.ts +0 -305
  98. package/src/compile/slug.ts +0 -37
  99. package/src/compile/stages.ts +0 -247
  100. package/src/compile/subtitle.ts +0 -35
  101. package/src/compile/swimlane-marks.ts +0 -87
  102. package/src/compile/swimlane.ts +0 -82
  103. package/src/compile/timeline.ts +0 -213
  104. package/src/compile/topology.ts +0 -44
  105. package/src/compile/tree.ts +0 -69
  106. package/src/compile/value-chart.ts +0 -337
  107. package/src/compile/values.ts +0 -432
  108. package/src/compile/word-state.ts +0 -82
  109. package/src/compile.ts +0 -3168
  110. package/src/focus.ts +0 -46
  111. package/src/input-size.ts +0 -181
  112. package/src/json-line-map.ts +0 -30
  113. package/src/json-parser.ts +0 -4306
  114. package/src/keywords.ts +0 -417
  115. package/src/near-name.ts +0 -42
  116. package/src/notation-lint.ts +0 -342
  117. package/src/relative-pos.ts +0 -251
  118. package/src/schemas/diagram.json +0 -3088
  119. package/src/types.ts +0 -1009
  120. package/src/v05/index.ts +0 -9
  121. package/src/v05/input-table.generated.ts +0 -138
  122. package/src/v05/parser-types.ts +0 -32
  123. package/src/v05/parser.ts +0 -6668
  124. package/src/v05/readout-table.generated.ts +0 -1088
  125. package/src/v05/removed-syntax.ts +0 -115
  126. package/src/value-syntax.ts +0 -313
  127. package/src/write-position.ts +0 -270
@@ -1,87 +0,0 @@
1
- import { SWIMLANE_SHAPES, type DslSwimlaneShape } from "../keywords";
2
- import type { DslActor, DslDocument, DslStep } from "../types";
3
-
4
- const 泳法図の印 = ["decision", "mark-start", "mark-end"] as const;
5
- type 泳法図の印 = (typeof 泳法図の印)[number];
6
-
7
- export type 泳法図の印の描き方 = "描く" | "札" | "省く";
8
-
9
- /** 段の箱で、分かれ道を普通の箱に添えて見分ける字。 */
10
- export const 分かれ道の札 = "分かれ道";
11
-
12
- /** 泳法図の形と印ごとに、描画側へ渡す形を決める表。 */
13
- export const 泳法図の印の描き方: Record<
14
- DslSwimlaneShape,
15
- Record<泳法図の印, 泳法図の印の描き方>
16
- > = {
17
- stages: {
18
- decision: "札",
19
- "mark-start": "省く",
20
- "mark-end": "省く",
21
- },
22
- metro: {
23
- decision: "描く",
24
- "mark-start": "描く",
25
- "mark-end": "描く",
26
- },
27
- timeline: {
28
- decision: "描く",
29
- "mark-start": "省く",
30
- "mark-end": "描く",
31
- },
32
- };
33
-
34
- /** 泳法図の3形で印をどう描くかを返し、それ以外の図と種類では返さない。 */
35
- export function 泳法図で印をどう描く(
36
- doc: Pick<DslDocument, "type" | "shape">,
37
- actor: Pick<DslActor, "kind">,
38
- ): 泳法図の印の描き方 | undefined {
39
- if (doc.type !== "swimlane") return undefined;
40
- if (!(SWIMLANE_SHAPES as readonly string[]).includes(doc.shape ?? "")) return undefined;
41
- if (!(泳法図の印 as readonly string[]).includes(actor.kind)) return undefined;
42
- return 泳法図の印の描き方[doc.shape as DslSwimlaneShape][actor.kind as 泳法図の印];
43
- }
44
-
45
- /**
46
- * 省く印を本文から外し、その印へ入る線と出る線を直接結ぶ。
47
- *
48
- * 繋いだ線は入る線の行と指定を保つ。説明だけは入る線が空なら出る線から受け継ぎ、
49
- * 後段が元の行から色や線種を写せるようにする。
50
- */
51
- export function 省く泳法図の印を外す(doc: DslDocument): DslDocument {
52
- const 省く印 = doc.actors.filter((actor) => 泳法図で印をどう描く(doc, actor) === "省く");
53
- if (省く印.length === 0) return doc;
54
-
55
- let actors = doc.actors;
56
- let flow = doc.flow;
57
- for (const mark of 省く印) {
58
- const 出る線 = flow.filter((step) => step.from === mark.name && step.to !== mark.name);
59
- const 既に在る組 = new Set(
60
- flow
61
- .filter((step) => step.from !== mark.name && step.to !== mark.name)
62
- .map((step) => `${step.from}\u0000${step.to}`),
63
- );
64
- const 繋ぎ直した: DslStep[] = [];
65
- for (const step of flow) {
66
- if (step.from !== mark.name && step.to !== mark.name) {
67
- 繋ぎ直した.push(step);
68
- continue;
69
- }
70
- if (step.to !== mark.name || step.from === mark.name) continue;
71
- for (const next of 出る線) {
72
- if (step.from === next.to) continue;
73
- const 組 = `${step.from}\u0000${next.to}`;
74
- if (既に在る組.has(組)) continue;
75
- 既に在る組.add(組);
76
- 繋ぎ直した.push({
77
- ...step,
78
- to: next.to,
79
- label: step.label === "" ? next.label : step.label,
80
- });
81
- }
82
- }
83
- actors = actors.filter((actor) => actor !== mark);
84
- flow = 繋ぎ直した;
85
- }
86
- return { ...doc, actors, flow };
87
- }
@@ -1,82 +0,0 @@
1
- import { swimlane } from "@cardenelabs/cdl";
2
- import type { CdlDiagram } from "@cardenelabs/cdl";
3
- import type { DslDocument } from "../types";
4
- import { compileGenericWithAnimate, 共通の組み立てへ回す } from "./generic";
5
- import { 描ける種別 } from "./kinds";
6
- import { 箱の題 } from "./node-title";
7
- import { slugify } from "./slug";
8
- import { STAGE_LANE_WIDTH } from "./stages";
9
- export function compileSwimlane(doc: DslDocument): CdlDiagram {
10
- // 形を指定した泳法図は動き・縦列・向きの有無で経路を分けない (#2797 / #2799)。
11
- // 段の箱の列と札の決め方は `compile/stages.ts` が持つ (#2831)。
12
- if (doc.shape === "stages" || doc.shape === "metro" || doc.shape === "timeline") {
13
- return compileGenericWithAnimate(doc, {
14
- kind: "swimlane",
15
- laneWidth: doc.shape === "stages" ? STAGE_LANE_WIDTH : 400,
16
- });
17
- }
18
- // 動きを書いた形と縦列を書いた形は共通の組み立てへ (#1263 / #2348 で 1 箇所にまとめた)。
19
- // **向きを書いた形も** (#1494)。 静止図の経路は並びを固定で持つので、
20
- // ここを通さないと書いた向きが黙って消える (縦列を書いた形と同じ理由)
21
- if (共通の組み立てへ回す("swimlane", doc, doc.direction !== undefined)) {
22
- return compileGenericWithAnimate(doc, { kind: "swimlane", laneWidth: 400 });
23
- }
24
- // swimlane preset は lane 配置 + 自由 node/edge。
25
- // v0.2 では actors を lane 化、 流れ の各 step から node を生成、 edge を引く。
26
- const swim = swimlane({
27
- id: slugify(doc.title),
28
- topic: doc.title,
29
- lanes: doc.actors.map((a) => a.name),
30
- });
31
-
32
- // 各 step で from / to の node を lane 内 stack 配置
33
- const placedNodes = new Set<string>();
34
- const laneStackCount = new Map<string, number>();
35
- let edgeIdx = 0;
36
-
37
- for (const s of doc.flow) {
38
- for (const actorName of [s.from, s.to]) {
39
- if (placedNodes.has(actorName)) continue;
40
- const laneId = swim.laneId(actorName);
41
- const actor = doc.actors.find((a) => a.name === actorName);
42
- const stack = laneStackCount.get(laneId) ?? 0;
43
- const nodeId = slugify(actorName) || `n${placedNodes.size}`;
44
- swim.node(nodeId, {
45
- lane: laneId,
46
- stack,
47
- kind: 描ける種別(actor?.kind),
48
- title: actorName,
49
- });
50
- laneStackCount.set(laneId, stack + 1);
51
- placedNodes.add(actorName);
52
- }
53
- const fromId = slugify(s.from);
54
- const toId = slugify(s.to);
55
- swim.edge(fromId, toId, {
56
- id: `e${edgeIdx++}-${fromId}-${toId}`,
57
- label: s.label,
58
- ...(s.sub ? { sub: s.sub } : {}),
59
- ...(s.side ? { side: s.side } : {}),
60
- });
61
- }
62
-
63
- // **箱が 1 つも置けなかった時は、 登場人物をそのまま置く** (#1219)。
64
- //
65
- // この図種は矢印の端から箱を作るため、 矢印が 1 本も無いと箱が 0 件になり `compile` が
66
- // 落ちる (実測 = 矢印を書かない図は本 Issue の前から落ちていた)。 解決できない矢印を
67
- // 外すと同じ形になるので、 受け皿を置く。
68
- //
69
- // **1 つでも置けた時は触らない**。 矢印に出てこない登場人物にも箱を置くと、 今まで枠だけ
70
- // だった所に箱が増えて既存の図の見た目が変わる (それを変えるかは別の判断)。
71
- if (placedNodes.size === 0) {
72
- doc.actors.forEach((a, i) => {
73
- swim.node(slugify(a.name) || `n${i}`, {
74
- lane: swim.laneId(a.name),
75
- stack: 0,
76
- kind: 描ける種別(a.kind),
77
- title: 箱の題(a),
78
- });
79
- });
80
- }
81
- return swim.build();
82
- }
@@ -1,213 +0,0 @@
1
- import type { DslDocument } from "../types";
2
- import { slugify } from "./slug";
3
-
4
- /** 見本の札と同じ横長の比率にする。 */
5
- export const TIMELINE_CARD_WIDTH = 420;
6
- export const TIMELINE_CARD_HEIGHT = 56;
7
-
8
- /** 分かれ道の脇に置く札は、見本どおり通常の札より少し短くする。 */
9
- export const TIMELINE_SIDE_CARD_WIDTH = 380;
10
-
11
- /** 描く側の `timeline-number` が半径 24・縁 4 の丸を描く大きさ。 */
12
- export const TIMELINE_NUMBER_SIZE = 52;
13
-
14
- /** 描く側が四辺を 8 内側へ縮めるため、実描画を見本の 124 x 92 にする大きさ。 */
15
- export const TIMELINE_DECISION_WIDTH = 140;
16
- export const TIMELINE_DECISION_HEIGHT = 108;
17
-
18
- /** 軸の lane は、軸上で最も広い菱形をはみ出させない幅にする。 */
19
- export const TIMELINE_AXIS_WIDTH = TIMELINE_DECISION_WIDTH;
20
-
21
- /**
22
- * 描く側は終わりの印を短辺いっぱいに描き、輪の太さの半分だけ半径を縮める。
23
- * `80 x 42` なら node-visibility の下限 80 x 40 を保ち、外輪の半径が 19 になる。
24
- */
25
- export const TIMELINE_END_WIDTH = 80;
26
- export const TIMELINE_END_HEIGHT = 42;
27
-
28
- /**
29
- * 軸から通常の札の内側までの距離。
30
- * 見本と 7 意匠の実測に合わせ、札の内側を軸の中心から 70 離す。
31
- */
32
- export const TIMELINE_AXIS_TO_CARD = 70;
33
-
34
- /** 正解頁の軸 x=800 と「持ち戻る」の左辺 x=1020 から測った距離。 */
35
- export const TIMELINE_AXIS_TO_SIDE_CARD = 220;
36
-
37
- /** 見本どおり、番号の段を 125 ずつ進める。 */
38
- export const TIMELINE_STEP_GAP = 125;
39
-
40
- /** 7 意匠とも前後の和が 285 なので、CSS で意匠を替える見本帳へ届く一つの値を使う。 */
41
- export const TIMELINE_DECISION_GAP = 142.5;
42
-
43
- /** 見本どおり、最後の番号から終わりの印まで 105 空ける。 */
44
- export const TIMELINE_END_GAP = 105;
45
-
46
- /** 軸の左右の札と、戻る線の折れ曲がりを図の中へ収める余白。 */
47
- const TIMELINE_SIDE_MARGIN = 160;
48
-
49
- const AXIS_X = TIMELINE_SIDE_MARGIN + TIMELINE_CARD_WIDTH + TIMELINE_AXIS_TO_CARD;
50
-
51
- /** 最初の札と番号の上側を図の中へ収める中心 y。 */
52
- const FIRST_STEP_Y = 60;
53
-
54
- const TIMELINE_WIDTH = AXIS_X * 2;
55
-
56
- export type TimelineEdgeKind = "advance" | "back" | "branch";
57
-
58
- export type TimelineStep = {
59
- cardId: string;
60
- numberId?: string;
61
- cardX: number;
62
- cardWidth: number;
63
- stage: number;
64
- y: number;
65
- };
66
-
67
- export type TimelinePlacement = {
68
- axisX: number;
69
- axisHeight: number;
70
- width: number;
71
- stepsHeight: number;
72
- steps: TimelineStep[];
73
- };
74
-
75
- /** 見た目の段の差で、進行線・戻り線・分かれ道を分ける。 */
76
- export function classifyTimelineEdge(fromStage: number, toStage: number): TimelineEdgeKind {
77
- if (toStage === fromStage + 1) return "advance";
78
- if (toStage < fromStage) return "back";
79
- return "branch";
80
- }
81
-
82
- /**
83
- * 分かれ道だけから入る普通の段のうち、分かれ道の直後に書かれていない段を脇の札にする。
84
- * 省く印は呼び出し前に除かれるため、配列の直前が「書いた順で次」の判定になる。
85
- */
86
- function timelineSideCards(doc: Pick<DslDocument, "actors" | "flow">): Map<string, string> {
87
- const actorsByName = new Map(doc.actors.map((actor) => [actor.name, actor]));
88
- const sideCards = new Map<string, string>();
89
- doc.actors.forEach((actor, index) => {
90
- if (actor.kind === "decision" || actor.kind === "mark-end") return;
91
- const incoming = doc.flow.filter((edge) => edge.to === actor.name);
92
- if (incoming.length === 0) return;
93
- if (!incoming.every((edge) => actorsByName.get(edge.from)?.kind === "decision")) return;
94
- if (doc.actors[index - 1]?.kind === "decision") return;
95
- const firstIncoming = incoming[0];
96
- if (firstIncoming === undefined) return;
97
- sideCards.set(actor.name, firstIncoming.from);
98
- });
99
- return sideCards;
100
- }
101
-
102
- function gapBefore(kind: string | undefined): number {
103
- if (kind === "decision") return TIMELINE_DECISION_GAP;
104
- if (kind === "mark-end") return TIMELINE_END_GAP;
105
- return TIMELINE_STEP_GAP;
106
- }
107
-
108
- /** 時間軸の絶対座標と、札に重ならない番号 id を返す。 */
109
- export function placeTimeline(
110
- doc: Pick<DslDocument, "actors" | "flow">,
111
- 軸に置く段: ReadonlySet<string> = new Set(),
112
- ): TimelinePlacement {
113
- const sideCardSource = timelineSideCards(doc);
114
- const cardIds = doc.actors.map((actor, index) => slugify(actor.name) || `n${index}`);
115
- const usedIds = new Set(cardIds);
116
- const stageByName = new Map<string, number>();
117
- const yByName = new Map<string, number>();
118
- let stage = -1;
119
- let y = FIRST_STEP_Y;
120
- let previousKind: string | undefined;
121
-
122
- for (const actor of doc.actors) {
123
- const source = sideCardSource.get(actor.name);
124
- if (source !== undefined) {
125
- const sourceStage = stageByName.get(source);
126
- const sourceY = yByName.get(source);
127
- if (sourceStage === undefined || sourceY === undefined) {
128
- throw new Error(`時間軸の脇の札 "${actor.name}" の分かれ道 "${source}" がありません`);
129
- }
130
- stageByName.set(actor.name, sourceStage);
131
- yByName.set(actor.name, sourceY);
132
- continue;
133
- }
134
- stage += 1;
135
- if (stage > 0) {
136
- y += previousKind === "decision" ? TIMELINE_DECISION_GAP : gapBefore(actor.kind);
137
- }
138
- stageByName.set(actor.name, stage);
139
- yByName.set(actor.name, y);
140
- previousKind = actor.kind;
141
- }
142
-
143
- const cardSideByName = new Map<string, "left" | "right">();
144
- doc.actors
145
- .map((actor, index) => ({ actor, index, y: yByName.get(actor.name) ?? FIRST_STEP_Y }))
146
- .filter(({ actor }) => !軸に置く段.has(actor.name))
147
- .sort((a, b) => a.y - b.y || a.index - b.index)
148
- .forEach(({ actor }, index) => cardSideByName.set(actor.name, index % 2 === 0 ? "left" : "right"));
149
-
150
- const cardLayoutByName = new Map<string, { centerX: number; width: number }>();
151
- for (const actor of doc.actors) {
152
- const sideCard = sideCardSource.has(actor.name);
153
- const width = sideCard ? TIMELINE_SIDE_CARD_WIDTH : TIMELINE_CARD_WIDTH;
154
- const axisToCard = sideCard ? TIMELINE_AXIS_TO_SIDE_CARD : TIMELINE_AXIS_TO_CARD;
155
- const side = cardSideByName.get(actor.name) ?? "left";
156
- cardLayoutByName.set(actor.name, {
157
- centerX: side === "left"
158
- ? AXIS_X - axisToCard - width / 2
159
- : AXIS_X + axisToCard + width / 2,
160
- width,
161
- });
162
- }
163
-
164
- for (const actor of doc.actors) {
165
- if (!sideCardSource.has(actor.name)) continue;
166
- const source = cardLayoutByName.get(actor.name);
167
- const sourceStage = stageByName.get(actor.name);
168
- if (source === undefined || sourceStage === undefined) continue;
169
- for (const edge of doc.flow.filter((item) => item.from === actor.name)) {
170
- const target = cardLayoutByName.get(edge.to);
171
- const targetStage = stageByName.get(edge.to);
172
- if (target === undefined || targetStage === undefined || targetStage >= sourceStage) continue;
173
- const targetLeft = target.centerX - target.width / 2;
174
- const targetRight = target.centerX + target.width / 2;
175
- if (source.centerX < targetLeft || source.centerX > targetRight) continue;
176
- /*
177
- * cardene777/cdl#1031: `back-detour` は札の上辺の中点どうしを結び、
178
- * 両端の札を障害物に数えない。右側の脇札も線札の clearance を保つ位置へ置く。
179
- */
180
- source.centerX = AXIS_X + TIMELINE_AXIS_TO_SIDE_CARD + source.width / 2;
181
- }
182
- }
183
-
184
- let 次の番号 = 1;
185
- const steps = doc.actors.map((actor, index): TimelineStep => {
186
- const sideCard = sideCardSource.has(actor.name);
187
- const 番号 = 軸に置く段.has(actor.name) || sideCard ? undefined : 次の番号++;
188
- const base = 番号 === undefined ? undefined : `timeline-number-${番号}`;
189
- let numberId = base;
190
- let suffix = 2;
191
- while (numberId !== undefined && usedIds.has(numberId)) numberId = `${base}-${suffix++}`;
192
- if (numberId !== undefined) usedIds.add(numberId);
193
- const cardLayout = cardLayoutByName.get(actor.name);
194
- if (cardLayout === undefined) throw new Error(`時間軸の札 "${actor.name}" の配置がありません`);
195
- return {
196
- cardId: cardIds[index]!,
197
- numberId,
198
- cardX: cardLayout.centerX,
199
- cardWidth: cardLayout.width,
200
- stage: stageByName.get(actor.name) ?? index,
201
- y: yByName.get(actor.name) ?? FIRST_STEP_Y,
202
- };
203
- });
204
- const lastY = Math.max(FIRST_STEP_Y, ...steps.map((step) => step.y));
205
- const rightEdge = Math.max(...steps.map((step) => step.cardX + step.cardWidth / 2));
206
- return {
207
- axisX: AXIS_X,
208
- axisHeight: lastY + TIMELINE_END_HEIGHT / 2,
209
- width: Math.max(TIMELINE_WIDTH, rightEdge + TIMELINE_SIDE_MARGIN),
210
- stepsHeight: lastY + TIMELINE_CARD_HEIGHT / 2 + TIMELINE_SIDE_MARGIN,
211
- steps,
212
- };
213
- }
@@ -1,44 +0,0 @@
1
- import { diagram, topology } from "@cardenelabs/cdl";
2
- import { 箱の題 } from "./node-title";
3
- import type { CdlDiagram } from "@cardenelabs/cdl";
4
- import type { DslDocument } from "../types";
5
-
6
- import { compileGenericWithAnimate, 共通の組み立てへ回す } from "./generic";
7
- import { 描ける種別 } from "./kinds";
8
-
9
- import { slugify } from "./slug";
10
-
11
- export function compileTopology(doc: DslDocument): CdlDiagram {
12
- // 動きを書いた形と縦列を書いた形は共通の組み立てへ (#1263 / #2348 で 1 箇所にまとめた)
13
- if (共通の組み立てへ回す("topology", doc)) {
14
- return compileGenericWithAnimate(doc, { kind: "topology", laneWidth: 460 });
15
- }
16
- // 登場人物が 0 人なら枠も作らない。 描画側の `topology()` は枠を必ず 1 つ作るため、 そのまま
17
- // 通すと中身の無い枠が残る (#1096)
18
- if (doc.actors.length === 0) {
19
- return diagram(slugify(doc.title), { topic: doc.title, type: "topology" }).build();
20
- }
21
- // topology preset ... actors を 1 つの group 内 container として配置
22
- // v0.3 で「group」 ブロックを追加して複数 group 対応検討
23
- const topo = topology({
24
- id: slugify(doc.title),
25
- topic: doc.title,
26
- });
27
- const groupId = "main";
28
- const groupBuilder = topo.group(groupId, { label: doc.title });
29
- for (const a of doc.actors) {
30
- groupBuilder.add({
31
- id: slugify(a.name) || a.name,
32
- kind: 描ける種別(a.kind),
33
- title: 箱の題(a),
34
- });
35
- }
36
- for (const s of doc.flow) {
37
- topo.connect(slugify(s.from), slugify(s.to), {
38
- label: s.label,
39
- ...(s.sub ? { sub: s.sub } : {}),
40
- ...(s.side ? { side: s.side } : {}),
41
- });
42
- }
43
- return topo.build();
44
- }
@@ -1,69 +0,0 @@
1
- import { diagram, 木の札の幅 } from "@cardenelabs/cdl";
2
- import type { CdlDiagram } from "@cardenelabs/cdl";
3
- import type { DslDocument } from "../types";
4
- import { 図表の大きさ, 図表の大きさを読む } from "./chart-fields";
5
- import { 矢印から親を決める, 放射に出す文字 } from "./hierarchy";
6
- import type { CompileNotice } from "./notice";
7
- import { slugify } from "./slug";
8
- import { 図の小見出し } from "./subtitle";
9
- /**
10
- * 木 (`type: tree`) の組み立て (#1154)。 描画側に 1 つの箱で渡す。
11
- *
12
- * 親子を `flow` の矢印で読む (`親 -> 子`)。 他の図表と違って `flow` を読むのは、親子が
13
- * 2 つの名前の関係で、 1 行 1 値では書けないため。
14
- */
15
- export function compileTree(doc: DslDocument, onNotice?: (n: CompileNotice) => void): CdlDiagram {
16
- const b = diagram(slugify(doc.title), { topic: doc.title, type: "tree" });
17
- // **同じ slug になる名前を先に見る**。 違う名前が同じ id に潰れると、 自分を親にしたと
18
- // 誤判定したり、 同じ id の要素が 2 つできたりする (review 指摘)
19
- const slug別 = new Map<string, string[]>();
20
- for (const a of doc.actors) {
21
- const k = slugify(a.name);
22
- slug別.set(k, [...(slug別.get(k) ?? []), a.name]);
23
- }
24
- const 名前 = new Set(slug別.keys());
25
- // **行番号を渡す**。 `DslActor` / `DslStep` は `pos.line` を持つので遡れる。 前回「持てない」
26
- // と書いたのは誤り (review 指摘)。 0 にすると画面が問題の行を案内できない
27
- const 伝える = (名: string, message: string, line = 0) => {
28
- onNotice?.({ kind: "chart-value-unreadable", actor: 名, line, message });
29
- if (typeof console !== "undefined" && console.warn) console.warn(`[dragon] ${message}`);
30
- };
31
- for (const [k, 群] of slug別) {
32
- if (群.length > 1) {
33
- 伝える(
34
- 群[0]!,
35
- `type: tree で ${群.join(" / ")} が同じ id (${k}) になります。 名前を変えてください`,
36
- );
37
- }
38
- }
39
- const 親 = 矢印から親を決める(doc, "tree", 名前, 伝える);
40
- const data: NonNullable<CdlDiagram["nodes"][number]["treeData"]> = doc.actors.map((a) => {
41
- const id = slugify(a.name);
42
- const p3 = 親.get(id);
43
- // 木も放射と同じく名前と補足を分けて渡す (#1332)。 分けないと補足が捨てられ、
44
- // 書いた文字が図に出ない
45
- return { id, ...放射に出す文字(a), ...(p3 !== undefined ? { parent: p3 } : {}) };
46
- });
47
- // 札の幅は葉の数で変わる (cdl#970)。 **規則は描画側が持つ** ので、ここでは引くだけにする。
48
- // 写すと、描画側が割付を変えた時に記法の側だけが古い幅を渡す。
49
- // 高さは段の数で決まり、描画側が既定を返す形なので表から取る
50
- const 既定W = 木の札の幅(data);
51
- const { w: W, h: H } = 図表の大きさを読む(doc, { w: 既定W, h: 図表の大きさ.tree.h });
52
- b.lane("chart", { width: W + 64 });
53
- b.node(`${slugify(doc.title) || "tree"}-chart`, {
54
- lane: "chart",
55
- stack: 0,
56
- kind: "tree-hierarchy",
57
- title: doc.title,
58
- ...図の小見出し(doc),
59
- w: W,
60
- h: H,
61
- treeData: data,
62
- ...(doc.treeNodeForm !== undefined ? { treeNodeForm: doc.treeNodeForm } : {}),
63
- ...(doc.treeSize !== undefined ? { treeSize: doc.treeSize } : {}),
64
- ...(doc.treeEdgeTone !== undefined ? { treeEdgeTone: doc.treeEdgeTone } : {}),
65
- ...(doc.treeEdgeHead !== undefined ? { treeEdgeHead: doc.treeEdgeHead } : {}),
66
- ...(doc.figureKindLabel !== undefined ? { figureKindLabel: doc.figureKindLabel } : {}),
67
- });
68
- return b.build();
69
- }