@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
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 矢印に書いた飾りが効かない時の、伝える欄の割り出しと呼び名 (#2366 で 1 箇所にまとめた)。
|
|
3
|
-
*
|
|
4
|
-
* 同じ判定を 3 経路が使う。
|
|
5
|
-
*
|
|
6
|
-
* | 経路 | 図種 | 起点 |
|
|
7
|
-
* |---|---|---|
|
|
8
|
-
* | 板の言づて | `sequence` | #2356 |
|
|
9
|
-
* | 骨格の図 | `tree` / `mind` | #2364 |
|
|
10
|
-
* | ガントチャート | `gantt` | #2366 |
|
|
11
|
-
*
|
|
12
|
-
* **葉に置く**。 板と骨格の判定は `compile.ts` に、ガントチャートの知らせは `compile/gantt.ts` にあり、
|
|
13
|
-
* 取り込む向きが逆なので、共通部分をどちらからも取り込める場所へ置く。
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* 効かない矢印の欄の呼び名 (#2356)。 **並べた順に知らせへ出す**。
|
|
18
|
-
*
|
|
19
|
-
* 呼び名を持たない欄は名前をそのまま出すので、ここに足し忘れても知らせは消えない。
|
|
20
|
-
* 複数の欄が 1 つの呼び名を持つ形 (名前のずらしが 3 欄) は、1 度だけ出す。
|
|
21
|
-
*
|
|
22
|
-
* **図種をまたいで 1 つの表にする** (#2364)。 同じ欄を図種ごとに別の文言で呼ぶと、
|
|
23
|
-
* 図種を変えた読み手が同じ飾りだと気付けない。 どの欄を伝えるかは図種ごとの除外が決める。
|
|
24
|
-
*/
|
|
25
|
-
export const 効かない矢印の欄の呼び名: readonly (readonly [string, string])[] = [
|
|
26
|
-
["label", "文字"],
|
|
27
|
-
["tone", "色味"],
|
|
28
|
-
["style", "線の種類"],
|
|
29
|
-
["sub", "添え字"],
|
|
30
|
-
["tailSub", "出どころ側の添え字"],
|
|
31
|
-
["side", "寄せ"],
|
|
32
|
-
// 名前のずらしも板には載せる先が無い (#1971)。 位置のずらし (`pos`) は名前のずらしに足す欄なので同じ扱い
|
|
33
|
-
["labelOffsetX", "名前のずらし"],
|
|
34
|
-
["labelOffsetY", "名前のずらし"],
|
|
35
|
-
["layoutPos", "名前のずらし"],
|
|
36
|
-
["posX1", "線の固定座標"],
|
|
37
|
-
["posY1", "線の固定座標"],
|
|
38
|
-
["posX2", "線の固定座標"],
|
|
39
|
-
["posY2", "線の固定座標"],
|
|
40
|
-
["waypoints", "線の固定座標"],
|
|
41
|
-
["labelPlate", "名前の下地"],
|
|
42
|
-
// 多重度も板には描く先が無い (#2107)。 他の図種は `reportCardinalityNotHonored` が知らせる
|
|
43
|
-
["cardinality", "多重度"],
|
|
44
|
-
["head", "端の形"],
|
|
45
|
-
["tailHead", "端の形"],
|
|
46
|
-
["headFill", "端の塗り"],
|
|
47
|
-
["tailHeadFill", "端の塗り"],
|
|
48
|
-
["relation", "関係の種類"],
|
|
49
|
-
["guard", "条件"],
|
|
50
|
-
["role", "役目"],
|
|
51
|
-
["overlay", "線への重ね"],
|
|
52
|
-
["widthBind", "値への追随"],
|
|
53
|
-
["strokeBind", "値への追随"],
|
|
54
|
-
["dashOffsetBind", "値への追随"],
|
|
55
|
-
];
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* 出どころと行き先だけを使う図で、効かないと伝えない矢印の欄 (#2364 / #2366)。
|
|
59
|
-
*
|
|
60
|
-
* 骨格の図 (`tree` / `mind`) は矢印を親子のつながりとして描き、
|
|
61
|
-
* ガントチャート (`gantt`) は矢印を前後の関係として読む。 どちらも向きしか使わないので除外は同じ。
|
|
62
|
-
*
|
|
63
|
-
* | 区分 | 欄 |
|
|
64
|
-
* |---|---|
|
|
65
|
-
* | 矢印が使う | 出どころ / 行き先 と、行番号と書いた場所 |
|
|
66
|
-
* | 別の知らせが受け持つ | 部品の端 (`part-node-ignored`) |
|
|
67
|
-
*
|
|
68
|
-
* 文字 (`label`) は除外しない = どちらの図種も描かないので伝える。
|
|
69
|
-
* 空の時だけ書いていない扱いにするのは `効かない矢印の欄を並べる` が受け持つ。
|
|
70
|
-
*
|
|
71
|
-
* **多重度 (`cardinality`) も除外しない**。 同じ行に 2 件並べない決まりがあり、
|
|
72
|
-
* 文字を書いた矢印ではこちらの知らせが先に出るため、多重度だけ別の知らせに回すと 1 行に 2 件並ぶ。
|
|
73
|
-
*/
|
|
74
|
-
export const 向きだけを使う図が伝えない矢印の欄: ReadonlySet<string> = new Set([
|
|
75
|
-
"no",
|
|
76
|
-
"from",
|
|
77
|
-
"to",
|
|
78
|
-
"pos",
|
|
79
|
-
"fromPartNode",
|
|
80
|
-
"toPartNode",
|
|
81
|
-
]);
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* 矢印に書いた欄のうち、効かないものの呼び名を並べる (#2366)。
|
|
85
|
-
*
|
|
86
|
-
* **伝える欄を並べず、描く欄を除いた残り全部を返す**。 効かない欄を並べる形にすると、
|
|
87
|
-
* 矢印に欄を足した日にその欄だけが一覧から漏れ、書いた人には「書いたのに何も起きない」
|
|
88
|
-
* としか見えない。 除外側を書けば、足し忘れは「余計に知らせる」 側へ倒れる。
|
|
89
|
-
*
|
|
90
|
-
* 空の文字は書いていない扱いにする = 記法は矢印の行に必ず文字の欄を作るため、
|
|
91
|
-
* 空でも「書いた」 とみなすと全ての矢印に知らせが出る。
|
|
92
|
-
*
|
|
93
|
-
* @param 矢印 記法から読んだ矢印 1 本
|
|
94
|
-
* @param 伝えない欄 その図種が描く欄と、別の知らせが受け持つ欄
|
|
95
|
-
* @returns 知らせに出す呼び名。 空なら伝えるものが無い
|
|
96
|
-
*/
|
|
97
|
-
export function 効かない矢印の欄を並べる(矢印: object, 伝えない欄: ReadonlySet<string>): string[] {
|
|
98
|
-
const 残り = new Set(
|
|
99
|
-
Object.entries(矢印 as Record<string, unknown>)
|
|
100
|
-
.filter(([欄, 値]) => 値 !== undefined && !伝えない欄.has(欄))
|
|
101
|
-
.map(([欄]) => 欄),
|
|
102
|
-
);
|
|
103
|
-
if (((矢印 as { label?: string }).label ?? "") === "") 残り.delete("label");
|
|
104
|
-
const 効かない: string[] = [];
|
|
105
|
-
for (const [欄, 呼び名] of 効かない矢印の欄の呼び名) {
|
|
106
|
-
if (!残り.delete(欄)) continue;
|
|
107
|
-
if (!効かない.includes(呼び名)) 効かない.push(呼び名);
|
|
108
|
-
}
|
|
109
|
-
// 呼び名を持たない欄は名前をそのまま出す = 読みにくい名前でも、黙って落とすよりは伝わる
|
|
110
|
-
効かない.push(...[...残り].sort());
|
|
111
|
-
return 効かない;
|
|
112
|
-
}
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import { ER_CARDINALITY_HEAD } from "@cardenelabs/cdl";
|
|
2
|
-
import type { EdgeHead, ErRelationCardinality } from "@cardenelabs/cdl";
|
|
3
|
-
import type { DslStep } from "../types";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* ER の関係 1 本を、記法から組み立て API の形へ直す (#2105)。
|
|
7
|
-
*
|
|
8
|
-
* ER は段を書くかどうかで組み立てが 2 つに分かれる。 段の無い図は描画側の `er()` を通り、
|
|
9
|
-
* 段を持つ図は段を書ける共通の組み立て (`compileGenericWithAnimate`) を通る。
|
|
10
|
-
* 多重度の語をそれぞれの組み立てが別々に読んでいた間、同じ語が 26 通りのうち 18 通りで
|
|
11
|
-
* 別の図になっていた (欄に書いた語が端に届かない / 段を持つ図に端が付かない)。
|
|
12
|
-
*
|
|
13
|
-
* **語を読むのはここ 1 か所** にし、両方の組み立てがここから作る。
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
/** 多重度の語と、それを見つける形。 語は描画側の `ErRelationCardinality` と同じ 6 語 */
|
|
17
|
-
export const CARDINALITY_PATTERNS: Array<[RegExp, ErRelationCardinality]> = [
|
|
18
|
-
[/1:1/, "1:1"],
|
|
19
|
-
[/1:N/i, "1:N"],
|
|
20
|
-
[/N:1/i, "N:1"],
|
|
21
|
-
[/N:M/i, "N:M"],
|
|
22
|
-
[/0\.\.1/, "0..1"],
|
|
23
|
-
[/1\.\.\*/, "1..*"],
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
/** 多重度から端の形が決まる語。 知らせに並べる時は手で書かず、描画側の表から導く (#2107) */
|
|
27
|
-
export const 端の形が決まる語 = Object.keys(ER_CARDINALITY_HEAD) as ErRelationCardinality[];
|
|
28
|
-
|
|
29
|
-
// cardinality token を「単語の途中でない」 境界で囲んだ RegExp を作る (parse / strip で共有する SSOT)。
|
|
30
|
-
// 前後が identifier 文字 (英数字 + アンダースコア) なら token とみなさない = `column:Metadata` の `n:M` /
|
|
31
|
-
// `10:11:12` の `1:1` / `field_1:N` の `1:N` を cardinality と誤認して壊すのを防ぐ
|
|
32
|
-
// (cc-codex #879 Round 9/10/11)。 `_` を含むのは ER label が DB schema 由来で snake_case 命名が多く、
|
|
33
|
-
// `_` 直後に cardinality 様の部分列が来る label が現実的に起こるため (`field_1:N` / `parent_N:M_child`)。
|
|
34
|
-
// strip と parse で別々に pattern.test / replace すると境界規則が drift するため、 この 1 関数を両経路で使う。
|
|
35
|
-
export function boundedCardinalityRegExp(pattern: RegExp, extraFlags = ""): RegExp {
|
|
36
|
-
const base = pattern.flags.includes("i") ? "i" : "";
|
|
37
|
-
return new RegExp(`(?<![A-Za-z0-9_])(?:${pattern.source})(?![A-Za-z0-9_])`, base + extraFlags);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function parseCardinalityFromLabel(label: string): ErRelationCardinality | null {
|
|
41
|
-
for (const [pattern, card] of CARDINALITY_PATTERNS) {
|
|
42
|
-
if (boundedCardinalityRegExp(pattern).test(label)) return card;
|
|
43
|
-
}
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// stripCardinality が「水平空白」 として畳んでよい文字を明示列挙する (space / tab / 全角空白 U+3000)。
|
|
48
|
-
// 改行系 (LF / CR / U+2028 line separator / U+2029 paragraph separator / vertical tab / form feed) は
|
|
49
|
-
// 含めない = これらは label の行構造として保持する (cc-codex #879 Round 5/6 指摘 = `\s` / `[^\S\r\n]`
|
|
50
|
-
// では Unicode 行区切りや CRLF を誤って畳んでしまう)。 括弧除去側と正規化側で同じ class を共有する。
|
|
51
|
-
export const HORIZONTAL_WS = " \\t\\u3000";
|
|
52
|
-
|
|
53
|
-
export const HWS = `[${HORIZONTAL_WS}]`;
|
|
54
|
-
|
|
55
|
-
export function stripCardinality(label: string): string {
|
|
56
|
-
let r = label;
|
|
57
|
-
let removed = false;
|
|
58
|
-
for (const [pattern] of CARDINALITY_PATTERNS) {
|
|
59
|
-
// cardinality token を「それを囲む括弧ごと 1 単位」 で除去する。
|
|
60
|
-
// まず `(1:N)` のように token を直接包む括弧つき形を除去し、 次に裸の token を除去する。
|
|
61
|
-
// 括弧を token 単位で消すことで、 label 中の cardinality と無関係な正当な括弧 (例
|
|
62
|
-
// `fn() now` の `()`) を壊さない (cc-codex #879 Round 4 指摘 = 空括弧の全域除去は過剰)。
|
|
63
|
-
// 括弧と token の間は水平空白のみ許容し、 改行を挟む形 (`(\n1:N\n)`) は括弧除去の対象外にする
|
|
64
|
-
// (改行を消費して行構造を壊すのを防ぐ、 Round 6 Finding 2)。
|
|
65
|
-
const src = pattern.source;
|
|
66
|
-
const flags = pattern.flags.includes("i") ? "gi" : "g";
|
|
67
|
-
const before = r;
|
|
68
|
-
r = r.replace(new RegExp(`\\(${HWS}*${src}${HWS}*\\)`, flags), "");
|
|
69
|
-
// 裸 token 除去 = parse と同じ単語境界付き matcher (boundedCardinalityRegExp) を global で適用する。
|
|
70
|
-
// 前後が英数字なら token とみなさないため、 timestamp (`10:11:12`) / 比率 (`10:11`) / alphabet 埋め込み
|
|
71
|
-
// (`column:Metadata`) を壊さず、 同一 token の複数出現 (`1:N and 1:N`) は全て消す。 parse 側と境界規則を
|
|
72
|
-
// 単一 SSOT にすることで strip/parse の乖離 (strip は消すが parse は残す等) を構造的に防ぐ
|
|
73
|
-
// (cc-codex #879 Round 9/10 = 数字境界だけ / strip 側だけの修正では 2 経路 drift + alphabet 埋め込み穴)。
|
|
74
|
-
r = r.replace(boundedCardinalityRegExp(pattern, "g"), "");
|
|
75
|
-
if (r !== before) removed = true;
|
|
76
|
-
}
|
|
77
|
-
// token を除去していない label は空白を一切いじらない (無条件適用でも改行 / 複数空白を保持する、
|
|
78
|
-
// cc-codex #879 Round 5 指摘 = 無条件正規化は改行を含む label を破壊した)。
|
|
79
|
-
if (!removed) return label;
|
|
80
|
-
// 除去で生じた水平空白 (space / tab / 全角空白) のみ単一化する (例 "A 1:N B" → "A B" → "A B")。
|
|
81
|
-
// 改行系は HWS に含めないため保持される。
|
|
82
|
-
// - 各行内の連続水平空白を単一化
|
|
83
|
-
// - 改行 (LF / CR) の前後の水平空白を除去 (改行直前の trailing 空白も落とす)
|
|
84
|
-
r = r
|
|
85
|
-
.replace(new RegExp(`${HWS}{2,}`, "g"), " ")
|
|
86
|
-
.replace(new RegExp(`${HWS}*([\\r\\n])${HWS}*`, "g"), "$1")
|
|
87
|
-
.replace(new RegExp(`^${HWS}+|${HWS}+$`, "g"), "");
|
|
88
|
-
// fallback = cardinality 除去後に「視覚的に意味のある文字」 が残らない場合は元 label を返す
|
|
89
|
-
// (Round 6 Finding 1 = 除去後に空白/不可視文字だけ残ると不可視 label になるのを防ぐ)。
|
|
90
|
-
//
|
|
91
|
-
// 「意味のある文字」 の判定は個別の空白/不可視文字を列挙 (denylist) すると際限が無く、
|
|
92
|
-
// Round 7 で `\s` → `\p{White_Space}` に変えたら NEL は拾えたが BOM を落とす等のいたちごっこに
|
|
93
|
-
// なった (cc-codex #879 Round 7/8/9)。 そこで Unicode の「見えない文字」 を 4 カテゴリで構造的に
|
|
94
|
-
// 判定する = 以下のいずれでもない可視文字が 1 つでもあれば意味あり。
|
|
95
|
-
// - White_Space ... 全空白 (space / tab / NBSP / NEL / 全角空白 / 各種 Unicode space / 改行系)
|
|
96
|
-
// - Cf (Format) ... BOM / ZWSP / ZWNJ / ZWJ / WORD JOINER / soft hyphen 等
|
|
97
|
-
// - Cc (Control) ... 制御文字
|
|
98
|
-
// - Default_Ignorable_Code_Point ... variation selector (Mn) / Hangul filler (Lo) 等、 Cf に
|
|
99
|
-
// 入らない不可視文字 (Cf/Cc/White_Space だけでは取りこぼすと Round 9 で判明)
|
|
100
|
-
// 4 カテゴリで Unicode の非表示文字を網羅する (Braille blank U+2800 や通常文字は content 維持)。
|
|
101
|
-
const hasVisible = /[^\p{White_Space}\p{Cf}\p{Cc}\p{Default_Ignorable_Code_Point}]/u.test(r);
|
|
102
|
-
return hasVisible ? r : label;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/** 欄に書いた語が 6 語のどれかそのものなら、その語。 大文字小文字は見本を見つける形と同じく問わない */
|
|
106
|
-
function 欄の語(書いた: string): ErRelationCardinality | null {
|
|
107
|
-
const 字 = 書いた.trim();
|
|
108
|
-
for (const [pattern, card] of CARDINALITY_PATTERNS) {
|
|
109
|
-
if (new RegExp(`^(?:${pattern.source})$`, pattern.flags).test(字)) return card;
|
|
110
|
-
}
|
|
111
|
-
return null;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* 矢印の欄に書いた多重度を読む。 空白だけの欄は書かなかったものとして `undefined` を返す。
|
|
116
|
-
*
|
|
117
|
-
* `語` は 6 語のどれかそのものならその語、そうでなければ `null` (名前に `(字)` と添えるだけで端を決めない形)。
|
|
118
|
-
* 組み立てが名前と端を決める時と、効かない形を知らせる時 (#2107) の両方がこれを読む = 判定が割れない
|
|
119
|
-
*/
|
|
120
|
-
export function 書いた多重度を読む(
|
|
121
|
-
欄: string | undefined,
|
|
122
|
-
): { 字: string; 語: ErRelationCardinality | null } | undefined {
|
|
123
|
-
const 字 = 欄?.trim();
|
|
124
|
-
if (!字) return undefined;
|
|
125
|
-
return { 字, 語: 欄の語(字) };
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/** 組み立て API の `er().relation` に渡す指定のうち、多重度と名前と端に関わる分 */
|
|
129
|
-
export type ERの関係の指定 = {
|
|
130
|
-
label?: string;
|
|
131
|
-
cardinality?: ErRelationCardinality;
|
|
132
|
-
head?: EdgeHead;
|
|
133
|
-
tailHead?: EdgeHead;
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* 記法の 1 行から、組み立て API に渡す指定を作る。
|
|
138
|
-
*
|
|
139
|
-
* **語は欄 (`cardinality`) を先に読み、無ければ名前から読む**。 名前に書いた語はどちらの場合も名前から外す
|
|
140
|
-
* (名前が語だけなら、名前を書かなかったものとして扱う = 組み立て API が語を名前として出す)。
|
|
141
|
-
*
|
|
142
|
-
* 欄に 6 語以外を書いた時 (`2..5` 等) は、名前に `(2..5)` と添えて端は決めない。 組み立て API の語は
|
|
143
|
-
* 6 語に限られ、それ以外を渡す口が無い。 書いた字を消さずに読み手へ見せる形にし、
|
|
144
|
-
* 描かない端があることは組み立ての知らせ (`cardinality-not-honored`、#2107) が伝える。
|
|
145
|
-
*/
|
|
146
|
-
export function ERの関係の指定を作る(
|
|
147
|
-
s: Pick<DslStep, "label" | "cardinality" | "head" | "tailHead">,
|
|
148
|
-
): ERの関係の指定 {
|
|
149
|
-
const 端 = {
|
|
150
|
-
...(s.head !== undefined ? { head: s.head } : {}),
|
|
151
|
-
...(s.tailHead !== undefined ? { tailHead: s.tailHead } : {}),
|
|
152
|
-
};
|
|
153
|
-
const 書いた = 書いた多重度を読む(s.cardinality);
|
|
154
|
-
if (書いた && 書いた.語 === null) {
|
|
155
|
-
return { label: s.label ? `${s.label} (${書いた.字})` : `(${書いた.字})`, ...端 };
|
|
156
|
-
}
|
|
157
|
-
const 語 = 書いた?.語 ?? parseCardinalityFromLabel(s.label);
|
|
158
|
-
if (語 === null) return { ...(s.label ? { label: s.label } : {}), ...端 };
|
|
159
|
-
// 欄に書いた時も名前の語は外す。 残すと、名前と名前の下の行に語が 2 度並ぶ (欄の語が勝つ)
|
|
160
|
-
const 名前 = 語を外した名前(s.label);
|
|
161
|
-
return { ...(名前 ? { label: 名前 } : {}), cardinality: 語, ...端 };
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/** 名前から多重度の語を外す。 語だけの名前は空にする */
|
|
165
|
-
function 語を外した名前(label: string): string {
|
|
166
|
-
if (parseCardinalityFromLabel(label) === null) return label;
|
|
167
|
-
const 外した = stripCardinality(label);
|
|
168
|
-
// 外すと見える字が残らない時、`stripCardinality` は元の名前を返す = 名前は語だけだった
|
|
169
|
-
return 外した === label ? "" : 外した;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* 指定を矢印の欄にする。 **組み立て API の `er().relation` と同じ規則**。
|
|
174
|
-
*
|
|
175
|
-
* 段を持つ図は `er()` を通らないので、ここに規則を写す。 写した規則が組み立て API とずれていないことは
|
|
176
|
-
* 検査 (`er-cardinality-notation.test.ts`) が 6 語の全ての組で突き合わせる。
|
|
177
|
-
*
|
|
178
|
-
* | 欄 | 決まり方 |
|
|
179
|
-
* |---|---|
|
|
180
|
-
* | 名前 (`label`) | 書いた名前。 無ければ語 |
|
|
181
|
-
* | 名前の下の行 (`sub`) | 名前と語の両方があり、端を明示していない時だけ語 |
|
|
182
|
-
* | 両端 (`tailHead` / `head`) | 明示が勝つ。 無ければ語から描画側の表 (`ER_CARDINALITY_HEAD`) で引く |
|
|
183
|
-
*/
|
|
184
|
-
export function ERの関係の矢印(指定: ERの関係の指定): {
|
|
185
|
-
label: string;
|
|
186
|
-
sub?: string;
|
|
187
|
-
head?: EdgeHead;
|
|
188
|
-
tailHead?: EdgeHead;
|
|
189
|
-
} {
|
|
190
|
-
const 表の端 = 指定.cardinality ? ER_CARDINALITY_HEAD[指定.cardinality] : undefined;
|
|
191
|
-
const 端を明示した = 指定.tailHead !== undefined || 指定.head !== undefined;
|
|
192
|
-
const head = 指定.head ?? 表の端?.head;
|
|
193
|
-
const tailHead = 指定.tailHead ?? 表の端?.tail;
|
|
194
|
-
return {
|
|
195
|
-
label: 指定.label ?? 指定.cardinality ?? "",
|
|
196
|
-
...(指定.label && 指定.cardinality && !端を明示した ? { sub: 指定.cardinality } : {}),
|
|
197
|
-
...(head !== undefined ? { head } : {}),
|
|
198
|
-
...(tailHead !== undefined ? { tailHead } : {}),
|
|
199
|
-
};
|
|
200
|
-
}
|
package/src/compile/flow.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { diagram, flow } 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 "./chain";
|
|
7
|
-
import { 箱の題 } from "./node-title";
|
|
8
|
-
import { slugify } from "./slug";
|
|
9
|
-
export function compileFlow(
|
|
10
|
-
doc: DslDocument,
|
|
11
|
-
/** 鎖に並べない部品を決める一覧 (#1987) */
|
|
12
|
-
partsCatalog?: Record<string, CdlDiagram>,
|
|
13
|
-
): CdlDiagram {
|
|
14
|
-
// v0.4 ... animation あり時 builder 直接経路で複数 phase 注入
|
|
15
|
-
// **縦列を書いた形は動きの有無に関わらず generic 経路へ** (#1263)。 動く図だけで効かせると、
|
|
16
|
-
// 同じ記法でも静止図では指定が黙って消える (実測 = 縦列 3 本のはずが 1 本になり知らせも出ない)
|
|
17
|
-
// **向きを書いた形も generic 経路へ** (#1494)。 静止図の経路は並びを固定で持つので、
|
|
18
|
-
// ここを通さないと書いた向きが黙って消える (縦列を書いた形と同じ理由)
|
|
19
|
-
//
|
|
20
|
-
// 振り分けは行の対応と端の知らせと同じ判定で行う (#1986)
|
|
21
|
-
if (!鎖でつなぐ形か(doc)) {
|
|
22
|
-
return compileGenericWithAnimate(doc, { kind: "flow", laneId: "main", laneWidth: 400 });
|
|
23
|
-
}
|
|
24
|
-
// 登場人物が 0 人なら枠も作らない。 描画側の `flow()` は枠を必ず 1 つ作るため、 そのまま
|
|
25
|
-
// 通すと中身の無い枠が残る (実測 = `title` と `type` だけの本文で枠 `flow` が空)。
|
|
26
|
-
// 枠を持たない図として返す = `swimlane` / `c4` が 0 人で枠 0 になるのと揃う。
|
|
27
|
-
// 鎖に並べる登場人物で見る = 行に書かれていない部品しか居ない図も枠を作らない (#1987)
|
|
28
|
-
const 並び = 鎖に並べる登場人物(doc, partsCatalog);
|
|
29
|
-
if (並び.length === 0) {
|
|
30
|
-
return diagram(slugify(doc.title), { topic: doc.title, type: "flow" }).build();
|
|
31
|
-
}
|
|
32
|
-
// flow preset は actors を順に step として配置、 step 間に edge auto
|
|
33
|
-
const flowBuilder = flow({
|
|
34
|
-
id: slugify(doc.title),
|
|
35
|
-
topic: doc.title,
|
|
36
|
-
});
|
|
37
|
-
// 各 actor を step として登録、 edge label は流れ から拾う
|
|
38
|
-
for (const a of 並び) {
|
|
39
|
-
// 名前から id を作れない時の番号は、書いた順の番号にする (部品を飛ばしても変わらない)
|
|
40
|
-
const i = doc.actors.indexOf(a);
|
|
41
|
-
// 直前の step との edge label = この actor を to に持つ flow から拾う
|
|
42
|
-
const incomingEdge = doc.flow.find((s) => s.to === a.name);
|
|
43
|
-
const edgeLabel = incomingEdge?.label;
|
|
44
|
-
flowBuilder.step(
|
|
45
|
-
{
|
|
46
|
-
id: slugify(a.name) || `n${i}`,
|
|
47
|
-
kind: 描ける種別(a.kind),
|
|
48
|
-
title: 箱の題(a),
|
|
49
|
-
},
|
|
50
|
-
edgeLabel,
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
return flowBuilder.build();
|
|
54
|
-
}
|