@intlify/message-compiler 11.1.2 → 12.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/dist/message-compiler.d.ts +6 -2
- package/dist/message-compiler.esm-browser.js +549 -547
- package/dist/message-compiler.esm-browser.prod.js +3 -3
- package/dist/message-compiler.esm-bundler.js +1 -1
- package/dist/message-compiler.global.js +551 -547
- package/dist/message-compiler.global.prod.js +3 -3
- package/dist/{message-compiler.mjs → message-compiler.js} +397 -395
- package/dist/{message-compiler.node.mjs → message-compiler.node.js} +1186 -1184
- package/package.json +8 -15
- package/dist/message-compiler.cjs +0 -1587
- package/dist/message-compiler.cjs.js +0 -1
- package/dist/message-compiler.cjs.prod.js +0 -1
- package/dist/message-compiler.prod.cjs +0 -1570
- package/index.js +0 -7
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* message-compiler
|
|
3
|
-
* (c)
|
|
2
|
+
* message-compiler v12.0.0-alpha.2
|
|
3
|
+
* (c) 2016-present kazuya kawaguchi and contributors
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
6
|
-
import { format,
|
|
6
|
+
import { format, isString, join, assign } from '@intlify/shared';
|
|
7
7
|
|
|
8
8
|
const LOCATION_STUB = {
|
|
9
9
|
start: { line: 1, column: 1, offset: 0 },
|
|
@@ -87,9 +87,318 @@ function defaultOnError(error) {
|
|
|
87
87
|
throw error;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
// eslint-disable-next-line
|
|
91
|
-
|
|
92
|
-
const
|
|
90
|
+
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
|
|
91
|
+
/// <reference types="source-map-js" />
|
|
92
|
+
const ERROR_DOMAIN$3 = 'parser';
|
|
93
|
+
function createCodeGenerator(ast, options) {
|
|
94
|
+
const { sourceMap, filename, breakLineCode, needIndent: _needIndent } = options;
|
|
95
|
+
const location = options.location !== false;
|
|
96
|
+
const _context = {
|
|
97
|
+
filename,
|
|
98
|
+
code: '',
|
|
99
|
+
column: 1,
|
|
100
|
+
line: 1,
|
|
101
|
+
offset: 0,
|
|
102
|
+
map: undefined,
|
|
103
|
+
breakLineCode,
|
|
104
|
+
needIndent: _needIndent,
|
|
105
|
+
indentLevel: 0
|
|
106
|
+
};
|
|
107
|
+
if (location && ast.loc) {
|
|
108
|
+
_context.source = ast.loc.source;
|
|
109
|
+
}
|
|
110
|
+
const context = () => _context;
|
|
111
|
+
function push(code, node) {
|
|
112
|
+
_context.code += code;
|
|
113
|
+
}
|
|
114
|
+
function _newline(n, withBreakLine = true) {
|
|
115
|
+
const _breakLineCode = withBreakLine ? breakLineCode : '';
|
|
116
|
+
push(_needIndent ? _breakLineCode + ` `.repeat(n) : _breakLineCode);
|
|
117
|
+
}
|
|
118
|
+
function indent(withNewLine = true) {
|
|
119
|
+
const level = ++_context.indentLevel;
|
|
120
|
+
withNewLine && _newline(level);
|
|
121
|
+
}
|
|
122
|
+
function deindent(withNewLine = true) {
|
|
123
|
+
const level = --_context.indentLevel;
|
|
124
|
+
withNewLine && _newline(level);
|
|
125
|
+
}
|
|
126
|
+
function newline() {
|
|
127
|
+
_newline(_context.indentLevel);
|
|
128
|
+
}
|
|
129
|
+
const helper = (key) => `_${key}`;
|
|
130
|
+
const needIndent = () => _context.needIndent;
|
|
131
|
+
return {
|
|
132
|
+
context,
|
|
133
|
+
push,
|
|
134
|
+
indent,
|
|
135
|
+
deindent,
|
|
136
|
+
newline,
|
|
137
|
+
helper,
|
|
138
|
+
needIndent
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function generateLinkedNode(generator, node) {
|
|
142
|
+
const { helper } = generator;
|
|
143
|
+
generator.push(`${helper("linked" /* HelperNameMap.LINKED */)}(`);
|
|
144
|
+
generateNode(generator, node.key);
|
|
145
|
+
if (node.modifier) {
|
|
146
|
+
generator.push(`, `);
|
|
147
|
+
generateNode(generator, node.modifier);
|
|
148
|
+
generator.push(`, _type`);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
generator.push(`, undefined, _type`);
|
|
152
|
+
}
|
|
153
|
+
generator.push(`)`);
|
|
154
|
+
}
|
|
155
|
+
function generateMessageNode(generator, node) {
|
|
156
|
+
const { helper, needIndent } = generator;
|
|
157
|
+
generator.push(`${helper("normalize" /* HelperNameMap.NORMALIZE */)}([`);
|
|
158
|
+
generator.indent(needIndent());
|
|
159
|
+
const length = node.items.length;
|
|
160
|
+
for (let i = 0; i < length; i++) {
|
|
161
|
+
generateNode(generator, node.items[i]);
|
|
162
|
+
if (i === length - 1) {
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
generator.push(', ');
|
|
166
|
+
}
|
|
167
|
+
generator.deindent(needIndent());
|
|
168
|
+
generator.push('])');
|
|
169
|
+
}
|
|
170
|
+
function generatePluralNode(generator, node) {
|
|
171
|
+
const { helper, needIndent } = generator;
|
|
172
|
+
if (node.cases.length > 1) {
|
|
173
|
+
generator.push(`${helper("plural" /* HelperNameMap.PLURAL */)}([`);
|
|
174
|
+
generator.indent(needIndent());
|
|
175
|
+
const length = node.cases.length;
|
|
176
|
+
for (let i = 0; i < length; i++) {
|
|
177
|
+
generateNode(generator, node.cases[i]);
|
|
178
|
+
if (i === length - 1) {
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
generator.push(', ');
|
|
182
|
+
}
|
|
183
|
+
generator.deindent(needIndent());
|
|
184
|
+
generator.push(`])`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
function generateResource(generator, node) {
|
|
188
|
+
if (node.body) {
|
|
189
|
+
generateNode(generator, node.body);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
generator.push('null');
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
function generateNode(generator, node) {
|
|
196
|
+
const { helper } = generator;
|
|
197
|
+
switch (node.type) {
|
|
198
|
+
case 0 /* NodeTypes.Resource */:
|
|
199
|
+
generateResource(generator, node);
|
|
200
|
+
break;
|
|
201
|
+
case 1 /* NodeTypes.Plural */:
|
|
202
|
+
generatePluralNode(generator, node);
|
|
203
|
+
break;
|
|
204
|
+
case 2 /* NodeTypes.Message */:
|
|
205
|
+
generateMessageNode(generator, node);
|
|
206
|
+
break;
|
|
207
|
+
case 6 /* NodeTypes.Linked */:
|
|
208
|
+
generateLinkedNode(generator, node);
|
|
209
|
+
break;
|
|
210
|
+
case 8 /* NodeTypes.LinkedModifier */:
|
|
211
|
+
generator.push(JSON.stringify(node.value), node);
|
|
212
|
+
break;
|
|
213
|
+
case 7 /* NodeTypes.LinkedKey */:
|
|
214
|
+
generator.push(JSON.stringify(node.value), node);
|
|
215
|
+
break;
|
|
216
|
+
case 5 /* NodeTypes.List */:
|
|
217
|
+
generator.push(`${helper("interpolate" /* HelperNameMap.INTERPOLATE */)}(${helper("list" /* HelperNameMap.LIST */)}(${node.index}))`, node);
|
|
218
|
+
break;
|
|
219
|
+
case 4 /* NodeTypes.Named */:
|
|
220
|
+
generator.push(`${helper("interpolate" /* HelperNameMap.INTERPOLATE */)}(${helper("named" /* HelperNameMap.NAMED */)}(${JSON.stringify(node.key)}))`, node);
|
|
221
|
+
break;
|
|
222
|
+
case 9 /* NodeTypes.Literal */:
|
|
223
|
+
generator.push(JSON.stringify(node.value), node);
|
|
224
|
+
break;
|
|
225
|
+
case 3 /* NodeTypes.Text */:
|
|
226
|
+
generator.push(JSON.stringify(node.value), node);
|
|
227
|
+
break;
|
|
228
|
+
default:
|
|
229
|
+
if ((process.env.NODE_ENV !== 'production')) {
|
|
230
|
+
throw createCompileError(CompileErrorCodes.UNHANDLED_CODEGEN_NODE_TYPE, null, {
|
|
231
|
+
domain: ERROR_DOMAIN$3,
|
|
232
|
+
args: [node.type]
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// generate code from AST
|
|
238
|
+
const generate = (ast, options = {}) => {
|
|
239
|
+
const mode = isString(options.mode) ? options.mode : 'normal';
|
|
240
|
+
const filename = isString(options.filename)
|
|
241
|
+
? options.filename
|
|
242
|
+
: 'message.intl';
|
|
243
|
+
const sourceMap = !!options.sourceMap;
|
|
244
|
+
// prettier-ignore
|
|
245
|
+
const breakLineCode = options.breakLineCode != null
|
|
246
|
+
? options.breakLineCode
|
|
247
|
+
: mode === 'arrow'
|
|
248
|
+
? ';'
|
|
249
|
+
: '\n';
|
|
250
|
+
const needIndent = options.needIndent ? options.needIndent : mode !== 'arrow';
|
|
251
|
+
const helpers = ast.helpers || [];
|
|
252
|
+
const generator = createCodeGenerator(ast, {
|
|
253
|
+
mode,
|
|
254
|
+
filename,
|
|
255
|
+
sourceMap,
|
|
256
|
+
breakLineCode,
|
|
257
|
+
needIndent
|
|
258
|
+
});
|
|
259
|
+
generator.push(mode === 'normal' ? `function __msg__ (ctx) {` : `(ctx) => {`);
|
|
260
|
+
generator.indent(needIndent);
|
|
261
|
+
if (helpers.length > 0) {
|
|
262
|
+
generator.push(`const { ${join(helpers.map(s => `${s}: _${s}`), ', ')} } = ctx`);
|
|
263
|
+
generator.newline();
|
|
264
|
+
}
|
|
265
|
+
generator.push(`return `);
|
|
266
|
+
generateNode(generator, ast);
|
|
267
|
+
generator.deindent(needIndent);
|
|
268
|
+
generator.push(`}`);
|
|
269
|
+
delete ast.helpers;
|
|
270
|
+
const { code, map } = generator.context();
|
|
271
|
+
return {
|
|
272
|
+
ast,
|
|
273
|
+
code,
|
|
274
|
+
map: map ? map.toJSON() : undefined // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
275
|
+
};
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
const ERROR_DOMAIN$2 = 'minifier';
|
|
279
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
280
|
+
function mangle(node) {
|
|
281
|
+
node.t = node.type;
|
|
282
|
+
switch (node.type) {
|
|
283
|
+
case 0 /* NodeTypes.Resource */: {
|
|
284
|
+
const resource = node;
|
|
285
|
+
mangle(resource.body);
|
|
286
|
+
resource.b = resource.body;
|
|
287
|
+
delete resource.body;
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
case 1 /* NodeTypes.Plural */: {
|
|
291
|
+
const plural = node;
|
|
292
|
+
const cases = plural.cases;
|
|
293
|
+
for (let i = 0; i < cases.length; i++) {
|
|
294
|
+
mangle(cases[i]);
|
|
295
|
+
}
|
|
296
|
+
plural.c = cases;
|
|
297
|
+
delete plural.cases;
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
case 2 /* NodeTypes.Message */: {
|
|
301
|
+
const message = node;
|
|
302
|
+
const items = message.items;
|
|
303
|
+
for (let i = 0; i < items.length; i++) {
|
|
304
|
+
mangle(items[i]);
|
|
305
|
+
}
|
|
306
|
+
message.i = items;
|
|
307
|
+
delete message.items;
|
|
308
|
+
if (message.static) {
|
|
309
|
+
message.s = message.static;
|
|
310
|
+
delete message.static;
|
|
311
|
+
}
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
case 3 /* NodeTypes.Text */:
|
|
315
|
+
case 9 /* NodeTypes.Literal */:
|
|
316
|
+
case 8 /* NodeTypes.LinkedModifier */:
|
|
317
|
+
case 7 /* NodeTypes.LinkedKey */: {
|
|
318
|
+
const valueNode = node;
|
|
319
|
+
if (valueNode.value) {
|
|
320
|
+
valueNode.v = valueNode.value;
|
|
321
|
+
delete valueNode.value;
|
|
322
|
+
}
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
case 6 /* NodeTypes.Linked */: {
|
|
326
|
+
const linked = node;
|
|
327
|
+
mangle(linked.key);
|
|
328
|
+
linked.k = linked.key;
|
|
329
|
+
delete linked.key;
|
|
330
|
+
if (linked.modifier) {
|
|
331
|
+
mangle(linked.modifier);
|
|
332
|
+
linked.m = linked.modifier;
|
|
333
|
+
delete linked.modifier;
|
|
334
|
+
}
|
|
335
|
+
break;
|
|
336
|
+
}
|
|
337
|
+
case 5 /* NodeTypes.List */: {
|
|
338
|
+
const list = node;
|
|
339
|
+
list.i = list.index;
|
|
340
|
+
delete list.index;
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
case 4 /* NodeTypes.Named */: {
|
|
344
|
+
const named = node;
|
|
345
|
+
named.k = named.key;
|
|
346
|
+
delete named.key;
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
default:
|
|
350
|
+
if ((process.env.NODE_ENV !== 'production')) {
|
|
351
|
+
throw createCompileError(CompileErrorCodes.UNHANDLED_MINIFIER_NODE_TYPE, null, {
|
|
352
|
+
domain: ERROR_DOMAIN$2,
|
|
353
|
+
args: [node.type]
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
delete node.type;
|
|
358
|
+
}
|
|
359
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
360
|
+
|
|
361
|
+
function optimize(ast) {
|
|
362
|
+
const body = ast.body;
|
|
363
|
+
if (body.type === 2 /* NodeTypes.Message */) {
|
|
364
|
+
optimizeMessageNode(body);
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
body.cases.forEach(c => optimizeMessageNode(c));
|
|
368
|
+
}
|
|
369
|
+
return ast;
|
|
370
|
+
}
|
|
371
|
+
function optimizeMessageNode(message) {
|
|
372
|
+
if (message.items.length === 1) {
|
|
373
|
+
const item = message.items[0];
|
|
374
|
+
if (item.type === 3 /* NodeTypes.Text */ || item.type === 9 /* NodeTypes.Literal */) {
|
|
375
|
+
message.static = item.value;
|
|
376
|
+
delete item.value; // optimization for size
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
else {
|
|
380
|
+
const values = [];
|
|
381
|
+
for (let i = 0; i < message.items.length; i++) {
|
|
382
|
+
const item = message.items[i];
|
|
383
|
+
if (!(item.type === 3 /* NodeTypes.Text */ || item.type === 9 /* NodeTypes.Literal */)) {
|
|
384
|
+
break;
|
|
385
|
+
}
|
|
386
|
+
if (item.value == null) {
|
|
387
|
+
break;
|
|
388
|
+
}
|
|
389
|
+
values.push(item.value);
|
|
390
|
+
}
|
|
391
|
+
if (values.length === message.items.length) {
|
|
392
|
+
message.static = join(values);
|
|
393
|
+
for (let i = 0; i < message.items.length; i++) {
|
|
394
|
+
const item = message.items[i];
|
|
395
|
+
if (item.type === 3 /* NodeTypes.Text */ || item.type === 9 /* NodeTypes.Literal */) {
|
|
396
|
+
delete item.value; // optimization for size
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
93
402
|
|
|
94
403
|
const CHAR_SP = ' ';
|
|
95
404
|
const CHAR_CR = '\r';
|
|
@@ -169,7 +478,7 @@ function createScanner(str) {
|
|
|
169
478
|
const EOF = undefined;
|
|
170
479
|
const DOT = '.';
|
|
171
480
|
const LITERAL_DELIMITER = "'";
|
|
172
|
-
const ERROR_DOMAIN$
|
|
481
|
+
const ERROR_DOMAIN$1 = 'tokenizer';
|
|
173
482
|
function createTokenizer(source, options = {}) {
|
|
174
483
|
const location = options.location !== false;
|
|
175
484
|
const _scnr = createScanner(source);
|
|
@@ -199,7 +508,7 @@ function createTokenizer(source, options = {}) {
|
|
|
199
508
|
if (onError) {
|
|
200
509
|
const loc = location ? createLocation(ctx.startLoc, pos) : null;
|
|
201
510
|
const err = createCompileError(code, loc, {
|
|
202
|
-
domain: ERROR_DOMAIN$
|
|
511
|
+
domain: ERROR_DOMAIN$1,
|
|
203
512
|
args
|
|
204
513
|
});
|
|
205
514
|
onError(err);
|
|
@@ -820,7 +1129,7 @@ function createTokenizer(source, options = {}) {
|
|
|
820
1129
|
};
|
|
821
1130
|
}
|
|
822
1131
|
|
|
823
|
-
const ERROR_DOMAIN
|
|
1132
|
+
const ERROR_DOMAIN = 'parser';
|
|
824
1133
|
// Backslash backslash, backslash quote, uHHHH, UHHHHHH.
|
|
825
1134
|
const KNOWN_ESCAPES = /(?:\\\\|\\'|\\u([0-9a-fA-F]{4})|\\U([0-9a-fA-F]{6}))/g;
|
|
826
1135
|
function fromEscapeSequence(match, codePoint4, codePoint6) {
|
|
@@ -852,7 +1161,7 @@ function createParser(options = {}) {
|
|
|
852
1161
|
if (onError) {
|
|
853
1162
|
const loc = location ? createLocation(start, end) : null;
|
|
854
1163
|
const err = createCompileError(code, loc, {
|
|
855
|
-
domain: ERROR_DOMAIN
|
|
1164
|
+
domain: ERROR_DOMAIN,
|
|
856
1165
|
args
|
|
857
1166
|
});
|
|
858
1167
|
onError(err);
|
|
@@ -1085,420 +1394,109 @@ function createParser(options = {}) {
|
|
|
1085
1394
|
const context = tokenizer.context();
|
|
1086
1395
|
const { offset, startLoc } = context;
|
|
1087
1396
|
const msgNode = parseMessage(tokenizer);
|
|
1088
|
-
if (context.currentType === 13 /* TokenTypes.EOF */) {
|
|
1089
|
-
return msgNode;
|
|
1090
|
-
}
|
|
1091
|
-
else {
|
|
1092
|
-
return parsePlural(tokenizer, offset, startLoc, msgNode);
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
function parse(source) {
|
|
1096
|
-
const tokenizer = createTokenizer(source, assign({}, options));
|
|
1097
|
-
const context = tokenizer.context();
|
|
1098
|
-
const node = startNode(0 /* NodeTypes.Resource */, context.offset, context.startLoc);
|
|
1099
|
-
if (location && node.loc) {
|
|
1100
|
-
node.loc.source = source;
|
|
1101
|
-
}
|
|
1102
|
-
node.body = parseResource(tokenizer);
|
|
1103
|
-
if (options.onCacheKey) {
|
|
1104
|
-
node.cacheKey = options.onCacheKey(source);
|
|
1105
|
-
}
|
|
1106
|
-
// assert whether achieved to EOF
|
|
1107
|
-
if (context.currentType !== 13 /* TokenTypes.EOF */) {
|
|
1108
|
-
emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, source[context.offset] || '');
|
|
1109
|
-
}
|
|
1110
|
-
endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
|
|
1111
|
-
return node;
|
|
1112
|
-
}
|
|
1113
|
-
return { parse };
|
|
1114
|
-
}
|
|
1115
|
-
function getTokenCaption(token) {
|
|
1116
|
-
if (token.type === 13 /* TokenTypes.EOF */) {
|
|
1117
|
-
return 'EOF';
|
|
1118
|
-
}
|
|
1119
|
-
const name = (token.value || '').replace(/\r?\n/gu, '\\n');
|
|
1120
|
-
return name.length > 10 ? name.slice(0, 9) + '…' : name;
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
function createTransformer(ast, options = {} // eslint-disable-line
|
|
1124
|
-
) {
|
|
1125
|
-
const _context = {
|
|
1126
|
-
ast,
|
|
1127
|
-
helpers: new Set()
|
|
1128
|
-
};
|
|
1129
|
-
const context = () => _context;
|
|
1130
|
-
const helper = (name) => {
|
|
1131
|
-
_context.helpers.add(name);
|
|
1132
|
-
return name;
|
|
1133
|
-
};
|
|
1134
|
-
return { context, helper };
|
|
1135
|
-
}
|
|
1136
|
-
function traverseNodes(nodes, transformer) {
|
|
1137
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
1138
|
-
traverseNode(nodes[i], transformer);
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
function traverseNode(node, transformer) {
|
|
1142
|
-
// TODO: if we need pre-hook of transform, should be implemented to here
|
|
1143
|
-
switch (node.type) {
|
|
1144
|
-
case 1 /* NodeTypes.Plural */:
|
|
1145
|
-
traverseNodes(node.cases, transformer);
|
|
1146
|
-
transformer.helper("plural" /* HelperNameMap.PLURAL */);
|
|
1147
|
-
break;
|
|
1148
|
-
case 2 /* NodeTypes.Message */:
|
|
1149
|
-
traverseNodes(node.items, transformer);
|
|
1150
|
-
break;
|
|
1151
|
-
case 6 /* NodeTypes.Linked */: {
|
|
1152
|
-
const linked = node;
|
|
1153
|
-
traverseNode(linked.key, transformer);
|
|
1154
|
-
transformer.helper("linked" /* HelperNameMap.LINKED */);
|
|
1155
|
-
transformer.helper("type" /* HelperNameMap.TYPE */);
|
|
1156
|
-
break;
|
|
1157
|
-
}
|
|
1158
|
-
case 5 /* NodeTypes.List */:
|
|
1159
|
-
transformer.helper("interpolate" /* HelperNameMap.INTERPOLATE */);
|
|
1160
|
-
transformer.helper("list" /* HelperNameMap.LIST */);
|
|
1161
|
-
break;
|
|
1162
|
-
case 4 /* NodeTypes.Named */:
|
|
1163
|
-
transformer.helper("interpolate" /* HelperNameMap.INTERPOLATE */);
|
|
1164
|
-
transformer.helper("named" /* HelperNameMap.NAMED */);
|
|
1165
|
-
break;
|
|
1166
|
-
}
|
|
1167
|
-
// TODO: if we need post-hook of transform, should be implemented to here
|
|
1168
|
-
}
|
|
1169
|
-
// transform AST
|
|
1170
|
-
function transform(ast, options = {} // eslint-disable-line
|
|
1171
|
-
) {
|
|
1172
|
-
const transformer = createTransformer(ast);
|
|
1173
|
-
transformer.helper("normalize" /* HelperNameMap.NORMALIZE */);
|
|
1174
|
-
// traverse
|
|
1175
|
-
ast.body && traverseNode(ast.body, transformer);
|
|
1176
|
-
// set meta information
|
|
1177
|
-
const context = transformer.context();
|
|
1178
|
-
ast.helpers = Array.from(context.helpers);
|
|
1179
|
-
}
|
|
1180
|
-
|
|
1181
|
-
function optimize(ast) {
|
|
1182
|
-
const body = ast.body;
|
|
1183
|
-
if (body.type === 2 /* NodeTypes.Message */) {
|
|
1184
|
-
optimizeMessageNode(body);
|
|
1185
|
-
}
|
|
1186
|
-
else {
|
|
1187
|
-
body.cases.forEach(c => optimizeMessageNode(c));
|
|
1188
|
-
}
|
|
1189
|
-
return ast;
|
|
1190
|
-
}
|
|
1191
|
-
function optimizeMessageNode(message) {
|
|
1192
|
-
if (message.items.length === 1) {
|
|
1193
|
-
const item = message.items[0];
|
|
1194
|
-
if (item.type === 3 /* NodeTypes.Text */ || item.type === 9 /* NodeTypes.Literal */) {
|
|
1195
|
-
message.static = item.value;
|
|
1196
|
-
delete item.value; // optimization for size
|
|
1197
|
-
}
|
|
1198
|
-
}
|
|
1199
|
-
else {
|
|
1200
|
-
const values = [];
|
|
1201
|
-
for (let i = 0; i < message.items.length; i++) {
|
|
1202
|
-
const item = message.items[i];
|
|
1203
|
-
if (!(item.type === 3 /* NodeTypes.Text */ || item.type === 9 /* NodeTypes.Literal */)) {
|
|
1204
|
-
break;
|
|
1205
|
-
}
|
|
1206
|
-
if (item.value == null) {
|
|
1207
|
-
break;
|
|
1208
|
-
}
|
|
1209
|
-
values.push(item.value);
|
|
1210
|
-
}
|
|
1211
|
-
if (values.length === message.items.length) {
|
|
1212
|
-
message.static = join(values);
|
|
1213
|
-
for (let i = 0; i < message.items.length; i++) {
|
|
1214
|
-
const item = message.items[i];
|
|
1215
|
-
if (item.type === 3 /* NodeTypes.Text */ || item.type === 9 /* NodeTypes.Literal */) {
|
|
1216
|
-
delete item.value; // optimization for size
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1221
|
-
}
|
|
1222
|
-
|
|
1223
|
-
const ERROR_DOMAIN$1 = 'minifier';
|
|
1224
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1225
|
-
function minify(node) {
|
|
1226
|
-
node.t = node.type;
|
|
1227
|
-
switch (node.type) {
|
|
1228
|
-
case 0 /* NodeTypes.Resource */: {
|
|
1229
|
-
const resource = node;
|
|
1230
|
-
minify(resource.body);
|
|
1231
|
-
resource.b = resource.body;
|
|
1232
|
-
delete resource.body;
|
|
1233
|
-
break;
|
|
1234
|
-
}
|
|
1235
|
-
case 1 /* NodeTypes.Plural */: {
|
|
1236
|
-
const plural = node;
|
|
1237
|
-
const cases = plural.cases;
|
|
1238
|
-
for (let i = 0; i < cases.length; i++) {
|
|
1239
|
-
minify(cases[i]);
|
|
1240
|
-
}
|
|
1241
|
-
plural.c = cases;
|
|
1242
|
-
delete plural.cases;
|
|
1243
|
-
break;
|
|
1244
|
-
}
|
|
1245
|
-
case 2 /* NodeTypes.Message */: {
|
|
1246
|
-
const message = node;
|
|
1247
|
-
const items = message.items;
|
|
1248
|
-
for (let i = 0; i < items.length; i++) {
|
|
1249
|
-
minify(items[i]);
|
|
1250
|
-
}
|
|
1251
|
-
message.i = items;
|
|
1252
|
-
delete message.items;
|
|
1253
|
-
if (message.static) {
|
|
1254
|
-
message.s = message.static;
|
|
1255
|
-
delete message.static;
|
|
1256
|
-
}
|
|
1257
|
-
break;
|
|
1258
|
-
}
|
|
1259
|
-
case 3 /* NodeTypes.Text */:
|
|
1260
|
-
case 9 /* NodeTypes.Literal */:
|
|
1261
|
-
case 8 /* NodeTypes.LinkedModifier */:
|
|
1262
|
-
case 7 /* NodeTypes.LinkedKey */: {
|
|
1263
|
-
const valueNode = node;
|
|
1264
|
-
if (valueNode.value) {
|
|
1265
|
-
valueNode.v = valueNode.value;
|
|
1266
|
-
delete valueNode.value;
|
|
1267
|
-
}
|
|
1268
|
-
break;
|
|
1269
|
-
}
|
|
1270
|
-
case 6 /* NodeTypes.Linked */: {
|
|
1271
|
-
const linked = node;
|
|
1272
|
-
minify(linked.key);
|
|
1273
|
-
linked.k = linked.key;
|
|
1274
|
-
delete linked.key;
|
|
1275
|
-
if (linked.modifier) {
|
|
1276
|
-
minify(linked.modifier);
|
|
1277
|
-
linked.m = linked.modifier;
|
|
1278
|
-
delete linked.modifier;
|
|
1279
|
-
}
|
|
1280
|
-
break;
|
|
1397
|
+
if (context.currentType === 13 /* TokenTypes.EOF */) {
|
|
1398
|
+
return msgNode;
|
|
1281
1399
|
}
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
list.i = list.index;
|
|
1285
|
-
delete list.index;
|
|
1286
|
-
break;
|
|
1400
|
+
else {
|
|
1401
|
+
return parsePlural(tokenizer, offset, startLoc, msgNode);
|
|
1287
1402
|
}
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1403
|
+
}
|
|
1404
|
+
function parse(source) {
|
|
1405
|
+
const tokenizer = createTokenizer(source, assign({}, options));
|
|
1406
|
+
const context = tokenizer.context();
|
|
1407
|
+
const node = startNode(0 /* NodeTypes.Resource */, context.offset, context.startLoc);
|
|
1408
|
+
if (location && node.loc) {
|
|
1409
|
+
node.loc.source = source;
|
|
1293
1410
|
}
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1411
|
+
node.body = parseResource(tokenizer);
|
|
1412
|
+
if (options.onCacheKey) {
|
|
1413
|
+
node.cacheKey = options.onCacheKey(source);
|
|
1414
|
+
}
|
|
1415
|
+
// assert whether achieved to EOF
|
|
1416
|
+
if (context.currentType !== 13 /* TokenTypes.EOF */) {
|
|
1417
|
+
emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, source[context.offset] || '');
|
|
1418
|
+
}
|
|
1419
|
+
endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
|
|
1420
|
+
return node;
|
|
1301
1421
|
}
|
|
1302
|
-
|
|
1422
|
+
return { parse };
|
|
1423
|
+
}
|
|
1424
|
+
function getTokenCaption(token) {
|
|
1425
|
+
if (token.type === 13 /* TokenTypes.EOF */) {
|
|
1426
|
+
return 'EOF';
|
|
1427
|
+
}
|
|
1428
|
+
const name = (token.value || '').replace(/\r?\n/gu, '\\n');
|
|
1429
|
+
return name.length > 10 ? name.slice(0, 9) + '…' : name;
|
|
1303
1430
|
}
|
|
1304
|
-
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
1305
1431
|
|
|
1306
|
-
// eslint-disable-
|
|
1307
|
-
|
|
1308
|
-
const ERROR_DOMAIN = 'parser';
|
|
1309
|
-
function createCodeGenerator(ast, options) {
|
|
1310
|
-
const { sourceMap, filename, breakLineCode, needIndent: _needIndent } = options;
|
|
1311
|
-
const location = options.location !== false;
|
|
1432
|
+
function createTransformer(ast, options = {} // eslint-disable-line
|
|
1433
|
+
) {
|
|
1312
1434
|
const _context = {
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
column: 1,
|
|
1316
|
-
line: 1,
|
|
1317
|
-
offset: 0,
|
|
1318
|
-
map: undefined,
|
|
1319
|
-
breakLineCode,
|
|
1320
|
-
needIndent: _needIndent,
|
|
1321
|
-
indentLevel: 0
|
|
1435
|
+
ast,
|
|
1436
|
+
helpers: new Set()
|
|
1322
1437
|
};
|
|
1323
|
-
if (location && ast.loc) {
|
|
1324
|
-
_context.source = ast.loc.source;
|
|
1325
|
-
}
|
|
1326
1438
|
const context = () => _context;
|
|
1327
|
-
|
|
1328
|
-
_context.
|
|
1329
|
-
|
|
1330
|
-
function _newline(n, withBreakLine = true) {
|
|
1331
|
-
const _breakLineCode = withBreakLine ? breakLineCode : '';
|
|
1332
|
-
push(_needIndent ? _breakLineCode + ` `.repeat(n) : _breakLineCode);
|
|
1333
|
-
}
|
|
1334
|
-
function indent(withNewLine = true) {
|
|
1335
|
-
const level = ++_context.indentLevel;
|
|
1336
|
-
withNewLine && _newline(level);
|
|
1337
|
-
}
|
|
1338
|
-
function deindent(withNewLine = true) {
|
|
1339
|
-
const level = --_context.indentLevel;
|
|
1340
|
-
withNewLine && _newline(level);
|
|
1341
|
-
}
|
|
1342
|
-
function newline() {
|
|
1343
|
-
_newline(_context.indentLevel);
|
|
1344
|
-
}
|
|
1345
|
-
const helper = (key) => `_${key}`;
|
|
1346
|
-
const needIndent = () => _context.needIndent;
|
|
1347
|
-
return {
|
|
1348
|
-
context,
|
|
1349
|
-
push,
|
|
1350
|
-
indent,
|
|
1351
|
-
deindent,
|
|
1352
|
-
newline,
|
|
1353
|
-
helper,
|
|
1354
|
-
needIndent
|
|
1439
|
+
const helper = (name) => {
|
|
1440
|
+
_context.helpers.add(name);
|
|
1441
|
+
return name;
|
|
1355
1442
|
};
|
|
1443
|
+
return { context, helper };
|
|
1356
1444
|
}
|
|
1357
|
-
function
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
generateNode(generator, node.key);
|
|
1361
|
-
if (node.modifier) {
|
|
1362
|
-
generator.push(`, `);
|
|
1363
|
-
generateNode(generator, node.modifier);
|
|
1364
|
-
generator.push(`, _type`);
|
|
1365
|
-
}
|
|
1366
|
-
else {
|
|
1367
|
-
generator.push(`, undefined, _type`);
|
|
1368
|
-
}
|
|
1369
|
-
generator.push(`)`);
|
|
1370
|
-
}
|
|
1371
|
-
function generateMessageNode(generator, node) {
|
|
1372
|
-
const { helper, needIndent } = generator;
|
|
1373
|
-
generator.push(`${helper("normalize" /* HelperNameMap.NORMALIZE */)}([`);
|
|
1374
|
-
generator.indent(needIndent());
|
|
1375
|
-
const length = node.items.length;
|
|
1376
|
-
for (let i = 0; i < length; i++) {
|
|
1377
|
-
generateNode(generator, node.items[i]);
|
|
1378
|
-
if (i === length - 1) {
|
|
1379
|
-
break;
|
|
1380
|
-
}
|
|
1381
|
-
generator.push(', ');
|
|
1382
|
-
}
|
|
1383
|
-
generator.deindent(needIndent());
|
|
1384
|
-
generator.push('])');
|
|
1385
|
-
}
|
|
1386
|
-
function generatePluralNode(generator, node) {
|
|
1387
|
-
const { helper, needIndent } = generator;
|
|
1388
|
-
if (node.cases.length > 1) {
|
|
1389
|
-
generator.push(`${helper("plural" /* HelperNameMap.PLURAL */)}([`);
|
|
1390
|
-
generator.indent(needIndent());
|
|
1391
|
-
const length = node.cases.length;
|
|
1392
|
-
for (let i = 0; i < length; i++) {
|
|
1393
|
-
generateNode(generator, node.cases[i]);
|
|
1394
|
-
if (i === length - 1) {
|
|
1395
|
-
break;
|
|
1396
|
-
}
|
|
1397
|
-
generator.push(', ');
|
|
1398
|
-
}
|
|
1399
|
-
generator.deindent(needIndent());
|
|
1400
|
-
generator.push(`])`);
|
|
1401
|
-
}
|
|
1402
|
-
}
|
|
1403
|
-
function generateResource(generator, node) {
|
|
1404
|
-
if (node.body) {
|
|
1405
|
-
generateNode(generator, node.body);
|
|
1406
|
-
}
|
|
1407
|
-
else {
|
|
1408
|
-
generator.push('null');
|
|
1445
|
+
function traverseNodes(nodes, transformer) {
|
|
1446
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
1447
|
+
traverseNode(nodes[i], transformer);
|
|
1409
1448
|
}
|
|
1410
1449
|
}
|
|
1411
|
-
function
|
|
1412
|
-
|
|
1450
|
+
function traverseNode(node, transformer) {
|
|
1451
|
+
// TODO: if we need pre-hook of transform, should be implemented to here
|
|
1413
1452
|
switch (node.type) {
|
|
1414
|
-
case 0 /* NodeTypes.Resource */:
|
|
1415
|
-
generateResource(generator, node);
|
|
1416
|
-
break;
|
|
1417
1453
|
case 1 /* NodeTypes.Plural */:
|
|
1418
|
-
|
|
1454
|
+
traverseNodes(node.cases, transformer);
|
|
1455
|
+
transformer.helper("plural" /* HelperNameMap.PLURAL */);
|
|
1419
1456
|
break;
|
|
1420
1457
|
case 2 /* NodeTypes.Message */:
|
|
1421
|
-
|
|
1422
|
-
break;
|
|
1423
|
-
case 6 /* NodeTypes.Linked */:
|
|
1424
|
-
generateLinkedNode(generator, node);
|
|
1425
|
-
break;
|
|
1426
|
-
case 8 /* NodeTypes.LinkedModifier */:
|
|
1427
|
-
generator.push(JSON.stringify(node.value), node);
|
|
1458
|
+
traverseNodes(node.items, transformer);
|
|
1428
1459
|
break;
|
|
1429
|
-
case
|
|
1430
|
-
|
|
1460
|
+
case 6 /* NodeTypes.Linked */: {
|
|
1461
|
+
const linked = node;
|
|
1462
|
+
traverseNode(linked.key, transformer);
|
|
1463
|
+
transformer.helper("linked" /* HelperNameMap.LINKED */);
|
|
1464
|
+
transformer.helper("type" /* HelperNameMap.TYPE */);
|
|
1431
1465
|
break;
|
|
1466
|
+
}
|
|
1432
1467
|
case 5 /* NodeTypes.List */:
|
|
1433
|
-
|
|
1468
|
+
transformer.helper("interpolate" /* HelperNameMap.INTERPOLATE */);
|
|
1469
|
+
transformer.helper("list" /* HelperNameMap.LIST */);
|
|
1434
1470
|
break;
|
|
1435
1471
|
case 4 /* NodeTypes.Named */:
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
case 9 /* NodeTypes.Literal */:
|
|
1439
|
-
generator.push(JSON.stringify(node.value), node);
|
|
1440
|
-
break;
|
|
1441
|
-
case 3 /* NodeTypes.Text */:
|
|
1442
|
-
generator.push(JSON.stringify(node.value), node);
|
|
1472
|
+
transformer.helper("interpolate" /* HelperNameMap.INTERPOLATE */);
|
|
1473
|
+
transformer.helper("named" /* HelperNameMap.NAMED */);
|
|
1443
1474
|
break;
|
|
1444
|
-
default:
|
|
1445
|
-
if ((process.env.NODE_ENV !== 'production')) {
|
|
1446
|
-
throw createCompileError(CompileErrorCodes.UNHANDLED_CODEGEN_NODE_TYPE, null, {
|
|
1447
|
-
domain: ERROR_DOMAIN,
|
|
1448
|
-
args: [node.type]
|
|
1449
|
-
});
|
|
1450
|
-
}
|
|
1451
1475
|
}
|
|
1476
|
+
// TODO: if we need post-hook of transform, should be implemented to here
|
|
1477
|
+
}
|
|
1478
|
+
// transform AST
|
|
1479
|
+
function transform(ast, options = {} // eslint-disable-line
|
|
1480
|
+
) {
|
|
1481
|
+
const transformer = createTransformer(ast);
|
|
1482
|
+
transformer.helper("normalize" /* HelperNameMap.NORMALIZE */);
|
|
1483
|
+
// traverse
|
|
1484
|
+
ast.body && traverseNode(ast.body, transformer);
|
|
1485
|
+
// set meta information
|
|
1486
|
+
const context = transformer.context();
|
|
1487
|
+
ast.helpers = Array.from(context.helpers);
|
|
1452
1488
|
}
|
|
1453
|
-
// generate code from AST
|
|
1454
|
-
const generate = (ast, options = {}) => {
|
|
1455
|
-
const mode = isString(options.mode) ? options.mode : 'normal';
|
|
1456
|
-
const filename = isString(options.filename)
|
|
1457
|
-
? options.filename
|
|
1458
|
-
: 'message.intl';
|
|
1459
|
-
const sourceMap = !!options.sourceMap;
|
|
1460
|
-
// prettier-ignore
|
|
1461
|
-
const breakLineCode = options.breakLineCode != null
|
|
1462
|
-
? options.breakLineCode
|
|
1463
|
-
: mode === 'arrow'
|
|
1464
|
-
? ';'
|
|
1465
|
-
: '\n';
|
|
1466
|
-
const needIndent = options.needIndent ? options.needIndent : mode !== 'arrow';
|
|
1467
|
-
const helpers = ast.helpers || [];
|
|
1468
|
-
const generator = createCodeGenerator(ast, {
|
|
1469
|
-
mode,
|
|
1470
|
-
filename,
|
|
1471
|
-
sourceMap,
|
|
1472
|
-
breakLineCode,
|
|
1473
|
-
needIndent
|
|
1474
|
-
});
|
|
1475
|
-
generator.push(mode === 'normal' ? `function __msg__ (ctx) {` : `(ctx) => {`);
|
|
1476
|
-
generator.indent(needIndent);
|
|
1477
|
-
if (helpers.length > 0) {
|
|
1478
|
-
generator.push(`const { ${join(helpers.map(s => `${s}: _${s}`), ', ')} } = ctx`);
|
|
1479
|
-
generator.newline();
|
|
1480
|
-
}
|
|
1481
|
-
generator.push(`return `);
|
|
1482
|
-
generateNode(generator, ast);
|
|
1483
|
-
generator.deindent(needIndent);
|
|
1484
|
-
generator.push(`}`);
|
|
1485
|
-
delete ast.helpers;
|
|
1486
|
-
const { code, map } = generator.context();
|
|
1487
|
-
return {
|
|
1488
|
-
ast,
|
|
1489
|
-
code,
|
|
1490
|
-
map: map ? map.toJSON() : undefined // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
1491
|
-
};
|
|
1492
|
-
};
|
|
1493
1489
|
|
|
1494
1490
|
function baseCompile(source, options = {}) {
|
|
1495
1491
|
const assignedOptions = assign({}, options);
|
|
1496
1492
|
const jit = !!assignedOptions.jit;
|
|
1497
|
-
const
|
|
1498
|
-
const
|
|
1493
|
+
const enableMangle = !!assignedOptions.mangle;
|
|
1494
|
+
const enableOptimize = assignedOptions.optimize == null ? true : assignedOptions.optimize;
|
|
1499
1495
|
// parse source codes
|
|
1500
1496
|
const parser = createParser(assignedOptions);
|
|
1501
1497
|
const ast = parser.parse(source);
|
|
1498
|
+
// TODO:
|
|
1499
|
+
// With the introduction of Jit compilation, code generation is no longer necessary. This function may no longer be needed since tree-shaking is not possible.
|
|
1502
1500
|
if (!jit) {
|
|
1503
1501
|
// transform ASTs
|
|
1504
1502
|
transform(ast, assignedOptions);
|
|
@@ -1507,12 +1505,16 @@ function baseCompile(source, options = {}) {
|
|
|
1507
1505
|
}
|
|
1508
1506
|
else {
|
|
1509
1507
|
// optimize ASTs
|
|
1510
|
-
|
|
1508
|
+
enableOptimize && optimize(ast);
|
|
1511
1509
|
// minimize ASTs
|
|
1512
|
-
|
|
1510
|
+
enableMangle && mangle(ast);
|
|
1513
1511
|
// In JIT mode, no ast transform, no code generation.
|
|
1514
1512
|
return { ast, code: '' };
|
|
1515
1513
|
}
|
|
1516
1514
|
}
|
|
1517
1515
|
|
|
1518
|
-
|
|
1516
|
+
// eslint-disable-next-line no-useless-escape
|
|
1517
|
+
const RE_HTML_TAG = /<\/?[\w\s="/.':;#-\/]+>/;
|
|
1518
|
+
const detectHtmlTag = (source) => RE_HTML_TAG.test(source);
|
|
1519
|
+
|
|
1520
|
+
export { COMPILE_ERROR_CODES_EXTEND_POINT, CompileErrorCodes, ERROR_DOMAIN, LOCATION_STUB, baseCompile, createCompileError, createLocation, createParser, createPosition, defaultOnError, detectHtmlTag, errorMessages, mangle, optimize };
|