@intlify/bundle-utils 11.2.6 → 11.2.7

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.
Files changed (3) hide show
  1. package/lib/index.cjs +149 -205
  2. package/lib/index.mjs +137 -205
  3. package/package.json +3 -6
package/lib/index.cjs CHANGED
@@ -3,8 +3,6 @@
3
3
  const module$1 = require('node:module');
4
4
  const shared = require('@intlify/shared');
5
5
  const acorn = require('acorn');
6
- const escodegen = require('escodegen');
7
- const estreeWalker = require('estree-walker');
8
6
  const messageCompiler = require('@intlify/message-compiler');
9
7
  const sourceMapJs = require('source-map-js');
10
8
  const jsoncEslintParser = require('jsonc-eslint-parser');
@@ -14,7 +12,20 @@ const yamlEslintParser = require('yaml-eslint-parser');
14
12
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
15
13
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
16
14
 
15
+ function _interopNamespaceCompat(e) {
16
+ if (e && typeof e === 'object' && 'default' in e) return e;
17
+ const n = Object.create(null);
18
+ if (e) {
19
+ for (const k in e) {
20
+ n[k] = e[k];
21
+ }
22
+ }
23
+ n.default = e;
24
+ return n;
25
+ }
26
+
17
27
  const module__default = /*#__PURE__*/_interopDefaultCompat(module$1);
28
+ const messageCompiler__namespace = /*#__PURE__*/_interopNamespaceCompat(messageCompiler);
18
29
 
19
30
  const _require = module__default.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
20
31
  function checkInstallPackage(pkg, debug) {
@@ -160,6 +171,14 @@ const ON_ERROR_NOOP = () => {
160
171
  function parsePath(path) {
161
172
  return path ? path.join(".") : "";
162
173
  }
174
+ const COMPILE_ERROR_MESSAGES = messageCompiler__namespace.errorMessages;
175
+ function getCompileErrorMessage(err) {
176
+ if (err.message !== String(err.code)) {
177
+ return err.message;
178
+ }
179
+ const text = COMPILE_ERROR_MESSAGES?.[err.code];
180
+ return text ? text.replace(/:\s*\\?'?\{\d+\}'?/g, "") : err.message;
181
+ }
163
182
  function generateMessageFunction(msg, options = {}, path) {
164
183
  const env = options.env != null ? options.env : "development";
165
184
  const strictMessage = shared.isBoolean(options.strictMessage) ? options.strictMessage : true;
@@ -188,7 +207,7 @@ function generateMessageFunction(msg, options = {}, path) {
188
207
  domain: err.domain,
189
208
  location: err.location
190
209
  };
191
- onError(err.message, extra);
210
+ onError(getCompileErrorMessage(err), extra);
192
211
  errors.push(err);
193
212
  }
194
213
  };
@@ -300,7 +319,7 @@ function generateResourceAst(msg, options = {}, path) {
300
319
  domain: err.domain,
301
320
  location: err.location
302
321
  };
303
- onError(err.message, extra);
322
+ onError(getCompileErrorMessage(err), extra);
304
323
  errors.push(err);
305
324
  }
306
325
  };
@@ -349,6 +368,11 @@ function describeValue(value) {
349
368
  if (value === void 0) return "undefined";
350
369
  return `a ${typeof value}`;
351
370
  }
371
+ function stringifyValue(value) {
372
+ if (typeof value === "number") return Object.is(value, -0) ? "-0" : String(value);
373
+ if (value === void 0) return "undefined";
374
+ return JSON.stringify(value);
375
+ }
352
376
  function createResourceError(message, options) {
353
377
  return new Error(`${message} in ${describeResource(options)}.`);
354
378
  }
@@ -452,222 +476,121 @@ function scanAst(ast) {
452
476
  return false;
453
477
  }
454
478
  function _generate$2(generator, node, options = {}) {
455
- const propsCountStack = [];
456
- const pathStack = [];
457
- const itemsCountStack = [];
458
- const skipStack = [];
459
479
  const { forceStringify } = generator.context();
460
480
  const codeMaps = /* @__PURE__ */ new Map();
461
481
  const { type, sourceMap, isGlobal, locale, jit } = options;
482
+ const source = options.source ?? "";
462
483
  const _codegenFn = jit ? generateResourceAst : generateMessageFunction;
463
- function codegenFn(value) {
464
- const { code, map } = _codegenFn(value, options, pathStack);
484
+ function codegenFn(value, path) {
485
+ const { code, map } = _codegenFn(value, options, path);
465
486
  sourceMap && map != null && codeMaps.set(value, map);
466
487
  return code;
467
488
  }
468
489
  const componentNamespace = "_Component";
469
490
  const variableDeclarations = [];
470
- estreeWalker.walk(node, {
471
- /**
472
- * NOTE:
473
- * force cast to Node of `estree-walker@3.x`,
474
- * because `estree-walker@3.x` is not dual packages,
475
- * so it's support only esm only ...
476
- */
477
- // @ts-ignore
478
- enter(node2, _parent) {
479
- if (_parent?.type != null) this.skip();
480
- switch (node2.type) {
481
- case "ExportDefaultDeclaration":
482
- this.skip();
483
- break;
484
- case "ImportDeclaration":
485
- generator.push(options.source?.slice(node2.start, node2.end));
486
- generator.newline();
487
- break;
488
- case "VariableDeclaration":
489
- generator.push(options.source?.slice(node2.start, node2.end));
490
- generator.newline();
491
- variableDeclarations.push(
492
- ...node2.declarations.map((x) => `\`${x.id.name}\``)
493
- );
494
- break;
495
- }
491
+ const { body } = node;
492
+ const exportDefault = body.find(
493
+ (statement) => statement.type === "ExportDefaultDeclaration"
494
+ );
495
+ const resource = exportDefault.declaration;
496
+ for (const statement of body) {
497
+ if (statement === exportDefault) continue;
498
+ generator.push(sourceOf(source, statement));
499
+ generator.newline();
500
+ if (statement.type === "VariableDeclaration") {
501
+ variableDeclarations.push(
502
+ ...statement.declarations.map((x) => `\`${x.id.name}\``)
503
+ );
496
504
  }
497
- });
505
+ }
498
506
  if (variableDeclarations.length > 0) {
499
507
  options?.onWarn?.(
500
508
  `
501
509
  Variable declarations are not optimized - found ${variableDeclarations.join(", ")}`
502
510
  );
503
511
  }
504
- estreeWalker.walk(node, {
505
- /**
506
- * NOTE:
507
- * force cast to Node of `estree-walker@3.x`,
508
- * because `estree-walker@3.x` is not dual packages,
509
- * so it's support only esm only ...
510
- */
511
- // @ts-ignore
512
- enter(node2, parent) {
513
- if (parent?.type === "Program") {
514
- switch (node2.type) {
515
- case "ImportDeclaration":
516
- case "VariableDeclaration":
517
- case "VariableDeclarator":
518
- this.skip();
512
+ const messages = [];
513
+ function collect(value, path) {
514
+ if (value.type === "ObjectExpression") {
515
+ for (const property of value.properties) {
516
+ if (property.type === "Property" && property.kind === "init" && !property.method && !property.shorthand) {
517
+ collect(property.value, [...path, keyOf(source, property)]);
519
518
  }
520
- } else if (parent?.type === "ArrayExpression") {
521
- const lastIndex = itemsCountStack.length - 1;
522
- const currentCount = parent.elements.length - itemsCountStack[lastIndex];
523
- pathStack.push(currentCount.toString());
524
- itemsCountStack[lastIndex] = --itemsCountStack[lastIndex];
525
- } else if (parent?.type === "ObjectExpression") {
526
- const lastIndex = propsCountStack.length - 1;
527
- propsCountStack[lastIndex] = --propsCountStack[lastIndex];
528
- }
529
- switch (node2.type) {
530
- case "Program":
531
- if (type === "plain") {
532
- generator.push(`const resource = `);
533
- } else if (type === "sfc") {
534
- const localeName = JSON.stringify(locale ?? '""');
535
- const variableName = !isGlobal ? "__i18n" : "__i18nGlobal";
536
- generator.push(`export default function (Component) {`);
537
- generator.indent();
538
- generator.pushline(`const ${componentNamespace} = Component`);
539
- generator.pushline(
540
- `${componentNamespace}.${variableName} = ${componentNamespace}.${variableName} || []`
541
- );
542
- generator.push(`${componentNamespace}.${variableName}.push({`);
543
- generator.indent();
544
- generator.pushline(`"locale": ${localeName},`);
545
- generator.push(`"resource": `);
546
- }
547
- break;
548
- case "ObjectExpression":
549
- generator.push("{");
550
- generator.indent();
551
- propsCountStack.push(node2.properties.length);
552
- break;
553
- case "ArrayExpression":
554
- generator.push("[");
555
- generator.indent();
556
- itemsCountStack.push(node2.elements.length);
557
- break;
558
- case "Property":
559
- if (parent?.type !== "ObjectExpression") break;
560
- if (node2.key.type !== "Literal" && node2.key.type !== "Identifier") break;
561
- const name = node2.key.type === "Literal" ? String(node2.key.value) : node2.key.name;
562
- const strName = JSON.stringify(name);
563
- if (isJSONablePrimitiveLiteral(node2.value)) {
564
- generator.push(`${strName}: `);
565
- pathStack.push(name);
566
- const value = getValue(node2.value);
567
- const strValue = JSON.stringify(value);
568
- if (node2.value.type === "Literal" && shared.isString(node2.value.value) || node2.value.type === "TemplateLiteral") {
569
- generator.push(codegenFn(value), node2.value, value);
570
- } else if (forceStringify) {
571
- generator.push(codegenFn(strValue), node2.value, strValue);
572
- } else {
573
- generator.push(strValue);
574
- }
575
- skipStack.push(false);
576
- } else if (node2.value.type === "ArrayExpression" || node2.value.type === "ObjectExpression") {
577
- generator.push(`${strName}: `);
578
- pathStack.push(name);
579
- skipStack.push(false);
580
- } else if (node2.value.type === "FunctionExpression" || node2.value.type === "ArrowFunctionExpression") {
581
- generator.push(`${strName}: `);
582
- pathStack.push(name);
583
- const code = escodegen.generate(node2.value, {
584
- format: { compact: true }
585
- });
586
- generator.push(code, node2.value, code);
587
- skipStack.push(false);
588
- } else {
589
- const skipProperty = "regex" in node2.value;
590
- if (!skipProperty && node2.type === "Property") {
591
- const identifierName = node2.value.type === "Identifier" && String(node2.value.name) || node2.value.type === "Literal" && String(node2.value.value);
592
- generator.push(`${strName}: ${identifierName || name}`);
593
- skipStack.push(false);
594
- } else {
595
- skipStack.push(true);
596
- }
597
- }
598
- break;
599
- case "SpreadElement":
600
- const spreadIdentifier = node2.argument.type === "Identifier" && String(node2.argument.name) || node2.argument.type === "Literal" && String(node2.argument.value);
601
- generator.push(`...${spreadIdentifier}`);
602
- break;
603
- default:
604
- if (parent?.type === "ArrayExpression") {
605
- if (isJSONablePrimitiveLiteral(node2)) {
606
- const value = getValue(node2);
607
- const strValue = JSON.stringify(value);
608
- if (node2.type === "Literal" && shared.isString(node2.value) || node2.type === "TemplateLiteral") {
609
- generator.push(codegenFn(value), node2, value);
610
- } else if (forceStringify) {
611
- generator.push(codegenFn(strValue), node2, strValue);
612
- } else {
613
- generator.push(strValue);
614
- }
615
- skipStack.push(false);
616
- } else {
617
- skipStack.push(true);
618
- }
619
- }
620
- break;
621
- }
622
- },
623
- /**
624
- * NOTE:
625
- * force cast to Node of `estree-walker@3.x`,
626
- * because `estree-walker@3.x` is not dual packages,
627
- * so it's support only esm only ...
628
- */
629
- // @ts-ignore
630
- leave(node2, parent) {
631
- switch (node2.type) {
632
- case "Program":
633
- if (type === "plain") {
634
- generator.push("\n");
635
- generator.push("export default resource");
636
- } else if (type === "sfc") {
637
- generator.deindent();
638
- generator.push("})");
639
- generator.deindent();
640
- generator.pushline("}");
641
- }
642
- break;
643
- case "ObjectExpression":
644
- if (propsCountStack[propsCountStack.length - 1] === 0) {
645
- pathStack.pop();
646
- propsCountStack.pop();
647
- }
648
- generator.deindent();
649
- generator.push("}");
650
- break;
651
- case "ArrayExpression":
652
- if (itemsCountStack[itemsCountStack.length - 1] === 0) {
653
- pathStack.pop();
654
- itemsCountStack.pop();
655
- }
656
- generator.deindent();
657
- generator.push("]");
658
- break;
659
519
  }
660
- if (parent?.type === "ArrayExpression" || parent?.type === "ObjectExpression") {
661
- const stackArr = node2.type === "Property" ? propsCountStack : itemsCountStack;
662
- if (stackArr[stackArr.length - 1] !== 0) {
663
- pathStack.pop();
664
- !skipStack.pop() && generator.pushline(",");
520
+ } else if (value.type === "ArrayExpression") {
521
+ value.elements.forEach((element, index) => {
522
+ if (element != null && element.type !== "SpreadElement") {
523
+ collect(element, [...path, String(index)]);
665
524
  }
525
+ });
526
+ } else if (isMessageLiteral(value)) {
527
+ const message = getValue(value);
528
+ if (shared.isString(message)) {
529
+ messages.push({ node: value, value: message, code: codegenFn(message, path) });
530
+ } else if (forceStringify) {
531
+ const strMessage = JSON.stringify(message);
532
+ messages.push({ node: value, value: strMessage, code: codegenFn(strMessage, path) });
666
533
  }
667
534
  }
668
- });
535
+ }
536
+ collect(resource, []);
537
+ if (type === "plain") {
538
+ generator.push(`const resource = `);
539
+ } else if (type === "sfc") {
540
+ const localeName = JSON.stringify(locale ?? '""');
541
+ const variableName = !isGlobal ? "__i18n" : "__i18nGlobal";
542
+ generator.push(`export default function (Component) {`);
543
+ generator.indent();
544
+ generator.pushline(`const ${componentNamespace} = Component`);
545
+ generator.pushline(
546
+ `${componentNamespace}.${variableName} = ${componentNamespace}.${variableName} || []`
547
+ );
548
+ generator.push(`${componentNamespace}.${variableName}.push({`);
549
+ generator.indent();
550
+ generator.pushline(`"locale": ${localeName},`);
551
+ generator.push(`"resource": `);
552
+ }
553
+ let offset = rangeOf(resource).start;
554
+ for (const message of messages) {
555
+ generator.push(source.slice(offset, rangeOf(message.node).start));
556
+ generator.push(message.code, message.node, message.value);
557
+ offset = rangeOf(message.node).end;
558
+ }
559
+ generator.push(source.slice(offset, rangeOf(resource).end));
560
+ if (type === "plain") {
561
+ generator.push("\n");
562
+ generator.push("export default resource");
563
+ } else if (type === "sfc") {
564
+ generator.deindent();
565
+ generator.push("})");
566
+ generator.deindent();
567
+ generator.pushline("}");
568
+ }
669
569
  return codeMaps;
670
570
  }
571
+ function rangeOf(node) {
572
+ return node;
573
+ }
574
+ function sourceOf(source, node) {
575
+ const { start, end } = rangeOf(node);
576
+ return source.slice(start, end);
577
+ }
578
+ function keyOf(source, property) {
579
+ const { key } = property;
580
+ if (property.computed) {
581
+ return sourceOf(source, key);
582
+ }
583
+ return key.type === "Identifier" ? key.name : String(key.value);
584
+ }
585
+ function isMessageLiteral(node) {
586
+ if (node.type === "Literal" && "regex" in node) {
587
+ return false;
588
+ }
589
+ if (node.type === "TemplateLiteral" && node.expressions.length > 0) {
590
+ return false;
591
+ }
592
+ return isJSONablePrimitiveLiteral(node);
593
+ }
671
594
  function isJSONablePrimitiveLiteral(node) {
672
595
  return node.type === "Literal" && (shared.isString(node.value) || shared.isNumber(node.value) || shared.isBoolean(node.value) || node.value === null) || node.type === "TemplateLiteral";
673
596
  }
@@ -773,6 +696,19 @@ function _generate$1(generator, node, options = {}) {
773
696
  sourceMap && map != null && codeMaps.set(value, map);
774
697
  return code;
775
698
  }
699
+ function pushExpressionValue(node2) {
700
+ const value = jsoncEslintParser.getStaticJSONValue(node2);
701
+ if (shared.isString(value)) {
702
+ generator.push(codegenFn(value), node2, value);
703
+ return;
704
+ }
705
+ const strValue = stringifyValue(value);
706
+ if (forceStringify) {
707
+ generator.push(codegenFn(strValue), node2, strValue);
708
+ } else {
709
+ generator.push(strValue);
710
+ }
711
+ }
776
712
  const componentNamespace = "_Component";
777
713
  jsoncEslintParser.traverseNodes(node, {
778
714
  enterNode(node2, parent) {
@@ -829,6 +765,8 @@ function _generate$1(generator, node, options = {}) {
829
765
  } else {
830
766
  generator.push(strValue2);
831
767
  }
768
+ } else if (node2.value.type !== "JSONObjectExpression" && node2.value.type !== "JSONArrayExpression") {
769
+ pushExpressionValue(node2.value);
832
770
  }
833
771
  break;
834
772
  }
@@ -844,6 +782,14 @@ function _generate$1(generator, node, options = {}) {
844
782
  generator.push(strValue);
845
783
  }
846
784
  break;
785
+ case "JSONUnaryExpression":
786
+ case "JSONIdentifier":
787
+ case "JSONTemplateLiteral":
788
+ case "JSONBinaryExpression":
789
+ if (parent.type === "JSONArrayExpression") {
790
+ pushExpressionValue(node2);
791
+ }
792
+ break;
847
793
  }
848
794
  },
849
795
  leaveNode(node2, parent) {
@@ -894,12 +840,10 @@ async function generate$1(targetSource, options) {
894
840
  const _options = Object.assign({}, DEFAULT_OPTIONS, options, {
895
841
  source: value
896
842
  });
897
- if (_options.filename && /.[c|m]?ts$/.test(_options.filename)) {
898
- const transformed = await esbuild.transform(value, { loader: "ts" });
899
- if (transformed && transformed.code) {
900
- value = transformed.code;
901
- _options.source = transformed.code;
902
- }
843
+ const transformed = await esbuild.transform(value, { loader: "ts" });
844
+ if (transformed && transformed.code) {
845
+ value = transformed.code;
846
+ _options.source = transformed.code;
903
847
  }
904
848
  return generate$3(value, _options);
905
849
  }
@@ -1066,7 +1010,7 @@ function _generate(generator, node, options = {}) {
1066
1010
  const name = node2.key.value;
1067
1011
  const value = node2.value.value;
1068
1012
  const strName = JSON.stringify(name);
1069
- const strValue = JSON.stringify(value);
1013
+ const strValue = stringifyValue(value);
1070
1014
  name && pathStack.push(name.toString());
1071
1015
  generator.push(`${strName}: `);
1072
1016
  if (shared.isString(value)) {
@@ -1085,7 +1029,7 @@ function _generate(generator, node, options = {}) {
1085
1029
  case "YAMLScalar":
1086
1030
  if (parent.type === "YAMLSequence") {
1087
1031
  const value = node2.value;
1088
- const strValue = JSON.stringify(value);
1032
+ const strValue = stringifyValue(value);
1089
1033
  if (shared.isString(value)) {
1090
1034
  generator.push(codegenFn(value), node2, value);
1091
1035
  } else if (forceStringify) {
package/lib/index.mjs CHANGED
@@ -1,8 +1,7 @@
1
1
  import module$1 from 'node:module';
2
2
  import { isBoolean, format, escapeHtml, friendlyJSONstringify, isString, isNumber } from '@intlify/shared';
3
3
  import { parse } from 'acorn';
4
- import { generate as generate$4 } from 'escodegen';
5
- import { walk } from 'estree-walker';
4
+ import * as messageCompiler from '@intlify/message-compiler';
6
5
  import { LOCATION_STUB, detectHtmlTag, baseCompile } from '@intlify/message-compiler';
7
6
  import { SourceMapGenerator, SourceMapConsumer } from 'source-map-js';
8
7
  import { parseJSON, getStaticJSONValue, traverseNodes } from 'jsonc-eslint-parser';
@@ -153,6 +152,14 @@ const ON_ERROR_NOOP = () => {
153
152
  function parsePath(path) {
154
153
  return path ? path.join(".") : "";
155
154
  }
155
+ const COMPILE_ERROR_MESSAGES = messageCompiler.errorMessages;
156
+ function getCompileErrorMessage(err) {
157
+ if (err.message !== String(err.code)) {
158
+ return err.message;
159
+ }
160
+ const text = COMPILE_ERROR_MESSAGES?.[err.code];
161
+ return text ? text.replace(/:\s*\\?'?\{\d+\}'?/g, "") : err.message;
162
+ }
156
163
  function generateMessageFunction(msg, options = {}, path) {
157
164
  const env = options.env != null ? options.env : "development";
158
165
  const strictMessage = isBoolean(options.strictMessage) ? options.strictMessage : true;
@@ -181,7 +188,7 @@ function generateMessageFunction(msg, options = {}, path) {
181
188
  domain: err.domain,
182
189
  location: err.location
183
190
  };
184
- onError(err.message, extra);
191
+ onError(getCompileErrorMessage(err), extra);
185
192
  errors.push(err);
186
193
  }
187
194
  };
@@ -293,7 +300,7 @@ function generateResourceAst(msg, options = {}, path) {
293
300
  domain: err.domain,
294
301
  location: err.location
295
302
  };
296
- onError(err.message, extra);
303
+ onError(getCompileErrorMessage(err), extra);
297
304
  errors.push(err);
298
305
  }
299
306
  };
@@ -342,6 +349,11 @@ function describeValue(value) {
342
349
  if (value === void 0) return "undefined";
343
350
  return `a ${typeof value}`;
344
351
  }
352
+ function stringifyValue(value) {
353
+ if (typeof value === "number") return Object.is(value, -0) ? "-0" : String(value);
354
+ if (value === void 0) return "undefined";
355
+ return JSON.stringify(value);
356
+ }
345
357
  function createResourceError(message, options) {
346
358
  return new Error(`${message} in ${describeResource(options)}.`);
347
359
  }
@@ -445,222 +457,121 @@ function scanAst(ast) {
445
457
  return false;
446
458
  }
447
459
  function _generate$2(generator, node, options = {}) {
448
- const propsCountStack = [];
449
- const pathStack = [];
450
- const itemsCountStack = [];
451
- const skipStack = [];
452
460
  const { forceStringify } = generator.context();
453
461
  const codeMaps = /* @__PURE__ */ new Map();
454
462
  const { type, sourceMap, isGlobal, locale, jit } = options;
463
+ const source = options.source ?? "";
455
464
  const _codegenFn = jit ? generateResourceAst : generateMessageFunction;
456
- function codegenFn(value) {
457
- const { code, map } = _codegenFn(value, options, pathStack);
465
+ function codegenFn(value, path) {
466
+ const { code, map } = _codegenFn(value, options, path);
458
467
  sourceMap && map != null && codeMaps.set(value, map);
459
468
  return code;
460
469
  }
461
470
  const componentNamespace = "_Component";
462
471
  const variableDeclarations = [];
463
- walk(node, {
464
- /**
465
- * NOTE:
466
- * force cast to Node of `estree-walker@3.x`,
467
- * because `estree-walker@3.x` is not dual packages,
468
- * so it's support only esm only ...
469
- */
470
- // @ts-ignore
471
- enter(node2, _parent) {
472
- if (_parent?.type != null) this.skip();
473
- switch (node2.type) {
474
- case "ExportDefaultDeclaration":
475
- this.skip();
476
- break;
477
- case "ImportDeclaration":
478
- generator.push(options.source?.slice(node2.start, node2.end));
479
- generator.newline();
480
- break;
481
- case "VariableDeclaration":
482
- generator.push(options.source?.slice(node2.start, node2.end));
483
- generator.newline();
484
- variableDeclarations.push(
485
- ...node2.declarations.map((x) => `\`${x.id.name}\``)
486
- );
487
- break;
488
- }
472
+ const { body } = node;
473
+ const exportDefault = body.find(
474
+ (statement) => statement.type === "ExportDefaultDeclaration"
475
+ );
476
+ const resource = exportDefault.declaration;
477
+ for (const statement of body) {
478
+ if (statement === exportDefault) continue;
479
+ generator.push(sourceOf(source, statement));
480
+ generator.newline();
481
+ if (statement.type === "VariableDeclaration") {
482
+ variableDeclarations.push(
483
+ ...statement.declarations.map((x) => `\`${x.id.name}\``)
484
+ );
489
485
  }
490
- });
486
+ }
491
487
  if (variableDeclarations.length > 0) {
492
488
  options?.onWarn?.(
493
489
  `
494
490
  Variable declarations are not optimized - found ${variableDeclarations.join(", ")}`
495
491
  );
496
492
  }
497
- walk(node, {
498
- /**
499
- * NOTE:
500
- * force cast to Node of `estree-walker@3.x`,
501
- * because `estree-walker@3.x` is not dual packages,
502
- * so it's support only esm only ...
503
- */
504
- // @ts-ignore
505
- enter(node2, parent) {
506
- if (parent?.type === "Program") {
507
- switch (node2.type) {
508
- case "ImportDeclaration":
509
- case "VariableDeclaration":
510
- case "VariableDeclarator":
511
- this.skip();
493
+ const messages = [];
494
+ function collect(value, path) {
495
+ if (value.type === "ObjectExpression") {
496
+ for (const property of value.properties) {
497
+ if (property.type === "Property" && property.kind === "init" && !property.method && !property.shorthand) {
498
+ collect(property.value, [...path, keyOf(source, property)]);
512
499
  }
513
- } else if (parent?.type === "ArrayExpression") {
514
- const lastIndex = itemsCountStack.length - 1;
515
- const currentCount = parent.elements.length - itemsCountStack[lastIndex];
516
- pathStack.push(currentCount.toString());
517
- itemsCountStack[lastIndex] = --itemsCountStack[lastIndex];
518
- } else if (parent?.type === "ObjectExpression") {
519
- const lastIndex = propsCountStack.length - 1;
520
- propsCountStack[lastIndex] = --propsCountStack[lastIndex];
521
- }
522
- switch (node2.type) {
523
- case "Program":
524
- if (type === "plain") {
525
- generator.push(`const resource = `);
526
- } else if (type === "sfc") {
527
- const localeName = JSON.stringify(locale ?? '""');
528
- const variableName = !isGlobal ? "__i18n" : "__i18nGlobal";
529
- generator.push(`export default function (Component) {`);
530
- generator.indent();
531
- generator.pushline(`const ${componentNamespace} = Component`);
532
- generator.pushline(
533
- `${componentNamespace}.${variableName} = ${componentNamespace}.${variableName} || []`
534
- );
535
- generator.push(`${componentNamespace}.${variableName}.push({`);
536
- generator.indent();
537
- generator.pushline(`"locale": ${localeName},`);
538
- generator.push(`"resource": `);
539
- }
540
- break;
541
- case "ObjectExpression":
542
- generator.push("{");
543
- generator.indent();
544
- propsCountStack.push(node2.properties.length);
545
- break;
546
- case "ArrayExpression":
547
- generator.push("[");
548
- generator.indent();
549
- itemsCountStack.push(node2.elements.length);
550
- break;
551
- case "Property":
552
- if (parent?.type !== "ObjectExpression") break;
553
- if (node2.key.type !== "Literal" && node2.key.type !== "Identifier") break;
554
- const name = node2.key.type === "Literal" ? String(node2.key.value) : node2.key.name;
555
- const strName = JSON.stringify(name);
556
- if (isJSONablePrimitiveLiteral(node2.value)) {
557
- generator.push(`${strName}: `);
558
- pathStack.push(name);
559
- const value = getValue(node2.value);
560
- const strValue = JSON.stringify(value);
561
- if (node2.value.type === "Literal" && isString(node2.value.value) || node2.value.type === "TemplateLiteral") {
562
- generator.push(codegenFn(value), node2.value, value);
563
- } else if (forceStringify) {
564
- generator.push(codegenFn(strValue), node2.value, strValue);
565
- } else {
566
- generator.push(strValue);
567
- }
568
- skipStack.push(false);
569
- } else if (node2.value.type === "ArrayExpression" || node2.value.type === "ObjectExpression") {
570
- generator.push(`${strName}: `);
571
- pathStack.push(name);
572
- skipStack.push(false);
573
- } else if (node2.value.type === "FunctionExpression" || node2.value.type === "ArrowFunctionExpression") {
574
- generator.push(`${strName}: `);
575
- pathStack.push(name);
576
- const code = generate$4(node2.value, {
577
- format: { compact: true }
578
- });
579
- generator.push(code, node2.value, code);
580
- skipStack.push(false);
581
- } else {
582
- const skipProperty = "regex" in node2.value;
583
- if (!skipProperty && node2.type === "Property") {
584
- const identifierName = node2.value.type === "Identifier" && String(node2.value.name) || node2.value.type === "Literal" && String(node2.value.value);
585
- generator.push(`${strName}: ${identifierName || name}`);
586
- skipStack.push(false);
587
- } else {
588
- skipStack.push(true);
589
- }
590
- }
591
- break;
592
- case "SpreadElement":
593
- const spreadIdentifier = node2.argument.type === "Identifier" && String(node2.argument.name) || node2.argument.type === "Literal" && String(node2.argument.value);
594
- generator.push(`...${spreadIdentifier}`);
595
- break;
596
- default:
597
- if (parent?.type === "ArrayExpression") {
598
- if (isJSONablePrimitiveLiteral(node2)) {
599
- const value = getValue(node2);
600
- const strValue = JSON.stringify(value);
601
- if (node2.type === "Literal" && isString(node2.value) || node2.type === "TemplateLiteral") {
602
- generator.push(codegenFn(value), node2, value);
603
- } else if (forceStringify) {
604
- generator.push(codegenFn(strValue), node2, strValue);
605
- } else {
606
- generator.push(strValue);
607
- }
608
- skipStack.push(false);
609
- } else {
610
- skipStack.push(true);
611
- }
612
- }
613
- break;
614
- }
615
- },
616
- /**
617
- * NOTE:
618
- * force cast to Node of `estree-walker@3.x`,
619
- * because `estree-walker@3.x` is not dual packages,
620
- * so it's support only esm only ...
621
- */
622
- // @ts-ignore
623
- leave(node2, parent) {
624
- switch (node2.type) {
625
- case "Program":
626
- if (type === "plain") {
627
- generator.push("\n");
628
- generator.push("export default resource");
629
- } else if (type === "sfc") {
630
- generator.deindent();
631
- generator.push("})");
632
- generator.deindent();
633
- generator.pushline("}");
634
- }
635
- break;
636
- case "ObjectExpression":
637
- if (propsCountStack[propsCountStack.length - 1] === 0) {
638
- pathStack.pop();
639
- propsCountStack.pop();
640
- }
641
- generator.deindent();
642
- generator.push("}");
643
- break;
644
- case "ArrayExpression":
645
- if (itemsCountStack[itemsCountStack.length - 1] === 0) {
646
- pathStack.pop();
647
- itemsCountStack.pop();
648
- }
649
- generator.deindent();
650
- generator.push("]");
651
- break;
652
500
  }
653
- if (parent?.type === "ArrayExpression" || parent?.type === "ObjectExpression") {
654
- const stackArr = node2.type === "Property" ? propsCountStack : itemsCountStack;
655
- if (stackArr[stackArr.length - 1] !== 0) {
656
- pathStack.pop();
657
- !skipStack.pop() && generator.pushline(",");
501
+ } else if (value.type === "ArrayExpression") {
502
+ value.elements.forEach((element, index) => {
503
+ if (element != null && element.type !== "SpreadElement") {
504
+ collect(element, [...path, String(index)]);
658
505
  }
506
+ });
507
+ } else if (isMessageLiteral(value)) {
508
+ const message = getValue(value);
509
+ if (isString(message)) {
510
+ messages.push({ node: value, value: message, code: codegenFn(message, path) });
511
+ } else if (forceStringify) {
512
+ const strMessage = JSON.stringify(message);
513
+ messages.push({ node: value, value: strMessage, code: codegenFn(strMessage, path) });
659
514
  }
660
515
  }
661
- });
516
+ }
517
+ collect(resource, []);
518
+ if (type === "plain") {
519
+ generator.push(`const resource = `);
520
+ } else if (type === "sfc") {
521
+ const localeName = JSON.stringify(locale ?? '""');
522
+ const variableName = !isGlobal ? "__i18n" : "__i18nGlobal";
523
+ generator.push(`export default function (Component) {`);
524
+ generator.indent();
525
+ generator.pushline(`const ${componentNamespace} = Component`);
526
+ generator.pushline(
527
+ `${componentNamespace}.${variableName} = ${componentNamespace}.${variableName} || []`
528
+ );
529
+ generator.push(`${componentNamespace}.${variableName}.push({`);
530
+ generator.indent();
531
+ generator.pushline(`"locale": ${localeName},`);
532
+ generator.push(`"resource": `);
533
+ }
534
+ let offset = rangeOf(resource).start;
535
+ for (const message of messages) {
536
+ generator.push(source.slice(offset, rangeOf(message.node).start));
537
+ generator.push(message.code, message.node, message.value);
538
+ offset = rangeOf(message.node).end;
539
+ }
540
+ generator.push(source.slice(offset, rangeOf(resource).end));
541
+ if (type === "plain") {
542
+ generator.push("\n");
543
+ generator.push("export default resource");
544
+ } else if (type === "sfc") {
545
+ generator.deindent();
546
+ generator.push("})");
547
+ generator.deindent();
548
+ generator.pushline("}");
549
+ }
662
550
  return codeMaps;
663
551
  }
552
+ function rangeOf(node) {
553
+ return node;
554
+ }
555
+ function sourceOf(source, node) {
556
+ const { start, end } = rangeOf(node);
557
+ return source.slice(start, end);
558
+ }
559
+ function keyOf(source, property) {
560
+ const { key } = property;
561
+ if (property.computed) {
562
+ return sourceOf(source, key);
563
+ }
564
+ return key.type === "Identifier" ? key.name : String(key.value);
565
+ }
566
+ function isMessageLiteral(node) {
567
+ if (node.type === "Literal" && "regex" in node) {
568
+ return false;
569
+ }
570
+ if (node.type === "TemplateLiteral" && node.expressions.length > 0) {
571
+ return false;
572
+ }
573
+ return isJSONablePrimitiveLiteral(node);
574
+ }
664
575
  function isJSONablePrimitiveLiteral(node) {
665
576
  return node.type === "Literal" && (isString(node.value) || isNumber(node.value) || isBoolean(node.value) || node.value === null) || node.type === "TemplateLiteral";
666
577
  }
@@ -766,6 +677,19 @@ function _generate$1(generator, node, options = {}) {
766
677
  sourceMap && map != null && codeMaps.set(value, map);
767
678
  return code;
768
679
  }
680
+ function pushExpressionValue(node2) {
681
+ const value = getStaticJSONValue(node2);
682
+ if (isString(value)) {
683
+ generator.push(codegenFn(value), node2, value);
684
+ return;
685
+ }
686
+ const strValue = stringifyValue(value);
687
+ if (forceStringify) {
688
+ generator.push(codegenFn(strValue), node2, strValue);
689
+ } else {
690
+ generator.push(strValue);
691
+ }
692
+ }
769
693
  const componentNamespace = "_Component";
770
694
  traverseNodes(node, {
771
695
  enterNode(node2, parent) {
@@ -822,6 +746,8 @@ function _generate$1(generator, node, options = {}) {
822
746
  } else {
823
747
  generator.push(strValue2);
824
748
  }
749
+ } else if (node2.value.type !== "JSONObjectExpression" && node2.value.type !== "JSONArrayExpression") {
750
+ pushExpressionValue(node2.value);
825
751
  }
826
752
  break;
827
753
  }
@@ -837,6 +763,14 @@ function _generate$1(generator, node, options = {}) {
837
763
  generator.push(strValue);
838
764
  }
839
765
  break;
766
+ case "JSONUnaryExpression":
767
+ case "JSONIdentifier":
768
+ case "JSONTemplateLiteral":
769
+ case "JSONBinaryExpression":
770
+ if (parent.type === "JSONArrayExpression") {
771
+ pushExpressionValue(node2);
772
+ }
773
+ break;
840
774
  }
841
775
  },
842
776
  leaveNode(node2, parent) {
@@ -887,12 +821,10 @@ async function generate$1(targetSource, options) {
887
821
  const _options = Object.assign({}, DEFAULT_OPTIONS, options, {
888
822
  source: value
889
823
  });
890
- if (_options.filename && /.[c|m]?ts$/.test(_options.filename)) {
891
- const transformed = await transform(value, { loader: "ts" });
892
- if (transformed && transformed.code) {
893
- value = transformed.code;
894
- _options.source = transformed.code;
895
- }
824
+ const transformed = await transform(value, { loader: "ts" });
825
+ if (transformed && transformed.code) {
826
+ value = transformed.code;
827
+ _options.source = transformed.code;
896
828
  }
897
829
  return generate$3(value, _options);
898
830
  }
@@ -1059,7 +991,7 @@ function _generate(generator, node, options = {}) {
1059
991
  const name = node2.key.value;
1060
992
  const value = node2.value.value;
1061
993
  const strName = JSON.stringify(name);
1062
- const strValue = JSON.stringify(value);
994
+ const strValue = stringifyValue(value);
1063
995
  name && pathStack.push(name.toString());
1064
996
  generator.push(`${strName}: `);
1065
997
  if (isString(value)) {
@@ -1078,7 +1010,7 @@ function _generate(generator, node, options = {}) {
1078
1010
  case "YAMLScalar":
1079
1011
  if (parent.type === "YAMLSequence") {
1080
1012
  const value = node2.value;
1081
- const strValue = JSON.stringify(value);
1013
+ const strValue = stringifyValue(value);
1082
1014
  if (isString(value)) {
1083
1015
  generator.push(codegenFn(value), node2, value);
1084
1016
  } else if (forceStringify) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@intlify/bundle-utils",
3
3
  "description": "Bundle utilities for Intlify project",
4
- "version": "11.2.6",
4
+ "version": "11.2.7",
5
5
  "author": {
6
6
  "name": "kazuya kawaguchi",
7
7
  "email": "kawakazu80@gmail.com"
@@ -18,18 +18,15 @@
18
18
  }
19
19
  },
20
20
  "dependencies": {
21
- "@intlify/message-compiler": "~11.4.2",
22
- "@intlify/shared": "~11.4.2",
21
+ "@intlify/message-compiler": "~11.4.15",
22
+ "@intlify/shared": "~11.4.15",
23
23
  "acorn": "^8.8.2",
24
24
  "esbuild": "^0.25.4",
25
- "escodegen": "^2.1.0",
26
- "estree-walker": "^2.0.2",
27
25
  "jsonc-eslint-parser": "^2.3.0",
28
26
  "source-map-js": "^1.2.1",
29
27
  "yaml-eslint-parser": "^1.2.2"
30
28
  },
31
29
  "devDependencies": {
32
- "@types/escodegen": "^0.0.10",
33
30
  "@types/estree": "^1.0.0",
34
31
  "unbuild": "^3.6.1"
35
32
  },