@intlify/message-compiler 12.0.0-alpha.2 → 12.0.0-alpha.4

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,1520 +1,1256 @@
1
- /*!
2
- * message-compiler v12.0.0-alpha.2
3
- * (c) 2016-present kazuya kawaguchi and contributors
4
- * Released under the MIT License.
5
- */
6
- import { format, isString, join, assign } from '@intlify/shared';
7
-
1
+ /**
2
+ * @intlify/message-compiler v12.0.0-alpha.4
3
+ * (c) 2016-present kazuya kawaguchi and contributors
4
+ * @license MIT
5
+ **/
6
+ import { assign, format, isString, join } from "@intlify/shared";
7
+ //#region packages/message-compiler/src/nodes.ts
8
+ let NodeTypes = /* @__PURE__ */ function(NodeTypes) {
9
+ NodeTypes[NodeTypes["Resource"] = 0] = "Resource";
10
+ NodeTypes[NodeTypes["Plural"] = 1] = "Plural";
11
+ NodeTypes[NodeTypes["Message"] = 2] = "Message";
12
+ NodeTypes[NodeTypes["Text"] = 3] = "Text";
13
+ NodeTypes[NodeTypes["Named"] = 4] = "Named";
14
+ NodeTypes[NodeTypes["List"] = 5] = "List";
15
+ NodeTypes[NodeTypes["Linked"] = 6] = "Linked";
16
+ NodeTypes[NodeTypes["LinkedKey"] = 7] = "LinkedKey";
17
+ NodeTypes[NodeTypes["LinkedModifier"] = 8] = "LinkedModifier";
18
+ NodeTypes[NodeTypes["Literal"] = 9] = "Literal";
19
+ return NodeTypes;
20
+ }({});
21
+ //#endregion
22
+ //#region packages/message-compiler/src/location.ts
8
23
  const LOCATION_STUB = {
9
- start: { line: 1, column: 1, offset: 0 },
10
- end: { line: 1, column: 1, offset: 0 }
24
+ start: {
25
+ line: 1,
26
+ column: 1,
27
+ offset: 0
28
+ },
29
+ end: {
30
+ line: 1,
31
+ column: 1,
32
+ offset: 0
33
+ }
11
34
  };
12
35
  function createPosition(line, column, offset) {
13
- return { line, column, offset };
36
+ return {
37
+ line,
38
+ column,
39
+ offset
40
+ };
14
41
  }
15
42
  function createLocation(start, end, source) {
16
- const loc = { start, end };
17
- if (source != null) {
18
- loc.source = source;
19
- }
20
- return loc;
43
+ const loc = {
44
+ start,
45
+ end
46
+ };
47
+ if (source != null) loc.source = source;
48
+ return loc;
21
49
  }
22
-
50
+ //#endregion
51
+ //#region packages/message-compiler/src/helpers.ts
52
+ let HelperNameMap = /* @__PURE__ */ function(HelperNameMap) {
53
+ HelperNameMap["LIST"] = "list";
54
+ HelperNameMap["NAMED"] = "named";
55
+ HelperNameMap["PLURAL"] = "plural";
56
+ HelperNameMap["LINKED"] = "linked";
57
+ HelperNameMap["MESSAGE"] = "message";
58
+ HelperNameMap["TYPE"] = "type";
59
+ HelperNameMap["INTERPOLATE"] = "interpolate";
60
+ HelperNameMap["NORMALIZE"] = "normalize";
61
+ HelperNameMap["VALUES"] = "values";
62
+ return HelperNameMap;
63
+ }({});
64
+ const RE_HTML_TAG = /<[\w\s=":;#-/]+>/;
65
+ const detectHtmlTag = (source) => RE_HTML_TAG.test(source);
66
+ //#endregion
67
+ //#region packages/message-compiler/src/errors.ts
23
68
  const CompileErrorCodes = {
24
- // tokenizer error codes
25
- EXPECTED_TOKEN: 1,
26
- INVALID_TOKEN_IN_PLACEHOLDER: 2,
27
- UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER: 3,
28
- UNKNOWN_ESCAPE_SEQUENCE: 4,
29
- INVALID_UNICODE_ESCAPE_SEQUENCE: 5,
30
- UNBALANCED_CLOSING_BRACE: 6,
31
- UNTERMINATED_CLOSING_BRACE: 7,
32
- EMPTY_PLACEHOLDER: 8,
33
- NOT_ALLOW_NEST_PLACEHOLDER: 9,
34
- INVALID_LINKED_FORMAT: 10,
35
- // parser error codes
36
- MUST_HAVE_MESSAGES_IN_PLURAL: 11,
37
- UNEXPECTED_EMPTY_LINKED_MODIFIER: 12,
38
- UNEXPECTED_EMPTY_LINKED_KEY: 13,
39
- UNEXPECTED_LEXICAL_ANALYSIS: 14,
40
- // generator error codes
41
- UNHANDLED_CODEGEN_NODE_TYPE: 15,
42
- // minifier error codes
43
- UNHANDLED_MINIFIER_NODE_TYPE: 16
69
+ EXPECTED_TOKEN: 1,
70
+ INVALID_TOKEN_IN_PLACEHOLDER: 2,
71
+ UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER: 3,
72
+ UNKNOWN_ESCAPE_SEQUENCE: 4,
73
+ INVALID_UNICODE_ESCAPE_SEQUENCE: 5,
74
+ UNBALANCED_CLOSING_BRACE: 6,
75
+ UNTERMINATED_CLOSING_BRACE: 7,
76
+ EMPTY_PLACEHOLDER: 8,
77
+ NOT_ALLOW_NEST_PLACEHOLDER: 9,
78
+ INVALID_LINKED_FORMAT: 10,
79
+ MUST_HAVE_MESSAGES_IN_PLURAL: 11,
80
+ UNEXPECTED_EMPTY_LINKED_MODIFIER: 12,
81
+ UNEXPECTED_EMPTY_LINKED_KEY: 13,
82
+ UNEXPECTED_LEXICAL_ANALYSIS: 14,
83
+ UNHANDLED_CODEGEN_NODE_TYPE: 15,
84
+ UNHANDLED_MINIFIER_NODE_TYPE: 16
44
85
  };
45
- // Special value for higher-order compilers to pick up the last code
46
- // to avoid collision of error codes.
47
- // This should always be kept as the last item.
48
86
  const COMPILE_ERROR_CODES_EXTEND_POINT = 17;
49
87
  /** @internal */
50
88
  const errorMessages = {
51
- // tokenizer error messages
52
- [CompileErrorCodes.EXPECTED_TOKEN]: `Expected token: '{0}'`,
53
- [CompileErrorCodes.INVALID_TOKEN_IN_PLACEHOLDER]: `Invalid token in placeholder: '{0}'`,
54
- [CompileErrorCodes.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER]: `Unterminated single quote in placeholder`,
55
- [CompileErrorCodes.UNKNOWN_ESCAPE_SEQUENCE]: `Unknown escape sequence: \\{0}`,
56
- [CompileErrorCodes.INVALID_UNICODE_ESCAPE_SEQUENCE]: `Invalid unicode escape sequence: {0}`,
57
- [CompileErrorCodes.UNBALANCED_CLOSING_BRACE]: `Unbalanced closing brace`,
58
- [CompileErrorCodes.UNTERMINATED_CLOSING_BRACE]: `Unterminated closing brace`,
59
- [CompileErrorCodes.EMPTY_PLACEHOLDER]: `Empty placeholder`,
60
- [CompileErrorCodes.NOT_ALLOW_NEST_PLACEHOLDER]: `Not allowed nest placeholder`,
61
- [CompileErrorCodes.INVALID_LINKED_FORMAT]: `Invalid linked format`,
62
- // parser error messages
63
- [CompileErrorCodes.MUST_HAVE_MESSAGES_IN_PLURAL]: `Plural must have messages`,
64
- [CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_MODIFIER]: `Unexpected empty linked modifier`,
65
- [CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_KEY]: `Unexpected empty linked key`,
66
- [CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS]: `Unexpected lexical analysis in token: '{0}'`,
67
- // generator error messages
68
- [CompileErrorCodes.UNHANDLED_CODEGEN_NODE_TYPE]: `unhandled codegen node type: '{0}'`,
69
- // minimizer error messages
70
- [CompileErrorCodes.UNHANDLED_MINIFIER_NODE_TYPE]: `unhandled mimifier node type: '{0}'`
89
+ [CompileErrorCodes.EXPECTED_TOKEN]: `Expected token: '{0}'`,
90
+ [CompileErrorCodes.INVALID_TOKEN_IN_PLACEHOLDER]: `Invalid token in placeholder: '{0}'`,
91
+ [CompileErrorCodes.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER]: `Unterminated single quote in placeholder`,
92
+ [CompileErrorCodes.UNKNOWN_ESCAPE_SEQUENCE]: `Unknown escape sequence: \\{0}`,
93
+ [CompileErrorCodes.INVALID_UNICODE_ESCAPE_SEQUENCE]: `Invalid unicode escape sequence: {0}`,
94
+ [CompileErrorCodes.UNBALANCED_CLOSING_BRACE]: `Unbalanced closing brace`,
95
+ [CompileErrorCodes.UNTERMINATED_CLOSING_BRACE]: `Unterminated closing brace`,
96
+ [CompileErrorCodes.EMPTY_PLACEHOLDER]: `Empty placeholder`,
97
+ [CompileErrorCodes.NOT_ALLOW_NEST_PLACEHOLDER]: `Not allowed nest placeholder`,
98
+ [CompileErrorCodes.INVALID_LINKED_FORMAT]: `Invalid linked format`,
99
+ [CompileErrorCodes.MUST_HAVE_MESSAGES_IN_PLURAL]: `Plural must have messages`,
100
+ [CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_MODIFIER]: `Unexpected empty linked modifier`,
101
+ [CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_KEY]: `Unexpected empty linked key`,
102
+ [CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS]: `Unexpected lexical analysis in token: '{0}'`,
103
+ [CompileErrorCodes.UNHANDLED_CODEGEN_NODE_TYPE]: `unhandled codegen node type: '{0}'`,
104
+ [CompileErrorCodes.UNHANDLED_MINIFIER_NODE_TYPE]: `unhandled mimifier node type: '{0}'`
71
105
  };
72
106
  function createCompileError(code, loc, options = {}) {
73
- const { domain, messages, args } = options;
74
- const msg = (process.env.NODE_ENV !== 'production')
75
- ? format((messages || errorMessages)[code] || '', ...(args || []))
76
- : code;
77
- const error = new SyntaxError(String(msg));
78
- error.code = code;
79
- if (loc) {
80
- error.location = loc;
81
- }
82
- error.domain = domain;
83
- return error;
107
+ const { domain, messages, args } = options;
108
+ const msg = format((messages || errorMessages)[code] || "", ...args || []);
109
+ const error = new SyntaxError(String(msg));
110
+ error.code = code;
111
+ if (loc) error.location = loc;
112
+ error.domain = domain;
113
+ return error;
84
114
  }
85
115
  /** @internal */
86
116
  function defaultOnError(error) {
87
- throw error;
117
+ throw error;
88
118
  }
89
-
90
- // eslint-disable-next-line @typescript-eslint/triple-slash-reference
91
- /// <reference types="source-map-js" />
92
- const ERROR_DOMAIN$3 = 'parser';
119
+ //#endregion
120
+ //#region packages/message-compiler/src/generator.ts
121
+ const ERROR_DOMAIN$3 = "parser";
93
122
  function createCodeGenerator(ast, options) {
94
- const { sourceMap, filename, breakLineCode, needIndent: _needIndent } = options;
95
- const location = options.location !== false;
96
- const _context = {
97
- filename,
98
- code: '',
99
- column: 1,
100
- line: 1,
101
- offset: 0,
102
- map: undefined,
103
- breakLineCode,
104
- needIndent: _needIndent,
105
- indentLevel: 0
106
- };
107
- if (location && ast.loc) {
108
- _context.source = ast.loc.source;
109
- }
110
- const context = () => _context;
111
- function push(code, node) {
112
- _context.code += code;
113
- }
114
- function _newline(n, withBreakLine = true) {
115
- const _breakLineCode = withBreakLine ? breakLineCode : '';
116
- push(_needIndent ? _breakLineCode + ` `.repeat(n) : _breakLineCode);
117
- }
118
- function indent(withNewLine = true) {
119
- const level = ++_context.indentLevel;
120
- withNewLine && _newline(level);
121
- }
122
- function deindent(withNewLine = true) {
123
- const level = --_context.indentLevel;
124
- withNewLine && _newline(level);
125
- }
126
- function newline() {
127
- _newline(_context.indentLevel);
128
- }
129
- const helper = (key) => `_${key}`;
130
- const needIndent = () => _context.needIndent;
131
- return {
132
- context,
133
- push,
134
- indent,
135
- deindent,
136
- newline,
137
- helper,
138
- needIndent
139
- };
123
+ const { sourceMap, filename, breakLineCode, needIndent: _needIndent } = options;
124
+ const location = options.location !== false;
125
+ const _context = {
126
+ filename,
127
+ code: "",
128
+ column: 1,
129
+ line: 1,
130
+ offset: 0,
131
+ map: void 0,
132
+ breakLineCode,
133
+ needIndent: _needIndent,
134
+ indentLevel: 0
135
+ };
136
+ if (location && ast.loc) _context.source = ast.loc.source;
137
+ const context = () => _context;
138
+ function push(code, node) {
139
+ _context.code += code;
140
+ }
141
+ function _newline(n, withBreakLine = true) {
142
+ const _breakLineCode = withBreakLine ? breakLineCode : "";
143
+ push(_needIndent ? _breakLineCode + ` `.repeat(n) : _breakLineCode);
144
+ }
145
+ function indent(withNewLine = true) {
146
+ const level = ++_context.indentLevel;
147
+ withNewLine && _newline(level);
148
+ }
149
+ function deindent(withNewLine = true) {
150
+ const level = --_context.indentLevel;
151
+ withNewLine && _newline(level);
152
+ }
153
+ function newline() {
154
+ _newline(_context.indentLevel);
155
+ }
156
+ const helper = (key) => `_${key}`;
157
+ const needIndent = () => _context.needIndent;
158
+ return {
159
+ context,
160
+ push,
161
+ indent,
162
+ deindent,
163
+ newline,
164
+ helper,
165
+ needIndent
166
+ };
140
167
  }
141
168
  function generateLinkedNode(generator, node) {
142
- const { helper } = generator;
143
- generator.push(`${helper("linked" /* HelperNameMap.LINKED */)}(`);
144
- generateNode(generator, node.key);
145
- if (node.modifier) {
146
- generator.push(`, `);
147
- generateNode(generator, node.modifier);
148
- generator.push(`, _type`);
149
- }
150
- else {
151
- generator.push(`, undefined, _type`);
152
- }
153
- generator.push(`)`);
169
+ const { helper } = generator;
170
+ generator.push(`${helper("linked")}(`);
171
+ generateNode(generator, node.key);
172
+ if (node.modifier) {
173
+ generator.push(`, `);
174
+ generateNode(generator, node.modifier);
175
+ generator.push(`, _type`);
176
+ } else generator.push(`, undefined, _type`);
177
+ generator.push(`)`);
154
178
  }
155
179
  function generateMessageNode(generator, node) {
156
- const { helper, needIndent } = generator;
157
- generator.push(`${helper("normalize" /* HelperNameMap.NORMALIZE */)}([`);
158
- generator.indent(needIndent());
159
- const length = node.items.length;
160
- for (let i = 0; i < length; i++) {
161
- generateNode(generator, node.items[i]);
162
- if (i === length - 1) {
163
- break;
164
- }
165
- generator.push(', ');
166
- }
167
- generator.deindent(needIndent());
168
- generator.push('])');
180
+ const { helper, needIndent } = generator;
181
+ generator.push(`${helper("normalize")}([`);
182
+ generator.indent(needIndent());
183
+ const length = node.items.length;
184
+ for (let i = 0; i < length; i++) {
185
+ generateNode(generator, node.items[i]);
186
+ if (i === length - 1) break;
187
+ generator.push(", ");
188
+ }
189
+ generator.deindent(needIndent());
190
+ generator.push("])");
169
191
  }
170
192
  function generatePluralNode(generator, node) {
171
- const { helper, needIndent } = generator;
172
- if (node.cases.length > 1) {
173
- generator.push(`${helper("plural" /* HelperNameMap.PLURAL */)}([`);
174
- generator.indent(needIndent());
175
- const length = node.cases.length;
176
- for (let i = 0; i < length; i++) {
177
- generateNode(generator, node.cases[i]);
178
- if (i === length - 1) {
179
- break;
180
- }
181
- generator.push(', ');
182
- }
183
- generator.deindent(needIndent());
184
- generator.push(`])`);
185
- }
193
+ const { helper, needIndent } = generator;
194
+ if (node.cases.length > 1) {
195
+ generator.push(`${helper("plural")}([`);
196
+ generator.indent(needIndent());
197
+ const length = node.cases.length;
198
+ for (let i = 0; i < length; i++) {
199
+ generateNode(generator, node.cases[i]);
200
+ if (i === length - 1) break;
201
+ generator.push(", ");
202
+ }
203
+ generator.deindent(needIndent());
204
+ generator.push(`])`);
205
+ }
186
206
  }
187
207
  function generateResource(generator, node) {
188
- if (node.body) {
189
- generateNode(generator, node.body);
190
- }
191
- else {
192
- generator.push('null');
193
- }
208
+ if (node.body) generateNode(generator, node.body);
209
+ else generator.push("null");
194
210
  }
195
211
  function generateNode(generator, node) {
196
- const { helper } = generator;
197
- switch (node.type) {
198
- case 0 /* NodeTypes.Resource */:
199
- generateResource(generator, node);
200
- break;
201
- case 1 /* NodeTypes.Plural */:
202
- generatePluralNode(generator, node);
203
- break;
204
- case 2 /* NodeTypes.Message */:
205
- generateMessageNode(generator, node);
206
- break;
207
- case 6 /* NodeTypes.Linked */:
208
- generateLinkedNode(generator, node);
209
- break;
210
- case 8 /* NodeTypes.LinkedModifier */:
211
- generator.push(JSON.stringify(node.value), node);
212
- break;
213
- case 7 /* NodeTypes.LinkedKey */:
214
- generator.push(JSON.stringify(node.value), node);
215
- break;
216
- case 5 /* NodeTypes.List */:
217
- generator.push(`${helper("interpolate" /* HelperNameMap.INTERPOLATE */)}(${helper("list" /* HelperNameMap.LIST */)}(${node.index}))`, node);
218
- break;
219
- case 4 /* NodeTypes.Named */:
220
- generator.push(`${helper("interpolate" /* HelperNameMap.INTERPOLATE */)}(${helper("named" /* HelperNameMap.NAMED */)}(${JSON.stringify(node.key)}))`, node);
221
- break;
222
- case 9 /* NodeTypes.Literal */:
223
- generator.push(JSON.stringify(node.value), node);
224
- break;
225
- case 3 /* NodeTypes.Text */:
226
- generator.push(JSON.stringify(node.value), node);
227
- break;
228
- default:
229
- if ((process.env.NODE_ENV !== 'production')) {
230
- throw createCompileError(CompileErrorCodes.UNHANDLED_CODEGEN_NODE_TYPE, null, {
231
- domain: ERROR_DOMAIN$3,
232
- args: [node.type]
233
- });
234
- }
235
- }
212
+ const { helper } = generator;
213
+ switch (node.type) {
214
+ case 0:
215
+ generateResource(generator, node);
216
+ break;
217
+ case 1:
218
+ generatePluralNode(generator, node);
219
+ break;
220
+ case 2:
221
+ generateMessageNode(generator, node);
222
+ break;
223
+ case 6:
224
+ generateLinkedNode(generator, node);
225
+ break;
226
+ case 8:
227
+ generator.push(JSON.stringify(node.value), node);
228
+ break;
229
+ case 7:
230
+ generator.push(JSON.stringify(node.value), node);
231
+ break;
232
+ case 5:
233
+ generator.push(`${helper("interpolate")}(${helper("list")}(${node.index}))`, node);
234
+ break;
235
+ case 4:
236
+ generator.push(`${helper("interpolate")}(${helper("named")}(${JSON.stringify(node.key)}))`, node);
237
+ break;
238
+ case 9:
239
+ generator.push(JSON.stringify(node.value), node);
240
+ break;
241
+ case 3:
242
+ generator.push(JSON.stringify(node.value), node);
243
+ break;
244
+ default: throw createCompileError(CompileErrorCodes.UNHANDLED_CODEGEN_NODE_TYPE, null, {
245
+ domain: ERROR_DOMAIN$3,
246
+ args: [node.type]
247
+ });
248
+ }
236
249
  }
237
- // generate code from AST
238
250
  const generate = (ast, options = {}) => {
239
- const mode = isString(options.mode) ? options.mode : 'normal';
240
- const filename = isString(options.filename)
241
- ? options.filename
242
- : 'message.intl';
243
- const sourceMap = !!options.sourceMap;
244
- // prettier-ignore
245
- const breakLineCode = options.breakLineCode != null
246
- ? options.breakLineCode
247
- : mode === 'arrow'
248
- ? ';'
249
- : '\n';
250
- const needIndent = options.needIndent ? options.needIndent : mode !== 'arrow';
251
- const helpers = ast.helpers || [];
252
- const generator = createCodeGenerator(ast, {
253
- mode,
254
- filename,
255
- sourceMap,
256
- breakLineCode,
257
- needIndent
258
- });
259
- generator.push(mode === 'normal' ? `function __msg__ (ctx) {` : `(ctx) => {`);
260
- generator.indent(needIndent);
261
- if (helpers.length > 0) {
262
- generator.push(`const { ${join(helpers.map(s => `${s}: _${s}`), ', ')} } = ctx`);
263
- generator.newline();
264
- }
265
- generator.push(`return `);
266
- generateNode(generator, ast);
267
- generator.deindent(needIndent);
268
- generator.push(`}`);
269
- delete ast.helpers;
270
- const { code, map } = generator.context();
271
- return {
272
- ast,
273
- code,
274
- map: map ? map.toJSON() : undefined // eslint-disable-line @typescript-eslint/no-explicit-any
275
- };
251
+ const mode = isString(options.mode) ? options.mode : "normal";
252
+ const filename = isString(options.filename) ? options.filename : "message.intl";
253
+ const sourceMap = !!options.sourceMap;
254
+ const breakLineCode = options.breakLineCode != null ? options.breakLineCode : mode === "arrow" ? ";" : "\n";
255
+ const needIndent = options.needIndent ? options.needIndent : mode !== "arrow";
256
+ const helpers = ast.helpers || [];
257
+ const generator = createCodeGenerator(ast, {
258
+ mode,
259
+ filename,
260
+ sourceMap,
261
+ breakLineCode,
262
+ needIndent
263
+ });
264
+ generator.push(mode === "normal" ? `function __msg__ (ctx) {` : `(ctx) => {`);
265
+ generator.indent(needIndent);
266
+ if (helpers.length > 0) {
267
+ generator.push(`const { ${join(helpers.map((s) => `${s}: _${s}`), ", ")} } = ctx`);
268
+ generator.newline();
269
+ }
270
+ generator.push(`return `);
271
+ generateNode(generator, ast);
272
+ generator.deindent(needIndent);
273
+ generator.push(`}`);
274
+ delete ast.helpers;
275
+ const { code, map } = generator.context();
276
+ return {
277
+ ast,
278
+ code,
279
+ map: map ? map.toJSON() : void 0
280
+ };
276
281
  };
277
-
278
- const ERROR_DOMAIN$2 = 'minifier';
279
- /* eslint-disable @typescript-eslint/no-explicit-any */
282
+ //#endregion
283
+ //#region packages/message-compiler/src/mangler.ts
284
+ const ERROR_DOMAIN$2 = "minifier";
280
285
  function mangle(node) {
281
- node.t = node.type;
282
- switch (node.type) {
283
- case 0 /* NodeTypes.Resource */: {
284
- const resource = node;
285
- mangle(resource.body);
286
- resource.b = resource.body;
287
- delete resource.body;
288
- break;
289
- }
290
- case 1 /* NodeTypes.Plural */: {
291
- const plural = node;
292
- const cases = plural.cases;
293
- for (let i = 0; i < cases.length; i++) {
294
- mangle(cases[i]);
295
- }
296
- plural.c = cases;
297
- delete plural.cases;
298
- break;
299
- }
300
- case 2 /* NodeTypes.Message */: {
301
- const message = node;
302
- const items = message.items;
303
- for (let i = 0; i < items.length; i++) {
304
- mangle(items[i]);
305
- }
306
- message.i = items;
307
- delete message.items;
308
- if (message.static) {
309
- message.s = message.static;
310
- delete message.static;
311
- }
312
- break;
313
- }
314
- case 3 /* NodeTypes.Text */:
315
- case 9 /* NodeTypes.Literal */:
316
- case 8 /* NodeTypes.LinkedModifier */:
317
- case 7 /* NodeTypes.LinkedKey */: {
318
- const valueNode = node;
319
- if (valueNode.value) {
320
- valueNode.v = valueNode.value;
321
- delete valueNode.value;
322
- }
323
- break;
324
- }
325
- case 6 /* NodeTypes.Linked */: {
326
- const linked = node;
327
- mangle(linked.key);
328
- linked.k = linked.key;
329
- delete linked.key;
330
- if (linked.modifier) {
331
- mangle(linked.modifier);
332
- linked.m = linked.modifier;
333
- delete linked.modifier;
334
- }
335
- break;
336
- }
337
- case 5 /* NodeTypes.List */: {
338
- const list = node;
339
- list.i = list.index;
340
- delete list.index;
341
- break;
342
- }
343
- case 4 /* NodeTypes.Named */: {
344
- const named = node;
345
- named.k = named.key;
346
- delete named.key;
347
- break;
348
- }
349
- default:
350
- if ((process.env.NODE_ENV !== 'production')) {
351
- throw createCompileError(CompileErrorCodes.UNHANDLED_MINIFIER_NODE_TYPE, null, {
352
- domain: ERROR_DOMAIN$2,
353
- args: [node.type]
354
- });
355
- }
356
- }
357
- delete node.type;
286
+ node.t = node.type;
287
+ switch (node.type) {
288
+ case 0: {
289
+ const resource = node;
290
+ mangle(resource.body);
291
+ resource.b = resource.body;
292
+ delete resource.body;
293
+ break;
294
+ }
295
+ case 1: {
296
+ const plural = node;
297
+ const cases = plural.cases;
298
+ for (let i = 0; i < cases.length; i++) mangle(cases[i]);
299
+ plural.c = cases;
300
+ delete plural.cases;
301
+ break;
302
+ }
303
+ case 2: {
304
+ const message = node;
305
+ const items = message.items;
306
+ for (let i = 0; i < items.length; i++) mangle(items[i]);
307
+ message.i = items;
308
+ delete message.items;
309
+ if (message.static) {
310
+ message.s = message.static;
311
+ delete message.static;
312
+ }
313
+ break;
314
+ }
315
+ case 3:
316
+ case 9:
317
+ case 8:
318
+ case 7: {
319
+ const valueNode = node;
320
+ if (valueNode.value) {
321
+ valueNode.v = valueNode.value;
322
+ delete valueNode.value;
323
+ }
324
+ break;
325
+ }
326
+ case 6: {
327
+ const linked = node;
328
+ mangle(linked.key);
329
+ linked.k = linked.key;
330
+ delete linked.key;
331
+ if (linked.modifier) {
332
+ mangle(linked.modifier);
333
+ linked.m = linked.modifier;
334
+ delete linked.modifier;
335
+ }
336
+ break;
337
+ }
338
+ case 5: {
339
+ const list = node;
340
+ list.i = list.index;
341
+ delete list.index;
342
+ break;
343
+ }
344
+ case 4: {
345
+ const named = node;
346
+ named.k = named.key;
347
+ delete named.key;
348
+ break;
349
+ }
350
+ default: throw createCompileError(CompileErrorCodes.UNHANDLED_MINIFIER_NODE_TYPE, null, {
351
+ domain: ERROR_DOMAIN$2,
352
+ args: [node.type]
353
+ });
354
+ }
355
+ delete node.type;
358
356
  }
359
- /* eslint-enable @typescript-eslint/no-explicit-any */
360
-
357
+ //#endregion
358
+ //#region packages/message-compiler/src/optimizer.ts
361
359
  function optimize(ast) {
362
- const body = ast.body;
363
- if (body.type === 2 /* NodeTypes.Message */) {
364
- optimizeMessageNode(body);
365
- }
366
- else {
367
- body.cases.forEach(c => optimizeMessageNode(c));
368
- }
369
- return ast;
360
+ const body = ast.body;
361
+ if (body.type === 2) optimizeMessageNode(body);
362
+ else body.cases.forEach((c) => optimizeMessageNode(c));
363
+ return ast;
370
364
  }
371
365
  function optimizeMessageNode(message) {
372
- if (message.items.length === 1) {
373
- const item = message.items[0];
374
- if (item.type === 3 /* NodeTypes.Text */ || item.type === 9 /* NodeTypes.Literal */) {
375
- message.static = item.value;
376
- delete item.value; // optimization for size
377
- }
378
- }
379
- else {
380
- const values = [];
381
- for (let i = 0; i < message.items.length; i++) {
382
- const item = message.items[i];
383
- if (!(item.type === 3 /* NodeTypes.Text */ || item.type === 9 /* NodeTypes.Literal */)) {
384
- break;
385
- }
386
- if (item.value == null) {
387
- break;
388
- }
389
- values.push(item.value);
390
- }
391
- if (values.length === message.items.length) {
392
- message.static = join(values);
393
- for (let i = 0; i < message.items.length; i++) {
394
- const item = message.items[i];
395
- if (item.type === 3 /* NodeTypes.Text */ || item.type === 9 /* NodeTypes.Literal */) {
396
- delete item.value; // optimization for size
397
- }
398
- }
399
- }
400
- }
366
+ if (message.items.length === 1) {
367
+ const item = message.items[0];
368
+ if (item.type === 3 || item.type === 9) {
369
+ message.static = item.value;
370
+ delete item.value;
371
+ }
372
+ } else {
373
+ const values = [];
374
+ for (let i = 0; i < message.items.length; i++) {
375
+ const item = message.items[i];
376
+ if (!(item.type === 3 || item.type === 9)) break;
377
+ if (item.value == null) break;
378
+ values.push(item.value);
379
+ }
380
+ if (values.length === message.items.length) {
381
+ message.static = join(values);
382
+ for (let i = 0; i < message.items.length; i++) {
383
+ const item = message.items[i];
384
+ if (item.type === 3 || item.type === 9) delete item.value;
385
+ }
386
+ }
387
+ }
401
388
  }
402
-
403
- const CHAR_SP = ' ';
404
- const CHAR_CR = '\r';
405
- const CHAR_LF = '\n';
406
- const CHAR_LS = String.fromCharCode(0x2028);
407
- const CHAR_PS = String.fromCharCode(0x2029);
408
389
  function createScanner(str) {
409
- const _buf = str;
410
- let _index = 0;
411
- let _line = 1;
412
- let _column = 1;
413
- let _peekOffset = 0;
414
- const isCRLF = (index) => _buf[index] === CHAR_CR && _buf[index + 1] === CHAR_LF;
415
- const isLF = (index) => _buf[index] === CHAR_LF;
416
- const isPS = (index) => _buf[index] === CHAR_PS;
417
- const isLS = (index) => _buf[index] === CHAR_LS;
418
- const isLineEnd = (index) => isCRLF(index) || isLF(index) || isPS(index) || isLS(index);
419
- const index = () => _index;
420
- const line = () => _line;
421
- const column = () => _column;
422
- const peekOffset = () => _peekOffset;
423
- const charAt = (offset) => isCRLF(offset) || isPS(offset) || isLS(offset) ? CHAR_LF : _buf[offset];
424
- const currentChar = () => charAt(_index);
425
- const currentPeek = () => charAt(_index + _peekOffset);
426
- function next() {
427
- _peekOffset = 0;
428
- if (isLineEnd(_index)) {
429
- _line++;
430
- _column = 0;
431
- }
432
- if (isCRLF(_index)) {
433
- _index++;
434
- }
435
- _index++;
436
- _column++;
437
- return _buf[_index];
438
- }
439
- function peek() {
440
- if (isCRLF(_index + _peekOffset)) {
441
- _peekOffset++;
442
- }
443
- _peekOffset++;
444
- return _buf[_index + _peekOffset];
445
- }
446
- function reset() {
447
- _index = 0;
448
- _line = 1;
449
- _column = 1;
450
- _peekOffset = 0;
451
- }
452
- function resetPeek(offset = 0) {
453
- _peekOffset = offset;
454
- }
455
- function skipToPeek() {
456
- const target = _index + _peekOffset;
457
- while (target !== _index) {
458
- next();
459
- }
460
- _peekOffset = 0;
461
- }
462
- return {
463
- index,
464
- line,
465
- column,
466
- peekOffset,
467
- charAt,
468
- currentChar,
469
- currentPeek,
470
- next,
471
- peek,
472
- reset,
473
- resetPeek,
474
- skipToPeek
475
- };
390
+ const _buf = str;
391
+ let _index = 0;
392
+ let _line = 1;
393
+ let _column = 1;
394
+ let _peekOffset = 0;
395
+ const isCRLF = (index) => _buf[index] === "\r" && _buf[index + 1] === "\n";
396
+ const isLF = (index) => _buf[index] === "\n";
397
+ const isPS = (index) => _buf[index] === "\u2029";
398
+ const isLS = (index) => _buf[index] === "\u2028";
399
+ const isLineEnd = (index) => isCRLF(index) || isLF(index) || isPS(index) || isLS(index);
400
+ const index = () => _index;
401
+ const line = () => _line;
402
+ const column = () => _column;
403
+ const peekOffset = () => _peekOffset;
404
+ const charAt = (offset) => isCRLF(offset) || isPS(offset) || isLS(offset) ? "\n" : _buf[offset];
405
+ const currentChar = () => charAt(_index);
406
+ const currentPeek = () => charAt(_index + _peekOffset);
407
+ function next() {
408
+ _peekOffset = 0;
409
+ if (isLineEnd(_index)) {
410
+ _line++;
411
+ _column = 0;
412
+ }
413
+ if (isCRLF(_index)) _index++;
414
+ _index++;
415
+ _column++;
416
+ return _buf[_index];
417
+ }
418
+ function peek() {
419
+ if (isCRLF(_index + _peekOffset)) _peekOffset++;
420
+ _peekOffset++;
421
+ return _buf[_index + _peekOffset];
422
+ }
423
+ function reset() {
424
+ _index = 0;
425
+ _line = 1;
426
+ _column = 1;
427
+ _peekOffset = 0;
428
+ }
429
+ function resetPeek(offset = 0) {
430
+ _peekOffset = offset;
431
+ }
432
+ function skipToPeek() {
433
+ const target = _index + _peekOffset;
434
+ while (target !== _index) next();
435
+ _peekOffset = 0;
436
+ }
437
+ return {
438
+ index,
439
+ line,
440
+ column,
441
+ peekOffset,
442
+ charAt,
443
+ currentChar,
444
+ currentPeek,
445
+ next,
446
+ peek,
447
+ reset,
448
+ resetPeek,
449
+ skipToPeek
450
+ };
476
451
  }
477
-
478
- const EOF = undefined;
479
- const DOT = '.';
452
+ //#endregion
453
+ //#region packages/message-compiler/src/tokenizer.ts
454
+ const EOF = void 0;
455
+ const DOT = ".";
480
456
  const LITERAL_DELIMITER = "'";
481
- const ERROR_DOMAIN$1 = 'tokenizer';
457
+ const ERROR_DOMAIN$1 = "tokenizer";
482
458
  function createTokenizer(source, options = {}) {
483
- const location = options.location !== false;
484
- const _scnr = createScanner(source);
485
- const currentOffset = () => _scnr.index();
486
- const currentPosition = () => createPosition(_scnr.line(), _scnr.column(), _scnr.index());
487
- const _initLoc = currentPosition();
488
- const _initOffset = currentOffset();
489
- const _context = {
490
- currentType: 13 /* TokenTypes.EOF */,
491
- offset: _initOffset,
492
- startLoc: _initLoc,
493
- endLoc: _initLoc,
494
- lastType: 13 /* TokenTypes.EOF */,
495
- lastOffset: _initOffset,
496
- lastStartLoc: _initLoc,
497
- lastEndLoc: _initLoc,
498
- braceNest: 0,
499
- inLinked: false,
500
- text: ''
501
- };
502
- const context = () => _context;
503
- const { onError } = options;
504
- function emitError(code, pos, offset, ...args) {
505
- const ctx = context();
506
- pos.column += offset;
507
- pos.offset += offset;
508
- if (onError) {
509
- const loc = location ? createLocation(ctx.startLoc, pos) : null;
510
- const err = createCompileError(code, loc, {
511
- domain: ERROR_DOMAIN$1,
512
- args
513
- });
514
- onError(err);
515
- }
516
- }
517
- function getToken(context, type, value) {
518
- context.endLoc = currentPosition();
519
- context.currentType = type;
520
- const token = { type };
521
- if (location) {
522
- token.loc = createLocation(context.startLoc, context.endLoc);
523
- }
524
- if (value != null) {
525
- token.value = value;
526
- }
527
- return token;
528
- }
529
- const getEndToken = (context) => getToken(context, 13 /* TokenTypes.EOF */);
530
- function eat(scnr, ch) {
531
- if (scnr.currentChar() === ch) {
532
- scnr.next();
533
- return ch;
534
- }
535
- else {
536
- emitError(CompileErrorCodes.EXPECTED_TOKEN, currentPosition(), 0, ch);
537
- return '';
538
- }
539
- }
540
- function peekSpaces(scnr) {
541
- let buf = '';
542
- while (scnr.currentPeek() === CHAR_SP || scnr.currentPeek() === CHAR_LF) {
543
- buf += scnr.currentPeek();
544
- scnr.peek();
545
- }
546
- return buf;
547
- }
548
- function skipSpaces(scnr) {
549
- const buf = peekSpaces(scnr);
550
- scnr.skipToPeek();
551
- return buf;
552
- }
553
- function isIdentifierStart(ch) {
554
- if (ch === EOF) {
555
- return false;
556
- }
557
- const cc = ch.charCodeAt(0);
558
- return ((cc >= 97 && cc <= 122) || // a-z
559
- (cc >= 65 && cc <= 90) || // A-Z
560
- cc === 95 // _
561
- );
562
- }
563
- function isNumberStart(ch) {
564
- if (ch === EOF) {
565
- return false;
566
- }
567
- const cc = ch.charCodeAt(0);
568
- return cc >= 48 && cc <= 57; // 0-9
569
- }
570
- function isNamedIdentifierStart(scnr, context) {
571
- const { currentType } = context;
572
- if (currentType !== 2 /* TokenTypes.BraceLeft */) {
573
- return false;
574
- }
575
- peekSpaces(scnr);
576
- const ret = isIdentifierStart(scnr.currentPeek());
577
- scnr.resetPeek();
578
- return ret;
579
- }
580
- function isListIdentifierStart(scnr, context) {
581
- const { currentType } = context;
582
- if (currentType !== 2 /* TokenTypes.BraceLeft */) {
583
- return false;
584
- }
585
- peekSpaces(scnr);
586
- const ch = scnr.currentPeek() === '-' ? scnr.peek() : scnr.currentPeek();
587
- const ret = isNumberStart(ch);
588
- scnr.resetPeek();
589
- return ret;
590
- }
591
- function isLiteralStart(scnr, context) {
592
- const { currentType } = context;
593
- if (currentType !== 2 /* TokenTypes.BraceLeft */) {
594
- return false;
595
- }
596
- peekSpaces(scnr);
597
- const ret = scnr.currentPeek() === LITERAL_DELIMITER;
598
- scnr.resetPeek();
599
- return ret;
600
- }
601
- function isLinkedDotStart(scnr, context) {
602
- const { currentType } = context;
603
- if (currentType !== 7 /* TokenTypes.LinkedAlias */) {
604
- return false;
605
- }
606
- peekSpaces(scnr);
607
- const ret = scnr.currentPeek() === "." /* TokenChars.LinkedDot */;
608
- scnr.resetPeek();
609
- return ret;
610
- }
611
- function isLinkedModifierStart(scnr, context) {
612
- const { currentType } = context;
613
- if (currentType !== 8 /* TokenTypes.LinkedDot */) {
614
- return false;
615
- }
616
- peekSpaces(scnr);
617
- const ret = isIdentifierStart(scnr.currentPeek());
618
- scnr.resetPeek();
619
- return ret;
620
- }
621
- function isLinkedDelimiterStart(scnr, context) {
622
- const { currentType } = context;
623
- if (!(currentType === 7 /* TokenTypes.LinkedAlias */ ||
624
- currentType === 11 /* TokenTypes.LinkedModifier */)) {
625
- return false;
626
- }
627
- peekSpaces(scnr);
628
- const ret = scnr.currentPeek() === ":" /* TokenChars.LinkedDelimiter */;
629
- scnr.resetPeek();
630
- return ret;
631
- }
632
- function isLinkedReferStart(scnr, context) {
633
- const { currentType } = context;
634
- if (currentType !== 9 /* TokenTypes.LinkedDelimiter */) {
635
- return false;
636
- }
637
- const fn = () => {
638
- const ch = scnr.currentPeek();
639
- if (ch === "{" /* TokenChars.BraceLeft */) {
640
- return isIdentifierStart(scnr.peek());
641
- }
642
- else if (ch === "@" /* TokenChars.LinkedAlias */ ||
643
- ch === "|" /* TokenChars.Pipe */ ||
644
- ch === ":" /* TokenChars.LinkedDelimiter */ ||
645
- ch === "." /* TokenChars.LinkedDot */ ||
646
- ch === CHAR_SP ||
647
- !ch) {
648
- return false;
649
- }
650
- else if (ch === CHAR_LF) {
651
- scnr.peek();
652
- return fn();
653
- }
654
- else {
655
- // other characters
656
- return isTextStart(scnr, false);
657
- }
658
- };
659
- const ret = fn();
660
- scnr.resetPeek();
661
- return ret;
662
- }
663
- function isPluralStart(scnr) {
664
- peekSpaces(scnr);
665
- const ret = scnr.currentPeek() === "|" /* TokenChars.Pipe */;
666
- scnr.resetPeek();
667
- return ret;
668
- }
669
- function isTextStart(scnr, reset = true) {
670
- const fn = (hasSpace = false, prev = '') => {
671
- const ch = scnr.currentPeek();
672
- if (ch === "{" /* TokenChars.BraceLeft */) {
673
- return hasSpace;
674
- }
675
- else if (ch === "@" /* TokenChars.LinkedAlias */ || !ch) {
676
- return hasSpace;
677
- }
678
- else if (ch === "|" /* TokenChars.Pipe */) {
679
- return !(prev === CHAR_SP || prev === CHAR_LF);
680
- }
681
- else if (ch === CHAR_SP) {
682
- scnr.peek();
683
- return fn(true, CHAR_SP);
684
- }
685
- else if (ch === CHAR_LF) {
686
- scnr.peek();
687
- return fn(true, CHAR_LF);
688
- }
689
- else {
690
- return true;
691
- }
692
- };
693
- const ret = fn();
694
- reset && scnr.resetPeek();
695
- return ret;
696
- }
697
- function takeChar(scnr, fn) {
698
- const ch = scnr.currentChar();
699
- if (ch === EOF) {
700
- return EOF;
701
- }
702
- if (fn(ch)) {
703
- scnr.next();
704
- return ch;
705
- }
706
- return null;
707
- }
708
- function isIdentifier(ch) {
709
- const cc = ch.charCodeAt(0);
710
- return ((cc >= 97 && cc <= 122) || // a-z
711
- (cc >= 65 && cc <= 90) || // A-Z
712
- (cc >= 48 && cc <= 57) || // 0-9
713
- cc === 95 || // _
714
- cc === 36 // $
715
- );
716
- }
717
- function takeIdentifierChar(scnr) {
718
- return takeChar(scnr, isIdentifier);
719
- }
720
- function isNamedIdentifier(ch) {
721
- const cc = ch.charCodeAt(0);
722
- return ((cc >= 97 && cc <= 122) || // a-z
723
- (cc >= 65 && cc <= 90) || // A-Z
724
- (cc >= 48 && cc <= 57) || // 0-9
725
- cc === 95 || // _
726
- cc === 36 || // $
727
- cc === 45 // -
728
- );
729
- }
730
- function takeNamedIdentifierChar(scnr) {
731
- return takeChar(scnr, isNamedIdentifier);
732
- }
733
- function isDigit(ch) {
734
- const cc = ch.charCodeAt(0);
735
- return cc >= 48 && cc <= 57; // 0-9
736
- }
737
- function takeDigit(scnr) {
738
- return takeChar(scnr, isDigit);
739
- }
740
- function isHexDigit(ch) {
741
- const cc = ch.charCodeAt(0);
742
- return ((cc >= 48 && cc <= 57) || // 0-9
743
- (cc >= 65 && cc <= 70) || // A-F
744
- (cc >= 97 && cc <= 102)); // a-f
745
- }
746
- function takeHexDigit(scnr) {
747
- return takeChar(scnr, isHexDigit);
748
- }
749
- function getDigits(scnr) {
750
- let ch = '';
751
- let num = '';
752
- while ((ch = takeDigit(scnr))) {
753
- num += ch;
754
- }
755
- return num;
756
- }
757
- function readText(scnr) {
758
- let buf = '';
759
- while (true) {
760
- const ch = scnr.currentChar();
761
- if (ch === "{" /* TokenChars.BraceLeft */ ||
762
- ch === "}" /* TokenChars.BraceRight */ ||
763
- ch === "@" /* TokenChars.LinkedAlias */ ||
764
- ch === "|" /* TokenChars.Pipe */ ||
765
- !ch) {
766
- break;
767
- }
768
- else if (ch === CHAR_SP || ch === CHAR_LF) {
769
- if (isTextStart(scnr)) {
770
- buf += ch;
771
- scnr.next();
772
- }
773
- else if (isPluralStart(scnr)) {
774
- break;
775
- }
776
- else {
777
- buf += ch;
778
- scnr.next();
779
- }
780
- }
781
- else {
782
- buf += ch;
783
- scnr.next();
784
- }
785
- }
786
- return buf;
787
- }
788
- function readNamedIdentifier(scnr) {
789
- skipSpaces(scnr);
790
- let ch = '';
791
- let name = '';
792
- while ((ch = takeNamedIdentifierChar(scnr))) {
793
- name += ch;
794
- }
795
- if (scnr.currentChar() === EOF) {
796
- emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
797
- }
798
- return name;
799
- }
800
- function readListIdentifier(scnr) {
801
- skipSpaces(scnr);
802
- let value = '';
803
- if (scnr.currentChar() === '-') {
804
- scnr.next();
805
- value += `-${getDigits(scnr)}`;
806
- }
807
- else {
808
- value += getDigits(scnr);
809
- }
810
- if (scnr.currentChar() === EOF) {
811
- emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
812
- }
813
- return value;
814
- }
815
- function isLiteral(ch) {
816
- return ch !== LITERAL_DELIMITER && ch !== CHAR_LF;
817
- }
818
- function readLiteral(scnr) {
819
- skipSpaces(scnr);
820
- // eslint-disable-next-line no-useless-escape
821
- eat(scnr, `\'`);
822
- let ch = '';
823
- let literal = '';
824
- while ((ch = takeChar(scnr, isLiteral))) {
825
- if (ch === '\\') {
826
- literal += readEscapeSequence(scnr);
827
- }
828
- else {
829
- literal += ch;
830
- }
831
- }
832
- const current = scnr.currentChar();
833
- if (current === CHAR_LF || current === EOF) {
834
- emitError(CompileErrorCodes.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER, currentPosition(), 0);
835
- // TODO: Is it correct really?
836
- if (current === CHAR_LF) {
837
- scnr.next();
838
- // eslint-disable-next-line no-useless-escape
839
- eat(scnr, `\'`);
840
- }
841
- return literal;
842
- }
843
- // eslint-disable-next-line no-useless-escape
844
- eat(scnr, `\'`);
845
- return literal;
846
- }
847
- function readEscapeSequence(scnr) {
848
- const ch = scnr.currentChar();
849
- switch (ch) {
850
- case '\\':
851
- case `\'`: // eslint-disable-line no-useless-escape
852
- scnr.next();
853
- return `\\${ch}`;
854
- case 'u':
855
- return readUnicodeEscapeSequence(scnr, ch, 4);
856
- case 'U':
857
- return readUnicodeEscapeSequence(scnr, ch, 6);
858
- default:
859
- emitError(CompileErrorCodes.UNKNOWN_ESCAPE_SEQUENCE, currentPosition(), 0, ch);
860
- return '';
861
- }
862
- }
863
- function readUnicodeEscapeSequence(scnr, unicode, digits) {
864
- eat(scnr, unicode);
865
- let sequence = '';
866
- for (let i = 0; i < digits; i++) {
867
- const ch = takeHexDigit(scnr);
868
- if (!ch) {
869
- emitError(CompileErrorCodes.INVALID_UNICODE_ESCAPE_SEQUENCE, currentPosition(), 0, `\\${unicode}${sequence}${scnr.currentChar()}`);
870
- break;
871
- }
872
- sequence += ch;
873
- }
874
- return `\\${unicode}${sequence}`;
875
- }
876
- function isInvalidIdentifier(ch) {
877
- return (ch !== "{" /* TokenChars.BraceLeft */ &&
878
- ch !== "}" /* TokenChars.BraceRight */ &&
879
- ch !== CHAR_SP &&
880
- ch !== CHAR_LF);
881
- }
882
- function readInvalidIdentifier(scnr) {
883
- skipSpaces(scnr);
884
- let ch = '';
885
- let identifiers = '';
886
- while ((ch = takeChar(scnr, isInvalidIdentifier))) {
887
- identifiers += ch;
888
- }
889
- return identifiers;
890
- }
891
- function readLinkedModifier(scnr) {
892
- let ch = '';
893
- let name = '';
894
- while ((ch = takeIdentifierChar(scnr))) {
895
- name += ch;
896
- }
897
- return name;
898
- }
899
- function readLinkedRefer(scnr) {
900
- const fn = (buf) => {
901
- const ch = scnr.currentChar();
902
- if (ch === "{" /* TokenChars.BraceLeft */ ||
903
- ch === "@" /* TokenChars.LinkedAlias */ ||
904
- ch === "|" /* TokenChars.Pipe */ ||
905
- ch === "(" /* TokenChars.ParenLeft */ ||
906
- ch === ")" /* TokenChars.ParenRight */ ||
907
- !ch) {
908
- return buf;
909
- }
910
- else if (ch === CHAR_SP) {
911
- return buf;
912
- }
913
- else if (ch === CHAR_LF || ch === DOT) {
914
- buf += ch;
915
- scnr.next();
916
- return fn(buf);
917
- }
918
- else {
919
- buf += ch;
920
- scnr.next();
921
- return fn(buf);
922
- }
923
- };
924
- return fn('');
925
- }
926
- function readPlural(scnr) {
927
- skipSpaces(scnr);
928
- const plural = eat(scnr, "|" /* TokenChars.Pipe */);
929
- skipSpaces(scnr);
930
- return plural;
931
- }
932
- // TODO: We need refactoring of token parsing ...
933
- function readTokenInPlaceholder(scnr, context) {
934
- let token = null;
935
- const ch = scnr.currentChar();
936
- switch (ch) {
937
- case "{" /* TokenChars.BraceLeft */:
938
- if (context.braceNest >= 1) {
939
- emitError(CompileErrorCodes.NOT_ALLOW_NEST_PLACEHOLDER, currentPosition(), 0);
940
- }
941
- scnr.next();
942
- token = getToken(context, 2 /* TokenTypes.BraceLeft */, "{" /* TokenChars.BraceLeft */);
943
- skipSpaces(scnr);
944
- context.braceNest++;
945
- return token;
946
- case "}" /* TokenChars.BraceRight */:
947
- if (context.braceNest > 0 &&
948
- context.currentType === 2 /* TokenTypes.BraceLeft */) {
949
- emitError(CompileErrorCodes.EMPTY_PLACEHOLDER, currentPosition(), 0);
950
- }
951
- scnr.next();
952
- token = getToken(context, 3 /* TokenTypes.BraceRight */, "}" /* TokenChars.BraceRight */);
953
- context.braceNest--;
954
- context.braceNest > 0 && skipSpaces(scnr);
955
- if (context.inLinked && context.braceNest === 0) {
956
- context.inLinked = false;
957
- }
958
- return token;
959
- case "@" /* TokenChars.LinkedAlias */:
960
- if (context.braceNest > 0) {
961
- emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
962
- }
963
- token = readTokenInLinked(scnr, context) || getEndToken(context);
964
- context.braceNest = 0;
965
- return token;
966
- default: {
967
- let validNamedIdentifier = true;
968
- let validListIdentifier = true;
969
- let validLiteral = true;
970
- if (isPluralStart(scnr)) {
971
- if (context.braceNest > 0) {
972
- emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
973
- }
974
- token = getToken(context, 1 /* TokenTypes.Pipe */, readPlural(scnr));
975
- // reset
976
- context.braceNest = 0;
977
- context.inLinked = false;
978
- return token;
979
- }
980
- if (context.braceNest > 0 &&
981
- (context.currentType === 4 /* TokenTypes.Named */ ||
982
- context.currentType === 5 /* TokenTypes.List */ ||
983
- context.currentType === 6 /* TokenTypes.Literal */)) {
984
- emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
985
- context.braceNest = 0;
986
- return readToken(scnr, context);
987
- }
988
- if ((validNamedIdentifier = isNamedIdentifierStart(scnr, context))) {
989
- token = getToken(context, 4 /* TokenTypes.Named */, readNamedIdentifier(scnr));
990
- skipSpaces(scnr);
991
- return token;
992
- }
993
- if ((validListIdentifier = isListIdentifierStart(scnr, context))) {
994
- token = getToken(context, 5 /* TokenTypes.List */, readListIdentifier(scnr));
995
- skipSpaces(scnr);
996
- return token;
997
- }
998
- if ((validLiteral = isLiteralStart(scnr, context))) {
999
- token = getToken(context, 6 /* TokenTypes.Literal */, readLiteral(scnr));
1000
- skipSpaces(scnr);
1001
- return token;
1002
- }
1003
- if (!validNamedIdentifier && !validListIdentifier && !validLiteral) {
1004
- // TODO: we should be re-designed invalid cases, when we will extend message syntax near the future ...
1005
- token = getToken(context, 12 /* TokenTypes.InvalidPlace */, readInvalidIdentifier(scnr));
1006
- emitError(CompileErrorCodes.INVALID_TOKEN_IN_PLACEHOLDER, currentPosition(), 0, token.value);
1007
- skipSpaces(scnr);
1008
- return token;
1009
- }
1010
- break;
1011
- }
1012
- }
1013
- return token;
1014
- }
1015
- // TODO: We need refactoring of token parsing ...
1016
- function readTokenInLinked(scnr, context) {
1017
- const { currentType } = context;
1018
- let token = null;
1019
- const ch = scnr.currentChar();
1020
- if ((currentType === 7 /* TokenTypes.LinkedAlias */ ||
1021
- currentType === 8 /* TokenTypes.LinkedDot */ ||
1022
- currentType === 11 /* TokenTypes.LinkedModifier */ ||
1023
- currentType === 9 /* TokenTypes.LinkedDelimiter */) &&
1024
- (ch === CHAR_LF || ch === CHAR_SP)) {
1025
- emitError(CompileErrorCodes.INVALID_LINKED_FORMAT, currentPosition(), 0);
1026
- }
1027
- switch (ch) {
1028
- case "@" /* TokenChars.LinkedAlias */:
1029
- scnr.next();
1030
- token = getToken(context, 7 /* TokenTypes.LinkedAlias */, "@" /* TokenChars.LinkedAlias */);
1031
- context.inLinked = true;
1032
- return token;
1033
- case "." /* TokenChars.LinkedDot */:
1034
- skipSpaces(scnr);
1035
- scnr.next();
1036
- return getToken(context, 8 /* TokenTypes.LinkedDot */, "." /* TokenChars.LinkedDot */);
1037
- case ":" /* TokenChars.LinkedDelimiter */:
1038
- skipSpaces(scnr);
1039
- scnr.next();
1040
- return getToken(context, 9 /* TokenTypes.LinkedDelimiter */, ":" /* TokenChars.LinkedDelimiter */);
1041
- default:
1042
- if (isPluralStart(scnr)) {
1043
- token = getToken(context, 1 /* TokenTypes.Pipe */, readPlural(scnr));
1044
- // reset
1045
- context.braceNest = 0;
1046
- context.inLinked = false;
1047
- return token;
1048
- }
1049
- if (isLinkedDotStart(scnr, context) ||
1050
- isLinkedDelimiterStart(scnr, context)) {
1051
- skipSpaces(scnr);
1052
- return readTokenInLinked(scnr, context);
1053
- }
1054
- if (isLinkedModifierStart(scnr, context)) {
1055
- skipSpaces(scnr);
1056
- return getToken(context, 11 /* TokenTypes.LinkedModifier */, readLinkedModifier(scnr));
1057
- }
1058
- if (isLinkedReferStart(scnr, context)) {
1059
- skipSpaces(scnr);
1060
- if (ch === "{" /* TokenChars.BraceLeft */) {
1061
- // scan the placeholder
1062
- return readTokenInPlaceholder(scnr, context) || token;
1063
- }
1064
- else {
1065
- return getToken(context, 10 /* TokenTypes.LinkedKey */, readLinkedRefer(scnr));
1066
- }
1067
- }
1068
- if (currentType === 7 /* TokenTypes.LinkedAlias */) {
1069
- emitError(CompileErrorCodes.INVALID_LINKED_FORMAT, currentPosition(), 0);
1070
- }
1071
- context.braceNest = 0;
1072
- context.inLinked = false;
1073
- return readToken(scnr, context);
1074
- }
1075
- }
1076
- // TODO: We need refactoring of token parsing ...
1077
- function readToken(scnr, context) {
1078
- let token = { type: 13 /* TokenTypes.EOF */ };
1079
- if (context.braceNest > 0) {
1080
- return readTokenInPlaceholder(scnr, context) || getEndToken(context);
1081
- }
1082
- if (context.inLinked) {
1083
- return readTokenInLinked(scnr, context) || getEndToken(context);
1084
- }
1085
- const ch = scnr.currentChar();
1086
- switch (ch) {
1087
- case "{" /* TokenChars.BraceLeft */:
1088
- return readTokenInPlaceholder(scnr, context) || getEndToken(context);
1089
- case "}" /* TokenChars.BraceRight */:
1090
- emitError(CompileErrorCodes.UNBALANCED_CLOSING_BRACE, currentPosition(), 0);
1091
- scnr.next();
1092
- return getToken(context, 3 /* TokenTypes.BraceRight */, "}" /* TokenChars.BraceRight */);
1093
- case "@" /* TokenChars.LinkedAlias */:
1094
- return readTokenInLinked(scnr, context) || getEndToken(context);
1095
- default: {
1096
- if (isPluralStart(scnr)) {
1097
- token = getToken(context, 1 /* TokenTypes.Pipe */, readPlural(scnr));
1098
- // reset
1099
- context.braceNest = 0;
1100
- context.inLinked = false;
1101
- return token;
1102
- }
1103
- if (isTextStart(scnr)) {
1104
- return getToken(context, 0 /* TokenTypes.Text */, readText(scnr));
1105
- }
1106
- break;
1107
- }
1108
- }
1109
- return token;
1110
- }
1111
- function nextToken() {
1112
- const { currentType, offset, startLoc, endLoc } = _context;
1113
- _context.lastType = currentType;
1114
- _context.lastOffset = offset;
1115
- _context.lastStartLoc = startLoc;
1116
- _context.lastEndLoc = endLoc;
1117
- _context.offset = currentOffset();
1118
- _context.startLoc = currentPosition();
1119
- if (_scnr.currentChar() === EOF) {
1120
- return getToken(_context, 13 /* TokenTypes.EOF */);
1121
- }
1122
- return readToken(_scnr, _context);
1123
- }
1124
- return {
1125
- nextToken,
1126
- currentOffset,
1127
- currentPosition,
1128
- context
1129
- };
459
+ const location = options.location !== false;
460
+ const _scnr = createScanner(source);
461
+ const currentOffset = () => _scnr.index();
462
+ const currentPosition = () => createPosition(_scnr.line(), _scnr.column(), _scnr.index());
463
+ const _initLoc = currentPosition();
464
+ const _initOffset = currentOffset();
465
+ const _context = {
466
+ currentType: 13,
467
+ offset: _initOffset,
468
+ startLoc: _initLoc,
469
+ endLoc: _initLoc,
470
+ lastType: 13,
471
+ lastOffset: _initOffset,
472
+ lastStartLoc: _initLoc,
473
+ lastEndLoc: _initLoc,
474
+ braceNest: 0,
475
+ inLinked: false,
476
+ text: ""
477
+ };
478
+ const context = () => _context;
479
+ const { onError } = options;
480
+ function emitError(code, pos, offset, ...args) {
481
+ const ctx = context();
482
+ pos.column += offset;
483
+ pos.offset += offset;
484
+ if (onError) onError(createCompileError(code, location ? createLocation(ctx.startLoc, pos) : null, {
485
+ domain: ERROR_DOMAIN$1,
486
+ args
487
+ }));
488
+ }
489
+ function getToken(context, type, value) {
490
+ context.endLoc = currentPosition();
491
+ context.currentType = type;
492
+ const token = { type };
493
+ if (location) token.loc = createLocation(context.startLoc, context.endLoc);
494
+ if (value != null) token.value = value;
495
+ return token;
496
+ }
497
+ const getEndToken = (context) => getToken(context, 13);
498
+ function eat(scnr, ch) {
499
+ if (scnr.currentChar() === ch) {
500
+ scnr.next();
501
+ return ch;
502
+ } else {
503
+ emitError(CompileErrorCodes.EXPECTED_TOKEN, currentPosition(), 0, ch);
504
+ return "";
505
+ }
506
+ }
507
+ function peekSpaces(scnr) {
508
+ let buf = "";
509
+ while (scnr.currentPeek() === " " || scnr.currentPeek() === "\n") {
510
+ buf += scnr.currentPeek();
511
+ scnr.peek();
512
+ }
513
+ return buf;
514
+ }
515
+ function skipSpaces(scnr) {
516
+ const buf = peekSpaces(scnr);
517
+ scnr.skipToPeek();
518
+ return buf;
519
+ }
520
+ function isIdentifierStart(ch) {
521
+ if (ch === EOF) return false;
522
+ const cc = ch.charCodeAt(0);
523
+ return cc >= 97 && cc <= 122 || cc >= 65 && cc <= 90 || cc === 95;
524
+ }
525
+ function isNumberStart(ch) {
526
+ if (ch === EOF) return false;
527
+ const cc = ch.charCodeAt(0);
528
+ return cc >= 48 && cc <= 57;
529
+ }
530
+ function isNamedIdentifierStart(scnr, context) {
531
+ const { currentType } = context;
532
+ if (currentType !== 2) return false;
533
+ peekSpaces(scnr);
534
+ const ret = isIdentifierStart(scnr.currentPeek());
535
+ scnr.resetPeek();
536
+ return ret;
537
+ }
538
+ function isListIdentifierStart(scnr, context) {
539
+ const { currentType } = context;
540
+ if (currentType !== 2) return false;
541
+ peekSpaces(scnr);
542
+ const ret = isNumberStart(scnr.currentPeek() === "-" ? scnr.peek() : scnr.currentPeek());
543
+ scnr.resetPeek();
544
+ return ret;
545
+ }
546
+ function isLiteralStart(scnr, context) {
547
+ const { currentType } = context;
548
+ if (currentType !== 2) return false;
549
+ peekSpaces(scnr);
550
+ const ret = scnr.currentPeek() === LITERAL_DELIMITER;
551
+ scnr.resetPeek();
552
+ return ret;
553
+ }
554
+ function isLinkedDotStart(scnr, context) {
555
+ const { currentType } = context;
556
+ if (currentType !== 7) return false;
557
+ peekSpaces(scnr);
558
+ const ret = scnr.currentPeek() === ".";
559
+ scnr.resetPeek();
560
+ return ret;
561
+ }
562
+ function isLinkedModifierStart(scnr, context) {
563
+ const { currentType } = context;
564
+ if (currentType !== 8) return false;
565
+ peekSpaces(scnr);
566
+ const ret = isIdentifierStart(scnr.currentPeek());
567
+ scnr.resetPeek();
568
+ return ret;
569
+ }
570
+ function isLinkedDelimiterStart(scnr, context) {
571
+ const { currentType } = context;
572
+ if (!(currentType === 7 || currentType === 11)) return false;
573
+ peekSpaces(scnr);
574
+ const ret = scnr.currentPeek() === ":";
575
+ scnr.resetPeek();
576
+ return ret;
577
+ }
578
+ function isLinkedReferStart(scnr, context) {
579
+ const { currentType } = context;
580
+ if (currentType !== 9) return false;
581
+ const fn = () => {
582
+ const ch = scnr.currentPeek();
583
+ if (ch === "{") return isIdentifierStart(scnr.peek());
584
+ else if (ch === "@" || ch === "|" || ch === ":" || ch === "." || ch === " " || !ch) return false;
585
+ else if (ch === "\n") {
586
+ scnr.peek();
587
+ return fn();
588
+ } else return isTextStart(scnr, false);
589
+ };
590
+ const ret = fn();
591
+ scnr.resetPeek();
592
+ return ret;
593
+ }
594
+ function isPluralStart(scnr) {
595
+ peekSpaces(scnr);
596
+ const ret = scnr.currentPeek() === "|";
597
+ scnr.resetPeek();
598
+ return ret;
599
+ }
600
+ function isTextStart(scnr, reset = true) {
601
+ const fn = (hasSpace = false, prev = "") => {
602
+ const ch = scnr.currentPeek();
603
+ if (ch === "{") return hasSpace;
604
+ else if (ch === "@" || !ch) return hasSpace;
605
+ else if (ch === "|") return !(prev === " " || prev === "\n");
606
+ else if (ch === " ") {
607
+ scnr.peek();
608
+ return fn(true, " ");
609
+ } else if (ch === "\n") {
610
+ scnr.peek();
611
+ return fn(true, "\n");
612
+ } else return true;
613
+ };
614
+ const ret = fn();
615
+ reset && scnr.resetPeek();
616
+ return ret;
617
+ }
618
+ function takeChar(scnr, fn) {
619
+ const ch = scnr.currentChar();
620
+ if (ch === EOF) return EOF;
621
+ if (fn(ch)) {
622
+ scnr.next();
623
+ return ch;
624
+ }
625
+ return null;
626
+ }
627
+ function isIdentifier(ch) {
628
+ const cc = ch.charCodeAt(0);
629
+ return cc >= 97 && cc <= 122 || cc >= 65 && cc <= 90 || cc >= 48 && cc <= 57 || cc === 95 || cc === 36;
630
+ }
631
+ function takeIdentifierChar(scnr) {
632
+ return takeChar(scnr, isIdentifier);
633
+ }
634
+ function isNamedIdentifier(ch) {
635
+ const cc = ch.charCodeAt(0);
636
+ return cc >= 97 && cc <= 122 || cc >= 65 && cc <= 90 || cc >= 48 && cc <= 57 || cc === 95 || cc === 36 || cc === 45;
637
+ }
638
+ function takeNamedIdentifierChar(scnr) {
639
+ return takeChar(scnr, isNamedIdentifier);
640
+ }
641
+ function isDigit(ch) {
642
+ const cc = ch.charCodeAt(0);
643
+ return cc >= 48 && cc <= 57;
644
+ }
645
+ function takeDigit(scnr) {
646
+ return takeChar(scnr, isDigit);
647
+ }
648
+ function isHexDigit(ch) {
649
+ const cc = ch.charCodeAt(0);
650
+ return cc >= 48 && cc <= 57 || cc >= 65 && cc <= 70 || cc >= 97 && cc <= 102;
651
+ }
652
+ function takeHexDigit(scnr) {
653
+ return takeChar(scnr, isHexDigit);
654
+ }
655
+ function getDigits(scnr) {
656
+ let ch = "";
657
+ let num = "";
658
+ while (ch = takeDigit(scnr)) num += ch;
659
+ return num;
660
+ }
661
+ function readText(scnr) {
662
+ let buf = "";
663
+ while (true) {
664
+ const ch = scnr.currentChar();
665
+ if (ch === "\\") {
666
+ const nextCh = scnr.peek();
667
+ if (nextCh === "{" || nextCh === "}" || nextCh === "@" || nextCh === "|" || nextCh === "\\") {
668
+ buf += ch + nextCh;
669
+ scnr.next();
670
+ scnr.next();
671
+ } else {
672
+ scnr.resetPeek();
673
+ buf += ch;
674
+ scnr.next();
675
+ }
676
+ } else if (ch === "{" || ch === "}" || ch === "@" || ch === "|" || !ch) break;
677
+ else if (ch === " " || ch === "\n") if (isTextStart(scnr)) {
678
+ buf += ch;
679
+ scnr.next();
680
+ } else if (isPluralStart(scnr)) break;
681
+ else {
682
+ buf += ch;
683
+ scnr.next();
684
+ }
685
+ else {
686
+ buf += ch;
687
+ scnr.next();
688
+ }
689
+ }
690
+ return buf;
691
+ }
692
+ function readNamedIdentifier(scnr) {
693
+ skipSpaces(scnr);
694
+ let ch = "";
695
+ let name = "";
696
+ while (ch = takeNamedIdentifierChar(scnr)) name += ch;
697
+ const currentChar = scnr.currentChar();
698
+ if (currentChar && currentChar !== "}" && currentChar !== EOF && currentChar !== " " && currentChar !== "\n" && currentChar !== " ") {
699
+ const invalidPart = readInvalidIdentifier(scnr);
700
+ emitError(CompileErrorCodes.INVALID_TOKEN_IN_PLACEHOLDER, currentPosition(), 0, name + invalidPart);
701
+ return name + invalidPart;
702
+ }
703
+ if (scnr.currentChar() === EOF) emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
704
+ return name;
705
+ }
706
+ function readListIdentifier(scnr) {
707
+ skipSpaces(scnr);
708
+ let value = "";
709
+ if (scnr.currentChar() === "-") {
710
+ scnr.next();
711
+ value += `-${getDigits(scnr)}`;
712
+ } else value += getDigits(scnr);
713
+ if (scnr.currentChar() === EOF) emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
714
+ return value;
715
+ }
716
+ function isLiteral(ch) {
717
+ return ch !== LITERAL_DELIMITER && ch !== "\n";
718
+ }
719
+ function readLiteral(scnr) {
720
+ skipSpaces(scnr);
721
+ eat(scnr, `'`);
722
+ let ch = "";
723
+ let literal = "";
724
+ while (ch = takeChar(scnr, isLiteral)) if (ch === "\\") literal += readEscapeSequence(scnr);
725
+ else literal += ch;
726
+ const current = scnr.currentChar();
727
+ if (current === "\n" || current === EOF) {
728
+ emitError(CompileErrorCodes.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER, currentPosition(), 0);
729
+ if (current === "\n") {
730
+ scnr.next();
731
+ eat(scnr, `'`);
732
+ }
733
+ return literal;
734
+ }
735
+ eat(scnr, `'`);
736
+ return literal;
737
+ }
738
+ function readEscapeSequence(scnr) {
739
+ const ch = scnr.currentChar();
740
+ switch (ch) {
741
+ case "\\":
742
+ case `'`:
743
+ scnr.next();
744
+ return `\\${ch}`;
745
+ case "u": return readUnicodeEscapeSequence(scnr, ch, 4);
746
+ case "U": return readUnicodeEscapeSequence(scnr, ch, 6);
747
+ default:
748
+ emitError(CompileErrorCodes.UNKNOWN_ESCAPE_SEQUENCE, currentPosition(), 0, ch);
749
+ return "";
750
+ }
751
+ }
752
+ function readUnicodeEscapeSequence(scnr, unicode, digits) {
753
+ eat(scnr, unicode);
754
+ let sequence = "";
755
+ for (let i = 0; i < digits; i++) {
756
+ const ch = takeHexDigit(scnr);
757
+ if (!ch) {
758
+ emitError(CompileErrorCodes.INVALID_UNICODE_ESCAPE_SEQUENCE, currentPosition(), 0, `\\${unicode}${sequence}${scnr.currentChar()}`);
759
+ break;
760
+ }
761
+ sequence += ch;
762
+ }
763
+ return `\\${unicode}${sequence}`;
764
+ }
765
+ function isInvalidIdentifier(ch) {
766
+ return ch !== "{" && ch !== "}" && ch !== " " && ch !== "\n";
767
+ }
768
+ function readInvalidIdentifier(scnr) {
769
+ skipSpaces(scnr);
770
+ let ch = "";
771
+ let identifiers = "";
772
+ while (ch = takeChar(scnr, isInvalidIdentifier)) identifiers += ch;
773
+ return identifiers;
774
+ }
775
+ function readLinkedModifier(scnr) {
776
+ let ch = "";
777
+ let name = "";
778
+ while (ch = takeIdentifierChar(scnr)) name += ch;
779
+ return name;
780
+ }
781
+ function readLinkedRefer(scnr) {
782
+ const fn = (buf) => {
783
+ const ch = scnr.currentChar();
784
+ if (ch === "{" || ch === "@" || ch === "|" || ch === "(" || ch === ")" || !ch) return buf;
785
+ else if (ch === " ") return buf;
786
+ else if (ch === "\n" || ch === DOT) {
787
+ buf += ch;
788
+ scnr.next();
789
+ return fn(buf);
790
+ } else {
791
+ buf += ch;
792
+ scnr.next();
793
+ return fn(buf);
794
+ }
795
+ };
796
+ return fn("");
797
+ }
798
+ function readPlural(scnr) {
799
+ skipSpaces(scnr);
800
+ const plural = eat(scnr, "|");
801
+ skipSpaces(scnr);
802
+ return plural;
803
+ }
804
+ function readTokenInPlaceholder(scnr, context) {
805
+ let token = null;
806
+ switch (scnr.currentChar()) {
807
+ case "{":
808
+ if (context.braceNest >= 1) emitError(CompileErrorCodes.NOT_ALLOW_NEST_PLACEHOLDER, currentPosition(), 0);
809
+ scnr.next();
810
+ token = getToken(context, 2, "{");
811
+ skipSpaces(scnr);
812
+ context.braceNest++;
813
+ return token;
814
+ case "}":
815
+ if (context.braceNest > 0 && context.currentType === 2) emitError(CompileErrorCodes.EMPTY_PLACEHOLDER, currentPosition(), 0);
816
+ scnr.next();
817
+ token = getToken(context, 3, "}");
818
+ context.braceNest--;
819
+ context.braceNest > 0 && skipSpaces(scnr);
820
+ if (context.inLinked && context.braceNest === 0) context.inLinked = false;
821
+ return token;
822
+ case "@":
823
+ if (context.braceNest > 0) emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
824
+ token = readTokenInLinked(scnr, context) || getEndToken(context);
825
+ context.braceNest = 0;
826
+ return token;
827
+ default: {
828
+ let validNamedIdentifier = true;
829
+ let validListIdentifier = true;
830
+ let validLiteral = true;
831
+ if (isPluralStart(scnr)) {
832
+ if (context.braceNest > 0) emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
833
+ token = getToken(context, 1, readPlural(scnr));
834
+ context.braceNest = 0;
835
+ context.inLinked = false;
836
+ return token;
837
+ }
838
+ if (context.braceNest > 0 && (context.currentType === 4 || context.currentType === 5 || context.currentType === 6)) {
839
+ emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
840
+ context.braceNest = 0;
841
+ return readToken(scnr, context);
842
+ }
843
+ if (validNamedIdentifier = isNamedIdentifierStart(scnr, context)) {
844
+ token = getToken(context, 4, readNamedIdentifier(scnr));
845
+ skipSpaces(scnr);
846
+ return token;
847
+ }
848
+ if (validListIdentifier = isListIdentifierStart(scnr, context)) {
849
+ token = getToken(context, 5, readListIdentifier(scnr));
850
+ skipSpaces(scnr);
851
+ return token;
852
+ }
853
+ if (validLiteral = isLiteralStart(scnr, context)) {
854
+ token = getToken(context, 6, readLiteral(scnr));
855
+ skipSpaces(scnr);
856
+ return token;
857
+ }
858
+ if (!validNamedIdentifier && !validListIdentifier && !validLiteral) {
859
+ token = getToken(context, 12, readInvalidIdentifier(scnr));
860
+ emitError(CompileErrorCodes.INVALID_TOKEN_IN_PLACEHOLDER, currentPosition(), 0, token.value);
861
+ skipSpaces(scnr);
862
+ return token;
863
+ }
864
+ break;
865
+ }
866
+ }
867
+ return token;
868
+ }
869
+ function readTokenInLinked(scnr, context) {
870
+ const { currentType } = context;
871
+ let token = null;
872
+ const ch = scnr.currentChar();
873
+ if ((currentType === 7 || currentType === 8 || currentType === 11 || currentType === 9) && (ch === "\n" || ch === " ")) emitError(CompileErrorCodes.INVALID_LINKED_FORMAT, currentPosition(), 0);
874
+ switch (ch) {
875
+ case "@":
876
+ scnr.next();
877
+ token = getToken(context, 7, "@");
878
+ context.inLinked = true;
879
+ return token;
880
+ case ".":
881
+ skipSpaces(scnr);
882
+ scnr.next();
883
+ return getToken(context, 8, ".");
884
+ case ":":
885
+ skipSpaces(scnr);
886
+ scnr.next();
887
+ return getToken(context, 9, ":");
888
+ default:
889
+ if (isPluralStart(scnr)) {
890
+ token = getToken(context, 1, readPlural(scnr));
891
+ context.braceNest = 0;
892
+ context.inLinked = false;
893
+ return token;
894
+ }
895
+ if (isLinkedDotStart(scnr, context) || isLinkedDelimiterStart(scnr, context)) {
896
+ skipSpaces(scnr);
897
+ return readTokenInLinked(scnr, context);
898
+ }
899
+ if (isLinkedModifierStart(scnr, context)) {
900
+ skipSpaces(scnr);
901
+ return getToken(context, 11, readLinkedModifier(scnr));
902
+ }
903
+ if (isLinkedReferStart(scnr, context)) {
904
+ skipSpaces(scnr);
905
+ if (ch === "{") return readTokenInPlaceholder(scnr, context) || token;
906
+ else return getToken(context, 10, readLinkedRefer(scnr));
907
+ }
908
+ if (currentType === 7) emitError(CompileErrorCodes.INVALID_LINKED_FORMAT, currentPosition(), 0);
909
+ context.braceNest = 0;
910
+ context.inLinked = false;
911
+ return readToken(scnr, context);
912
+ }
913
+ }
914
+ function readToken(scnr, context) {
915
+ let token = { type: 13 };
916
+ if (context.braceNest > 0) return readTokenInPlaceholder(scnr, context) || getEndToken(context);
917
+ if (context.inLinked) return readTokenInLinked(scnr, context) || getEndToken(context);
918
+ switch (scnr.currentChar()) {
919
+ case "{": return readTokenInPlaceholder(scnr, context) || getEndToken(context);
920
+ case "}":
921
+ emitError(CompileErrorCodes.UNBALANCED_CLOSING_BRACE, currentPosition(), 0);
922
+ scnr.next();
923
+ return getToken(context, 3, "}");
924
+ case "@": return readTokenInLinked(scnr, context) || getEndToken(context);
925
+ default:
926
+ if (isPluralStart(scnr)) {
927
+ token = getToken(context, 1, readPlural(scnr));
928
+ context.braceNest = 0;
929
+ context.inLinked = false;
930
+ return token;
931
+ }
932
+ if (isTextStart(scnr)) return getToken(context, 0, readText(scnr));
933
+ break;
934
+ }
935
+ return token;
936
+ }
937
+ function nextToken() {
938
+ const { currentType, offset, startLoc, endLoc } = _context;
939
+ _context.lastType = currentType;
940
+ _context.lastOffset = offset;
941
+ _context.lastStartLoc = startLoc;
942
+ _context.lastEndLoc = endLoc;
943
+ _context.offset = currentOffset();
944
+ _context.startLoc = currentPosition();
945
+ if (_scnr.currentChar() === EOF) return getToken(_context, 13);
946
+ return readToken(_scnr, _context);
947
+ }
948
+ return {
949
+ nextToken,
950
+ currentOffset,
951
+ currentPosition,
952
+ context
953
+ };
954
+ }
955
+ //#endregion
956
+ //#region packages/message-compiler/src/parser.ts
957
+ const ERROR_DOMAIN = "parser";
958
+ const KNOWN_ESCAPES = /\\\\|\\'|\\u([0-9a-fA-F]{4})|\\U([0-9a-fA-F]{6})/g;
959
+ const TEXT_ESCAPES = /\\([\\@{}|])/g;
960
+ function fromTextEscapeSequence(_match, char) {
961
+ return char;
1130
962
  }
1131
-
1132
- const ERROR_DOMAIN = 'parser';
1133
- // Backslash backslash, backslash quote, uHHHH, UHHHHHH.
1134
- const KNOWN_ESCAPES = /(?:\\\\|\\'|\\u([0-9a-fA-F]{4})|\\U([0-9a-fA-F]{6}))/g;
1135
963
  function fromEscapeSequence(match, codePoint4, codePoint6) {
1136
- switch (match) {
1137
- case `\\\\`:
1138
- return `\\`;
1139
- // eslint-disable-next-line no-useless-escape
1140
- case `\\\'`:
1141
- // eslint-disable-next-line no-useless-escape
1142
- return `\'`;
1143
- default: {
1144
- const codePoint = parseInt(codePoint4 || codePoint6, 16);
1145
- if (codePoint <= 0xd7ff || codePoint >= 0xe000) {
1146
- return String.fromCodePoint(codePoint);
1147
- }
1148
- // invalid ...
1149
- // Replace them with U+FFFD REPLACEMENT CHARACTER.
1150
- return '�';
1151
- }
1152
- }
964
+ switch (match) {
965
+ case `\\\\`: return `\\`;
966
+ case `\\'`: return `'`;
967
+ default: {
968
+ const codePoint = parseInt(codePoint4 || codePoint6, 16);
969
+ if (codePoint <= 55295 || codePoint >= 57344) return String.fromCodePoint(codePoint);
970
+ return "�";
971
+ }
972
+ }
1153
973
  }
1154
974
  function createParser(options = {}) {
1155
- const location = options.location !== false;
1156
- const { onError } = options;
1157
- function emitError(tokenzer, code, start, offset, ...args) {
1158
- const end = tokenzer.currentPosition();
1159
- end.offset += offset;
1160
- end.column += offset;
1161
- if (onError) {
1162
- const loc = location ? createLocation(start, end) : null;
1163
- const err = createCompileError(code, loc, {
1164
- domain: ERROR_DOMAIN,
1165
- args
1166
- });
1167
- onError(err);
1168
- }
1169
- }
1170
- function startNode(type, offset, loc) {
1171
- const node = { type };
1172
- if (location) {
1173
- node.start = offset;
1174
- node.end = offset;
1175
- node.loc = { start: loc, end: loc };
1176
- }
1177
- return node;
1178
- }
1179
- function endNode(node, offset, pos, type) {
1180
- if (location) {
1181
- node.end = offset;
1182
- if (node.loc) {
1183
- node.loc.end = pos;
1184
- }
1185
- }
1186
- }
1187
- function parseText(tokenizer, value) {
1188
- const context = tokenizer.context();
1189
- const node = startNode(3 /* NodeTypes.Text */, context.offset, context.startLoc);
1190
- node.value = value;
1191
- endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
1192
- return node;
1193
- }
1194
- function parseList(tokenizer, index) {
1195
- const context = tokenizer.context();
1196
- const { lastOffset: offset, lastStartLoc: loc } = context; // get brace left loc
1197
- const node = startNode(5 /* NodeTypes.List */, offset, loc);
1198
- node.index = parseInt(index, 10);
1199
- tokenizer.nextToken(); // skip brach right
1200
- endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
1201
- return node;
1202
- }
1203
- function parseNamed(tokenizer, key) {
1204
- const context = tokenizer.context();
1205
- const { lastOffset: offset, lastStartLoc: loc } = context; // get brace left loc
1206
- const node = startNode(4 /* NodeTypes.Named */, offset, loc);
1207
- node.key = key;
1208
- tokenizer.nextToken(); // skip brach right
1209
- endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
1210
- return node;
1211
- }
1212
- function parseLiteral(tokenizer, value) {
1213
- const context = tokenizer.context();
1214
- const { lastOffset: offset, lastStartLoc: loc } = context; // get brace left loc
1215
- const node = startNode(9 /* NodeTypes.Literal */, offset, loc);
1216
- node.value = value.replace(KNOWN_ESCAPES, fromEscapeSequence);
1217
- tokenizer.nextToken(); // skip brach right
1218
- endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
1219
- return node;
1220
- }
1221
- function parseLinkedModifier(tokenizer) {
1222
- const token = tokenizer.nextToken();
1223
- const context = tokenizer.context();
1224
- const { lastOffset: offset, lastStartLoc: loc } = context; // get linked dot loc
1225
- const node = startNode(8 /* NodeTypes.LinkedModifier */, offset, loc);
1226
- if (token.type !== 11 /* TokenTypes.LinkedModifier */) {
1227
- // empty modifier
1228
- emitError(tokenizer, CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_MODIFIER, context.lastStartLoc, 0);
1229
- node.value = '';
1230
- endNode(node, offset, loc);
1231
- return {
1232
- nextConsumeToken: token,
1233
- node
1234
- };
1235
- }
1236
- // check token
1237
- if (token.value == null) {
1238
- emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1239
- }
1240
- node.value = token.value || '';
1241
- endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
1242
- return {
1243
- node
1244
- };
1245
- }
1246
- function parseLinkedKey(tokenizer, value) {
1247
- const context = tokenizer.context();
1248
- const node = startNode(7 /* NodeTypes.LinkedKey */, context.offset, context.startLoc);
1249
- node.value = value;
1250
- endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
1251
- return node;
1252
- }
1253
- function parseLinked(tokenizer) {
1254
- const context = tokenizer.context();
1255
- const linkedNode = startNode(6 /* NodeTypes.Linked */, context.offset, context.startLoc);
1256
- let token = tokenizer.nextToken();
1257
- if (token.type === 8 /* TokenTypes.LinkedDot */) {
1258
- const parsed = parseLinkedModifier(tokenizer);
1259
- linkedNode.modifier = parsed.node;
1260
- token = parsed.nextConsumeToken || tokenizer.nextToken();
1261
- }
1262
- // asset check token
1263
- if (token.type !== 9 /* TokenTypes.LinkedDelimiter */) {
1264
- emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1265
- }
1266
- token = tokenizer.nextToken();
1267
- // skip brace left
1268
- if (token.type === 2 /* TokenTypes.BraceLeft */) {
1269
- token = tokenizer.nextToken();
1270
- }
1271
- switch (token.type) {
1272
- case 10 /* TokenTypes.LinkedKey */:
1273
- if (token.value == null) {
1274
- emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1275
- }
1276
- linkedNode.key = parseLinkedKey(tokenizer, token.value || '');
1277
- break;
1278
- case 4 /* TokenTypes.Named */:
1279
- if (token.value == null) {
1280
- emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1281
- }
1282
- linkedNode.key = parseNamed(tokenizer, token.value || '');
1283
- break;
1284
- case 5 /* TokenTypes.List */:
1285
- if (token.value == null) {
1286
- emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1287
- }
1288
- linkedNode.key = parseList(tokenizer, token.value || '');
1289
- break;
1290
- case 6 /* TokenTypes.Literal */:
1291
- if (token.value == null) {
1292
- emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1293
- }
1294
- linkedNode.key = parseLiteral(tokenizer, token.value || '');
1295
- break;
1296
- default: {
1297
- // empty key
1298
- emitError(tokenizer, CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_KEY, context.lastStartLoc, 0);
1299
- const nextContext = tokenizer.context();
1300
- const emptyLinkedKeyNode = startNode(7 /* NodeTypes.LinkedKey */, nextContext.offset, nextContext.startLoc);
1301
- emptyLinkedKeyNode.value = '';
1302
- endNode(emptyLinkedKeyNode, nextContext.offset, nextContext.startLoc);
1303
- linkedNode.key = emptyLinkedKeyNode;
1304
- endNode(linkedNode, nextContext.offset, nextContext.startLoc);
1305
- return {
1306
- nextConsumeToken: token,
1307
- node: linkedNode
1308
- };
1309
- }
1310
- }
1311
- endNode(linkedNode, tokenizer.currentOffset(), tokenizer.currentPosition());
1312
- return {
1313
- node: linkedNode
1314
- };
1315
- }
1316
- function parseMessage(tokenizer) {
1317
- const context = tokenizer.context();
1318
- const startOffset = context.currentType === 1 /* TokenTypes.Pipe */
1319
- ? tokenizer.currentOffset()
1320
- : context.offset;
1321
- const startLoc = context.currentType === 1 /* TokenTypes.Pipe */
1322
- ? context.endLoc
1323
- : context.startLoc;
1324
- const node = startNode(2 /* NodeTypes.Message */, startOffset, startLoc);
1325
- node.items = [];
1326
- let nextToken = null;
1327
- do {
1328
- const token = nextToken || tokenizer.nextToken();
1329
- nextToken = null;
1330
- switch (token.type) {
1331
- case 0 /* TokenTypes.Text */:
1332
- if (token.value == null) {
1333
- emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1334
- }
1335
- node.items.push(parseText(tokenizer, token.value || ''));
1336
- break;
1337
- case 5 /* TokenTypes.List */:
1338
- if (token.value == null) {
1339
- emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1340
- }
1341
- node.items.push(parseList(tokenizer, token.value || ''));
1342
- break;
1343
- case 4 /* TokenTypes.Named */:
1344
- if (token.value == null) {
1345
- emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1346
- }
1347
- node.items.push(parseNamed(tokenizer, token.value || ''));
1348
- break;
1349
- case 6 /* TokenTypes.Literal */:
1350
- if (token.value == null) {
1351
- emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1352
- }
1353
- node.items.push(parseLiteral(tokenizer, token.value || ''));
1354
- break;
1355
- case 7 /* TokenTypes.LinkedAlias */: {
1356
- const parsed = parseLinked(tokenizer);
1357
- node.items.push(parsed.node);
1358
- nextToken = parsed.nextConsumeToken || null;
1359
- break;
1360
- }
1361
- }
1362
- } while (context.currentType !== 13 /* TokenTypes.EOF */ &&
1363
- context.currentType !== 1 /* TokenTypes.Pipe */);
1364
- // adjust message node loc
1365
- const endOffset = context.currentType === 1 /* TokenTypes.Pipe */
1366
- ? context.lastOffset
1367
- : tokenizer.currentOffset();
1368
- const endLoc = context.currentType === 1 /* TokenTypes.Pipe */
1369
- ? context.lastEndLoc
1370
- : tokenizer.currentPosition();
1371
- endNode(node, endOffset, endLoc);
1372
- return node;
1373
- }
1374
- function parsePlural(tokenizer, offset, loc, msgNode) {
1375
- const context = tokenizer.context();
1376
- let hasEmptyMessage = msgNode.items.length === 0;
1377
- const node = startNode(1 /* NodeTypes.Plural */, offset, loc);
1378
- node.cases = [];
1379
- node.cases.push(msgNode);
1380
- do {
1381
- const msg = parseMessage(tokenizer);
1382
- if (!hasEmptyMessage) {
1383
- hasEmptyMessage = msg.items.length === 0;
1384
- }
1385
- node.cases.push(msg);
1386
- } while (context.currentType !== 13 /* TokenTypes.EOF */);
1387
- if (hasEmptyMessage) {
1388
- emitError(tokenizer, CompileErrorCodes.MUST_HAVE_MESSAGES_IN_PLURAL, loc, 0);
1389
- }
1390
- endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
1391
- return node;
1392
- }
1393
- function parseResource(tokenizer) {
1394
- const context = tokenizer.context();
1395
- const { offset, startLoc } = context;
1396
- const msgNode = parseMessage(tokenizer);
1397
- if (context.currentType === 13 /* TokenTypes.EOF */) {
1398
- return msgNode;
1399
- }
1400
- else {
1401
- return parsePlural(tokenizer, offset, startLoc, msgNode);
1402
- }
1403
- }
1404
- function parse(source) {
1405
- const tokenizer = createTokenizer(source, assign({}, options));
1406
- const context = tokenizer.context();
1407
- const node = startNode(0 /* NodeTypes.Resource */, context.offset, context.startLoc);
1408
- if (location && node.loc) {
1409
- node.loc.source = source;
1410
- }
1411
- node.body = parseResource(tokenizer);
1412
- if (options.onCacheKey) {
1413
- node.cacheKey = options.onCacheKey(source);
1414
- }
1415
- // assert whether achieved to EOF
1416
- if (context.currentType !== 13 /* TokenTypes.EOF */) {
1417
- emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, source[context.offset] || '');
1418
- }
1419
- endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
1420
- return node;
1421
- }
1422
- return { parse };
975
+ const location = options.location !== false;
976
+ const { onError } = options;
977
+ function emitError(tokenzer, code, start, offset, ...args) {
978
+ const end = tokenzer.currentPosition();
979
+ end.offset += offset;
980
+ end.column += offset;
981
+ if (onError) onError(createCompileError(code, location ? createLocation(start, end) : null, {
982
+ domain: ERROR_DOMAIN,
983
+ args
984
+ }));
985
+ }
986
+ function startNode(type, offset, loc) {
987
+ const node = { type };
988
+ if (location) {
989
+ node.start = offset;
990
+ node.end = offset;
991
+ node.loc = {
992
+ start: loc,
993
+ end: loc
994
+ };
995
+ }
996
+ return node;
997
+ }
998
+ function endNode(node, offset, pos, type) {
999
+ if (type) node.type = type;
1000
+ if (location) {
1001
+ node.end = offset;
1002
+ if (node.loc) node.loc.end = pos;
1003
+ }
1004
+ }
1005
+ function parseText(tokenizer, value) {
1006
+ const context = tokenizer.context();
1007
+ const node = startNode(3, context.offset, context.startLoc);
1008
+ node.value = value.replace(TEXT_ESCAPES, fromTextEscapeSequence);
1009
+ endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
1010
+ return node;
1011
+ }
1012
+ function parseList(tokenizer, index) {
1013
+ const { lastOffset: offset, lastStartLoc: loc } = tokenizer.context();
1014
+ const node = startNode(5, offset, loc);
1015
+ node.index = parseInt(index, 10);
1016
+ tokenizer.nextToken();
1017
+ endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
1018
+ return node;
1019
+ }
1020
+ function parseNamed(tokenizer, key) {
1021
+ const { lastOffset: offset, lastStartLoc: loc } = tokenizer.context();
1022
+ const node = startNode(4, offset, loc);
1023
+ node.key = key;
1024
+ tokenizer.nextToken();
1025
+ endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
1026
+ return node;
1027
+ }
1028
+ function parseLiteral(tokenizer, value) {
1029
+ const { lastOffset: offset, lastStartLoc: loc } = tokenizer.context();
1030
+ const node = startNode(9, offset, loc);
1031
+ node.value = value.replace(KNOWN_ESCAPES, fromEscapeSequence);
1032
+ tokenizer.nextToken();
1033
+ endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
1034
+ return node;
1035
+ }
1036
+ function parseLinkedModifier(tokenizer) {
1037
+ const token = tokenizer.nextToken();
1038
+ const context = tokenizer.context();
1039
+ const { lastOffset: offset, lastStartLoc: loc } = context;
1040
+ const node = startNode(8, offset, loc);
1041
+ if (token.type !== 11) {
1042
+ emitError(tokenizer, CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_MODIFIER, context.lastStartLoc, 0);
1043
+ node.value = "";
1044
+ endNode(node, offset, loc);
1045
+ return {
1046
+ nextConsumeToken: token,
1047
+ node
1048
+ };
1049
+ }
1050
+ if (token.value == null) emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1051
+ node.value = token.value || "";
1052
+ endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
1053
+ return { node };
1054
+ }
1055
+ function parseLinkedKey(tokenizer, value) {
1056
+ const context = tokenizer.context();
1057
+ const node = startNode(7, context.offset, context.startLoc);
1058
+ node.value = value;
1059
+ endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
1060
+ return node;
1061
+ }
1062
+ function parseLinked(tokenizer) {
1063
+ const context = tokenizer.context();
1064
+ const linkedNode = startNode(6, context.offset, context.startLoc);
1065
+ let token = tokenizer.nextToken();
1066
+ if (token.type === 8) {
1067
+ const parsed = parseLinkedModifier(tokenizer);
1068
+ linkedNode.modifier = parsed.node;
1069
+ token = parsed.nextConsumeToken || tokenizer.nextToken();
1070
+ }
1071
+ if (token.type !== 9) emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1072
+ token = tokenizer.nextToken();
1073
+ if (token.type === 2) token = tokenizer.nextToken();
1074
+ switch (token.type) {
1075
+ case 10:
1076
+ if (token.value == null) emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1077
+ linkedNode.key = parseLinkedKey(tokenizer, token.value || "");
1078
+ break;
1079
+ case 4:
1080
+ if (token.value == null) emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1081
+ linkedNode.key = parseNamed(tokenizer, token.value || "");
1082
+ break;
1083
+ case 5:
1084
+ if (token.value == null) emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1085
+ linkedNode.key = parseList(tokenizer, token.value || "");
1086
+ break;
1087
+ case 6:
1088
+ if (token.value == null) emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1089
+ linkedNode.key = parseLiteral(tokenizer, token.value || "");
1090
+ break;
1091
+ default: {
1092
+ emitError(tokenizer, CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_KEY, context.lastStartLoc, 0);
1093
+ const nextContext = tokenizer.context();
1094
+ const emptyLinkedKeyNode = startNode(7, nextContext.offset, nextContext.startLoc);
1095
+ emptyLinkedKeyNode.value = "";
1096
+ endNode(emptyLinkedKeyNode, nextContext.offset, nextContext.startLoc);
1097
+ linkedNode.key = emptyLinkedKeyNode;
1098
+ endNode(linkedNode, nextContext.offset, nextContext.startLoc);
1099
+ return {
1100
+ nextConsumeToken: token,
1101
+ node: linkedNode
1102
+ };
1103
+ }
1104
+ }
1105
+ endNode(linkedNode, tokenizer.currentOffset(), tokenizer.currentPosition());
1106
+ return { node: linkedNode };
1107
+ }
1108
+ function parseMessage(tokenizer) {
1109
+ const context = tokenizer.context();
1110
+ const node = startNode(2, context.currentType === 1 ? tokenizer.currentOffset() : context.offset, context.currentType === 1 ? context.endLoc : context.startLoc);
1111
+ node.items = [];
1112
+ let nextToken = null;
1113
+ do {
1114
+ const token = nextToken || tokenizer.nextToken();
1115
+ nextToken = null;
1116
+ switch (token.type) {
1117
+ case 0:
1118
+ if (token.value == null) emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1119
+ node.items.push(parseText(tokenizer, token.value || ""));
1120
+ break;
1121
+ case 5:
1122
+ if (token.value == null) emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1123
+ node.items.push(parseList(tokenizer, token.value || ""));
1124
+ break;
1125
+ case 4:
1126
+ if (token.value == null) emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1127
+ node.items.push(parseNamed(tokenizer, token.value || ""));
1128
+ break;
1129
+ case 6:
1130
+ if (token.value == null) emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
1131
+ node.items.push(parseLiteral(tokenizer, token.value || ""));
1132
+ break;
1133
+ case 7: {
1134
+ const parsed = parseLinked(tokenizer);
1135
+ node.items.push(parsed.node);
1136
+ nextToken = parsed.nextConsumeToken || null;
1137
+ break;
1138
+ }
1139
+ }
1140
+ } while (context.currentType !== 13 && context.currentType !== 1);
1141
+ endNode(node, context.currentType === 1 ? context.lastOffset : tokenizer.currentOffset(), context.currentType === 1 ? context.lastEndLoc : tokenizer.currentPosition());
1142
+ return node;
1143
+ }
1144
+ function parsePlural(tokenizer, offset, loc, msgNode) {
1145
+ const context = tokenizer.context();
1146
+ let hasEmptyMessage = msgNode.items.length === 0;
1147
+ const node = startNode(1, offset, loc);
1148
+ node.cases = [];
1149
+ node.cases.push(msgNode);
1150
+ do {
1151
+ const msg = parseMessage(tokenizer);
1152
+ if (!hasEmptyMessage) hasEmptyMessage = msg.items.length === 0;
1153
+ node.cases.push(msg);
1154
+ } while (context.currentType !== 13);
1155
+ if (hasEmptyMessage) emitError(tokenizer, CompileErrorCodes.MUST_HAVE_MESSAGES_IN_PLURAL, loc, 0);
1156
+ endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
1157
+ return node;
1158
+ }
1159
+ function parseResource(tokenizer) {
1160
+ const context = tokenizer.context();
1161
+ const { offset, startLoc } = context;
1162
+ const msgNode = parseMessage(tokenizer);
1163
+ if (context.currentType === 13) return msgNode;
1164
+ else return parsePlural(tokenizer, offset, startLoc, msgNode);
1165
+ }
1166
+ function parse(source) {
1167
+ const tokenizer = createTokenizer(source, assign({}, options));
1168
+ const context = tokenizer.context();
1169
+ const node = startNode(0, context.offset, context.startLoc);
1170
+ if (location && node.loc) node.loc.source = source;
1171
+ node.body = parseResource(tokenizer);
1172
+ if (options.onCacheKey) node.cacheKey = options.onCacheKey(source);
1173
+ if (context.currentType !== 13) emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, source[context.offset] || "");
1174
+ endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
1175
+ return node;
1176
+ }
1177
+ return { parse };
1423
1178
  }
1424
1179
  function getTokenCaption(token) {
1425
- if (token.type === 13 /* TokenTypes.EOF */) {
1426
- return 'EOF';
1427
- }
1428
- const name = (token.value || '').replace(/\r?\n/gu, '\\n');
1429
- return name.length > 10 ? name.slice(0, 9) + '…' : name;
1180
+ if (token.type === 13) return "EOF";
1181
+ const name = (token.value || "").replace(/\r?\n/gu, "\\n");
1182
+ return name.length > 10 ? name.slice(0, 9) + "…" : name;
1430
1183
  }
1431
-
1432
- function createTransformer(ast, options = {} // eslint-disable-line
1433
- ) {
1434
- const _context = {
1435
- ast,
1436
- helpers: new Set()
1437
- };
1438
- const context = () => _context;
1439
- const helper = (name) => {
1440
- _context.helpers.add(name);
1441
- return name;
1442
- };
1443
- return { context, helper };
1184
+ //#endregion
1185
+ //#region packages/message-compiler/src/transformer.ts
1186
+ function createTransformer(ast, _options = {}) {
1187
+ const _context = {
1188
+ ast,
1189
+ helpers: /* @__PURE__ */ new Set()
1190
+ };
1191
+ const context = () => _context;
1192
+ const helper = (name) => {
1193
+ _context.helpers.add(name);
1194
+ return name;
1195
+ };
1196
+ return {
1197
+ context,
1198
+ helper
1199
+ };
1444
1200
  }
1445
1201
  function traverseNodes(nodes, transformer) {
1446
- for (let i = 0; i < nodes.length; i++) {
1447
- traverseNode(nodes[i], transformer);
1448
- }
1202
+ for (let i = 0; i < nodes.length; i++) traverseNode(nodes[i], transformer);
1449
1203
  }
1450
1204
  function traverseNode(node, transformer) {
1451
- // TODO: if we need pre-hook of transform, should be implemented to here
1452
- switch (node.type) {
1453
- case 1 /* NodeTypes.Plural */:
1454
- traverseNodes(node.cases, transformer);
1455
- transformer.helper("plural" /* HelperNameMap.PLURAL */);
1456
- break;
1457
- case 2 /* NodeTypes.Message */:
1458
- traverseNodes(node.items, transformer);
1459
- break;
1460
- case 6 /* NodeTypes.Linked */: {
1461
- const linked = node;
1462
- traverseNode(linked.key, transformer);
1463
- transformer.helper("linked" /* HelperNameMap.LINKED */);
1464
- transformer.helper("type" /* HelperNameMap.TYPE */);
1465
- break;
1466
- }
1467
- case 5 /* NodeTypes.List */:
1468
- transformer.helper("interpolate" /* HelperNameMap.INTERPOLATE */);
1469
- transformer.helper("list" /* HelperNameMap.LIST */);
1470
- break;
1471
- case 4 /* NodeTypes.Named */:
1472
- transformer.helper("interpolate" /* HelperNameMap.INTERPOLATE */);
1473
- transformer.helper("named" /* HelperNameMap.NAMED */);
1474
- break;
1475
- }
1476
- // TODO: if we need post-hook of transform, should be implemented to here
1205
+ switch (node.type) {
1206
+ case 1:
1207
+ traverseNodes(node.cases, transformer);
1208
+ transformer.helper("plural");
1209
+ break;
1210
+ case 2:
1211
+ traverseNodes(node.items, transformer);
1212
+ break;
1213
+ case 6:
1214
+ traverseNode(node.key, transformer);
1215
+ transformer.helper("linked");
1216
+ transformer.helper("type");
1217
+ break;
1218
+ case 5:
1219
+ transformer.helper("interpolate");
1220
+ transformer.helper("list");
1221
+ break;
1222
+ case 4:
1223
+ transformer.helper("interpolate");
1224
+ transformer.helper("named");
1225
+ break;
1226
+ }
1477
1227
  }
1478
- // transform AST
1479
- function transform(ast, options = {} // eslint-disable-line
1480
- ) {
1481
- const transformer = createTransformer(ast);
1482
- transformer.helper("normalize" /* HelperNameMap.NORMALIZE */);
1483
- // traverse
1484
- ast.body && traverseNode(ast.body, transformer);
1485
- // set meta information
1486
- const context = transformer.context();
1487
- ast.helpers = Array.from(context.helpers);
1228
+ function transform(ast, _options = {}) {
1229
+ const transformer = createTransformer(ast);
1230
+ transformer.helper("normalize");
1231
+ ast.body && traverseNode(ast.body, transformer);
1232
+ const context = transformer.context();
1233
+ ast.helpers = Array.from(context.helpers);
1488
1234
  }
1489
-
1235
+ //#endregion
1236
+ //#region packages/message-compiler/src/compiler.ts
1490
1237
  function baseCompile(source, options = {}) {
1491
- const assignedOptions = assign({}, options);
1492
- const jit = !!assignedOptions.jit;
1493
- const enableMangle = !!assignedOptions.mangle;
1494
- const enableOptimize = assignedOptions.optimize == null ? true : assignedOptions.optimize;
1495
- // parse source codes
1496
- const parser = createParser(assignedOptions);
1497
- const ast = parser.parse(source);
1498
- // TODO:
1499
- // With the introduction of Jit compilation, code generation is no longer necessary. This function may no longer be needed since tree-shaking is not possible.
1500
- if (!jit) {
1501
- // transform ASTs
1502
- transform(ast, assignedOptions);
1503
- // generate javascript codes
1504
- return generate(ast, assignedOptions);
1505
- }
1506
- else {
1507
- // optimize ASTs
1508
- enableOptimize && optimize(ast);
1509
- // minimize ASTs
1510
- enableMangle && mangle(ast);
1511
- // In JIT mode, no ast transform, no code generation.
1512
- return { ast, code: '' };
1513
- }
1238
+ const assignedOptions = assign({}, options);
1239
+ const jit = !!assignedOptions.jit;
1240
+ const enableMangle = !!assignedOptions.mangle;
1241
+ const enableOptimize = assignedOptions.optimize == null ? true : assignedOptions.optimize;
1242
+ const ast = createParser(assignedOptions).parse(source);
1243
+ if (!jit) {
1244
+ transform(ast, assignedOptions);
1245
+ return generate(ast, assignedOptions);
1246
+ } else {
1247
+ enableOptimize && optimize(ast);
1248
+ enableMangle && mangle(ast);
1249
+ return {
1250
+ ast,
1251
+ code: ""
1252
+ };
1253
+ }
1514
1254
  }
1515
-
1516
- // eslint-disable-next-line no-useless-escape
1517
- const RE_HTML_TAG = /<\/?[\w\s="/.':;#-\/]+>/;
1518
- const detectHtmlTag = (source) => RE_HTML_TAG.test(source);
1519
-
1520
- export { COMPILE_ERROR_CODES_EXTEND_POINT, CompileErrorCodes, ERROR_DOMAIN, LOCATION_STUB, baseCompile, createCompileError, createLocation, createParser, createPosition, defaultOnError, detectHtmlTag, errorMessages, mangle, optimize };
1255
+ //#endregion
1256
+ export { COMPILE_ERROR_CODES_EXTEND_POINT, CompileErrorCodes, ERROR_DOMAIN, HelperNameMap, LOCATION_STUB, NodeTypes, baseCompile, createCompileError, createLocation, createParser, createPosition, defaultOnError, detectHtmlTag, errorMessages, mangle, optimize };