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