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