@cardenelabs/dragon 0.35.0 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -3
- package/dist/cli.cjs +597 -375
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +597 -375
- package/dist/cli.js.map +1 -1
- package/dist/export.cjs +104 -37
- package/dist/export.cjs.map +1 -1
- package/dist/export.d.cts +1 -1
- package/dist/export.d.ts +1 -1
- package/dist/export.js +104 -37
- package/dist/export.js.map +1 -1
- package/dist/index.cjs +833 -526
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -15
- package/dist/index.d.ts +21 -15
- package/dist/index.js +833 -526
- package/dist/index.js.map +1 -1
- package/dist/player.global.js +2 -2
- package/dist/{schema-BBWfniwH.d.cts → schema-9VLameDG.d.cts} +15 -3
- package/dist/{schema-BBWfniwH.d.ts → schema-9VLameDG.d.ts} +15 -3
- package/package.json +20 -8
- package/src/cli.ts +13 -14
- package/src/figure-text.ts +1 -1
- package/src/index.ts +4 -4
- package/src/look/values.ts +16 -4
- package/src/messages.ts +158 -80
- package/src/parser.ts +402 -245
- package/src/player.ts +80 -9
- package/src/printer.ts +90 -60
- package/src/render/parts.ts +28 -8
- package/src/render/svg.ts +128 -33
- package/src/schema.ts +1 -1
- package/src/tokenize.ts +11 -8
- package/src/view.ts +5 -2
- package/src/words.ts +39 -65
|
@@ -14,10 +14,22 @@ declare function resolvePalette(id?: string): Palette;
|
|
|
14
14
|
/** 区画や箱を分ける色の役。灰 (slate) と硬貨 (coin) は分類の色として順に配らない。 */
|
|
15
15
|
declare const COLOR_ORDER: readonly ["blue", "amber", "green", "violet", "rose"];
|
|
16
16
|
type ColorKey = (typeof COLOR_ORDER)[number] | "slate" | "coin";
|
|
17
|
+
/** 見せ方を決める字の大きさ。全体を枠に収めた時の箱の名前がこれを下回ると寄って追う。 */
|
|
18
|
+
declare const READABLE_PX = 10.5;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* dragon記法の語 (#3137)。
|
|
22
|
+
*
|
|
23
|
+
* 行の種類は行の頭の英語の語で決まり、属性は `[<鍵>: <値>]` で書く。
|
|
24
|
+
* 語は英語だけで、原本の JSON が使う名前に揃え、記法と JSON で覚える語を 1 組にする。
|
|
25
|
+
*
|
|
26
|
+
* 言葉の型 (`NotationLang`) は、誤りの文と図の中の字の言葉を選ぶために持つ。
|
|
27
|
+
* 語が英語だけなので、記法の file から言葉は決めず、呼ぶ側が渡す。
|
|
28
|
+
*
|
|
29
|
+
* 型が欠けを止める。原本の JSON の値 (図の種類、運ぶ物、見せ方、名前の側) に語が無い時は、型の検査が落ちる。
|
|
30
|
+
*/
|
|
17
31
|
|
|
18
32
|
type NotationLang = "ja" | "en";
|
|
19
|
-
/** 記法の言葉。最初の行の図の種類の語で決まり、決まらなければ `undefined` */
|
|
20
|
-
declare function notationLanguage(notation: string): NotationLang | undefined;
|
|
21
33
|
|
|
22
34
|
type Color = "blue" | "amber" | "green" | "violet" | "rose" | "slate" | "coin";
|
|
23
35
|
interface Region {
|
|
@@ -109,4 +121,4 @@ interface CheckOptions {
|
|
|
109
121
|
/** 原本の JSON を検査する。版が道具より新しいかは見ない (`readDiagram` が見る)。 */
|
|
110
122
|
declare function validateDiagram(input: unknown, options?: CheckOptions): Checked;
|
|
111
123
|
|
|
112
|
-
export { type Box as B, type CheckOptions as C, type Diagram as D, type FieldError as F, type LabelSide as L, type NotationLang as N, PALETTES as P,
|
|
124
|
+
export { type Box as B, type CheckOptions as C, type Diagram as D, type FieldError as F, type LabelSide as L, type NotationLang as N, PALETTES as P, READABLE_PX as R, type Step as S, type Theme as T, type ViewMode as V, type ColorKey as a, type Carry as b, type Checked as c, type Color as d, DEFAULT_PALETTE as e, type DiagramEvent as f, type Palette as g, type Region as h, resolvePalette as r, validateDiagram as v };
|
|
@@ -14,10 +14,22 @@ declare function resolvePalette(id?: string): Palette;
|
|
|
14
14
|
/** 区画や箱を分ける色の役。灰 (slate) と硬貨 (coin) は分類の色として順に配らない。 */
|
|
15
15
|
declare const COLOR_ORDER: readonly ["blue", "amber", "green", "violet", "rose"];
|
|
16
16
|
type ColorKey = (typeof COLOR_ORDER)[number] | "slate" | "coin";
|
|
17
|
+
/** 見せ方を決める字の大きさ。全体を枠に収めた時の箱の名前がこれを下回ると寄って追う。 */
|
|
18
|
+
declare const READABLE_PX = 10.5;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* dragon記法の語 (#3137)。
|
|
22
|
+
*
|
|
23
|
+
* 行の種類は行の頭の英語の語で決まり、属性は `[<鍵>: <値>]` で書く。
|
|
24
|
+
* 語は英語だけで、原本の JSON が使う名前に揃え、記法と JSON で覚える語を 1 組にする。
|
|
25
|
+
*
|
|
26
|
+
* 言葉の型 (`NotationLang`) は、誤りの文と図の中の字の言葉を選ぶために持つ。
|
|
27
|
+
* 語が英語だけなので、記法の file から言葉は決めず、呼ぶ側が渡す。
|
|
28
|
+
*
|
|
29
|
+
* 型が欠けを止める。原本の JSON の値 (図の種類、運ぶ物、見せ方、名前の側) に語が無い時は、型の検査が落ちる。
|
|
30
|
+
*/
|
|
17
31
|
|
|
18
32
|
type NotationLang = "ja" | "en";
|
|
19
|
-
/** 記法の言葉。最初の行の図の種類の語で決まり、決まらなければ `undefined` */
|
|
20
|
-
declare function notationLanguage(notation: string): NotationLang | undefined;
|
|
21
33
|
|
|
22
34
|
type Color = "blue" | "amber" | "green" | "violet" | "rose" | "slate" | "coin";
|
|
23
35
|
interface Region {
|
|
@@ -109,4 +121,4 @@ interface CheckOptions {
|
|
|
109
121
|
/** 原本の JSON を検査する。版が道具より新しいかは見ない (`readDiagram` が見る)。 */
|
|
110
122
|
declare function validateDiagram(input: unknown, options?: CheckOptions): Checked;
|
|
111
123
|
|
|
112
|
-
export { type Box as B, type CheckOptions as C, type Diagram as D, type FieldError as F, type LabelSide as L, type NotationLang as N, PALETTES as P,
|
|
124
|
+
export { type Box as B, type CheckOptions as C, type Diagram as D, type FieldError as F, type LabelSide as L, type NotationLang as N, PALETTES as P, READABLE_PX as R, type Step as S, type Theme as T, type ViewMode as V, type ColorKey as a, type Carry as b, type Checked as c, type Color as d, DEFAULT_PALETTE as e, type DiagramEvent as f, type Palette as g, type Region as h, resolvePalette as r, validateDiagram as v };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cardenelabs/dragon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.0",
|
|
4
4
|
"description": "Dragon — 動く図を、人は行ごとの記法で、AI は JSON で書く。時系列図と構成図を段ごとに動かし、mp4・GIF・HTML・PNG に書き出す。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "cardene777",
|
|
@@ -26,21 +26,32 @@
|
|
|
26
26
|
"module": "./dist/index.js",
|
|
27
27
|
"types": "./dist/index.d.ts",
|
|
28
28
|
"bin": {
|
|
29
|
-
"dragon": "
|
|
29
|
+
"dragon": "dist/cli.js"
|
|
30
30
|
},
|
|
31
31
|
"exports": {
|
|
32
32
|
".": {
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
"import": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"default": "./dist/index.js"
|
|
36
|
+
},
|
|
37
|
+
"require": {
|
|
38
|
+
"types": "./dist/index.d.cts",
|
|
39
|
+
"default": "./dist/index.cjs"
|
|
40
|
+
}
|
|
36
41
|
},
|
|
37
42
|
"./fonts": {
|
|
38
43
|
"import": "./dist/fonts.js",
|
|
39
44
|
"require": "./dist/fonts.cjs"
|
|
40
45
|
},
|
|
41
46
|
"./export": {
|
|
42
|
-
"
|
|
43
|
-
|
|
47
|
+
"import": {
|
|
48
|
+
"types": "./dist/export.d.ts",
|
|
49
|
+
"default": "./dist/export.js"
|
|
50
|
+
},
|
|
51
|
+
"require": {
|
|
52
|
+
"types": "./dist/export.d.cts",
|
|
53
|
+
"default": "./dist/export.cjs"
|
|
54
|
+
}
|
|
44
55
|
}
|
|
45
56
|
},
|
|
46
57
|
"files": [
|
|
@@ -66,7 +77,8 @@
|
|
|
66
77
|
"test": "cd ../.. && vitest run packages/dragon",
|
|
67
78
|
"test:watch": "cd ../.. && vitest packages/dragon",
|
|
68
79
|
"lint": "tsc --noEmit",
|
|
69
|
-
"
|
|
80
|
+
"check:pack": "node scripts/check-pack.mjs",
|
|
81
|
+
"prepublishOnly": "pnpm run typecheck && pnpm run test && pnpm run build && pnpm run check:pack"
|
|
70
82
|
},
|
|
71
83
|
"peerDependencies": {
|
|
72
84
|
"playwright-core": ">=1.49.0"
|
package/src/cli.ts
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* `dragon export <図の file>` の命令。原本の JSON (`.json`) か記法 (`.dragon`) を読み、mp4、GIF、HTML、PNG を書き出す。
|
|
4
4
|
* 書き出した file の path を 1 行ずつ出す。
|
|
5
5
|
*
|
|
6
|
-
* 使い方の文と誤りの文は、図の中の字と同じ言葉で出す (#3003)。`--lang`
|
|
7
|
-
*
|
|
6
|
+
* 使い方の文と誤りの文は、図の中の字と同じ言葉で出す (#3003)。`--lang` を渡せばその言葉、無ければ日本語。
|
|
7
|
+
* dragon記法の語は英語だけで file から言葉が決まらないため、記法の file も JSON の原本と同じに扱う (#3137)。
|
|
8
8
|
*/
|
|
9
9
|
import { readFileSync } from "node:fs";
|
|
10
10
|
import { basename, extname, resolve } from "node:path";
|
|
@@ -12,7 +12,7 @@ import { parseArgs } from "node:util";
|
|
|
12
12
|
import { type ExportFormat, exportDiagram, FORMATS } from "./export/index";
|
|
13
13
|
import { PALETTES, type Theme } from "./look/values";
|
|
14
14
|
import { parseNotation } from "./parser";
|
|
15
|
-
import {
|
|
15
|
+
import type { NotationLang } from "./words";
|
|
16
16
|
|
|
17
17
|
const OPTIONS = {
|
|
18
18
|
out: { type: "string" },
|
|
@@ -54,7 +54,7 @@ const CLI_TEXT: Record<NotationLang, CliText> = {
|
|
|
54
54
|
" --width <px> 枠の幅。見せ方を選び、寄って見せる窓の幅になる",
|
|
55
55
|
` --palette <名前> 色味 (${PALETTE_NAMES})`,
|
|
56
56
|
" --theme <明暗> light か dark",
|
|
57
|
-
" --lang <言葉> 図の中の字と命令の文の言葉 (ja か en)
|
|
57
|
+
" --lang <言葉> 図の中の字と命令の文の言葉 (ja か en)。既定は ja",
|
|
58
58
|
" --fps <数> mp4 の 1 秒のコマの数 (既定 30)",
|
|
59
59
|
" --gif-fps <数> GIF の 1 秒のコマの数 (既定 10)",
|
|
60
60
|
" --format <形> 書き出す形を , で区切る (既定 mp4,gif,html,png)",
|
|
@@ -76,7 +76,7 @@ const CLI_TEXT: Record<NotationLang, CliText> = {
|
|
|
76
76
|
" --width <px> Frame width. Picks the view and sets the window width when following",
|
|
77
77
|
` --palette <name> Colors (${PALETTE_NAMES})`,
|
|
78
78
|
" --theme <mode> light or dark",
|
|
79
|
-
" --lang <lang> Language of the diagram text and command messages (ja or en). Defaults to
|
|
79
|
+
" --lang <lang> Language of the diagram text and command messages (ja or en). Defaults to ja",
|
|
80
80
|
" --fps <n> Frames per second of the mp4 (default 30)",
|
|
81
81
|
" --gif-fps <n> Frames per second of the GIF (default 10)",
|
|
82
82
|
" --format <list> Formats to write, separated by , (default mp4,gif,html,png)",
|
|
@@ -147,8 +147,8 @@ function failedPath(error: unknown): string | undefined {
|
|
|
147
147
|
return typeof error.path === "string" ? error.path : undefined;
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
/** 図の file
|
|
151
|
-
function read(file: string, text: CliText
|
|
150
|
+
/** 図の file を読む。記法の行の誤りは `lang` の言葉で出す */
|
|
151
|
+
function read(file: string, text: CliText, lang: NotationLang): unknown {
|
|
152
152
|
let source: string;
|
|
153
153
|
try {
|
|
154
154
|
source = readFileSync(file, "utf8");
|
|
@@ -158,15 +158,14 @@ function read(file: string, text: CliText): { diagram: unknown; lang?: NotationL
|
|
|
158
158
|
}
|
|
159
159
|
if (extname(file) !== ".dragon") {
|
|
160
160
|
try {
|
|
161
|
-
return
|
|
161
|
+
return JSON.parse(source);
|
|
162
162
|
} catch (error) {
|
|
163
163
|
throw new Error(text.badJson(file, detail(error)));
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
|
-
const parsed = parseNotation(source);
|
|
166
|
+
const parsed = parseNotation(source, { lang });
|
|
167
167
|
if (!parsed.ok) throw new Error(parsed.errors.map((e) => `${file}:${e.line} ${e.message}`).join("\n"));
|
|
168
|
-
|
|
169
|
-
return lang === undefined ? { diagram: parsed.diagram } : { diagram: parsed.diagram, lang };
|
|
168
|
+
return parsed.diagram;
|
|
170
169
|
}
|
|
171
170
|
|
|
172
171
|
async function main(argv: string[]): Promise<number> {
|
|
@@ -202,9 +201,9 @@ async function main(argv: string[]): Promise<number> {
|
|
|
202
201
|
const width = number(values.width);
|
|
203
202
|
const fps = number(values.fps);
|
|
204
203
|
const gifFps = number(values["gif-fps"]);
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
const
|
|
204
|
+
// 言葉は渡した物だけで決める。渡さなければ、書き出しの既定 (日本語) になる
|
|
205
|
+
const lang = isLang(chosen) ? chosen : undefined;
|
|
206
|
+
const diagram = read(file, early, lang ?? "ja");
|
|
208
207
|
let result: Awaited<ReturnType<typeof exportDiagram>>;
|
|
209
208
|
try {
|
|
210
209
|
result = await exportDiagram(diagram, {
|
package/src/figure-text.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* dragon の入口。
|
|
3
3
|
*
|
|
4
|
-
* 図の原本は JSON
|
|
4
|
+
* 図の原本は JSON で、人は行の頭の英語の語で行の種類を決める dragon記法で書く。記法と JSON は行き来でき、
|
|
5
5
|
* JSON は JSON Schema 1 本で検査する。原本から図を描き、頁に置いて段ごとに動かす。
|
|
6
6
|
* 頁に字を読み込むのは別の入口 `@cardenelabs/dragon/fonts`。
|
|
7
7
|
*/
|
|
8
8
|
export { extractDiagrams, type Fence } from "./markdown";
|
|
9
9
|
export { type LineError, type ParseOptions, type Parsed, parseNotation } from "./parser";
|
|
10
|
-
export {
|
|
11
|
-
export {
|
|
10
|
+
export { printNotation } from "./printer";
|
|
11
|
+
export type { NotationLang } from "./words";
|
|
12
12
|
export {
|
|
13
13
|
type Box,
|
|
14
14
|
type Carry,
|
|
@@ -27,7 +27,7 @@ export {
|
|
|
27
27
|
export { FORMAT_VERSION, type Migrated, migrateFile, type Read, readDiagram } from "./version";
|
|
28
28
|
export type { Layout } from "./layout/scene";
|
|
29
29
|
export { FONTS } from "./look/fonts";
|
|
30
|
-
export { DEFAULT_PALETTE, type Palette, PALETTES, resolvePalette, type Theme } from "./look/values";
|
|
30
|
+
export { DEFAULT_PALETTE, type Palette, PALETTES, READABLE_PX, resolvePalette, type Theme } from "./look/values";
|
|
31
31
|
export { mountDiagram, type Player } from "./player";
|
|
32
32
|
export { type Rendered, type RenderOptions, renderDiagram } from "./render/svg";
|
|
33
33
|
export type { Timeline } from "./timeline";
|
package/src/look/values.ts
CHANGED
|
@@ -97,8 +97,16 @@ export const LOOK = {
|
|
|
97
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
98
|
shadow: { near: 0.8, far: 4, nearY: 1, farY: 3 },
|
|
99
99
|
mini: { w: 168, pad: 8, title: 14, inset: 12, radius: 10 },
|
|
100
|
-
/**
|
|
101
|
-
|
|
100
|
+
/**
|
|
101
|
+
* 寄って追う見せ方の窓の高さの、幅に対する割合と下限。
|
|
102
|
+
* `fitMinH` は見える高さに収める時 (#3047) の窓の高さの下限で、これより低い枠では収めずに枠の中で送る。
|
|
103
|
+
* `narrow` は縦長の全体図を出す枠の幅の下限で、これより狭い枠 (携帯の幅) では全体図を出さずに窓へ幅を渡す (#3055)。
|
|
104
|
+
* `badgeRoom` は番号の丸が窓から外れる段で窓を寄せ直す時に、丸の周りに空ける幅 (#3046)。
|
|
105
|
+
* `headRoom` は時系列図の図の頭の箱の下端から、窓に線を見せ始める所までの幅 (#3118)。
|
|
106
|
+
* `head` は時系列図の窓の上端に貼る頭の列の頭の箱で、アイコンを外した名前と下の字の 2 段 (#3120)。
|
|
107
|
+
* `pad` は頭の列の上下の余白、`h` は箱の高さ、`nameY` と `subY` は箱の上端から名前と下の字の基準線まで
|
|
108
|
+
*/
|
|
109
|
+
follow: { aspect: 0.75, minH: 320, fitMinH: 160, ease: 0.6, narrow: 440, badgeRoom: 8, headRoom: 10, head: { pad: 8, h: 40, nameY: 17, subY: 31 } },
|
|
102
110
|
/** 色を混ぜる割合 (%) */
|
|
103
111
|
mix: { icon: 14, regionIcon: 16, regionIconEdge: 34, cap: 12, capEdge: 42, badgePast: 14, badgePastEdge: 70, mini: 62, miniBand: 16, miniBandEdge: 36, view: 6 },
|
|
104
112
|
/** 字の並びの基準線を、置きたい高さの真ん中からどれだけ下げるか */
|
|
@@ -106,8 +114,12 @@ export const LOOK = {
|
|
|
106
114
|
/** 浮いて出る物が下から上がる長さと、弾んで出る物の始まりの大きさ */
|
|
107
115
|
rise: 5,
|
|
108
116
|
popFrom: 0.4,
|
|
109
|
-
/**
|
|
110
|
-
|
|
117
|
+
/**
|
|
118
|
+
* 動きを嫌わない人の頁の部品。
|
|
119
|
+
* `narrow` は段の本文の帯を横 1 列に並べる帯の中身の幅の下限で、これより狭い帯 (携帯の幅) では題と本文を釦と番号の段の下に置く (#3057、#3069)。
|
|
120
|
+
* `touch` はその狭い帯で段を送る釦の縦横で、指で押せる大きさにする (#3069)
|
|
121
|
+
*/
|
|
122
|
+
player: { gap: 10, radius: 12, button: 36, touch: 44, hidden: 1, focus: 2, narrow: 440 },
|
|
111
123
|
} as const;
|
|
112
124
|
|
|
113
125
|
/** 動きの長さ (秒)。 */
|
package/src/messages.ts
CHANGED
|
@@ -1,119 +1,197 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 記法の誤りの文 (#2997)。
|
|
2
|
+
* dragon記法の誤りの文 (#2997、#3137)。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* 文の中の記法の語は語の表から引き、表と文で語が食い違わないようにする。
|
|
4
|
+
* 記法の語は英語だけで file から言葉が決まらないため、誤りの文は呼ぶ側が渡した言葉
|
|
5
|
+
* (渡さなければ日本語) で出す。文の中の記法の語は語の表から引き、表と文で語が食い違わないようにする。
|
|
7
6
|
*/
|
|
8
7
|
import { COLORS } from "./schema";
|
|
9
|
-
import {
|
|
8
|
+
import { CARRIES, HEADS, KINDS, type NotationLang, SIDES, VIEWS } from "./words";
|
|
9
|
+
|
|
10
|
+
/** 新しい形のどの行の書き方を示すか。今の形の行に当たった時に、誤りの文が書き方を示す */
|
|
11
|
+
export type Shape = "sequence" | "architecture" | "group" | "box" | "strip" | "view" | "step" | "say" | "code" | "act" | "note" | "set";
|
|
10
12
|
|
|
11
13
|
export interface Messages {
|
|
12
14
|
noHead: string;
|
|
13
15
|
badHead: string;
|
|
16
|
+
/** 今の形の `word` を書いた行。`shape` の行の書き方を示す */
|
|
17
|
+
oldForm: (word: string, shape: Shape) => string;
|
|
18
|
+
unknownHead: (word: string) => string;
|
|
14
19
|
duplicate: (id: string) => string;
|
|
20
|
+
needsId: (word: string) => string;
|
|
21
|
+
badId: (id: string) => string;
|
|
22
|
+
afterId: string;
|
|
15
23
|
undeclaredBox: (id: string) => string;
|
|
16
24
|
noBody: (title: string) => string;
|
|
17
25
|
emptyStepTitle: string;
|
|
18
26
|
noBoxes: string;
|
|
19
27
|
noSteps: string;
|
|
20
|
-
|
|
21
|
-
|
|
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;
|
|
28
|
+
emptySay: string;
|
|
29
|
+
sayTwice: string;
|
|
30
30
|
codeTwice: string;
|
|
31
|
+
emptyCode: string;
|
|
31
32
|
declarationInStep: string;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
stepLineBeforeStep: string;
|
|
34
|
+
nestedGroup: string;
|
|
35
|
+
strayEnd: string;
|
|
36
|
+
endTakesNothing: string;
|
|
37
|
+
unclosedGroup: (id: string) => string;
|
|
38
|
+
regionReopened: (id: string) => string;
|
|
39
|
+
emptyName: (id: string) => string;
|
|
40
|
+
stripTwice: string;
|
|
41
|
+
stripShape: string;
|
|
42
|
+
emptyStripField: string;
|
|
38
43
|
stripUndeclared: string;
|
|
39
|
-
stripTagOnce: string;
|
|
40
44
|
noSuchField: (field: string) => string;
|
|
41
45
|
stripNeedsValue: string;
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
actShape: string;
|
|
47
|
+
noteShape: string;
|
|
48
|
+
edgeShape: string;
|
|
49
|
+
emptyLabel: string;
|
|
50
|
+
quoteUnclosed: string;
|
|
51
|
+
afterQuote: string;
|
|
52
|
+
attrUnclosed: string;
|
|
53
|
+
attrNoColon: (raw: string) => string;
|
|
54
|
+
attrNoValue: (key: string) => string;
|
|
55
|
+
attrTwice: (key: string) => string;
|
|
56
|
+
badAttr: (key: string, allowed: readonly string[]) => string;
|
|
57
|
+
badColor: string;
|
|
58
|
+
badView: string;
|
|
59
|
+
badCarry: string;
|
|
60
|
+
badSide: string;
|
|
61
|
+
carryTwice: string;
|
|
44
62
|
}
|
|
45
63
|
|
|
64
|
+
const list = (words: readonly string[]): string => words.join(" / ");
|
|
65
|
+
|
|
46
66
|
const ja = (): Messages => {
|
|
47
|
-
const
|
|
67
|
+
const shapes: Record<Shape, string> = {
|
|
68
|
+
sequence: "sequence <題>",
|
|
69
|
+
architecture: "architecture <題>",
|
|
70
|
+
group: "group <名札> as <名前> [note: <添え書き>] から end まで",
|
|
71
|
+
box: "box <名札> as <名前> [note: <下の小さな字>]",
|
|
72
|
+
strip: "strip <題>: <欄>, <欄>",
|
|
73
|
+
view: "sequence <題> [view: follow]",
|
|
74
|
+
step: "step <段の題>",
|
|
75
|
+
say: "say <段の本文>",
|
|
76
|
+
code: "code <命令>",
|
|
77
|
+
act: "act <名札>: <処理の名前>",
|
|
78
|
+
note: "note <名札>: <下の小さな字>",
|
|
79
|
+
set: "set <欄>: <値> [tag: <札>]",
|
|
80
|
+
};
|
|
48
81
|
return {
|
|
49
|
-
noHead: `最初の行に図の種類 (${
|
|
50
|
-
badHead: `最初の行は ${
|
|
82
|
+
noHead: `最初の行に図の種類 (${list(KINDS)}) と題を書く`,
|
|
83
|
+
badHead: `最初の行は ${KINDS.join(" か ")} で始め、続けて題を書く`,
|
|
84
|
+
oldForm: (word, shape) => `${word} は今の形の書き方。新しい形では ${shapes[shape]} と書く`,
|
|
85
|
+
unknownHead: (word) => `${word} は行の頭に書けない。行は ${list(HEADS)} か、<名札> -> <名札> で始める`,
|
|
51
86
|
duplicate: (id) => `${id} は既に宣言した名札`,
|
|
87
|
+
needsId: (word) => `${word} の後ろに名札を書く`,
|
|
88
|
+
badId: (id) => `${id} は名札に使えない。名札には空白と [ ] 「 」 = : を含めない`,
|
|
89
|
+
afterId: "名札の後ろには as <名前> か属性を書く",
|
|
52
90
|
undeclaredBox: (id) => `${id} という箱は宣言していない`,
|
|
53
|
-
noBody: (title) => `段「${title}」に本文 (
|
|
54
|
-
emptyStepTitle: "
|
|
91
|
+
noBody: (title) => `段「${title}」に本文 (say の行) が要る`,
|
|
92
|
+
emptyStepTitle: "step の後ろに段の題を書く",
|
|
55
93
|
noBoxes: "箱を 1 つ以上宣言する",
|
|
56
|
-
noSteps: "段 (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
94
|
+
noSteps: "段 (step の行) を 1 つ以上書く",
|
|
95
|
+
emptySay: "say の後ろか、その下に字下げした行に段の本文を書く",
|
|
96
|
+
sayTwice: "1 つの段に say は 1 つまで。長い本文は say の下に字下げして続ける",
|
|
97
|
+
codeTwice: "1 つの段に code は 1 行まで",
|
|
98
|
+
emptyCode: "code の後ろに命令を書く",
|
|
99
|
+
declarationInStep: "group と box と strip は最初の step より前に書く",
|
|
100
|
+
stepLineBeforeStep: "線と say と code と act と note と set は step の下に書く",
|
|
101
|
+
nestedGroup: "group の中に group は書けない。先に end で閉じる",
|
|
102
|
+
strayEnd: "end の前に、閉じる group が無い",
|
|
103
|
+
endTakesNothing: "end の後ろには何も書かない",
|
|
104
|
+
unclosedGroup: (id) => `group ${id} を end で閉じていない`,
|
|
105
|
+
regionReopened: (id) => `group ${id} は宣言済み。もう一度開く時は group ${id} だけを書き、名前と属性は最初の宣言に書く`,
|
|
63
106
|
emptyName: (id) => `${id} の名前が空`,
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
107
|
+
stripTwice: "strip は 1 つだけ宣言する",
|
|
108
|
+
stripShape: "strip は strip <題>: <欄>, <欄> の形で書く",
|
|
109
|
+
emptyStripField: "strip の欄の名前が空",
|
|
110
|
+
stripUndeclared: "set を書く前に、strip <題>: <欄>, <欄> で帯を宣言する",
|
|
111
|
+
noSuchField: (field) => `${field} という欄は strip に無い`,
|
|
112
|
+
stripNeedsValue: "set は set <欄>: <値> か set <欄> [tag: <札>] の形で書く",
|
|
113
|
+
actShape: "act は act <名札>: <処理の名前> の形で書く",
|
|
114
|
+
noteShape: "note は note <名札>: <下の小さな字> の形で書く",
|
|
115
|
+
edgeShape: "線は <名札> -> <名札>: <線の名前> [<属性>] の形で書く",
|
|
116
|
+
emptyLabel: "線の : の後ろに線の名前を書く。名前を書かない時は : も書かない",
|
|
117
|
+
quoteUnclosed: '" で始めた字を " で閉じていない',
|
|
118
|
+
afterQuote: '" で閉じた字の後ろには、属性か次の , だけを書く',
|
|
119
|
+
attrUnclosed: "属性は [ で始めて ] で閉じ、行の終わりに置く",
|
|
120
|
+
attrNoColon: (raw) => `[${raw}] は書けない。属性は [<鍵>: <値>] の形で書く`,
|
|
121
|
+
attrNoValue: (key) => `${key}: の後ろに値を書く`,
|
|
122
|
+
attrTwice: (key) => `${key} は 1 つの行に 1 つまで`,
|
|
123
|
+
badAttr: (key, allowed) => `${key} はこの行に書けない属性。書けるのは ${list(allowed)}`,
|
|
124
|
+
badColor: `color は ${list(COLORS)} のどれか`,
|
|
125
|
+
badView: `view は ${list(VIEWS)} のどれか`,
|
|
126
|
+
badCarry: `carry は ${list(CARRIES)} のどれか。札は tag: <値> で書く`,
|
|
127
|
+
badSide: `side は ${list(SIDES)} のどれか`,
|
|
128
|
+
carryTwice: "運ぶ物は 1 本の線に 1 つまで。carry と tag は一緒に書かない",
|
|
80
129
|
};
|
|
81
130
|
};
|
|
82
131
|
|
|
83
132
|
const en = (): Messages => {
|
|
84
|
-
const
|
|
133
|
+
const shapes: Record<Shape, string> = {
|
|
134
|
+
sequence: "sequence <title>",
|
|
135
|
+
architecture: "architecture <title>",
|
|
136
|
+
group: "group <id> as <name> [note: <note>] through end",
|
|
137
|
+
box: "box <id> as <name> [note: <caption>]",
|
|
138
|
+
strip: "strip <title>: <field>, <field>",
|
|
139
|
+
view: "sequence <title> [view: follow]",
|
|
140
|
+
step: "step <step title>",
|
|
141
|
+
say: "say <step body>",
|
|
142
|
+
code: "code <command>",
|
|
143
|
+
act: "act <id>: <action>",
|
|
144
|
+
note: "note <id>: <caption>",
|
|
145
|
+
set: "set <field>: <value> [tag: <tag>]",
|
|
146
|
+
};
|
|
85
147
|
return {
|
|
86
|
-
noHead: `Write the diagram kind (${
|
|
87
|
-
badHead: `Start the first line with ${
|
|
148
|
+
noHead: `Write the diagram kind (${list(KINDS)}) and a title on the first line`,
|
|
149
|
+
badHead: `Start the first line with ${KINDS.join(" or ")}, followed by the title`,
|
|
150
|
+
oldForm: (word, shape) => `${word} is the old notation. Write ${shapes[shape]} instead`,
|
|
151
|
+
unknownHead: (word) => `A line cannot start with ${word}. Start a line with ${list(HEADS)}, or <id> -> <id>`,
|
|
88
152
|
duplicate: (id) => `${id} is already declared`,
|
|
153
|
+
needsId: (word) => `Write an id after ${word}`,
|
|
154
|
+
badId: (id) => `${id} cannot be an id. An id has no spaces and none of [ ] 「 」 = :`,
|
|
155
|
+
afterId: "Write as <name> or attributes after the id",
|
|
89
156
|
undeclaredBox: (id) => `No box named ${id} is declared`,
|
|
90
|
-
noBody: (title) => `Step "${title}" needs a body (a line
|
|
91
|
-
emptyStepTitle: "Write a title after
|
|
157
|
+
noBody: (title) => `Step "${title}" needs a body (a say line)`,
|
|
158
|
+
emptyStepTitle: "Write a title after step",
|
|
92
159
|
noBoxes: "Declare at least one box",
|
|
93
|
-
noSteps: "Write at least one step (a line
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
160
|
+
noSteps: "Write at least one step (a step line)",
|
|
161
|
+
emptySay: "Write the step body after say, or on indented lines below it",
|
|
162
|
+
sayTwice: "A step takes one say. Continue a long body on indented lines below it",
|
|
163
|
+
codeTwice: "A step takes at most one code line",
|
|
164
|
+
emptyCode: "Write the command after code",
|
|
165
|
+
declarationInStep: "Write group, box and strip before the first step",
|
|
166
|
+
stepLineBeforeStep: "Write lines, say, code, act, note and set under a step",
|
|
167
|
+
nestedGroup: "A group cannot hold another group. Close it with end first",
|
|
168
|
+
strayEnd: "There is no group for this end to close",
|
|
169
|
+
endTakesNothing: "Write nothing after end",
|
|
170
|
+
unclosedGroup: (id) => `group ${id} is not closed with end`,
|
|
171
|
+
regionReopened: (id) => `group ${id} is already declared. To open it again, write only group ${id}; put the name and attributes on the first one`,
|
|
100
172
|
emptyName: (id) => `${id} has an empty name`,
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
173
|
+
stripTwice: "Declare only one strip",
|
|
174
|
+
stripShape: "Write a strip as strip <title>: <field>, <field>",
|
|
175
|
+
emptyStripField: "A strip field name is empty",
|
|
176
|
+
stripUndeclared: "Declare the strip as strip <title>: <field>, <field> before writing set",
|
|
177
|
+
noSuchField: (field) => `The strip has no field named ${field}`,
|
|
178
|
+
stripNeedsValue: "Write set as set <field>: <value> or set <field> [tag: <tag>]",
|
|
179
|
+
actShape: "Write act as act <id>: <action>",
|
|
180
|
+
noteShape: "Write note as note <id>: <caption>",
|
|
181
|
+
edgeShape: "Write a line as <id> -> <id>: <label> [<attributes>]",
|
|
182
|
+
emptyLabel: "Write the label after the : of a line, or leave out the : as well",
|
|
183
|
+
quoteUnclosed: 'A value that starts with " is not closed with "',
|
|
184
|
+
afterQuote: 'After a value closed with ", write only attributes or the next ,',
|
|
185
|
+
attrUnclosed: "Start attributes with [, close them with ], and put them at the end of the line",
|
|
186
|
+
attrNoColon: (raw) => `[${raw}] cannot be read. Write an attribute as [<key>: <value>]`,
|
|
187
|
+
attrNoValue: (key) => `Write a value after ${key}:`,
|
|
188
|
+
attrTwice: (key) => `Write ${key} only once on a line`,
|
|
189
|
+
badAttr: (key, allowed) => `${key} cannot be written on this line. Write ${list(allowed)}`,
|
|
190
|
+
badColor: `color is one of ${list(COLORS)}`,
|
|
191
|
+
badView: `view is one of ${list(VIEWS)}`,
|
|
192
|
+
badCarry: `carry is one of ${list(CARRIES)}. Write a tag as tag: <value>`,
|
|
193
|
+
badSide: `side is one of ${list(SIDES)}`,
|
|
194
|
+
carryTwice: "A line carries one thing. Do not write carry and tag together",
|
|
117
195
|
};
|
|
118
196
|
};
|
|
119
197
|
|