@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.
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 +53 -27
  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
@@ -0,0 +1,209 @@
1
+ {
2
+ "clear": {
3
+ "name": "澄んだ色",
4
+ "note": "白い地に、中くらいの明るさの鮮やかな 6 色。今の見本帳の色",
5
+ "light": {
6
+ "page": "#f3f4f7",
7
+ "bg": "#ffffff",
8
+ "surf": "#ffffff",
9
+ "sunk": "#f5f6f8",
10
+ "ink": "#12141a",
11
+ "ink2": "#3f4451",
12
+ "mute": "#6b7180",
13
+ "hair": "#12141a1c",
14
+ "line": "#12141a40",
15
+ "sh": "#101828",
16
+ "on-c": "#ffffff",
17
+ "c-blue": "#467deb",
18
+ "t-blue": "#2e62ce",
19
+ "c-amber": "#d28008",
20
+ "t-amber": "#975b04",
21
+ "c-green": "#0ea886",
22
+ "t-green": "#07775e",
23
+ "c-violet": "#6c3bb2",
24
+ "t-violet": "#6c3bb2",
25
+ "c-rose": "#ba3e40",
26
+ "t-rose": "#b83c3f",
27
+ "c-slate": "#5d6677",
28
+ "t-slate": "#5d6677",
29
+ "coin": "#e9b114",
30
+ "coint": "#856300",
31
+ "coinin": "#a8740c",
32
+ "tint": "5%",
33
+ "edge": "20%",
34
+ "shA": ".05",
35
+ "shB": ".08",
36
+ "carry": "#65686f"
37
+ },
38
+ "dark": {
39
+ "page": "#08090c",
40
+ "bg": "#0d0e12",
41
+ "surf": "#17191f",
42
+ "sunk": "#121419",
43
+ "ink": "#eceef3",
44
+ "ink2": "#c4c8d2",
45
+ "mute": "#9198a6",
46
+ "hair": "#eceef31f",
47
+ "line": "#eceef340",
48
+ "sh": "#000000",
49
+ "on-c": "#0d0e12",
50
+ "c-blue": "#7e7ef6",
51
+ "t-blue": "#989cfd",
52
+ "c-amber": "#c78135",
53
+ "t-amber": "#dd954b",
54
+ "c-green": "#20ac7a",
55
+ "t-green": "#35b986",
56
+ "c-violet": "#695b9f",
57
+ "t-violet": "#a79ae3",
58
+ "c-rose": "#bc434b",
59
+ "t-rose": "#fd7d81",
60
+ "c-slate": "#9ba3b2",
61
+ "t-slate": "#9da5b4",
62
+ "coin": "#f0c040",
63
+ "coint": "#f0c040",
64
+ "coinin": "#9a6a0c",
65
+ "tint": "6%",
66
+ "edge": "19%",
67
+ "shA": ".45",
68
+ "shB": ".35"
69
+ }
70
+ },
71
+ "paper": {
72
+ "name": "紙と墨",
73
+ "note": "生成りの紙の地に、藍 / 黄土 / 苔 / 葡萄 / 朱 / 鈍のくすんだ 6 色",
74
+ "light": {
75
+ "page": "#ece7dd",
76
+ "bg": "#f9f6f0",
77
+ "surf": "#fffcf6",
78
+ "sunk": "#f2ede4",
79
+ "ink": "#221e18",
80
+ "ink2": "#4b453b",
81
+ "mute": "#7b7366",
82
+ "hair": "#221e181f",
83
+ "line": "#221e1847",
84
+ "sh": "#3a2a10",
85
+ "on-c": "#fffcf6",
86
+ "c-blue": "#487dd5",
87
+ "t-blue": "#2d60b5",
88
+ "c-amber": "#c38405",
89
+ "t-amber": "#885a01",
90
+ "c-green": "#57a271",
91
+ "t-green": "#237143",
92
+ "c-violet": "#904698",
93
+ "t-violet": "#904698",
94
+ "c-rose": "#a9513e",
95
+ "t-rose": "#9f4836",
96
+ "c-slate": "#6a645a",
97
+ "t-slate": "#696359",
98
+ "coin": "#d4a52a",
99
+ "coint": "#7d5e05",
100
+ "coinin": "#9a7016",
101
+ "tint": "6%",
102
+ "edge": "22%",
103
+ "shA": ".06",
104
+ "shB": ".07",
105
+ "carry": "#68635c"
106
+ },
107
+ "dark": {
108
+ "page": "#0e0d0b",
109
+ "bg": "#15130f",
110
+ "surf": "#1e1b17",
111
+ "sunk": "#191612",
112
+ "ink": "#ede6d8",
113
+ "ink2": "#cbc2b1",
114
+ "mute": "#9c9283",
115
+ "hair": "#ede6d81f",
116
+ "line": "#ede6d842",
117
+ "sh": "#000000",
118
+ "on-c": "#15130f",
119
+ "c-blue": "#5785d5",
120
+ "t-blue": "#76a6f9",
121
+ "c-amber": "#be8802",
122
+ "t-amber": "#d59e2f",
123
+ "c-green": "#52aa71",
124
+ "t-green": "#61b87e",
125
+ "c-violet": "#90529b",
126
+ "t-violet": "#d08edb",
127
+ "c-rose": "#bb4e3d",
128
+ "t-rose": "#f98672",
129
+ "c-slate": "#a9a295",
130
+ "t-slate": "#aca598",
131
+ "coin": "#dcb24e",
132
+ "coint": "#dcb24e",
133
+ "coinin": "#8a6a14",
134
+ "tint": "6%",
135
+ "edge": "19%",
136
+ "shA": ".45",
137
+ "shB": ".35"
138
+ }
139
+ },
140
+ "night": {
141
+ "name": "夜の計器",
142
+ "note": "青みの黒の地に、光る水色 / 琥珀 / 若緑 / 菫 / 桃 の 6 色。明るい側は青灰の地",
143
+ "light": {
144
+ "page": "#e9eef5",
145
+ "bg": "#f6f9fc",
146
+ "surf": "#ffffff",
147
+ "sunk": "#eef3f8",
148
+ "ink": "#0b1424",
149
+ "ink2": "#34425a",
150
+ "mute": "#64748b",
151
+ "hair": "#0b14241c",
152
+ "line": "#0b142440",
153
+ "sh": "#0b1424",
154
+ "on-c": "#ffffff",
155
+ "c-blue": "#0385cd",
156
+ "t-blue": "#086aa3",
157
+ "c-amber": "#ba8e0f",
158
+ "t-amber": "#7f5f04",
159
+ "c-green": "#0a8857",
160
+ "t-green": "#027449",
161
+ "c-violet": "#5839ba",
162
+ "t-violet": "#5839ba",
163
+ "c-rose": "#dd4a94",
164
+ "t-rose": "#b82375",
165
+ "c-slate": "#64748b",
166
+ "t-slate": "#56667c",
167
+ "coin": "#eab308",
168
+ "coint": "#7e6005",
169
+ "coinin": "#a16207",
170
+ "tint": "5%",
171
+ "edge": "22%",
172
+ "shA": ".06",
173
+ "shB": ".09",
174
+ "carry": "#596579"
175
+ },
176
+ "dark": {
177
+ "page": "#060a12",
178
+ "bg": "#0a101c",
179
+ "surf": "#111a2a",
180
+ "sunk": "#0d1522",
181
+ "ink": "#e6edf7",
182
+ "ink2": "#b8c4d6",
183
+ "mute": "#8090a8",
184
+ "hair": "#e6edf71c",
185
+ "line": "#9fb3d145",
186
+ "sh": "#000000",
187
+ "on-c": "#0a101c",
188
+ "c-blue": "#3884b6",
189
+ "t-blue": "#62ace1",
190
+ "c-amber": "#be8533",
191
+ "t-amber": "#d59b4b",
192
+ "c-green": "#3ba774",
193
+ "t-green": "#4fb884",
194
+ "c-violet": "#7d4ecd",
195
+ "t-violet": "#b494fd",
196
+ "c-rose": "#bc3a74",
197
+ "t-rose": "#ff77ad",
198
+ "c-slate": "#96a3b5",
199
+ "t-slate": "#99a6b8",
200
+ "coin": "#facc15",
201
+ "coint": "#facc15",
202
+ "coinin": "#a16207",
203
+ "tint": "6%",
204
+ "edge": "19%",
205
+ "shA": ".5",
206
+ "shB": ".4"
207
+ }
208
+ }
209
+ }
@@ -0,0 +1,155 @@
1
+ /**
2
+ * 図の見た目の値の表。色、字の大きさ、余白、動きの長さをここに 1 つにまとめる。
3
+ *
4
+ * 描く file (`layout/`、`render/`、`timeline.ts`、`view.ts`、`player.ts`) は色の値と字の大きさを
5
+ * 直接書かず、この表から読む。値は見本帳 (`docs/design/base/`) の部品と同じにしてある。
6
+ * 色味の値は見本帳の `palettes.json` の写しで、色味ごとに明るい背景と暗い背景で別の値を持つ。
7
+ */
8
+ import palettes from "./palettes.json";
9
+ import { FONTS, type Family } from "./fonts";
10
+
11
+ export type Theme = "light" | "dark";
12
+
13
+ export interface Palette {
14
+ id: string;
15
+ name: string;
16
+ note: string;
17
+ light: Record<string, string>;
18
+ dark: Record<string, string>;
19
+ }
20
+
21
+ /** 色味を指定しない時と、知らない名前を渡した時に使う色味。 */
22
+ export const DEFAULT_PALETTE = "paper";
23
+
24
+ export const PALETTES: Readonly<Record<string, Palette>> = Object.fromEntries(
25
+ Object.entries(palettes as Record<string, Omit<Palette, "id">>).map(([id, p]) => [id, { id, ...p }]),
26
+ );
27
+
28
+ /** 名前から色味を引く。指定が無いか、知らない名前 (外した墨と朱の `ink` を含む) なら紙と墨。 */
29
+ export function resolvePalette(id?: string): Palette {
30
+ const found = id !== undefined && Object.hasOwn(PALETTES, id) ? PALETTES[id] : undefined;
31
+ return found ?? (PALETTES[DEFAULT_PALETTE] as Palette);
32
+ }
33
+
34
+ /** 色味の値を CSS の変数として並べる。 */
35
+ export function paletteVars(palette: Palette, theme: Theme): string {
36
+ return Object.entries(palette[theme])
37
+ .map(([key, value]) => `--${key}:${value}`)
38
+ .join(";");
39
+ }
40
+
41
+ /** 字の変数。同梱した 2 つの字を 1 度だけ名指し、字を使う所はどれもこの変数を読む。 */
42
+ export const FONT_VARS = `--sans:"${FONTS.sans}";--mono:"${FONTS.mono}"`;
43
+
44
+ /** 区画や箱を分ける色の役。灰 (slate) と硬貨 (coin) は分類の色として順に配らない。 */
45
+ export const COLOR_ORDER = ["blue", "amber", "green", "violet", "rose"] as const;
46
+ export type ColorKey = (typeof COLOR_ORDER)[number] | "slate" | "coin";
47
+
48
+ export interface TextStyle {
49
+ size: number;
50
+ weight: number;
51
+ family: Family;
52
+ }
53
+
54
+ const text = (size: number, weight: number, family: Family = "sans"): TextStyle => ({ size, weight, family });
55
+
56
+ /** 字の大きさと太さ。どれも 10.5 以上にする。 */
57
+ export const TYPE = {
58
+ boxName: text(13, 650),
59
+ boxSub: text(11, 500),
60
+ boxSubStrong: text(11, 700),
61
+ regionName: text(12.5, 700),
62
+ regionNote: text(11, 500),
63
+ label: text(11, 600, "mono"),
64
+ labelJa: text(11, 650),
65
+ action: text(11, 650),
66
+ badge: text(10.5, 700, "mono"),
67
+ carrier: text(10.5, 700, "mono"),
68
+ carrierJa: text(10.5, 700),
69
+ stripTitle: text(12.5, 700),
70
+ fieldName: text(10.5, 600),
71
+ fieldValue: text(12, 600, "mono"),
72
+ fieldValueJa: text(12, 600),
73
+ tag: text(10.5, 700),
74
+ miniTitle: text(10.5, 700),
75
+ stepTitle: text(15, 700),
76
+ stepBody: text(13.5, 500),
77
+ stepNo: text(13, 700, "mono"),
78
+ button: text(14, 700),
79
+ } as const;
80
+
81
+ /** 置き場所と部品の大きさ。単位は図の座標 (字が原寸の時の px)。 */
82
+ export const LOOK = {
83
+ /** 部品どうしの最小の隙間 */
84
+ gap: 10,
85
+ /** 図の外周の余白 */
86
+ margin: 14,
87
+ box: { h: 72, minW: 92, padX: 12, radius: 12, icon: 24, iconRadius: 7, iconY: -16, iconScale: 0.74, nameY: 12, subY: 27 },
88
+ region: { pad: 18, gap: 10, radius: 14, inset: 14, icon: 24, iconRadius: 7, iconScale: 0.68, nameY: 58, line: 16, minH: 108 },
89
+ architecture: { columns: 4, columnGap: 56, maxColumnGap: 160, rowGap: 44, labelRoom: 16 },
90
+ sequence: { columnGap: 40, labelRoom: 16, firstRow: 22, rowGap: 14, stepGap: 8, minPitch: 40, tail: 18, selfW: 34, selfH: 18 },
91
+ edge: { inset: 3, arrow: 6, arrowHalf: 3.5, parallel: 5, ghostDash: 5, flowDash: 9 },
92
+ label: { h: 20, padX: 9, radius: 10, offset: 22, side: 14, search: 4, searchMax: 400, soft: 6 },
93
+ action: { h: 22, padX: 10, radius: 11 },
94
+ badge: { r: 9.5, ring: 9, inset: 4, along: 14, short: 44 },
95
+ carrier: { envW: 24, envH: 17, coinR: 6.5, coinIn: 3.8, tagH: 18, tagPadX: 8, samples: 16 },
96
+ strip: { h: 72, line: 44, pad: 12, icon: 24, titleX: 44, fieldGap: 22, sepInset: 14, tagGap: 6, tagH: 15, tagPadX: 7, nameY: 22, valueY: 43 },
97
+ stroke: { hair: 1, edge: 1.7, edgeOn: 2.25, arrow: 1.5, flow: 1.3, halo: 7, on: 1.75, glyph: 2, lifeline: 1.2, envelope: 1.5, badgeRing: 1.5 },
98
+ shadow: { near: 0.8, far: 4, nearY: 1, farY: 3 },
99
+ mini: { w: 168, pad: 8, title: 14, inset: 12, radius: 10 },
100
+ /** 寄って追う見せ方の窓の高さの、幅に対する割合と下限 */
101
+ follow: { aspect: 0.75, minH: 320, ease: 0.6 },
102
+ /** 色を混ぜる割合 (%) */
103
+ mix: { icon: 14, regionIcon: 16, regionIconEdge: 34, cap: 12, capEdge: 42, badgePast: 14, badgePastEdge: 70, mini: 62, miniBand: 16, miniBandEdge: 36, view: 6 },
104
+ /** 字の並びの基準線を、置きたい高さの真ん中からどれだけ下げるか */
105
+ baseline: { label: 3.8, badge: 3.5, carrier: 3.7, stripTitle: 4.5, tag: 3.6, action: 3.8 },
106
+ /** 浮いて出る物が下から上がる長さと、弾んで出る物の始まりの大きさ */
107
+ rise: 5,
108
+ popFrom: 0.4,
109
+ /** 動きを嫌わない人の頁の部品 */
110
+ player: { gap: 10, radius: 12, button: 36, hidden: 1, focus: 2 },
111
+ } as const;
112
+
113
+ /** 動きの長さ (秒)。 */
114
+ export const MOTION = {
115
+ /** 最初の段の前に全体を見せる長さ */
116
+ intro: 1.4,
117
+ /** 最後の段の後に全体を見せる長さ */
118
+ outro: 4.6,
119
+ /** 繰り返す前に消えていく長さ */
120
+ tail: 0.6,
121
+ /** 段の長さ。本文の字数で伸ばし、段で起きることが全部見えてから dwell 秒は留める */
122
+ stepBase: 1.2,
123
+ perChar: 0.025,
124
+ stepMin: 2.2,
125
+ stepMax: 5,
126
+ dwell: 1.2,
127
+ /** 段の中で最初の線を引き始めるまでと、続く線を引き始める間 */
128
+ edgeAt: 0.1,
129
+ stagger: 0.5,
130
+ /** 線を引く長さ。運ぶ物を載せた線は運ぶ物が走るので長い */
131
+ draw: 0.55,
132
+ drawCarry: 0.9,
133
+ /** 処理を読む間 (次の線と書き換えはこれだけ待つ) と、書き換えが続く間 */
134
+ action: 0.9,
135
+ change: 0.12,
136
+ /** 箱の下の字が見えている短さの下限。これより早く次の字に替わる字は出さない */
137
+ minShow: 0.8,
138
+ /** 線の名前が線より遅れて出る長さと、出入りの長さ */
139
+ labelDelay: 0.15,
140
+ fade: 0.3,
141
+ popFade: 0.4,
142
+ untilFade: 0.2,
143
+ /** 段の止め絵を撮る時刻を、段の終わりからどれだけ前にするか */
144
+ still: 0.45,
145
+ } as const;
146
+
147
+ /** 見せ方を決める字の大きさ。全体を枠に収めた時の箱の名前がこれを下回ると寄って追う。 */
148
+ export const READABLE_PX = 10.5;
149
+
150
+ /** 動きの緩急。 */
151
+ export const EASE = {
152
+ inOut: "cubic-bezier(.65,0,.35,1)",
153
+ out: "cubic-bezier(.22,1,.36,1)",
154
+ pop: "cubic-bezier(.34,1.56,.64,1)",
155
+ } as const;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Markdown の中の dragon の囲み (```dragon) を、囲みごとに取り出す。
3
+ *
4
+ * 囲みの開き方と閉じ方は CommonMark に従う。` か ~ を 3 つ以上並べて開き、同じ字を開いた数以上
5
+ * 並べて閉じる。閉じていない囲みは文書の終わりまでを中身にする。dragon 以外の言語の囲みの中は読まない。
6
+ */
7
+ export interface Fence {
8
+ /** 囲みの中身 (記法) */
9
+ source: string;
10
+ /** 中身の 1 行目が文書の何行目か。記法の誤りの行を文書の行に直す時に足す */
11
+ line: number;
12
+ }
13
+
14
+ export function extractDiagrams(markdown: string): Fence[] {
15
+ const lines = markdown.split(/\r?\n/);
16
+ if (lines[lines.length - 1] === "") lines.pop();
17
+ const fences: Fence[] = [];
18
+ let open: { mark: string; dragon: boolean; start: number; body: string[] } | undefined;
19
+ lines.forEach((text, index) => {
20
+ if (!open) {
21
+ const found = /^ {0,3}(`{3,}|~{3,})\s*([^\s`]*)/.exec(text);
22
+ if (found) open = { mark: found[1] ?? "", dragon: found[2] === "dragon", start: index + 2, body: [] };
23
+ return;
24
+ }
25
+ const close = /^ {0,3}(`{3,}|~{3,})\s*$/.exec(text)?.[1];
26
+ if (close !== undefined && close[0] === open.mark[0] && close.length >= open.mark.length) {
27
+ if (open.dragon) fences.push({ source: open.body.join("\n"), line: open.start });
28
+ open = undefined;
29
+ return;
30
+ }
31
+ open.body.push(text);
32
+ });
33
+ if (open?.dragon) fences.push({ source: open.body.join("\n"), line: open.start });
34
+ return fences;
35
+ }
@@ -0,0 +1,122 @@
1
+ /**
2
+ * 記法の誤りの文 (#2997)。
3
+ *
4
+ * 誤りの文は file の言葉で出す。file の言葉は最初の行の図の種類の語で決まり、
5
+ * 最初の行が読めず決まらない時は、呼ぶ側が渡した言葉 (渡さなければ日本語) で出す。
6
+ * 文の中の記法の語は語の表から引き、表と文で語が食い違わないようにする。
7
+ */
8
+ import { COLORS } from "./schema";
9
+ import { type NotationLang, type WordGroup, type WORDS, wordOf } from "./words";
10
+
11
+ export interface Messages {
12
+ noHead: string;
13
+ badHead: string;
14
+ duplicate: (id: string) => string;
15
+ undeclaredBox: (id: string) => string;
16
+ noBody: (title: string) => string;
17
+ emptyStepTitle: string;
18
+ noBoxes: string;
19
+ noSteps: string;
20
+ viewTwice: string;
21
+ badView: string;
22
+ stripTwice: string;
23
+ emptyStripField: string;
24
+ stepLineBeforeStep: string;
25
+ unreadableDeclaration: string;
26
+ emptyName: (id: string) => string;
27
+ badColor: string;
28
+ regionFirst: (id: string) => string;
29
+ badAttr: (raw: string) => string;
30
+ codeTwice: string;
31
+ declarationInStep: string;
32
+ emptySwap: string;
33
+ unreadableStepLine: string;
34
+ edgeShape: string;
35
+ carryTwice: string;
36
+ tagNeedsValue: string;
37
+ carryTakesNoValue: (key: string) => string;
38
+ stripUndeclared: string;
39
+ stripTagOnce: string;
40
+ noSuchField: (field: string) => string;
41
+ stripNeedsValue: string;
42
+ /** 違う言葉の語 `word` を書いた時。`own` はこの file の言葉の同じ役割の語 */
43
+ otherLanguageWord: (word: string, own: string) => string;
44
+ }
45
+
46
+ const ja = (): Messages => {
47
+ const w = <G extends WordGroup>(group: G, value: keyof (typeof WORDS)[G]): string => wordOf(group, value, "ja");
48
+ return {
49
+ noHead: `最初の行に図の種類 (${w("kind", "sequence")} か ${w("kind", "architecture")}) と題を書く`,
50
+ badHead: `最初の行は ${w("kind", "sequence")} か ${w("kind", "architecture")} で始め、続けて題を書く`,
51
+ duplicate: (id) => `${id} は既に宣言した名札`,
52
+ undeclaredBox: (id) => `${id} という箱は宣言していない`,
53
+ noBody: (title) => `段「${title}」に本文 (> で始まる行) が要る`,
54
+ emptyStepTitle: "段の見出し (#) に題を書く",
55
+ noBoxes: "箱を 1 つ以上宣言する",
56
+ noSteps: "段 (# で始まる行) を 1 つ以上書く",
57
+ viewTwice: `${w("head", "view")}は 1 行だけ書く`,
58
+ badView: `${w("head", "view")}は ${w("view", "fixed")} か ${w("view", "follow")}`,
59
+ stripTwice: "中身の帯は 1 つだけ宣言する",
60
+ emptyStripField: "帯の欄の名前が空",
61
+ stepLineBeforeStep: "線や処理は段の見出し (#) の下に書く",
62
+ unreadableDeclaration: "読めない行。箱の宣言は <名札> = <名前>「<下の小さな字>」 の形で書く",
63
+ emptyName: (id) => `${id} の名前が空`,
64
+ badColor: `${w("attr", "color")}は ${COLORS.join(" / ")} のどれか`,
65
+ regionFirst: (id) => `${w("attr", "region")} ${id} を先に宣言する`,
66
+ badAttr: (raw) => `[${raw}] は書けない指定`,
67
+ codeTwice: "1 つの段に命令 (` で囲んだ行) は 1 行まで",
68
+ declarationInStep: "箱の宣言は最初の段の見出し (#) より前に書く",
69
+ emptySwap: "「」の中に書き換える字を書く",
70
+ unreadableStepLine: "読めない行。線は <名札> -> <名札> : <線の名前>、処理は <名札> : <処理の名前> の形で書く",
71
+ edgeShape: "線は <名札> -> <名札> : <線の名前> の形で書く",
72
+ carryTwice: "運ぶ物は 1 本の線に 1 つまで",
73
+ tagNeedsValue: `${w("carry", "tag")}には値を書く ([${w("carry", "tag")} <値>])`,
74
+ carryTakesNoValue: (key) => `[${key}] には値を書かない`,
75
+ stripUndeclared: `帯の値を書く前に、帯を宣言する (${w("head", "strip")} <題> = <欄>, <欄>)`,
76
+ stripTagOnce: "帯の札は 1 つまで",
77
+ noSuchField: (field) => `${field} という欄は帯に無い`,
78
+ stripNeedsValue: "帯の欄には = <値> か [<札>] を書く",
79
+ otherLanguageWord: (word, own) => `この図は日本語の語で書く。${word} ではなく ${own} と書く`,
80
+ };
81
+ };
82
+
83
+ const en = (): Messages => {
84
+ const w = <G extends WordGroup>(group: G, value: keyof (typeof WORDS)[G]): string => wordOf(group, value, "en");
85
+ return {
86
+ noHead: `Write the diagram kind (${w("kind", "sequence")} or ${w("kind", "architecture")}) and a title on the first line`,
87
+ badHead: `Start the first line with ${w("kind", "sequence")} or ${w("kind", "architecture")}, followed by the title`,
88
+ duplicate: (id) => `${id} is already declared`,
89
+ undeclaredBox: (id) => `No box named ${id} is declared`,
90
+ noBody: (title) => `Step "${title}" needs a body (a line starting with >)`,
91
+ emptyStepTitle: "Write a title after the step heading (#)",
92
+ noBoxes: "Declare at least one box",
93
+ noSteps: "Write at least one step (a line starting with #)",
94
+ viewTwice: `Write ${w("head", "view")} only once`,
95
+ badView: `${w("head", "view")} is ${w("view", "fixed")} or ${w("view", "follow")}`,
96
+ stripTwice: `Declare only one ${w("head", "strip")}`,
97
+ emptyStripField: `A ${w("head", "strip")} field name is empty`,
98
+ stepLineBeforeStep: "Write lines and actions under a step heading (#)",
99
+ unreadableDeclaration: 'Cannot read this line. Declare a box as <id> = <name> "<caption>"',
100
+ emptyName: (id) => `${id} has an empty name`,
101
+ badColor: `${w("attr", "color")} is one of ${COLORS.join(" / ")}`,
102
+ regionFirst: (id) => `Declare ${w("attr", "region")} ${id} first`,
103
+ badAttr: (raw) => `[${raw}] cannot be written here`,
104
+ codeTwice: "A step takes at most one command (a line in backticks)",
105
+ declarationInStep: "Declare boxes before the first step heading (#)",
106
+ emptySwap: 'Write the new caption inside "…"',
107
+ unreadableStepLine: "Cannot read this line. Write a line as <id> -> <id> : <label>, or an action as <id> : <action>",
108
+ edgeShape: "Write a line as <id> -> <id> : <label>",
109
+ carryTwice: "A line carries at most one thing",
110
+ tagNeedsValue: `${w("carry", "tag")} needs a value ([${w("carry", "tag")} <value>])`,
111
+ carryTakesNoValue: (key) => `[${key}] takes no value`,
112
+ stripUndeclared: `Declare the ${w("head", "strip")} before writing its values (${w("head", "strip")} <title> = <field>, <field>)`,
113
+ stripTagOnce: `A ${w("head", "strip")} value takes at most one tag`,
114
+ noSuchField: (field) => `The ${w("head", "strip")} has no field named ${field}`,
115
+ stripNeedsValue: `Write = <value> or [<tag>] after the ${w("head", "strip")} field`,
116
+ otherLanguageWord: (word, own) => `This diagram uses English words. Write ${own} instead of ${word}`,
117
+ };
118
+ };
119
+
120
+ const MESSAGES: Record<NotationLang, Messages> = { ja: ja(), en: en() };
121
+
122
+ export const messagesFor = (lang: NotationLang): Messages => MESSAGES[lang];