@saykit/config 0.6.0 → 0.6.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.
@@ -1,54 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_hash = require("../../hash-51ce8YiG.cjs");
3
- //#region src/features/messages/identifier.ts
4
- const AUTO_INCREMENT_IDENTIFIER = Symbol("auto-increment");
5
- function assignSequenceIdentifiers(message, sequence = { current: 0 }, equivalent = () => false) {
6
- const reserved = collectAssignedIdentifiers(message, equivalent);
7
- function next() {
8
- let identifier = `${sequence.current++}`;
9
- while (reserved.has(identifier)) identifier = `${sequence.current++}`;
10
- return identifier;
11
- }
12
- function walk(message) {
13
- if (message instanceof ArgumentMessage || message instanceof ElementMessage || message instanceof ChoiceMessage) {
14
- if (message.identifier === AUTO_INCREMENT_IDENTIFIER) message.identifier = next();
15
- }
16
- if (message instanceof CompositeMessage || message instanceof ElementMessage) for (const child of message.children) walk(child);
17
- if (message instanceof ChoiceMessage) for (const branch of message.branches) {
18
- if (branch.identifier === AUTO_INCREMENT_IDENTIFIER) branch.identifier = next();
19
- walk(branch.value);
20
- }
21
- }
22
- walk(message);
23
- }
24
- /**
25
- * Collect the identifiers already assigned before this pass runs, so generated
26
- * sequence numbers never shadow an explicit one (e.g. an element tagged `0`).
27
- *
28
- * A name is claimed by what produced it, not by the name alone. Two that differ
29
- * each compile to their own prop, and a translator moving them around a sentence
30
- * has to be able to tell them apart, so they are a build error. Repeats are fine
31
- * when nothing distinguishes them: the same variable interpolated twice is one
32
- * value, and two identical elements are one tag.
33
- */
34
- function collectAssignedIdentifiers(message, equivalent) {
35
- const tags = /* @__PURE__ */ new Map();
36
- const values = /* @__PURE__ */ new Map();
37
- function claim(claimed, identifier, expression, conflict) {
38
- if (claimed.has(identifier) && !equivalent(claimed.get(identifier), expression)) throw new Error(conflict);
39
- claimed.set(identifier, expression);
40
- }
41
- function walk(message) {
42
- if (message instanceof ElementMessage && typeof message.identifier === "string") claim(tags, message.identifier, message.expression, `Duplicate element tag '${message.identifier}', give each element in a message its own tag unless they are identical`);
43
- if ((message instanceof ArgumentMessage || message instanceof ChoiceMessage) && typeof message.identifier === "string") claim(values, message.identifier, message.expression, `Duplicate placeholder name '${message.identifier}', give each value in a message its own name unless they are identical`);
44
- if (message instanceof CompositeMessage || message instanceof ElementMessage) for (const child of message.children) walk(child);
45
- if (message instanceof ChoiceMessage) for (const branch of message.branches) walk(branch.value);
46
- }
47
- walk(message);
48
- for (const tag of tags.keys()) if (values.has(tag)) throw new Error(`Element tag '${tag}' collides with an argument of the same name`);
49
- return /* @__PURE__ */ new Set([...tags.keys(), ...values.keys()]);
50
- }
51
- //#endregion
52
3
  //#region src/features/messages/types.ts
53
4
  var Base = class {
54
5
  toICUString() {
@@ -117,6 +68,103 @@ var CompositeMessage = class extends Base {
117
68
  }
118
69
  };
119
70
  //#endregion
71
+ //#region src/features/messages/identifier.ts
72
+ const AUTO_INCREMENT_IDENTIFIER = Symbol("auto-increment");
73
+ /**
74
+ * An ICU case, either an exact value or a key. ICU reserves its own pattern
75
+ * syntax, so a key carries no punctuation and no whitespace.
76
+ */
77
+ const BRANCH_PATTERN = /^(?:=\d+|[^\p{Pattern_Syntax}\p{Pattern_White_Space}]+)$/u;
78
+ /**
79
+ * The ICU case a branch is written as. A number names an exact value rather
80
+ * than a key, and only `plural` and `ordinal` are allowed to select on one.
81
+ *
82
+ * Digits are read literally rather than coerced, because everything JavaScript
83
+ * is willing to call a number is not: `''`, `' '`, and `'+0'` all coerce to
84
+ * `=0`, which would pass for a key that selects zero and quietly leave the
85
+ * author's own key out of the catalogue. Anything else stays a key, where the
86
+ * whitespace or punctuation that made it numeric-looking is caught.
87
+ */
88
+ function getBranchCase(identifier) {
89
+ const key = String(identifier);
90
+ return /^\d+$/u.test(key) ? `=${+key}` : key;
91
+ }
92
+ /**
93
+ * Reject a branch key ICU cannot express, while the key is still attached to a
94
+ * file and a line.
95
+ *
96
+ * A hyphenated string union is ordinary application code and typechecks,
97
+ * builds, and extracts to a catalogue entry that looks perfectly normal — the
98
+ * only sign of trouble is a parse error at format time, in a message whose
99
+ * source is long gone.
100
+ */
101
+ function validateBranchIdentifier(kind, identifier) {
102
+ if (typeof identifier !== "string") return;
103
+ const branch = getBranchCase(identifier);
104
+ if (!BRANCH_PATTERN.test(branch)) {
105
+ const suggestion = suggestBranchIdentifier(identifier);
106
+ throw new Error(`Invalid ${kind} branch key '${identifier}', an ICU key cannot contain punctuation or whitespace` + (suggestion ? `, try '${suggestion}'` : ""));
107
+ }
108
+ if (kind === "select" && branch.startsWith("=")) throw new Error(`Invalid select branch key '${identifier}', a number selects an exact value, which only 'plural' and 'ordinal' accept`);
109
+ }
110
+ /**
111
+ * The nearest identifier-safe form of a key, so the error names the fix as well
112
+ * as the problem. The constraint comes from ICU rather than from anything the
113
+ * author wrote, and camel case is how the rest of the codebase already spells a
114
+ * name of more than one word.
115
+ */
116
+ function suggestBranchIdentifier(identifier) {
117
+ const suggestion = identifier.split(/[^\p{L}\p{N}]+/u).filter(Boolean).map((word, index) => index === 0 ? word : word[0].toUpperCase() + word.slice(1)).join("");
118
+ if (!BRANCH_PATTERN.test(suggestion) || !Number.isNaN(+suggestion)) return void 0;
119
+ return suggestion;
120
+ }
121
+ function assignSequenceIdentifiers(message, sequence = { current: 0 }, equivalent = () => false) {
122
+ const reserved = collectAssignedIdentifiers(message, equivalent);
123
+ function next() {
124
+ let identifier = `${sequence.current++}`;
125
+ while (reserved.has(identifier)) identifier = `${sequence.current++}`;
126
+ return identifier;
127
+ }
128
+ function walk(message) {
129
+ if (message instanceof ArgumentMessage || message instanceof ElementMessage || message instanceof ChoiceMessage) {
130
+ if (message.identifier === AUTO_INCREMENT_IDENTIFIER) message.identifier = next();
131
+ }
132
+ if (message instanceof CompositeMessage || message instanceof ElementMessage) for (const child of message.children) walk(child);
133
+ if (message instanceof ChoiceMessage) for (const branch of message.branches) {
134
+ if (branch.identifier === AUTO_INCREMENT_IDENTIFIER) branch.identifier = next();
135
+ walk(branch.value);
136
+ }
137
+ }
138
+ walk(message);
139
+ }
140
+ /**
141
+ * Collect the identifiers already assigned before this pass runs, so generated
142
+ * sequence numbers never shadow an explicit one (e.g. an element tagged `0`).
143
+ *
144
+ * A name is claimed by what produced it, not by the name alone. Two that differ
145
+ * each compile to their own prop, and a translator moving them around a sentence
146
+ * has to be able to tell them apart, so they are a build error. Repeats are fine
147
+ * when nothing distinguishes them: the same variable interpolated twice is one
148
+ * value, and two identical elements are one tag.
149
+ */
150
+ function collectAssignedIdentifiers(message, equivalent) {
151
+ const tags = /* @__PURE__ */ new Map();
152
+ const values = /* @__PURE__ */ new Map();
153
+ function claim(claimed, identifier, expression, conflict) {
154
+ if (claimed.has(identifier) && !equivalent(claimed.get(identifier), expression)) throw new Error(conflict);
155
+ claimed.set(identifier, expression);
156
+ }
157
+ function walk(message) {
158
+ if (message instanceof ElementMessage && typeof message.identifier === "string") claim(tags, message.identifier, message.expression, `Duplicate element tag '${message.identifier}', give each element in a message its own tag unless they are identical`);
159
+ if ((message instanceof ArgumentMessage || message instanceof ChoiceMessage) && typeof message.identifier === "string") claim(values, message.identifier, message.expression, `Duplicate placeholder name '${message.identifier}', give each value in a message its own name unless they are identical`);
160
+ if (message instanceof CompositeMessage || message instanceof ElementMessage) for (const child of message.children) walk(child);
161
+ if (message instanceof ChoiceMessage) for (const branch of message.branches) walk(branch.value);
162
+ }
163
+ walk(message);
164
+ for (const tag of tags.keys()) if (values.has(tag)) throw new Error(`Element tag '${tag}' collides with an argument of the same name`);
165
+ return /* @__PURE__ */ new Set([...tags.keys(), ...values.keys()]);
166
+ }
167
+ //#endregion
120
168
  //#region src/features/messages/convert.ts
121
169
  function convertMessageToIcu(message) {
122
170
  function internalConvertMessageToIcu(message) {
@@ -130,7 +178,7 @@ function convertMessageToIcu(message) {
130
178
  }
131
179
  case message instanceof ChoiceMessage: {
132
180
  const branches = message.branches.map(({ identifier, value }) => ({
133
- identifier: Number.isNaN(+String(identifier)) ? String(identifier) : `=${+String(identifier)}`,
181
+ identifier: getBranchCase(identifier),
134
182
  value: internalConvertMessageToIcu(value)
135
183
  })).map(({ identifier, value }) => ` ${identifier} {${value}}\n`).join("");
136
184
  const format = message.kind === "ordinal" ? "selectordinal" : message.kind;
@@ -152,3 +200,5 @@ exports.LiteralMessage = LiteralMessage;
152
200
  exports.assignSequenceIdentifiers = assignSequenceIdentifiers;
153
201
  exports.convertMessageToIcu = convertMessageToIcu;
154
202
  exports.generateHash = require_hash.generateHash;
203
+ exports.getBranchCase = getBranchCase;
204
+ exports.validateBranchIdentifier = validateBranchIdentifier;
@@ -1,5 +1,26 @@
1
1
  //#region src/features/messages/identifier.d.ts
2
2
  declare const AUTO_INCREMENT_IDENTIFIER: unique symbol;
3
+ /**
4
+ * The ICU case a branch is written as. A number names an exact value rather
5
+ * than a key, and only `plural` and `ordinal` are allowed to select on one.
6
+ *
7
+ * Digits are read literally rather than coerced, because everything JavaScript
8
+ * is willing to call a number is not: `''`, `' '`, and `'+0'` all coerce to
9
+ * `=0`, which would pass for a key that selects zero and quietly leave the
10
+ * author's own key out of the catalogue. Anything else stays a key, where the
11
+ * whitespace or punctuation that made it numeric-looking is caught.
12
+ */
13
+ declare function getBranchCase(identifier: string | typeof AUTO_INCREMENT_IDENTIFIER): string;
14
+ /**
15
+ * Reject a branch key ICU cannot express, while the key is still attached to a
16
+ * file and a line.
17
+ *
18
+ * A hyphenated string union is ordinary application code and typechecks,
19
+ * builds, and extracts to a catalogue entry that looks perfectly normal — the
20
+ * only sign of trouble is a parse error at format time, in a message whose
21
+ * source is long gone.
22
+ */
23
+ declare function validateBranchIdentifier(kind: string, identifier: string | typeof AUTO_INCREMENT_IDENTIFIER): void;
3
24
  /**
4
25
  * Decides whether two placeholders sharing a name are the same placeholder, and
5
26
  * so may share it. Only the syntax that produced them can answer that, so the
@@ -66,4 +87,4 @@ declare function convertMessageToIcu(message: Message): string;
66
87
  //#region src/features/messages/hash.d.ts
67
88
  declare function generateHash(input: string, context?: string): string;
68
89
  //#endregion
69
- export { AUTO_INCREMENT_IDENTIFIER, ArgumentMessage, ChoiceMessage, CompositeMessage, ElementMessage, LiteralMessage, Message, PlaceholderEquivalence, assignSequenceIdentifiers, convertMessageToIcu, generateHash };
90
+ export { AUTO_INCREMENT_IDENTIFIER, ArgumentMessage, ChoiceMessage, CompositeMessage, ElementMessage, LiteralMessage, Message, PlaceholderEquivalence, assignSequenceIdentifiers, convertMessageToIcu, generateHash, getBranchCase, validateBranchIdentifier };
@@ -1,5 +1,26 @@
1
1
  //#region src/features/messages/identifier.d.ts
2
2
  declare const AUTO_INCREMENT_IDENTIFIER: unique symbol;
3
+ /**
4
+ * The ICU case a branch is written as. A number names an exact value rather
5
+ * than a key, and only `plural` and `ordinal` are allowed to select on one.
6
+ *
7
+ * Digits are read literally rather than coerced, because everything JavaScript
8
+ * is willing to call a number is not: `''`, `' '`, and `'+0'` all coerce to
9
+ * `=0`, which would pass for a key that selects zero and quietly leave the
10
+ * author's own key out of the catalogue. Anything else stays a key, where the
11
+ * whitespace or punctuation that made it numeric-looking is caught.
12
+ */
13
+ declare function getBranchCase(identifier: string | typeof AUTO_INCREMENT_IDENTIFIER): string;
14
+ /**
15
+ * Reject a branch key ICU cannot express, while the key is still attached to a
16
+ * file and a line.
17
+ *
18
+ * A hyphenated string union is ordinary application code and typechecks,
19
+ * builds, and extracts to a catalogue entry that looks perfectly normal — the
20
+ * only sign of trouble is a parse error at format time, in a message whose
21
+ * source is long gone.
22
+ */
23
+ declare function validateBranchIdentifier(kind: string, identifier: string | typeof AUTO_INCREMENT_IDENTIFIER): void;
3
24
  /**
4
25
  * Decides whether two placeholders sharing a name are the same placeholder, and
5
26
  * so may share it. Only the syntax that produced them can answer that, so the
@@ -66,4 +87,4 @@ declare function convertMessageToIcu(message: Message): string;
66
87
  //#region src/features/messages/hash.d.ts
67
88
  declare function generateHash(input: string, context?: string): string;
68
89
  //#endregion
69
- export { AUTO_INCREMENT_IDENTIFIER, ArgumentMessage, ChoiceMessage, CompositeMessage, ElementMessage, LiteralMessage, Message, PlaceholderEquivalence, assignSequenceIdentifiers, convertMessageToIcu, generateHash };
90
+ export { AUTO_INCREMENT_IDENTIFIER, ArgumentMessage, ChoiceMessage, CompositeMessage, ElementMessage, LiteralMessage, Message, PlaceholderEquivalence, assignSequenceIdentifiers, convertMessageToIcu, generateHash, getBranchCase, validateBranchIdentifier };
@@ -1,53 +1,4 @@
1
1
  import { t as generateHash } from "../../hash-DvzpieJD.mjs";
2
- //#region src/features/messages/identifier.ts
3
- const AUTO_INCREMENT_IDENTIFIER = Symbol("auto-increment");
4
- function assignSequenceIdentifiers(message, sequence = { current: 0 }, equivalent = () => false) {
5
- const reserved = collectAssignedIdentifiers(message, equivalent);
6
- function next() {
7
- let identifier = `${sequence.current++}`;
8
- while (reserved.has(identifier)) identifier = `${sequence.current++}`;
9
- return identifier;
10
- }
11
- function walk(message) {
12
- if (message instanceof ArgumentMessage || message instanceof ElementMessage || message instanceof ChoiceMessage) {
13
- if (message.identifier === AUTO_INCREMENT_IDENTIFIER) message.identifier = next();
14
- }
15
- if (message instanceof CompositeMessage || message instanceof ElementMessage) for (const child of message.children) walk(child);
16
- if (message instanceof ChoiceMessage) for (const branch of message.branches) {
17
- if (branch.identifier === AUTO_INCREMENT_IDENTIFIER) branch.identifier = next();
18
- walk(branch.value);
19
- }
20
- }
21
- walk(message);
22
- }
23
- /**
24
- * Collect the identifiers already assigned before this pass runs, so generated
25
- * sequence numbers never shadow an explicit one (e.g. an element tagged `0`).
26
- *
27
- * A name is claimed by what produced it, not by the name alone. Two that differ
28
- * each compile to their own prop, and a translator moving them around a sentence
29
- * has to be able to tell them apart, so they are a build error. Repeats are fine
30
- * when nothing distinguishes them: the same variable interpolated twice is one
31
- * value, and two identical elements are one tag.
32
- */
33
- function collectAssignedIdentifiers(message, equivalent) {
34
- const tags = /* @__PURE__ */ new Map();
35
- const values = /* @__PURE__ */ new Map();
36
- function claim(claimed, identifier, expression, conflict) {
37
- if (claimed.has(identifier) && !equivalent(claimed.get(identifier), expression)) throw new Error(conflict);
38
- claimed.set(identifier, expression);
39
- }
40
- function walk(message) {
41
- if (message instanceof ElementMessage && typeof message.identifier === "string") claim(tags, message.identifier, message.expression, `Duplicate element tag '${message.identifier}', give each element in a message its own tag unless they are identical`);
42
- if ((message instanceof ArgumentMessage || message instanceof ChoiceMessage) && typeof message.identifier === "string") claim(values, message.identifier, message.expression, `Duplicate placeholder name '${message.identifier}', give each value in a message its own name unless they are identical`);
43
- if (message instanceof CompositeMessage || message instanceof ElementMessage) for (const child of message.children) walk(child);
44
- if (message instanceof ChoiceMessage) for (const branch of message.branches) walk(branch.value);
45
- }
46
- walk(message);
47
- for (const tag of tags.keys()) if (values.has(tag)) throw new Error(`Element tag '${tag}' collides with an argument of the same name`);
48
- return /* @__PURE__ */ new Set([...tags.keys(), ...values.keys()]);
49
- }
50
- //#endregion
51
2
  //#region src/features/messages/types.ts
52
3
  var Base = class {
53
4
  toICUString() {
@@ -116,6 +67,103 @@ var CompositeMessage = class extends Base {
116
67
  }
117
68
  };
118
69
  //#endregion
70
+ //#region src/features/messages/identifier.ts
71
+ const AUTO_INCREMENT_IDENTIFIER = Symbol("auto-increment");
72
+ /**
73
+ * An ICU case, either an exact value or a key. ICU reserves its own pattern
74
+ * syntax, so a key carries no punctuation and no whitespace.
75
+ */
76
+ const BRANCH_PATTERN = /^(?:=\d+|[^\p{Pattern_Syntax}\p{Pattern_White_Space}]+)$/u;
77
+ /**
78
+ * The ICU case a branch is written as. A number names an exact value rather
79
+ * than a key, and only `plural` and `ordinal` are allowed to select on one.
80
+ *
81
+ * Digits are read literally rather than coerced, because everything JavaScript
82
+ * is willing to call a number is not: `''`, `' '`, and `'+0'` all coerce to
83
+ * `=0`, which would pass for a key that selects zero and quietly leave the
84
+ * author's own key out of the catalogue. Anything else stays a key, where the
85
+ * whitespace or punctuation that made it numeric-looking is caught.
86
+ */
87
+ function getBranchCase(identifier) {
88
+ const key = String(identifier);
89
+ return /^\d+$/u.test(key) ? `=${+key}` : key;
90
+ }
91
+ /**
92
+ * Reject a branch key ICU cannot express, while the key is still attached to a
93
+ * file and a line.
94
+ *
95
+ * A hyphenated string union is ordinary application code and typechecks,
96
+ * builds, and extracts to a catalogue entry that looks perfectly normal — the
97
+ * only sign of trouble is a parse error at format time, in a message whose
98
+ * source is long gone.
99
+ */
100
+ function validateBranchIdentifier(kind, identifier) {
101
+ if (typeof identifier !== "string") return;
102
+ const branch = getBranchCase(identifier);
103
+ if (!BRANCH_PATTERN.test(branch)) {
104
+ const suggestion = suggestBranchIdentifier(identifier);
105
+ throw new Error(`Invalid ${kind} branch key '${identifier}', an ICU key cannot contain punctuation or whitespace` + (suggestion ? `, try '${suggestion}'` : ""));
106
+ }
107
+ if (kind === "select" && branch.startsWith("=")) throw new Error(`Invalid select branch key '${identifier}', a number selects an exact value, which only 'plural' and 'ordinal' accept`);
108
+ }
109
+ /**
110
+ * The nearest identifier-safe form of a key, so the error names the fix as well
111
+ * as the problem. The constraint comes from ICU rather than from anything the
112
+ * author wrote, and camel case is how the rest of the codebase already spells a
113
+ * name of more than one word.
114
+ */
115
+ function suggestBranchIdentifier(identifier) {
116
+ const suggestion = identifier.split(/[^\p{L}\p{N}]+/u).filter(Boolean).map((word, index) => index === 0 ? word : word[0].toUpperCase() + word.slice(1)).join("");
117
+ if (!BRANCH_PATTERN.test(suggestion) || !Number.isNaN(+suggestion)) return void 0;
118
+ return suggestion;
119
+ }
120
+ function assignSequenceIdentifiers(message, sequence = { current: 0 }, equivalent = () => false) {
121
+ const reserved = collectAssignedIdentifiers(message, equivalent);
122
+ function next() {
123
+ let identifier = `${sequence.current++}`;
124
+ while (reserved.has(identifier)) identifier = `${sequence.current++}`;
125
+ return identifier;
126
+ }
127
+ function walk(message) {
128
+ if (message instanceof ArgumentMessage || message instanceof ElementMessage || message instanceof ChoiceMessage) {
129
+ if (message.identifier === AUTO_INCREMENT_IDENTIFIER) message.identifier = next();
130
+ }
131
+ if (message instanceof CompositeMessage || message instanceof ElementMessage) for (const child of message.children) walk(child);
132
+ if (message instanceof ChoiceMessage) for (const branch of message.branches) {
133
+ if (branch.identifier === AUTO_INCREMENT_IDENTIFIER) branch.identifier = next();
134
+ walk(branch.value);
135
+ }
136
+ }
137
+ walk(message);
138
+ }
139
+ /**
140
+ * Collect the identifiers already assigned before this pass runs, so generated
141
+ * sequence numbers never shadow an explicit one (e.g. an element tagged `0`).
142
+ *
143
+ * A name is claimed by what produced it, not by the name alone. Two that differ
144
+ * each compile to their own prop, and a translator moving them around a sentence
145
+ * has to be able to tell them apart, so they are a build error. Repeats are fine
146
+ * when nothing distinguishes them: the same variable interpolated twice is one
147
+ * value, and two identical elements are one tag.
148
+ */
149
+ function collectAssignedIdentifiers(message, equivalent) {
150
+ const tags = /* @__PURE__ */ new Map();
151
+ const values = /* @__PURE__ */ new Map();
152
+ function claim(claimed, identifier, expression, conflict) {
153
+ if (claimed.has(identifier) && !equivalent(claimed.get(identifier), expression)) throw new Error(conflict);
154
+ claimed.set(identifier, expression);
155
+ }
156
+ function walk(message) {
157
+ if (message instanceof ElementMessage && typeof message.identifier === "string") claim(tags, message.identifier, message.expression, `Duplicate element tag '${message.identifier}', give each element in a message its own tag unless they are identical`);
158
+ if ((message instanceof ArgumentMessage || message instanceof ChoiceMessage) && typeof message.identifier === "string") claim(values, message.identifier, message.expression, `Duplicate placeholder name '${message.identifier}', give each value in a message its own name unless they are identical`);
159
+ if (message instanceof CompositeMessage || message instanceof ElementMessage) for (const child of message.children) walk(child);
160
+ if (message instanceof ChoiceMessage) for (const branch of message.branches) walk(branch.value);
161
+ }
162
+ walk(message);
163
+ for (const tag of tags.keys()) if (values.has(tag)) throw new Error(`Element tag '${tag}' collides with an argument of the same name`);
164
+ return /* @__PURE__ */ new Set([...tags.keys(), ...values.keys()]);
165
+ }
166
+ //#endregion
119
167
  //#region src/features/messages/convert.ts
120
168
  function convertMessageToIcu(message) {
121
169
  function internalConvertMessageToIcu(message) {
@@ -129,7 +177,7 @@ function convertMessageToIcu(message) {
129
177
  }
130
178
  case message instanceof ChoiceMessage: {
131
179
  const branches = message.branches.map(({ identifier, value }) => ({
132
- identifier: Number.isNaN(+String(identifier)) ? String(identifier) : `=${+String(identifier)}`,
180
+ identifier: getBranchCase(identifier),
133
181
  value: internalConvertMessageToIcu(value)
134
182
  })).map(({ identifier, value }) => ` ${identifier} {${value}}\n`).join("");
135
183
  const format = message.kind === "ordinal" ? "selectordinal" : message.kind;
@@ -142,4 +190,4 @@ function convertMessageToIcu(message) {
142
190
  return internalConvertMessageToIcu(message).trim();
143
191
  }
144
192
  //#endregion
145
- export { AUTO_INCREMENT_IDENTIFIER, ArgumentMessage, ChoiceMessage, CompositeMessage, ElementMessage, LiteralMessage, assignSequenceIdentifiers, convertMessageToIcu, generateHash };
193
+ export { AUTO_INCREMENT_IDENTIFIER, ArgumentMessage, ChoiceMessage, CompositeMessage, ElementMessage, LiteralMessage, assignSequenceIdentifiers, convertMessageToIcu, generateHash, getBranchCase, validateBranchIdentifier };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saykit/config",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "CLI and configuration tooling for saykit",
5
5
  "keywords": [
6
6
  "cli",