@cardenelabs/dragon 0.34.0 → 0.35.1
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 +39 -720
- package/dist/cli.cjs +4529 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.js +4523 -0
- package/dist/cli.js.map +1 -0
- package/dist/export.cjs +3912 -0
- package/dist/export.cjs.map +1 -0
- package/dist/export.d.cts +36 -0
- package/dist/export.d.ts +36 -0
- package/dist/export.js +3907 -0
- package/dist/export.js.map +1 -0
- package/dist/fonts.cjs +7 -0
- package/dist/fonts.cjs.map +1 -0
- package/dist/fonts.js +4 -0
- package/dist/fonts.js.map +1 -0
- package/dist/index.cjs +4105 -20356
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +227 -5522
- package/dist/index.d.ts +227 -5522
- package/dist/index.js +4091 -20283
- package/dist/index.js.map +1 -1
- package/dist/player.global.js +2 -0
- package/dist/schema-BBWfniwH.d.cts +112 -0
- package/dist/schema-BBWfniwH.d.ts +112 -0
- package/package.json +53 -27
- package/src/cli.ts +237 -0
- package/src/export/capture.ts +277 -0
- package/src/export/fonts.ts +68 -0
- package/src/export/html.ts +32 -0
- package/src/export/index.ts +146 -0
- package/src/field-messages.ts +104 -0
- package/src/figure-text.ts +42 -0
- package/src/index.ts +30 -283
- package/src/layout/architecture.ts +381 -0
- package/src/layout/measure.ts +21 -0
- package/src/layout/scene.ts +353 -0
- package/src/layout/sequence.ts +189 -0
- package/src/load-fonts.ts +8 -0
- package/src/look/fonts.ts +33 -0
- package/src/look/palettes.json +209 -0
- package/src/look/values.ts +155 -0
- package/src/markdown.ts +35 -0
- package/src/messages.ts +122 -0
- package/src/parser.ts +342 -310
- package/src/player-global.ts +4 -0
- package/src/player.ts +271 -0
- package/src/printer.ts +76 -0
- package/src/render/icons.ts +41 -0
- package/src/render/motion.ts +106 -0
- package/src/render/parts.ts +279 -0
- package/src/render/svg.ts +341 -0
- package/src/schema.ts +161 -16
- package/src/schemas/diagram.schema.json +150 -0
- package/src/schemas/validate-diagram.d.ts +12 -0
- package/src/schemas/validate-diagram.js +8 -0
- package/src/timeline.ts +166 -0
- package/src/tokenize.ts +20 -281
- package/src/version.ts +55 -0
- package/src/view.ts +16 -0
- package/src/words.ts +79 -0
- package/examples/quick-start.md +0 -142
- package/src/canvas-bounds.ts +0 -52
- package/src/color.ts +0 -197
- package/src/compile/actor-ids.ts +0 -297
- package/src/compile/actor-option-notice.ts +0 -379
- package/src/compile/actors.ts +0 -103
- package/src/compile/c4.ts +0 -74
- package/src/compile/chain.ts +0 -93
- package/src/compile/chart-fields.ts +0 -193
- package/src/compile/deep-rewrite.ts +0 -30
- package/src/compile/derived-source.ts +0 -18
- package/src/compile/direction.ts +0 -102
- package/src/compile/edge-option-notice.ts +0 -112
- package/src/compile/er-relation.ts +0 -200
- package/src/compile/flow.ts +0 -54
- package/src/compile/flowchart.ts +0 -344
- package/src/compile/funnel.ts +0 -87
- package/src/compile/gantt.ts +0 -337
- package/src/compile/generic.ts +0 -696
- package/src/compile/hierarchy.ts +0 -92
- package/src/compile/journey.ts +0 -93
- package/src/compile/kinds.ts +0 -139
- package/src/compile/lanes.ts +0 -138
- package/src/compile/metro.ts +0 -271
- package/src/compile/mind.ts +0 -393
- package/src/compile/node-title.ts +0 -24
- package/src/compile/notice.ts +0 -141
- package/src/compile/order.ts +0 -57
- package/src/compile/parts-lookup.ts +0 -17
- package/src/compile/parts.ts +0 -2709
- package/src/compile/placement-apply.ts +0 -689
- package/src/compile/placement.ts +0 -15
- package/src/compile/quadrant.ts +0 -265
- package/src/compile/record.ts +0 -75
- package/src/compile/row-marks.ts +0 -128
- package/src/compile/rows.ts +0 -40
- package/src/compile/sequence.ts +0 -305
- package/src/compile/slug.ts +0 -37
- package/src/compile/stages.ts +0 -247
- package/src/compile/subtitle.ts +0 -35
- package/src/compile/swimlane-marks.ts +0 -87
- package/src/compile/swimlane.ts +0 -82
- package/src/compile/timeline.ts +0 -213
- package/src/compile/topology.ts +0 -44
- package/src/compile/tree.ts +0 -69
- package/src/compile/value-chart.ts +0 -337
- package/src/compile/values.ts +0 -432
- package/src/compile/word-state.ts +0 -82
- package/src/compile.ts +0 -3168
- package/src/focus.ts +0 -46
- package/src/input-size.ts +0 -181
- package/src/json-line-map.ts +0 -30
- package/src/json-parser.ts +0 -4306
- package/src/keywords.ts +0 -417
- package/src/near-name.ts +0 -42
- package/src/notation-lint.ts +0 -342
- package/src/relative-pos.ts +0 -251
- package/src/schemas/diagram.json +0 -3088
- package/src/types.ts +0 -1009
- package/src/v05/index.ts +0 -9
- package/src/v05/input-table.generated.ts +0 -138
- package/src/v05/parser-types.ts +0 -32
- package/src/v05/parser.ts +0 -6668
- package/src/v05/readout-table.generated.ts +0 -1088
- package/src/v05/removed-syntax.ts +0 -115
- package/src/value-syntax.ts +0 -313
- package/src/write-position.ts +0 -270
package/src/compile/flowchart.ts
DELETED
|
@@ -1,344 +0,0 @@
|
|
|
1
|
-
import { flowchart } from "@cardenelabs/cdl";
|
|
2
|
-
import type { CdlDiagram } from "@cardenelabs/cdl";
|
|
3
|
-
import type { DslActor, DslDocument } from "../types";
|
|
4
|
-
import { 箱の題 } from "./node-title";
|
|
5
|
-
import { 縦列ごとの段を決める, 書いた縦列に置く } from "./lanes";
|
|
6
|
-
import { 並べる向き } from "./direction";
|
|
7
|
-
import { 測るために配置する } from "./parts";
|
|
8
|
-
import { slugify } from "./slug";
|
|
9
|
-
/**
|
|
10
|
-
* 記法の `type: flowchart` を分かれ道の図に直す (#2513)。
|
|
11
|
-
*
|
|
12
|
-
* 一覧には「フローチャート」 の見本が並び、描画の library にも `flowchart()` が在り、
|
|
13
|
-
* dragon の案内表にも「フローチャート」 が載っていた。 **記法だけが受理していなかった**ので、
|
|
14
|
-
* 一覧で見た図を同じ名前で書けなかった。
|
|
15
|
-
*
|
|
16
|
-
* 縦列は役割を分ける入れ物で、箱はその中に置く。 `swimlane` は登場人物 1 人が縦列 1 本に
|
|
17
|
-
* なるが、こちらは **登場人物が箱で、その `lane:` が役割の名前になる**。 分かれ道の図は
|
|
18
|
-
* 1 人の役割の中に複数の箱 (申請を出す / 直して出し直す) が並ぶため。
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* 記法の箱の種類を、描画側の分かれ道の箱の形へ読み替える。
|
|
23
|
-
*
|
|
24
|
-
* 描画側が受ける形は 5 つ (`process` / `decision` / `start` / `end` / `loop`)。
|
|
25
|
-
* 記法の側に 4 つ分の種類が在り、残る 1 つは書かない時の既定になる。
|
|
26
|
-
*
|
|
27
|
-
* | 記法に書く種類 | 描く形 | なぜ |
|
|
28
|
-
* |---|---|---|
|
|
29
|
-
* | `decision` | `decision` | 同じ名前がそのまま描画側にもある |
|
|
30
|
-
* | `mark-start` | `start` | 始まりの印 |
|
|
31
|
-
* | `mark-end` | `end` | 終わりの印 |
|
|
32
|
-
* | `loop` | `loop` | 終わりまで繰り返す箱 (#2523) |
|
|
33
|
-
* | それ以外 / 書かない | `process` | 普通の手順の箱 |
|
|
34
|
-
*
|
|
35
|
-
* **始まりと終わりの印は題を持たない**。 この決まりは `箱の題` が 15 図種と共有しており
|
|
36
|
-
* (#1466)、 塗った丸に字を載せる場所が無いため。 題を出したい時は `title:` を書けば使われる
|
|
37
|
-
* ので、黙って消える形ではない = ここで別の知らせを足さない。
|
|
38
|
-
*
|
|
39
|
-
* **`loop` は記法の種類として足した** (#2523)。 描画側は繰り返しを **形** としてだけ持ち、
|
|
40
|
-
* 箱の種類 (`NODE_KINDS` の 98 件) には持たない。 そのまま書くと部品の名前として扱われ、
|
|
41
|
-
* 「そんな部品は無い」 と言われるだけだった (実測)。
|
|
42
|
-
* 記法だけが持つ種類 (`DSL_ONLY_KINDS`) に置き、ここで形へ読み替える。
|
|
43
|
-
* 分かれ道の図以外で書いた時は `記法だけの種類の読み替え` が札に落とす。
|
|
44
|
-
*/
|
|
45
|
-
const 分かれ道の箱の形 = {
|
|
46
|
-
decision: "decision",
|
|
47
|
-
"mark-start": "start",
|
|
48
|
-
"mark-end": "end",
|
|
49
|
-
loop: "loop",
|
|
50
|
-
} as const;
|
|
51
|
-
|
|
52
|
-
type 分かれ道の形 = "process" | "decision" | "start" | "end" | "loop";
|
|
53
|
-
|
|
54
|
-
/*
|
|
55
|
-
* 横向きの見本で使う印の大きさ。
|
|
56
|
-
*
|
|
57
|
-
* 正の見本 (`docs/design/proposal/static/流れ-*.html`) は札幅 300 に対して、菱形が
|
|
58
|
-
* 248 × 148 (0.8267 × 0.4933)、始まりの丸が直径 34 (0.1133)、終わりの丸が直径 38
|
|
59
|
-
* (0.1267)。 dragon の普通の札幅 380 に掛け、1 px 単位へ丸めた。
|
|
60
|
-
*/
|
|
61
|
-
const 横向きの印の大きさ = {
|
|
62
|
-
decision: { w: 314, h: 187 },
|
|
63
|
-
"mark-start": { w: 43, h: 43 },
|
|
64
|
-
"mark-end": { w: 48, h: 48 },
|
|
65
|
-
} as const;
|
|
66
|
-
|
|
67
|
-
function 箱の形(actor: DslActor): 分かれ道の形 {
|
|
68
|
-
const kind = actor.kind;
|
|
69
|
-
if (kind !== undefined && kind in 分かれ道の箱の形) {
|
|
70
|
-
return 分かれ道の箱の形[kind as keyof typeof 分かれ道の箱の形];
|
|
71
|
-
}
|
|
72
|
-
return "process";
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* 縦列の名前を書いた順に並べる。
|
|
77
|
-
*
|
|
78
|
-
* **`lane:` を 1 つも書かない図でも描けるようにする**。 その時は縦列 1 本に全部入れる =
|
|
79
|
-
* 分かれ道そのもの (判断と枝) は縦列が無くても成立するため、役割を分けたくない人に
|
|
80
|
-
* `lane:` を強制しない。
|
|
81
|
-
*
|
|
82
|
-
* 書いた人と書かない人が混ざった図は、書かない箱を最初の縦列へ入れる。 行き先の規則が
|
|
83
|
-
* 要る形だが、`swimlane` の混在と違ってこちらは **箱が縦列そのものではない** ので、
|
|
84
|
-
* 入れ先が無いと箱を 1 つも置けない。
|
|
85
|
-
*
|
|
86
|
-
* **箱が 1 つも無い図では縦列も作らない**。 受け皿の縦列だけを置くと、中身の無い枠が
|
|
87
|
-
* 図に残る (実測 = 登場人物 0 人の図で枠が 1 本だけ描かれた)。
|
|
88
|
-
*/
|
|
89
|
-
function 縦列の並び(doc: DslDocument): string[] {
|
|
90
|
-
const 並び: string[] = [];
|
|
91
|
-
for (const a of doc.actors) {
|
|
92
|
-
const name = a.lane;
|
|
93
|
-
if (name === undefined || name === "") continue;
|
|
94
|
-
if (!並び.includes(name)) 並び.push(name);
|
|
95
|
-
}
|
|
96
|
-
if (並び.length > 0) return 並び;
|
|
97
|
-
return doc.actors.length > 0 ? ["本流"] : [];
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function compileFlowchart(doc: DslDocument): CdlDiagram {
|
|
101
|
-
const lanes = 縦列の並び(doc);
|
|
102
|
-
const 既定の縦列 = lanes[0];
|
|
103
|
-
/*
|
|
104
|
-
* 補足を書いた縦列だけ、0.127.0 の見出しの object 形へ広げる。
|
|
105
|
-
*
|
|
106
|
-
* 全縦列を `{ label }` にすると、subtitle を書いていない従来の flowchart まで見出しの
|
|
107
|
-
* 配置へ切り替わる。実測では経費申請の図が幅 1743 から 1986 へ広がり、線の札と箱の
|
|
108
|
-
* clearance も変わった。欄を書かない図を変えないため、従来どおり id の文字列を渡す。
|
|
109
|
-
*/
|
|
110
|
-
const 描く側の縦列 = (id: string): string | { label: string; subtitle: string } => {
|
|
111
|
-
const subtitle = doc.lanes?.[id]?.subtitle;
|
|
112
|
-
return subtitle === undefined ? id : { label: doc.lanes?.[id]?.label ?? id, subtitle };
|
|
113
|
-
};
|
|
114
|
-
const 描く側の縦列名 = (id: string): string => {
|
|
115
|
-
const lane = 描く側の縦列(id);
|
|
116
|
-
return typeof lane === "string" ? lane : lane.label;
|
|
117
|
-
};
|
|
118
|
-
/*
|
|
119
|
-
* 並べる向きを描く側へ渡す (#2524)。
|
|
120
|
-
*
|
|
121
|
-
* 記法の 縦 / 横 と描く側の綴りは 1 対 1 で対応する。 既定は 横 で、書かない図は
|
|
122
|
-
* 1 枚も並びが動かない (`既定の向き` が `topology` 以外に 横 を返す)。
|
|
123
|
-
*
|
|
124
|
-
* 縦 は縦列 1 本に全部の箱を積む形で、役割の名前は箱の上の小さな字へ移る
|
|
125
|
-
* (描く側が `承認者 · 判断` の形にする)。
|
|
126
|
-
*/
|
|
127
|
-
const 縦に積む = 並べる向き("flowchart", doc) === "縦";
|
|
128
|
-
|
|
129
|
-
const fc = flowchart({
|
|
130
|
-
id: slugify(doc.title),
|
|
131
|
-
topic: doc.title,
|
|
132
|
-
lanes: lanes.map(描く側の縦列),
|
|
133
|
-
direction: 縦に積む ? "vertical" : "horizontal",
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
/*
|
|
137
|
-
* 箱の id は名前から作る。 **重なったら並び順を足して分ける**。
|
|
138
|
-
*
|
|
139
|
-
* `slugify` は残せる字が 1 つも無い名前に `n` を返すため、記号だけの名前 (`***` / `---`)
|
|
140
|
-
* が 2 つあると同じ id になる。 記号の位置だけが違う名前 (`A-B` と `A/B`) も同じになる。
|
|
141
|
-
* 重なると後から置いた箱が前の箱を上書きし、矢印が別の箱へ向かう。
|
|
142
|
-
*/
|
|
143
|
-
const 使ったid = new Set<string>();
|
|
144
|
-
const idOf = (a: DslActor, i: number): string => {
|
|
145
|
-
const 元 = slugify(a.name);
|
|
146
|
-
if (!使ったid.has(元)) return 元;
|
|
147
|
-
let 候補 = `${元}-${i}`;
|
|
148
|
-
for (let k = i; 使ったid.has(候補); k++) 候補 = `${元}-${k + 1}`;
|
|
149
|
-
return 候補;
|
|
150
|
-
};
|
|
151
|
-
const id一覧 = new Map<string, string>();
|
|
152
|
-
/** 箱ごとに決まった id を書いた順で持つ。 決め直すと重なりの回避が二度効いて別の id になる */
|
|
153
|
-
const 決めたid: string[] = [];
|
|
154
|
-
|
|
155
|
-
doc.actors.forEach((a, i) => {
|
|
156
|
-
const id = idOf(a, i);
|
|
157
|
-
使ったid.add(id);
|
|
158
|
-
決めたid.push(id);
|
|
159
|
-
id一覧.set(a.name, id);
|
|
160
|
-
fc.node({
|
|
161
|
-
id,
|
|
162
|
-
title: 箱の題(a),
|
|
163
|
-
shape: 箱の形(a),
|
|
164
|
-
lane:
|
|
165
|
-
a.lane !== undefined && a.lane !== ""
|
|
166
|
-
? 描く側の縦列名(a.lane)
|
|
167
|
-
: (既定の縦列 === undefined
|
|
168
|
-
? ""
|
|
169
|
-
: 描く側の縦列名(既定の縦列)),
|
|
170
|
-
...(a.titleFontSize !== undefined ? { titleFontSize: a.titleFontSize } : {}),
|
|
171
|
-
...(a.markGap !== undefined ? { markGap: a.markGap } : {}),
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
const 描いた線: Array<{ step: (typeof doc.flow)[number]; from: string; to: string }> = [];
|
|
176
|
-
for (const s of doc.flow) {
|
|
177
|
-
const from = id一覧.get(s.from);
|
|
178
|
-
const to = id一覧.get(s.to);
|
|
179
|
-
// 箱に無い名前を指した矢印は引かない。 描画側は知らない id の位置を引けずに落ちる
|
|
180
|
-
if (from === undefined || to === undefined) continue;
|
|
181
|
-
fc.edge({
|
|
182
|
-
from,
|
|
183
|
-
to,
|
|
184
|
-
...(s.label !== undefined && s.label !== "" ? { label: s.label } : {}),
|
|
185
|
-
});
|
|
186
|
-
描いた線.push({ step: s, from, to });
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
const diagram = fc.build();
|
|
190
|
-
const 箱の一覧 = new Map(diagram.nodes.map((n) => [n.id, n]));
|
|
191
|
-
|
|
192
|
-
// cdl の flowchart builder は札固有の文字サイズと印の間隔を入力から写さないため、
|
|
193
|
-
// 記法の箱と確定した node id を対応させて build 後の payload へ補う。
|
|
194
|
-
doc.actors.forEach((actor, i) => {
|
|
195
|
-
const node = 箱の一覧.get(決めたid[i] ?? "");
|
|
196
|
-
if (node === undefined) return;
|
|
197
|
-
if (actor.titleFontSize !== undefined) node.titleFontSize = actor.titleFontSize;
|
|
198
|
-
if (actor.markGap !== undefined) node.markGap = actor.markGap;
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
/*
|
|
202
|
-
* 横向きだけを宅配の見本と同じ形へ直す。縦向きは役割と形の小見出しを箱の上へ移すことが
|
|
203
|
-
* 向きの読み分けになっているため、描画側が組み立てた従来の形を保つ。
|
|
204
|
-
*/
|
|
205
|
-
if (!縦に積む) {
|
|
206
|
-
doc.actors.forEach((actor, i) => {
|
|
207
|
-
const node = 箱の一覧.get(決めたid[i] ?? "");
|
|
208
|
-
if (node === undefined) return;
|
|
209
|
-
|
|
210
|
-
if (actor.kind === "decision") {
|
|
211
|
-
node.kind = "decision";
|
|
212
|
-
delete node.eyebrow;
|
|
213
|
-
Object.assign(node, 横向きの印の大きさ.decision);
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
if ((actor.kind === "mark-start" || actor.kind === "mark-end") && node.title === "") {
|
|
217
|
-
node.kind = actor.kind;
|
|
218
|
-
delete node.eyebrow;
|
|
219
|
-
Object.assign(node, 横向きの印の大きさ[actor.kind]);
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
if (actor.kind !== "loop" && actor.kind !== "mark-start" && actor.kind !== "mark-end") {
|
|
223
|
-
delete node.eyebrow;
|
|
224
|
-
}
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/*
|
|
229
|
-
* 形に読み替えなかった種類は、箱の見た目としてそのまま渡す。
|
|
230
|
-
*
|
|
231
|
-
* 描画側は形を箱の種類で表す (判断 = `card`、 印 = `event`、 手順 = `function`)。 その 3 つに
|
|
232
|
-
* 当たらない種類 (`database` / `service` 等) を捨てると、書いた人には手順の箱しか出ない。
|
|
233
|
-
* 残る図種では同じ書き方が箱の見た目になるので、ここだけ黙って消える形になっていた。
|
|
234
|
-
*
|
|
235
|
-
* **書いた箱だけを渡す** (`kindWritten`)。 記法は種類を書かない箱にも既定の `actor` を
|
|
236
|
-
* 入れるため、見ずに渡すと手順の箱が 1 つ残らず既定で塗り潰される (実測 = 7 箱の図で
|
|
237
|
-
* 手順の箱 4 つが描画側の `function` から `actor` へ変わった)。
|
|
238
|
-
*/
|
|
239
|
-
doc.actors.forEach((a, i) => {
|
|
240
|
-
if (a.kindWritten !== true) return;
|
|
241
|
-
if (a.kind === undefined || a.kind in 分かれ道の箱の形) return;
|
|
242
|
-
const node = 箱の一覧.get(決めたid[i] ?? "");
|
|
243
|
-
if (node !== undefined) node.kind = a.kind as typeof node.kind;
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
/*
|
|
247
|
-
* 横向きでは、同じ段にある菱形の高さを普通の札へ写さない。
|
|
248
|
-
*
|
|
249
|
-
* 描く側は `h` を書いた箱だけを段の最大高へ伸ばさない。種類ごとの高さをここへ写す時は、
|
|
250
|
-
* 箱を一時的に別々の段へ置いて描く側自身に中身から高さを出させる。固定値を写すと、
|
|
251
|
-
* `database` など書いた種類や長い題の高さが描く側の変更から外れてしまうため。
|
|
252
|
-
*/
|
|
253
|
-
if (!縦に積む && diagram.nodes.length > 0) {
|
|
254
|
-
const 自分の高さ = new Map(
|
|
255
|
-
測るために配置する({
|
|
256
|
-
...diagram,
|
|
257
|
-
nodes: diagram.nodes.map((node, index) => ({ ...node, stack: index })),
|
|
258
|
-
edges: [],
|
|
259
|
-
phases: [],
|
|
260
|
-
}).nodes.map((node) => [node.id, node.h]),
|
|
261
|
-
);
|
|
262
|
-
for (const node of diagram.nodes) {
|
|
263
|
-
if (node.kind === "decision" || node.kind === "mark-start" || node.kind === "mark-end") continue;
|
|
264
|
-
const h = 自分の高さ.get(node.id);
|
|
265
|
-
if (h !== undefined) node.h = h;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
/*
|
|
270
|
-
* 段は **箱を並べる図種すべてと同じ決め方** に従う (`縦列ごとの段を決める`)。
|
|
271
|
-
*
|
|
272
|
-
* 描画側は書いた順に 0 から詰めるため、書いた番号がそのまま消える。 全ての箱に縦列を
|
|
273
|
-
* 書いた図でだけ効かせるのは、縦列を書かない箱の段は残る図種でも効かないため = ここだけ
|
|
274
|
-
* 効かせると、効かないと伝える知らせのほうが誤りになる。
|
|
275
|
-
*
|
|
276
|
-
* **縦に積む図では触らない** (#2524)。 描く側が縦列 1 本に 0 から順に積んだ後で段を
|
|
277
|
-
* 書き直すと、同じ縦列に同じ段の箱が 2 つ並んで描く側が落ちる
|
|
278
|
-
* (`lane "flowchart-main" の stack=0 に node が重複`)。
|
|
279
|
-
*/
|
|
280
|
-
if (!縦に積む && 書いた縦列に置く("flowchart", doc)) {
|
|
281
|
-
const 段 = 縦列ごとの段を決める(doc.actors);
|
|
282
|
-
doc.actors.forEach((a, i) => {
|
|
283
|
-
const v = 段.get(a);
|
|
284
|
-
if (v === undefined) return;
|
|
285
|
-
const node = 箱の一覧.get(決めたid[i] ?? "");
|
|
286
|
-
if (node !== undefined) node.stack = v;
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/*
|
|
291
|
-
* 同じ縦列で間に箱を挟んで上へ戻る線だけ、箱の右外を回す。
|
|
292
|
-
*
|
|
293
|
-
* 隣の段への戻りは描く側の直線が最短で、下へ進む線も従来の通り道を保つ。 `side` を書いた
|
|
294
|
-
* 線は書き手が辺を選んでいるため、自動の経路と辺を一つも足さない。線の色・点線・札などは
|
|
295
|
-
* この後の共通処理 (`applyEdgeInlineOptions`) が従来どおり書き写す。
|
|
296
|
-
*/
|
|
297
|
-
const 対応済みの線 = new Set<string>();
|
|
298
|
-
描いた線.forEach(({ step, from: fromId, to: toId }) => {
|
|
299
|
-
const edge = diagram.edges.find(
|
|
300
|
-
(candidate) =>
|
|
301
|
-
!対応済みの線.has(candidate.id) && candidate.from === fromId && candidate.to === toId,
|
|
302
|
-
);
|
|
303
|
-
if (edge === undefined) return;
|
|
304
|
-
対応済みの線.add(edge.id);
|
|
305
|
-
if (step.side !== undefined) return;
|
|
306
|
-
const from = 箱の一覧.get(edge.from);
|
|
307
|
-
const to = 箱の一覧.get(edge.to);
|
|
308
|
-
if (
|
|
309
|
-
from === undefined ||
|
|
310
|
-
to === undefined ||
|
|
311
|
-
from.lane !== to.lane ||
|
|
312
|
-
from.stack === undefined ||
|
|
313
|
-
to.stack === undefined ||
|
|
314
|
-
to.stack >= from.stack
|
|
315
|
-
) return;
|
|
316
|
-
const fromStack = from.stack;
|
|
317
|
-
const toStack = to.stack;
|
|
318
|
-
const 間に箱がある = diagram.nodes.some(
|
|
319
|
-
(node) =>
|
|
320
|
-
node.lane === from.lane &&
|
|
321
|
-
node.stack !== undefined &&
|
|
322
|
-
node.stack > toStack &&
|
|
323
|
-
node.stack < fromStack,
|
|
324
|
-
);
|
|
325
|
-
if (!間に箱がある) return;
|
|
326
|
-
edge.routing = "back-detour";
|
|
327
|
-
edge.fromSide = "right";
|
|
328
|
-
edge.toSide = "right";
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
/*
|
|
332
|
-
* 段を書いた図では、描画側が自分で作った段を捨てる。
|
|
333
|
-
*
|
|
334
|
-
* 描画側の `flowchart()` は「全部を一度に光らせる」 段を 1 つ必ず作る。 それが残っていると
|
|
335
|
-
* 組み立ての後段 (`injectPhasesFallback`) が「段は既に在る」 と見て、書いた `animation:` を
|
|
336
|
-
* 1 段も入れない = 書いた `focus:` が黙って消える (実測 = 3 箱の図で `focus: [あ]` を書いても
|
|
337
|
-
* 3 箱とも光った)。
|
|
338
|
-
*
|
|
339
|
-
* 捨てるのは書いた時だけ。 書いていない図では描画側の段がそのまま既定の見せ方になる。
|
|
340
|
-
*/
|
|
341
|
-
if ((doc.animate?.phases.length ?? 0) > 0) diagram.phases = [];
|
|
342
|
-
|
|
343
|
-
return diagram;
|
|
344
|
-
}
|
package/src/compile/funnel.ts
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { diagram } from "@cardenelabs/cdl";
|
|
2
|
-
import type { CdlDiagram } from "@cardenelabs/cdl";
|
|
3
|
-
import type { DslDocument } from "../types";
|
|
4
|
-
import {
|
|
5
|
-
parseChartValue,
|
|
6
|
-
数の欄から参照できる名前,
|
|
7
|
-
参照する名前,
|
|
8
|
-
図表の大きさ,
|
|
9
|
-
図表の大きさを読む,
|
|
10
|
-
} from "./chart-fields";
|
|
11
|
-
|
|
12
|
-
import { 箱の題 } from "./node-title";
|
|
13
|
-
import type { CompileNotice } from "./notice";
|
|
14
|
-
import { slugify } from "./slug";
|
|
15
|
-
import { 図の小見出し } from "./subtitle";
|
|
16
|
-
/**
|
|
17
|
-
* 漏斗 (`type: funnel`) の組み立て (#1154)。 描画側に 1 つの箱で渡す。
|
|
18
|
-
*
|
|
19
|
-
* 登場人物ごとに **数** を読む (`- 訪問: "12000"`)。 段の人数なので負の数は読めない値として扱う。
|
|
20
|
-
*/
|
|
21
|
-
export function compileFunnel(doc: DslDocument, onNotice?: (n: CompileNotice) => void): CdlDiagram {
|
|
22
|
-
const b = diagram(slugify(doc.title), { topic: doc.title, type: "funnel" });
|
|
23
|
-
const { w: W, h: H } = 図表の大きさを読む(doc, 図表の大きさ.funnel);
|
|
24
|
-
b.lane("chart", { width: W + 64 });
|
|
25
|
-
const data: NonNullable<CdlDiagram["nodes"][number]["funnelData"]> = [];
|
|
26
|
-
const 読めない: string[] = [];
|
|
27
|
-
const 未宣言: string[] = [];
|
|
28
|
-
const 参照できる = 数の欄から参照できる名前(doc);
|
|
29
|
-
for (const a of doc.actors) {
|
|
30
|
-
const v = parseChartValue(a.value ?? a.subtitle);
|
|
31
|
-
// 段の数なので負に意味が無い (状態を読む欄は符号が決まらないので通す)
|
|
32
|
-
if (v === null || (typeof v === "number" && v < 0)) {
|
|
33
|
-
読めない.push(a.name);
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
// 数にならない参照は落とす (棒 / 折れ線 / 円と同じ扱い)
|
|
37
|
-
const 名前 = 参照する名前(v);
|
|
38
|
-
if (名前 !== null && !参照できる.has(名前)) {
|
|
39
|
-
未宣言.push(a.name);
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
data.push({
|
|
43
|
-
id: slugify(a.name),
|
|
44
|
-
title: 箱の題(a),
|
|
45
|
-
count: v,
|
|
46
|
-
...(a.tone !== undefined ? { tone: a.tone } : {}),
|
|
47
|
-
...(a.emphasis !== undefined ? { emphasis: a.emphasis } : {}),
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
if (未宣言.length > 0) {
|
|
51
|
-
const m3 = `type: funnel で数にならない値を参照した項目があります (段に載せません): ${未宣言.join(", ")}。 \`states:\` にその名前を数で書いてください`;
|
|
52
|
-
onNotice?.({ kind: "chart-value-unreadable", actor: 未宣言[0]!, line: 0, message: m3 });
|
|
53
|
-
if (typeof console !== "undefined" && console.warn) console.warn(`[dragon] ${m3}`);
|
|
54
|
-
}
|
|
55
|
-
if (読めない.length > 0) {
|
|
56
|
-
const m = `type: funnel で数を読めない項目があります (段に載せません): ${読めない.join(", ")}。 \`- 訪問: "12000"\` の形で書いてください`;
|
|
57
|
-
onNotice?.({ kind: "chart-value-unreadable", actor: 読めない[0]!, line: 0, message: m });
|
|
58
|
-
if (typeof console !== "undefined" && console.warn) console.warn(`[dragon] ${m}`);
|
|
59
|
-
}
|
|
60
|
-
// 矢印は描けない。 書かれていたら伝える (黙って捨てると「書いたのに効かない」 が残る)
|
|
61
|
-
if (doc.flow.length > 0) {
|
|
62
|
-
const m2 = `type: funnel では矢印を描けません (${doc.flow.length} 本を無視しました)。 関係を描くなら type: flow を使ってください`;
|
|
63
|
-
onNotice?.({
|
|
64
|
-
kind: "chart-edge-dropped",
|
|
65
|
-
actor: doc.flow[0]?.from ?? "",
|
|
66
|
-
line: doc.flow[0]?.pos?.line ?? 0,
|
|
67
|
-
message: m2,
|
|
68
|
-
});
|
|
69
|
-
if (typeof console !== "undefined" && console.warn) console.warn(`[dragon] ${m2}`);
|
|
70
|
-
}
|
|
71
|
-
b.node(`${slugify(doc.title) || "funnel"}-chart`, {
|
|
72
|
-
lane: "chart",
|
|
73
|
-
stack: 0,
|
|
74
|
-
kind: "funnel-stages",
|
|
75
|
-
title: doc.title,
|
|
76
|
-
...図の小見出し(doc),
|
|
77
|
-
w: W,
|
|
78
|
-
h: H,
|
|
79
|
-
funnelData: data,
|
|
80
|
-
...(doc.funnelForm !== undefined ? { funnelForm: doc.funnelForm } : {}),
|
|
81
|
-
...(doc.funnelRate !== undefined ? { funnelRate: doc.funnelRate } : {}),
|
|
82
|
-
...(doc.chartSeriesSkipMuted !== undefined
|
|
83
|
-
? { chartSeriesSkipMuted: doc.chartSeriesSkipMuted }
|
|
84
|
-
: {}),
|
|
85
|
-
});
|
|
86
|
-
return b.build();
|
|
87
|
-
}
|