@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,26 +1,11 @@
|
|
|
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
6
|
var IntlifyMessageCompiler = (function (exports) {
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
-
const LOCATION_STUB = {
|
|
10
|
-
start: { line: 1, column: 1, offset: 0 },
|
|
11
|
-
end: { line: 1, column: 1, offset: 0 }
|
|
12
|
-
};
|
|
13
|
-
function createPosition(line, column, offset) {
|
|
14
|
-
return { line, column, offset };
|
|
15
|
-
}
|
|
16
|
-
function createLocation(start, end, source) {
|
|
17
|
-
const loc = { start, end };
|
|
18
|
-
if (source != null) {
|
|
19
|
-
loc.source = source;
|
|
20
|
-
}
|
|
21
|
-
return loc;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
9
|
/**
|
|
25
10
|
* Original Utilities
|
|
26
11
|
* written by kazuya kawaguchi
|
|
@@ -46,6 +31,21 @@ var IntlifyMessageCompiler = (function (exports) {
|
|
|
46
31
|
return items.reduce((str, item, index) => (index === 0 ? str + item : str + separator + item), '');
|
|
47
32
|
}
|
|
48
33
|
|
|
34
|
+
const LOCATION_STUB = {
|
|
35
|
+
start: { line: 1, column: 1, offset: 0 },
|
|
36
|
+
end: { line: 1, column: 1, offset: 0 }
|
|
37
|
+
};
|
|
38
|
+
function createPosition(line, column, offset) {
|
|
39
|
+
return { line, column, offset };
|
|
40
|
+
}
|
|
41
|
+
function createLocation(start, end, source) {
|
|
42
|
+
const loc = { start, end };
|
|
43
|
+
if (source != null) {
|
|
44
|
+
loc.source = source;
|
|
45
|
+
}
|
|
46
|
+
return loc;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
49
|
const CompileErrorCodes = {
|
|
50
50
|
// tokenizer error codes
|
|
51
51
|
EXPECTED_TOKEN: 1,
|
|
@@ -112,164 +112,473 @@ var IntlifyMessageCompiler = (function (exports) {
|
|
|
112
112
|
throw error;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
// eslint-disable-next-line
|
|
116
|
-
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const isLineEnd = (index) => isCRLF(index) || isLF(index) || isPS(index) || isLS(index);
|
|
135
|
-
const index = () => _index;
|
|
136
|
-
const line = () => _line;
|
|
137
|
-
const column = () => _column;
|
|
138
|
-
const peekOffset = () => _peekOffset;
|
|
139
|
-
const charAt = (offset) => isCRLF(offset) || isPS(offset) || isLS(offset) ? CHAR_LF : _buf[offset];
|
|
140
|
-
const currentChar = () => charAt(_index);
|
|
141
|
-
const currentPeek = () => charAt(_index + _peekOffset);
|
|
142
|
-
function next() {
|
|
143
|
-
_peekOffset = 0;
|
|
144
|
-
if (isLineEnd(_index)) {
|
|
145
|
-
_line++;
|
|
146
|
-
_column = 0;
|
|
147
|
-
}
|
|
148
|
-
if (isCRLF(_index)) {
|
|
149
|
-
_index++;
|
|
150
|
-
}
|
|
151
|
-
_index++;
|
|
152
|
-
_column++;
|
|
153
|
-
return _buf[_index];
|
|
115
|
+
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
|
|
116
|
+
/// <reference types="source-map-js" />
|
|
117
|
+
const ERROR_DOMAIN$3 = 'parser';
|
|
118
|
+
function createCodeGenerator(ast, options) {
|
|
119
|
+
const { sourceMap, filename, breakLineCode, needIndent: _needIndent } = options;
|
|
120
|
+
const location = options.location !== false;
|
|
121
|
+
const _context = {
|
|
122
|
+
filename,
|
|
123
|
+
code: '',
|
|
124
|
+
column: 1,
|
|
125
|
+
line: 1,
|
|
126
|
+
offset: 0,
|
|
127
|
+
map: undefined,
|
|
128
|
+
breakLineCode,
|
|
129
|
+
needIndent: _needIndent,
|
|
130
|
+
indentLevel: 0
|
|
131
|
+
};
|
|
132
|
+
if (location && ast.loc) {
|
|
133
|
+
_context.source = ast.loc.source;
|
|
154
134
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
_peekOffset++;
|
|
160
|
-
return _buf[_index + _peekOffset];
|
|
135
|
+
const context = () => _context;
|
|
136
|
+
function push(code, node) {
|
|
137
|
+
_context.code += code;
|
|
161
138
|
}
|
|
162
|
-
function
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
_column = 1;
|
|
166
|
-
_peekOffset = 0;
|
|
139
|
+
function _newline(n, withBreakLine = true) {
|
|
140
|
+
const _breakLineCode = withBreakLine ? breakLineCode : '';
|
|
141
|
+
push(_needIndent ? _breakLineCode + ` `.repeat(n) : _breakLineCode);
|
|
167
142
|
}
|
|
168
|
-
function
|
|
169
|
-
|
|
143
|
+
function indent(withNewLine = true) {
|
|
144
|
+
const level = ++_context.indentLevel;
|
|
145
|
+
withNewLine && _newline(level);
|
|
170
146
|
}
|
|
171
|
-
function
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
147
|
+
function deindent(withNewLine = true) {
|
|
148
|
+
const level = --_context.indentLevel;
|
|
149
|
+
withNewLine && _newline(level);
|
|
150
|
+
}
|
|
151
|
+
function newline() {
|
|
152
|
+
_newline(_context.indentLevel);
|
|
177
153
|
}
|
|
154
|
+
const helper = (key) => `_${key}`;
|
|
155
|
+
const needIndent = () => _context.needIndent;
|
|
178
156
|
return {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
next,
|
|
187
|
-
peek,
|
|
188
|
-
reset,
|
|
189
|
-
resetPeek,
|
|
190
|
-
skipToPeek
|
|
157
|
+
context,
|
|
158
|
+
push,
|
|
159
|
+
indent,
|
|
160
|
+
deindent,
|
|
161
|
+
newline,
|
|
162
|
+
helper,
|
|
163
|
+
needIndent
|
|
191
164
|
};
|
|
192
165
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
const currentOffset = () => _scnr.index();
|
|
202
|
-
const currentPosition = () => createPosition(_scnr.line(), _scnr.column(), _scnr.index());
|
|
203
|
-
const _initLoc = currentPosition();
|
|
204
|
-
const _initOffset = currentOffset();
|
|
205
|
-
const _context = {
|
|
206
|
-
currentType: 13 /* TokenTypes.EOF */,
|
|
207
|
-
offset: _initOffset,
|
|
208
|
-
startLoc: _initLoc,
|
|
209
|
-
endLoc: _initLoc,
|
|
210
|
-
lastType: 13 /* TokenTypes.EOF */,
|
|
211
|
-
lastOffset: _initOffset,
|
|
212
|
-
lastStartLoc: _initLoc,
|
|
213
|
-
lastEndLoc: _initLoc,
|
|
214
|
-
braceNest: 0,
|
|
215
|
-
inLinked: false,
|
|
216
|
-
text: ''
|
|
217
|
-
};
|
|
218
|
-
const context = () => _context;
|
|
219
|
-
const { onError } = options;
|
|
220
|
-
function emitError(code, pos, offset, ...args) {
|
|
221
|
-
const ctx = context();
|
|
222
|
-
pos.column += offset;
|
|
223
|
-
pos.offset += offset;
|
|
224
|
-
if (onError) {
|
|
225
|
-
const loc = location ? createLocation(ctx.startLoc, pos) : null;
|
|
226
|
-
const err = createCompileError(code, loc, {
|
|
227
|
-
domain: ERROR_DOMAIN$3,
|
|
228
|
-
args
|
|
229
|
-
});
|
|
230
|
-
onError(err);
|
|
231
|
-
}
|
|
166
|
+
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`);
|
|
232
174
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
context.currentType = type;
|
|
236
|
-
const token = { type };
|
|
237
|
-
if (location) {
|
|
238
|
-
token.loc = createLocation(context.startLoc, context.endLoc);
|
|
239
|
-
}
|
|
240
|
-
if (value != null) {
|
|
241
|
-
token.value = value;
|
|
242
|
-
}
|
|
243
|
-
return token;
|
|
175
|
+
else {
|
|
176
|
+
generator.push(`, undefined, _type`);
|
|
244
177
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
178
|
+
generator.push(`)`);
|
|
179
|
+
}
|
|
180
|
+
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;
|
|
254
189
|
}
|
|
190
|
+
generator.push(', ');
|
|
255
191
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
192
|
+
generator.deindent(needIndent());
|
|
193
|
+
generator.push('])');
|
|
194
|
+
}
|
|
195
|
+
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(', ');
|
|
261
207
|
}
|
|
262
|
-
|
|
208
|
+
generator.deindent(needIndent());
|
|
209
|
+
generator.push(`])`);
|
|
263
210
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
211
|
+
}
|
|
212
|
+
function generateResource(generator, node) {
|
|
213
|
+
if (node.body) {
|
|
214
|
+
generateNode(generator, node.body);
|
|
268
215
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
216
|
+
else {
|
|
217
|
+
generator.push('null');
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
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
|
+
{
|
|
255
|
+
throw createCompileError(CompileErrorCodes.UNHANDLED_CODEGEN_NODE_TYPE, null, {
|
|
256
|
+
domain: ERROR_DOMAIN$3,
|
|
257
|
+
args: [node.type]
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// generate code from AST
|
|
263
|
+
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
|
+
};
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
const ERROR_DOMAIN$2 = 'minifier';
|
|
304
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
305
|
+
function mangle(node) {
|
|
306
|
+
node.t = node.type;
|
|
307
|
+
switch (node.type) {
|
|
308
|
+
case 0 /* NodeTypes.Resource */: {
|
|
309
|
+
const resource = node;
|
|
310
|
+
mangle(resource.body);
|
|
311
|
+
resource.b = resource.body;
|
|
312
|
+
delete resource.body;
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
case 1 /* NodeTypes.Plural */: {
|
|
316
|
+
const plural = node;
|
|
317
|
+
const cases = plural.cases;
|
|
318
|
+
for (let i = 0; i < cases.length; i++) {
|
|
319
|
+
mangle(cases[i]);
|
|
320
|
+
}
|
|
321
|
+
plural.c = cases;
|
|
322
|
+
delete plural.cases;
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
case 2 /* NodeTypes.Message */: {
|
|
326
|
+
const message = node;
|
|
327
|
+
const items = message.items;
|
|
328
|
+
for (let i = 0; i < items.length; i++) {
|
|
329
|
+
mangle(items[i]);
|
|
330
|
+
}
|
|
331
|
+
message.i = items;
|
|
332
|
+
delete message.items;
|
|
333
|
+
if (message.static) {
|
|
334
|
+
message.s = message.static;
|
|
335
|
+
delete message.static;
|
|
336
|
+
}
|
|
337
|
+
break;
|
|
338
|
+
}
|
|
339
|
+
case 3 /* NodeTypes.Text */:
|
|
340
|
+
case 9 /* NodeTypes.Literal */:
|
|
341
|
+
case 8 /* NodeTypes.LinkedModifier */:
|
|
342
|
+
case 7 /* NodeTypes.LinkedKey */: {
|
|
343
|
+
const valueNode = node;
|
|
344
|
+
if (valueNode.value) {
|
|
345
|
+
valueNode.v = valueNode.value;
|
|
346
|
+
delete valueNode.value;
|
|
347
|
+
}
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
case 6 /* NodeTypes.Linked */: {
|
|
351
|
+
const linked = node;
|
|
352
|
+
mangle(linked.key);
|
|
353
|
+
linked.k = linked.key;
|
|
354
|
+
delete linked.key;
|
|
355
|
+
if (linked.modifier) {
|
|
356
|
+
mangle(linked.modifier);
|
|
357
|
+
linked.m = linked.modifier;
|
|
358
|
+
delete linked.modifier;
|
|
359
|
+
}
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
case 5 /* NodeTypes.List */: {
|
|
363
|
+
const list = node;
|
|
364
|
+
list.i = list.index;
|
|
365
|
+
delete list.index;
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
368
|
+
case 4 /* NodeTypes.Named */: {
|
|
369
|
+
const named = node;
|
|
370
|
+
named.k = named.key;
|
|
371
|
+
delete named.key;
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
default:
|
|
375
|
+
{
|
|
376
|
+
throw createCompileError(CompileErrorCodes.UNHANDLED_MINIFIER_NODE_TYPE, null, {
|
|
377
|
+
domain: ERROR_DOMAIN$2,
|
|
378
|
+
args: [node.type]
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
delete node.type;
|
|
383
|
+
}
|
|
384
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
385
|
+
|
|
386
|
+
function optimize(ast) {
|
|
387
|
+
const body = ast.body;
|
|
388
|
+
if (body.type === 2 /* NodeTypes.Message */) {
|
|
389
|
+
optimizeMessageNode(body);
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
body.cases.forEach(c => optimizeMessageNode(c));
|
|
393
|
+
}
|
|
394
|
+
return ast;
|
|
395
|
+
}
|
|
396
|
+
function optimizeMessageNode(message) {
|
|
397
|
+
if (message.items.length === 1) {
|
|
398
|
+
const item = message.items[0];
|
|
399
|
+
if (item.type === 3 /* NodeTypes.Text */ || item.type === 9 /* NodeTypes.Literal */) {
|
|
400
|
+
message.static = item.value;
|
|
401
|
+
delete item.value; // optimization for size
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
const values = [];
|
|
406
|
+
for (let i = 0; i < message.items.length; i++) {
|
|
407
|
+
const item = message.items[i];
|
|
408
|
+
if (!(item.type === 3 /* NodeTypes.Text */ || item.type === 9 /* NodeTypes.Literal */)) {
|
|
409
|
+
break;
|
|
410
|
+
}
|
|
411
|
+
if (item.value == null) {
|
|
412
|
+
break;
|
|
413
|
+
}
|
|
414
|
+
values.push(item.value);
|
|
415
|
+
}
|
|
416
|
+
if (values.length === message.items.length) {
|
|
417
|
+
message.static = join(values);
|
|
418
|
+
for (let i = 0; i < message.items.length; i++) {
|
|
419
|
+
const item = message.items[i];
|
|
420
|
+
if (item.type === 3 /* NodeTypes.Text */ || item.type === 9 /* NodeTypes.Literal */) {
|
|
421
|
+
delete item.value; // optimization for size
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const CHAR_SP = ' ';
|
|
429
|
+
const CHAR_CR = '\r';
|
|
430
|
+
const CHAR_LF = '\n';
|
|
431
|
+
const CHAR_LS = String.fromCharCode(0x2028);
|
|
432
|
+
const CHAR_PS = String.fromCharCode(0x2029);
|
|
433
|
+
function createScanner(str) {
|
|
434
|
+
const _buf = str;
|
|
435
|
+
let _index = 0;
|
|
436
|
+
let _line = 1;
|
|
437
|
+
let _column = 1;
|
|
438
|
+
let _peekOffset = 0;
|
|
439
|
+
const isCRLF = (index) => _buf[index] === CHAR_CR && _buf[index + 1] === CHAR_LF;
|
|
440
|
+
const isLF = (index) => _buf[index] === CHAR_LF;
|
|
441
|
+
const isPS = (index) => _buf[index] === CHAR_PS;
|
|
442
|
+
const isLS = (index) => _buf[index] === CHAR_LS;
|
|
443
|
+
const isLineEnd = (index) => isCRLF(index) || isLF(index) || isPS(index) || isLS(index);
|
|
444
|
+
const index = () => _index;
|
|
445
|
+
const line = () => _line;
|
|
446
|
+
const column = () => _column;
|
|
447
|
+
const peekOffset = () => _peekOffset;
|
|
448
|
+
const charAt = (offset) => isCRLF(offset) || isPS(offset) || isLS(offset) ? CHAR_LF : _buf[offset];
|
|
449
|
+
const currentChar = () => charAt(_index);
|
|
450
|
+
const currentPeek = () => charAt(_index + _peekOffset);
|
|
451
|
+
function next() {
|
|
452
|
+
_peekOffset = 0;
|
|
453
|
+
if (isLineEnd(_index)) {
|
|
454
|
+
_line++;
|
|
455
|
+
_column = 0;
|
|
456
|
+
}
|
|
457
|
+
if (isCRLF(_index)) {
|
|
458
|
+
_index++;
|
|
459
|
+
}
|
|
460
|
+
_index++;
|
|
461
|
+
_column++;
|
|
462
|
+
return _buf[_index];
|
|
463
|
+
}
|
|
464
|
+
function peek() {
|
|
465
|
+
if (isCRLF(_index + _peekOffset)) {
|
|
466
|
+
_peekOffset++;
|
|
467
|
+
}
|
|
468
|
+
_peekOffset++;
|
|
469
|
+
return _buf[_index + _peekOffset];
|
|
470
|
+
}
|
|
471
|
+
function reset() {
|
|
472
|
+
_index = 0;
|
|
473
|
+
_line = 1;
|
|
474
|
+
_column = 1;
|
|
475
|
+
_peekOffset = 0;
|
|
476
|
+
}
|
|
477
|
+
function resetPeek(offset = 0) {
|
|
478
|
+
_peekOffset = offset;
|
|
479
|
+
}
|
|
480
|
+
function skipToPeek() {
|
|
481
|
+
const target = _index + _peekOffset;
|
|
482
|
+
while (target !== _index) {
|
|
483
|
+
next();
|
|
484
|
+
}
|
|
485
|
+
_peekOffset = 0;
|
|
486
|
+
}
|
|
487
|
+
return {
|
|
488
|
+
index,
|
|
489
|
+
line,
|
|
490
|
+
column,
|
|
491
|
+
peekOffset,
|
|
492
|
+
charAt,
|
|
493
|
+
currentChar,
|
|
494
|
+
currentPeek,
|
|
495
|
+
next,
|
|
496
|
+
peek,
|
|
497
|
+
reset,
|
|
498
|
+
resetPeek,
|
|
499
|
+
skipToPeek
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
const EOF = undefined;
|
|
504
|
+
const DOT = '.';
|
|
505
|
+
const LITERAL_DELIMITER = "'";
|
|
506
|
+
const ERROR_DOMAIN$1 = 'tokenizer';
|
|
507
|
+
function createTokenizer(source, options = {}) {
|
|
508
|
+
const location = options.location !== false;
|
|
509
|
+
const _scnr = createScanner(source);
|
|
510
|
+
const currentOffset = () => _scnr.index();
|
|
511
|
+
const currentPosition = () => createPosition(_scnr.line(), _scnr.column(), _scnr.index());
|
|
512
|
+
const _initLoc = currentPosition();
|
|
513
|
+
const _initOffset = currentOffset();
|
|
514
|
+
const _context = {
|
|
515
|
+
currentType: 13 /* TokenTypes.EOF */,
|
|
516
|
+
offset: _initOffset,
|
|
517
|
+
startLoc: _initLoc,
|
|
518
|
+
endLoc: _initLoc,
|
|
519
|
+
lastType: 13 /* TokenTypes.EOF */,
|
|
520
|
+
lastOffset: _initOffset,
|
|
521
|
+
lastStartLoc: _initLoc,
|
|
522
|
+
lastEndLoc: _initLoc,
|
|
523
|
+
braceNest: 0,
|
|
524
|
+
inLinked: false,
|
|
525
|
+
text: ''
|
|
526
|
+
};
|
|
527
|
+
const context = () => _context;
|
|
528
|
+
const { onError } = options;
|
|
529
|
+
function emitError(code, pos, offset, ...args) {
|
|
530
|
+
const ctx = context();
|
|
531
|
+
pos.column += offset;
|
|
532
|
+
pos.offset += offset;
|
|
533
|
+
if (onError) {
|
|
534
|
+
const loc = location ? createLocation(ctx.startLoc, pos) : null;
|
|
535
|
+
const err = createCompileError(code, loc, {
|
|
536
|
+
domain: ERROR_DOMAIN$1,
|
|
537
|
+
args
|
|
538
|
+
});
|
|
539
|
+
onError(err);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
function getToken(context, type, value) {
|
|
543
|
+
context.endLoc = currentPosition();
|
|
544
|
+
context.currentType = type;
|
|
545
|
+
const token = { type };
|
|
546
|
+
if (location) {
|
|
547
|
+
token.loc = createLocation(context.startLoc, context.endLoc);
|
|
548
|
+
}
|
|
549
|
+
if (value != null) {
|
|
550
|
+
token.value = value;
|
|
551
|
+
}
|
|
552
|
+
return token;
|
|
553
|
+
}
|
|
554
|
+
const getEndToken = (context) => getToken(context, 13 /* TokenTypes.EOF */);
|
|
555
|
+
function eat(scnr, ch) {
|
|
556
|
+
if (scnr.currentChar() === ch) {
|
|
557
|
+
scnr.next();
|
|
558
|
+
return ch;
|
|
559
|
+
}
|
|
560
|
+
else {
|
|
561
|
+
emitError(CompileErrorCodes.EXPECTED_TOKEN, currentPosition(), 0, ch);
|
|
562
|
+
return '';
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
function peekSpaces(scnr) {
|
|
566
|
+
let buf = '';
|
|
567
|
+
while (scnr.currentPeek() === CHAR_SP || scnr.currentPeek() === CHAR_LF) {
|
|
568
|
+
buf += scnr.currentPeek();
|
|
569
|
+
scnr.peek();
|
|
570
|
+
}
|
|
571
|
+
return buf;
|
|
572
|
+
}
|
|
573
|
+
function skipSpaces(scnr) {
|
|
574
|
+
const buf = peekSpaces(scnr);
|
|
575
|
+
scnr.skipToPeek();
|
|
576
|
+
return buf;
|
|
577
|
+
}
|
|
578
|
+
function isIdentifierStart(ch) {
|
|
579
|
+
if (ch === EOF) {
|
|
580
|
+
return false;
|
|
581
|
+
}
|
|
273
582
|
const cc = ch.charCodeAt(0);
|
|
274
583
|
return ((cc >= 97 && cc <= 122) || // a-z
|
|
275
584
|
(cc >= 65 && cc <= 90) || // A-Z
|
|
@@ -845,7 +1154,7 @@ var IntlifyMessageCompiler = (function (exports) {
|
|
|
845
1154
|
};
|
|
846
1155
|
}
|
|
847
1156
|
|
|
848
|
-
const ERROR_DOMAIN
|
|
1157
|
+
const ERROR_DOMAIN = 'parser';
|
|
849
1158
|
// Backslash backslash, backslash quote, uHHHH, UHHHHHH.
|
|
850
1159
|
const KNOWN_ESCAPES = /(?:\\\\|\\'|\\u([0-9a-fA-F]{4})|\\U([0-9a-fA-F]{6}))/g;
|
|
851
1160
|
function fromEscapeSequence(match, codePoint4, codePoint6) {
|
|
@@ -877,7 +1186,7 @@ var IntlifyMessageCompiler = (function (exports) {
|
|
|
877
1186
|
if (onError) {
|
|
878
1187
|
const loc = location ? createLocation(start, end) : null;
|
|
879
1188
|
const err = createCompileError(code, loc, {
|
|
880
|
-
domain: ERROR_DOMAIN
|
|
1189
|
+
domain: ERROR_DOMAIN,
|
|
881
1190
|
args
|
|
882
1191
|
});
|
|
883
1192
|
onError(err);
|
|
@@ -1110,420 +1419,109 @@ var IntlifyMessageCompiler = (function (exports) {
|
|
|
1110
1419
|
const context = tokenizer.context();
|
|
1111
1420
|
const { offset, startLoc } = context;
|
|
1112
1421
|
const msgNode = parseMessage(tokenizer);
|
|
1113
|
-
if (context.currentType === 13 /* TokenTypes.EOF */) {
|
|
1114
|
-
return msgNode;
|
|
1115
|
-
}
|
|
1116
|
-
else {
|
|
1117
|
-
return parsePlural(tokenizer, offset, startLoc, msgNode);
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
function parse(source) {
|
|
1121
|
-
const tokenizer = createTokenizer(source, assign({}, options));
|
|
1122
|
-
const context = tokenizer.context();
|
|
1123
|
-
const node = startNode(0 /* NodeTypes.Resource */, context.offset, context.startLoc);
|
|
1124
|
-
if (location && node.loc) {
|
|
1125
|
-
node.loc.source = source;
|
|
1126
|
-
}
|
|
1127
|
-
node.body = parseResource(tokenizer);
|
|
1128
|
-
if (options.onCacheKey) {
|
|
1129
|
-
node.cacheKey = options.onCacheKey(source);
|
|
1130
|
-
}
|
|
1131
|
-
// assert whether achieved to EOF
|
|
1132
|
-
if (context.currentType !== 13 /* TokenTypes.EOF */) {
|
|
1133
|
-
emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, source[context.offset] || '');
|
|
1134
|
-
}
|
|
1135
|
-
endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
|
|
1136
|
-
return node;
|
|
1137
|
-
}
|
|
1138
|
-
return { parse };
|
|
1139
|
-
}
|
|
1140
|
-
function getTokenCaption(token) {
|
|
1141
|
-
if (token.type === 13 /* TokenTypes.EOF */) {
|
|
1142
|
-
return 'EOF';
|
|
1143
|
-
}
|
|
1144
|
-
const name = (token.value || '').replace(/\r?\n/gu, '\\n');
|
|
1145
|
-
return name.length > 10 ? name.slice(0, 9) + '…' : name;
|
|
1146
|
-
}
|
|
1147
|
-
|
|
1148
|
-
function createTransformer(ast, options = {} // eslint-disable-line
|
|
1149
|
-
) {
|
|
1150
|
-
const _context = {
|
|
1151
|
-
ast,
|
|
1152
|
-
helpers: new Set()
|
|
1153
|
-
};
|
|
1154
|
-
const context = () => _context;
|
|
1155
|
-
const helper = (name) => {
|
|
1156
|
-
_context.helpers.add(name);
|
|
1157
|
-
return name;
|
|
1158
|
-
};
|
|
1159
|
-
return { context, helper };
|
|
1160
|
-
}
|
|
1161
|
-
function traverseNodes(nodes, transformer) {
|
|
1162
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
1163
|
-
traverseNode(nodes[i], transformer);
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
function traverseNode(node, transformer) {
|
|
1167
|
-
// TODO: if we need pre-hook of transform, should be implemented to here
|
|
1168
|
-
switch (node.type) {
|
|
1169
|
-
case 1 /* NodeTypes.Plural */:
|
|
1170
|
-
traverseNodes(node.cases, transformer);
|
|
1171
|
-
transformer.helper("plural" /* HelperNameMap.PLURAL */);
|
|
1172
|
-
break;
|
|
1173
|
-
case 2 /* NodeTypes.Message */:
|
|
1174
|
-
traverseNodes(node.items, transformer);
|
|
1175
|
-
break;
|
|
1176
|
-
case 6 /* NodeTypes.Linked */: {
|
|
1177
|
-
const linked = node;
|
|
1178
|
-
traverseNode(linked.key, transformer);
|
|
1179
|
-
transformer.helper("linked" /* HelperNameMap.LINKED */);
|
|
1180
|
-
transformer.helper("type" /* HelperNameMap.TYPE */);
|
|
1181
|
-
break;
|
|
1182
|
-
}
|
|
1183
|
-
case 5 /* NodeTypes.List */:
|
|
1184
|
-
transformer.helper("interpolate" /* HelperNameMap.INTERPOLATE */);
|
|
1185
|
-
transformer.helper("list" /* HelperNameMap.LIST */);
|
|
1186
|
-
break;
|
|
1187
|
-
case 4 /* NodeTypes.Named */:
|
|
1188
|
-
transformer.helper("interpolate" /* HelperNameMap.INTERPOLATE */);
|
|
1189
|
-
transformer.helper("named" /* HelperNameMap.NAMED */);
|
|
1190
|
-
break;
|
|
1191
|
-
}
|
|
1192
|
-
// TODO: if we need post-hook of transform, should be implemented to here
|
|
1193
|
-
}
|
|
1194
|
-
// transform AST
|
|
1195
|
-
function transform(ast, options = {} // eslint-disable-line
|
|
1196
|
-
) {
|
|
1197
|
-
const transformer = createTransformer(ast);
|
|
1198
|
-
transformer.helper("normalize" /* HelperNameMap.NORMALIZE */);
|
|
1199
|
-
// traverse
|
|
1200
|
-
ast.body && traverseNode(ast.body, transformer);
|
|
1201
|
-
// set meta information
|
|
1202
|
-
const context = transformer.context();
|
|
1203
|
-
ast.helpers = Array.from(context.helpers);
|
|
1204
|
-
}
|
|
1205
|
-
|
|
1206
|
-
function optimize(ast) {
|
|
1207
|
-
const body = ast.body;
|
|
1208
|
-
if (body.type === 2 /* NodeTypes.Message */) {
|
|
1209
|
-
optimizeMessageNode(body);
|
|
1210
|
-
}
|
|
1211
|
-
else {
|
|
1212
|
-
body.cases.forEach(c => optimizeMessageNode(c));
|
|
1213
|
-
}
|
|
1214
|
-
return ast;
|
|
1215
|
-
}
|
|
1216
|
-
function optimizeMessageNode(message) {
|
|
1217
|
-
if (message.items.length === 1) {
|
|
1218
|
-
const item = message.items[0];
|
|
1219
|
-
if (item.type === 3 /* NodeTypes.Text */ || item.type === 9 /* NodeTypes.Literal */) {
|
|
1220
|
-
message.static = item.value;
|
|
1221
|
-
delete item.value; // optimization for size
|
|
1222
|
-
}
|
|
1223
|
-
}
|
|
1224
|
-
else {
|
|
1225
|
-
const values = [];
|
|
1226
|
-
for (let i = 0; i < message.items.length; i++) {
|
|
1227
|
-
const item = message.items[i];
|
|
1228
|
-
if (!(item.type === 3 /* NodeTypes.Text */ || item.type === 9 /* NodeTypes.Literal */)) {
|
|
1229
|
-
break;
|
|
1230
|
-
}
|
|
1231
|
-
if (item.value == null) {
|
|
1232
|
-
break;
|
|
1233
|
-
}
|
|
1234
|
-
values.push(item.value);
|
|
1235
|
-
}
|
|
1236
|
-
if (values.length === message.items.length) {
|
|
1237
|
-
message.static = join(values);
|
|
1238
|
-
for (let i = 0; i < message.items.length; i++) {
|
|
1239
|
-
const item = message.items[i];
|
|
1240
|
-
if (item.type === 3 /* NodeTypes.Text */ || item.type === 9 /* NodeTypes.Literal */) {
|
|
1241
|
-
delete item.value; // optimization for size
|
|
1242
|
-
}
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
}
|
|
1246
|
-
}
|
|
1247
|
-
|
|
1248
|
-
const ERROR_DOMAIN$1 = 'minifier';
|
|
1249
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1250
|
-
function minify(node) {
|
|
1251
|
-
node.t = node.type;
|
|
1252
|
-
switch (node.type) {
|
|
1253
|
-
case 0 /* NodeTypes.Resource */: {
|
|
1254
|
-
const resource = node;
|
|
1255
|
-
minify(resource.body);
|
|
1256
|
-
resource.b = resource.body;
|
|
1257
|
-
delete resource.body;
|
|
1258
|
-
break;
|
|
1259
|
-
}
|
|
1260
|
-
case 1 /* NodeTypes.Plural */: {
|
|
1261
|
-
const plural = node;
|
|
1262
|
-
const cases = plural.cases;
|
|
1263
|
-
for (let i = 0; i < cases.length; i++) {
|
|
1264
|
-
minify(cases[i]);
|
|
1265
|
-
}
|
|
1266
|
-
plural.c = cases;
|
|
1267
|
-
delete plural.cases;
|
|
1268
|
-
break;
|
|
1269
|
-
}
|
|
1270
|
-
case 2 /* NodeTypes.Message */: {
|
|
1271
|
-
const message = node;
|
|
1272
|
-
const items = message.items;
|
|
1273
|
-
for (let i = 0; i < items.length; i++) {
|
|
1274
|
-
minify(items[i]);
|
|
1275
|
-
}
|
|
1276
|
-
message.i = items;
|
|
1277
|
-
delete message.items;
|
|
1278
|
-
if (message.static) {
|
|
1279
|
-
message.s = message.static;
|
|
1280
|
-
delete message.static;
|
|
1281
|
-
}
|
|
1282
|
-
break;
|
|
1283
|
-
}
|
|
1284
|
-
case 3 /* NodeTypes.Text */:
|
|
1285
|
-
case 9 /* NodeTypes.Literal */:
|
|
1286
|
-
case 8 /* NodeTypes.LinkedModifier */:
|
|
1287
|
-
case 7 /* NodeTypes.LinkedKey */: {
|
|
1288
|
-
const valueNode = node;
|
|
1289
|
-
if (valueNode.value) {
|
|
1290
|
-
valueNode.v = valueNode.value;
|
|
1291
|
-
delete valueNode.value;
|
|
1292
|
-
}
|
|
1293
|
-
break;
|
|
1294
|
-
}
|
|
1295
|
-
case 6 /* NodeTypes.Linked */: {
|
|
1296
|
-
const linked = node;
|
|
1297
|
-
minify(linked.key);
|
|
1298
|
-
linked.k = linked.key;
|
|
1299
|
-
delete linked.key;
|
|
1300
|
-
if (linked.modifier) {
|
|
1301
|
-
minify(linked.modifier);
|
|
1302
|
-
linked.m = linked.modifier;
|
|
1303
|
-
delete linked.modifier;
|
|
1304
|
-
}
|
|
1305
|
-
break;
|
|
1422
|
+
if (context.currentType === 13 /* TokenTypes.EOF */) {
|
|
1423
|
+
return msgNode;
|
|
1306
1424
|
}
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
list.i = list.index;
|
|
1310
|
-
delete list.index;
|
|
1311
|
-
break;
|
|
1425
|
+
else {
|
|
1426
|
+
return parsePlural(tokenizer, offset, startLoc, msgNode);
|
|
1312
1427
|
}
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1428
|
+
}
|
|
1429
|
+
function parse(source) {
|
|
1430
|
+
const tokenizer = createTokenizer(source, assign({}, options));
|
|
1431
|
+
const context = tokenizer.context();
|
|
1432
|
+
const node = startNode(0 /* NodeTypes.Resource */, context.offset, context.startLoc);
|
|
1433
|
+
if (location && node.loc) {
|
|
1434
|
+
node.loc.source = source;
|
|
1318
1435
|
}
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1436
|
+
node.body = parseResource(tokenizer);
|
|
1437
|
+
if (options.onCacheKey) {
|
|
1438
|
+
node.cacheKey = options.onCacheKey(source);
|
|
1439
|
+
}
|
|
1440
|
+
// assert whether achieved to EOF
|
|
1441
|
+
if (context.currentType !== 13 /* TokenTypes.EOF */) {
|
|
1442
|
+
emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, source[context.offset] || '');
|
|
1443
|
+
}
|
|
1444
|
+
endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
|
|
1445
|
+
return node;
|
|
1326
1446
|
}
|
|
1327
|
-
|
|
1447
|
+
return { parse };
|
|
1448
|
+
}
|
|
1449
|
+
function getTokenCaption(token) {
|
|
1450
|
+
if (token.type === 13 /* TokenTypes.EOF */) {
|
|
1451
|
+
return 'EOF';
|
|
1452
|
+
}
|
|
1453
|
+
const name = (token.value || '').replace(/\r?\n/gu, '\\n');
|
|
1454
|
+
return name.length > 10 ? name.slice(0, 9) + '…' : name;
|
|
1328
1455
|
}
|
|
1329
|
-
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
1330
1456
|
|
|
1331
|
-
// eslint-disable-
|
|
1332
|
-
|
|
1333
|
-
const ERROR_DOMAIN = 'parser';
|
|
1334
|
-
function createCodeGenerator(ast, options) {
|
|
1335
|
-
const { sourceMap, filename, breakLineCode, needIndent: _needIndent } = options;
|
|
1336
|
-
const location = options.location !== false;
|
|
1457
|
+
function createTransformer(ast, options = {} // eslint-disable-line
|
|
1458
|
+
) {
|
|
1337
1459
|
const _context = {
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
column: 1,
|
|
1341
|
-
line: 1,
|
|
1342
|
-
offset: 0,
|
|
1343
|
-
map: undefined,
|
|
1344
|
-
breakLineCode,
|
|
1345
|
-
needIndent: _needIndent,
|
|
1346
|
-
indentLevel: 0
|
|
1460
|
+
ast,
|
|
1461
|
+
helpers: new Set()
|
|
1347
1462
|
};
|
|
1348
|
-
if (location && ast.loc) {
|
|
1349
|
-
_context.source = ast.loc.source;
|
|
1350
|
-
}
|
|
1351
1463
|
const context = () => _context;
|
|
1352
|
-
|
|
1353
|
-
_context.
|
|
1354
|
-
|
|
1355
|
-
function _newline(n, withBreakLine = true) {
|
|
1356
|
-
const _breakLineCode = withBreakLine ? breakLineCode : '';
|
|
1357
|
-
push(_needIndent ? _breakLineCode + ` `.repeat(n) : _breakLineCode);
|
|
1358
|
-
}
|
|
1359
|
-
function indent(withNewLine = true) {
|
|
1360
|
-
const level = ++_context.indentLevel;
|
|
1361
|
-
withNewLine && _newline(level);
|
|
1362
|
-
}
|
|
1363
|
-
function deindent(withNewLine = true) {
|
|
1364
|
-
const level = --_context.indentLevel;
|
|
1365
|
-
withNewLine && _newline(level);
|
|
1366
|
-
}
|
|
1367
|
-
function newline() {
|
|
1368
|
-
_newline(_context.indentLevel);
|
|
1369
|
-
}
|
|
1370
|
-
const helper = (key) => `_${key}`;
|
|
1371
|
-
const needIndent = () => _context.needIndent;
|
|
1372
|
-
return {
|
|
1373
|
-
context,
|
|
1374
|
-
push,
|
|
1375
|
-
indent,
|
|
1376
|
-
deindent,
|
|
1377
|
-
newline,
|
|
1378
|
-
helper,
|
|
1379
|
-
needIndent
|
|
1464
|
+
const helper = (name) => {
|
|
1465
|
+
_context.helpers.add(name);
|
|
1466
|
+
return name;
|
|
1380
1467
|
};
|
|
1468
|
+
return { context, helper };
|
|
1381
1469
|
}
|
|
1382
|
-
function
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
generateNode(generator, node.key);
|
|
1386
|
-
if (node.modifier) {
|
|
1387
|
-
generator.push(`, `);
|
|
1388
|
-
generateNode(generator, node.modifier);
|
|
1389
|
-
generator.push(`, _type`);
|
|
1390
|
-
}
|
|
1391
|
-
else {
|
|
1392
|
-
generator.push(`, undefined, _type`);
|
|
1393
|
-
}
|
|
1394
|
-
generator.push(`)`);
|
|
1395
|
-
}
|
|
1396
|
-
function generateMessageNode(generator, node) {
|
|
1397
|
-
const { helper, needIndent } = generator;
|
|
1398
|
-
generator.push(`${helper("normalize" /* HelperNameMap.NORMALIZE */)}([`);
|
|
1399
|
-
generator.indent(needIndent());
|
|
1400
|
-
const length = node.items.length;
|
|
1401
|
-
for (let i = 0; i < length; i++) {
|
|
1402
|
-
generateNode(generator, node.items[i]);
|
|
1403
|
-
if (i === length - 1) {
|
|
1404
|
-
break;
|
|
1405
|
-
}
|
|
1406
|
-
generator.push(', ');
|
|
1407
|
-
}
|
|
1408
|
-
generator.deindent(needIndent());
|
|
1409
|
-
generator.push('])');
|
|
1410
|
-
}
|
|
1411
|
-
function generatePluralNode(generator, node) {
|
|
1412
|
-
const { helper, needIndent } = generator;
|
|
1413
|
-
if (node.cases.length > 1) {
|
|
1414
|
-
generator.push(`${helper("plural" /* HelperNameMap.PLURAL */)}([`);
|
|
1415
|
-
generator.indent(needIndent());
|
|
1416
|
-
const length = node.cases.length;
|
|
1417
|
-
for (let i = 0; i < length; i++) {
|
|
1418
|
-
generateNode(generator, node.cases[i]);
|
|
1419
|
-
if (i === length - 1) {
|
|
1420
|
-
break;
|
|
1421
|
-
}
|
|
1422
|
-
generator.push(', ');
|
|
1423
|
-
}
|
|
1424
|
-
generator.deindent(needIndent());
|
|
1425
|
-
generator.push(`])`);
|
|
1426
|
-
}
|
|
1427
|
-
}
|
|
1428
|
-
function generateResource(generator, node) {
|
|
1429
|
-
if (node.body) {
|
|
1430
|
-
generateNode(generator, node.body);
|
|
1431
|
-
}
|
|
1432
|
-
else {
|
|
1433
|
-
generator.push('null');
|
|
1470
|
+
function traverseNodes(nodes, transformer) {
|
|
1471
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
1472
|
+
traverseNode(nodes[i], transformer);
|
|
1434
1473
|
}
|
|
1435
1474
|
}
|
|
1436
|
-
function
|
|
1437
|
-
|
|
1475
|
+
function traverseNode(node, transformer) {
|
|
1476
|
+
// TODO: if we need pre-hook of transform, should be implemented to here
|
|
1438
1477
|
switch (node.type) {
|
|
1439
|
-
case 0 /* NodeTypes.Resource */:
|
|
1440
|
-
generateResource(generator, node);
|
|
1441
|
-
break;
|
|
1442
1478
|
case 1 /* NodeTypes.Plural */:
|
|
1443
|
-
|
|
1479
|
+
traverseNodes(node.cases, transformer);
|
|
1480
|
+
transformer.helper("plural" /* HelperNameMap.PLURAL */);
|
|
1444
1481
|
break;
|
|
1445
1482
|
case 2 /* NodeTypes.Message */:
|
|
1446
|
-
|
|
1447
|
-
break;
|
|
1448
|
-
case 6 /* NodeTypes.Linked */:
|
|
1449
|
-
generateLinkedNode(generator, node);
|
|
1450
|
-
break;
|
|
1451
|
-
case 8 /* NodeTypes.LinkedModifier */:
|
|
1452
|
-
generator.push(JSON.stringify(node.value), node);
|
|
1483
|
+
traverseNodes(node.items, transformer);
|
|
1453
1484
|
break;
|
|
1454
|
-
case
|
|
1455
|
-
|
|
1485
|
+
case 6 /* NodeTypes.Linked */: {
|
|
1486
|
+
const linked = node;
|
|
1487
|
+
traverseNode(linked.key, transformer);
|
|
1488
|
+
transformer.helper("linked" /* HelperNameMap.LINKED */);
|
|
1489
|
+
transformer.helper("type" /* HelperNameMap.TYPE */);
|
|
1456
1490
|
break;
|
|
1491
|
+
}
|
|
1457
1492
|
case 5 /* NodeTypes.List */:
|
|
1458
|
-
|
|
1493
|
+
transformer.helper("interpolate" /* HelperNameMap.INTERPOLATE */);
|
|
1494
|
+
transformer.helper("list" /* HelperNameMap.LIST */);
|
|
1459
1495
|
break;
|
|
1460
1496
|
case 4 /* NodeTypes.Named */:
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
case 9 /* NodeTypes.Literal */:
|
|
1464
|
-
generator.push(JSON.stringify(node.value), node);
|
|
1465
|
-
break;
|
|
1466
|
-
case 3 /* NodeTypes.Text */:
|
|
1467
|
-
generator.push(JSON.stringify(node.value), node);
|
|
1497
|
+
transformer.helper("interpolate" /* HelperNameMap.INTERPOLATE */);
|
|
1498
|
+
transformer.helper("named" /* HelperNameMap.NAMED */);
|
|
1468
1499
|
break;
|
|
1469
|
-
default:
|
|
1470
|
-
{
|
|
1471
|
-
throw createCompileError(CompileErrorCodes.UNHANDLED_CODEGEN_NODE_TYPE, null, {
|
|
1472
|
-
domain: ERROR_DOMAIN,
|
|
1473
|
-
args: [node.type]
|
|
1474
|
-
});
|
|
1475
|
-
}
|
|
1476
1500
|
}
|
|
1501
|
+
// TODO: if we need post-hook of transform, should be implemented to here
|
|
1502
|
+
}
|
|
1503
|
+
// transform AST
|
|
1504
|
+
function transform(ast, options = {} // eslint-disable-line
|
|
1505
|
+
) {
|
|
1506
|
+
const transformer = createTransformer(ast);
|
|
1507
|
+
transformer.helper("normalize" /* HelperNameMap.NORMALIZE */);
|
|
1508
|
+
// traverse
|
|
1509
|
+
ast.body && traverseNode(ast.body, transformer);
|
|
1510
|
+
// set meta information
|
|
1511
|
+
const context = transformer.context();
|
|
1512
|
+
ast.helpers = Array.from(context.helpers);
|
|
1477
1513
|
}
|
|
1478
|
-
// generate code from AST
|
|
1479
|
-
const generate = (ast, options = {}) => {
|
|
1480
|
-
const mode = isString(options.mode) ? options.mode : 'normal';
|
|
1481
|
-
const filename = isString(options.filename)
|
|
1482
|
-
? options.filename
|
|
1483
|
-
: 'message.intl';
|
|
1484
|
-
const sourceMap = !!options.sourceMap;
|
|
1485
|
-
// prettier-ignore
|
|
1486
|
-
const breakLineCode = options.breakLineCode != null
|
|
1487
|
-
? options.breakLineCode
|
|
1488
|
-
: mode === 'arrow'
|
|
1489
|
-
? ';'
|
|
1490
|
-
: '\n';
|
|
1491
|
-
const needIndent = options.needIndent ? options.needIndent : mode !== 'arrow';
|
|
1492
|
-
const helpers = ast.helpers || [];
|
|
1493
|
-
const generator = createCodeGenerator(ast, {
|
|
1494
|
-
mode,
|
|
1495
|
-
filename,
|
|
1496
|
-
sourceMap,
|
|
1497
|
-
breakLineCode,
|
|
1498
|
-
needIndent
|
|
1499
|
-
});
|
|
1500
|
-
generator.push(mode === 'normal' ? `function __msg__ (ctx) {` : `(ctx) => {`);
|
|
1501
|
-
generator.indent(needIndent);
|
|
1502
|
-
if (helpers.length > 0) {
|
|
1503
|
-
generator.push(`const { ${join(helpers.map(s => `${s}: _${s}`), ', ')} } = ctx`);
|
|
1504
|
-
generator.newline();
|
|
1505
|
-
}
|
|
1506
|
-
generator.push(`return `);
|
|
1507
|
-
generateNode(generator, ast);
|
|
1508
|
-
generator.deindent(needIndent);
|
|
1509
|
-
generator.push(`}`);
|
|
1510
|
-
delete ast.helpers;
|
|
1511
|
-
const { code, map } = generator.context();
|
|
1512
|
-
return {
|
|
1513
|
-
ast,
|
|
1514
|
-
code,
|
|
1515
|
-
map: map ? map.toJSON() : undefined // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
1516
|
-
};
|
|
1517
|
-
};
|
|
1518
1514
|
|
|
1519
1515
|
function baseCompile(source, options = {}) {
|
|
1520
1516
|
const assignedOptions = assign({}, options);
|
|
1521
1517
|
const jit = !!assignedOptions.jit;
|
|
1522
|
-
const
|
|
1523
|
-
const
|
|
1518
|
+
const enableMangle = !!assignedOptions.mangle;
|
|
1519
|
+
const enableOptimize = assignedOptions.optimize == null ? true : assignedOptions.optimize;
|
|
1524
1520
|
// parse source codes
|
|
1525
1521
|
const parser = createParser(assignedOptions);
|
|
1526
1522
|
const ast = parser.parse(source);
|
|
1523
|
+
// TODO:
|
|
1524
|
+
// 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.
|
|
1527
1525
|
if (!jit) {
|
|
1528
1526
|
// transform ASTs
|
|
1529
1527
|
transform(ast, assignedOptions);
|
|
@@ -1532,17 +1530,21 @@ var IntlifyMessageCompiler = (function (exports) {
|
|
|
1532
1530
|
}
|
|
1533
1531
|
else {
|
|
1534
1532
|
// optimize ASTs
|
|
1535
|
-
|
|
1533
|
+
enableOptimize && optimize(ast);
|
|
1536
1534
|
// minimize ASTs
|
|
1537
|
-
|
|
1535
|
+
enableMangle && mangle(ast);
|
|
1538
1536
|
// In JIT mode, no ast transform, no code generation.
|
|
1539
1537
|
return { ast, code: '' };
|
|
1540
1538
|
}
|
|
1541
1539
|
}
|
|
1542
1540
|
|
|
1541
|
+
// eslint-disable-next-line no-useless-escape
|
|
1542
|
+
const RE_HTML_TAG = /<\/?[\w\s="/.':;#-\/]+>/;
|
|
1543
|
+
const detectHtmlTag = (source) => RE_HTML_TAG.test(source);
|
|
1544
|
+
|
|
1543
1545
|
exports.COMPILE_ERROR_CODES_EXTEND_POINT = COMPILE_ERROR_CODES_EXTEND_POINT;
|
|
1544
1546
|
exports.CompileErrorCodes = CompileErrorCodes;
|
|
1545
|
-
exports.ERROR_DOMAIN = ERROR_DOMAIN
|
|
1547
|
+
exports.ERROR_DOMAIN = ERROR_DOMAIN;
|
|
1546
1548
|
exports.LOCATION_STUB = LOCATION_STUB;
|
|
1547
1549
|
exports.baseCompile = baseCompile;
|
|
1548
1550
|
exports.createCompileError = createCompileError;
|
|
@@ -1552,6 +1554,8 @@ var IntlifyMessageCompiler = (function (exports) {
|
|
|
1552
1554
|
exports.defaultOnError = defaultOnError;
|
|
1553
1555
|
exports.detectHtmlTag = detectHtmlTag;
|
|
1554
1556
|
exports.errorMessages = errorMessages;
|
|
1557
|
+
exports.mangle = mangle;
|
|
1558
|
+
exports.optimize = optimize;
|
|
1555
1559
|
|
|
1556
1560
|
return exports;
|
|
1557
1561
|
|