@intlify/bundle-utils 5.0.1 → 5.1.1

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/lib/js.d.ts CHANGED
@@ -2,10 +2,9 @@
2
2
  * Code generator for i18n js resource
3
3
  */
4
4
  /// <reference types="node" />
5
- import { ParseResult } from '@babel/parser';
6
- import type { File } from '@babel/types';
5
+ import type { Node } from 'estree';
7
6
  import type { CodeGenOptions, CodeGenResult } from './codegen';
8
7
  /**
9
8
  * @internal
10
9
  */
11
- export declare function generate(targetSource: string | Buffer, { type, bridge, exportESM, filename, inSourceMap, locale, isGlobal, sourceMap, env, forceStringify, onError, useClassComponent }: CodeGenOptions, injector?: () => string): CodeGenResult<ParseResult<File>>;
10
+ export declare function generate(targetSource: string | Buffer, { type, bridge, exportESM, filename, inSourceMap, locale, isGlobal, sourceMap, env, forceStringify, onError, useClassComponent, allowDynamic }: CodeGenOptions, injector?: () => string): CodeGenResult<Node>;
package/lib/js.js CHANGED
@@ -7,13 +7,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
7
7
  };
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.generate = void 0;
10
- const parser_1 = require("@babel/parser");
11
- const traverse_1 = __importDefault(require("@babel/traverse"));
10
+ const shared_1 = require("@intlify/shared");
11
+ const acorn_1 = require("acorn");
12
+ const estree_walker_1 = require("estree-walker");
13
+ const esquery_1 = __importDefault(require("esquery"));
12
14
  const codegen_1 = require("./codegen");
13
15
  /**
14
16
  * @internal
15
17
  */
16
- function generate(targetSource, { type = 'plain', bridge = false, exportESM = false, filename = 'vue-i18n-loader.js', inSourceMap = undefined, locale = '', isGlobal = false, sourceMap = false, env = 'development', forceStringify = false, onError = undefined, useClassComponent = false }, injector) {
18
+ function generate(targetSource, { type = 'plain', bridge = false, exportESM = false, filename = 'vue-i18n-loader.js', inSourceMap = undefined, locale = '', isGlobal = false, sourceMap = false, env = 'development', forceStringify = false, onError = undefined, useClassComponent = false, allowDynamic = false }, injector) {
17
19
  const target = Buffer.isBuffer(targetSource)
18
20
  ? targetSource.toString()
19
21
  : targetSource;
@@ -34,13 +36,36 @@ function generate(targetSource, { type = 'plain', bridge = false, exportESM = fa
34
36
  useClassComponent
35
37
  };
36
38
  const generator = (0, codegen_1.createCodeGenerator)(options);
37
- const ast = (0, parser_1.parse)(value, {
39
+ const ast = (0, acorn_1.parse)(value, {
40
+ ecmaVersion: 'latest',
38
41
  sourceType: 'module',
39
- sourceFilename: filename,
42
+ sourceFile: filename,
40
43
  allowImportExportEverywhere: true
41
44
  });
42
- if (ast.errors) {
43
- // TODO:
45
+ const astExportDefaultWithObject = (0, esquery_1.default)(ast, 'Program:has(ExportDefaultDeclaration):has(ObjectExpression)');
46
+ if (!allowDynamic) {
47
+ if (!astExportDefaultWithObject.length) {
48
+ throw new Error(`You need to define an object as the locale message with 'export default'.`);
49
+ }
50
+ }
51
+ else {
52
+ const astExportDefault = (0, esquery_1.default)(ast, 'Program:has(ExportDefaultDeclaration)');
53
+ if (!astExportDefault.length) {
54
+ throw new Error(`You need to define 'export default' that will return the locale messages.`);
55
+ }
56
+ if (!astExportDefaultWithObject.length) {
57
+ /**
58
+ * NOTE:
59
+ * If `allowDynamic` is `true`, do not transform the code by this function, return it as is.
60
+ * This means that the user **must transform locale messages ownself**.
61
+ * Especially at the production, you need to do locale messages pre-compiling.
62
+ */
63
+ return {
64
+ ast,
65
+ code: value,
66
+ map: inSourceMap
67
+ };
68
+ }
44
69
  }
45
70
  const codeMaps = generateNode(generator, ast, options, injector);
46
71
  const { code, map } = generator.context();
@@ -55,7 +80,7 @@ function generate(targetSource, { type = 'plain', bridge = false, exportESM = fa
55
80
  ? (0, codegen_1.mapLinesColumns)(map.toJSON(), codeMaps, inSourceMap) || null // eslint-disable-line @typescript-eslint/no-explicit-any
56
81
  : null;
57
82
  return {
58
- ast: ast,
83
+ ast,
59
84
  code,
60
85
  map: newMap != null ? newMap : undefined
61
86
  };
@@ -75,9 +100,15 @@ function generateNode(generator, node, options, injector) {
75
100
  : useClassComponent
76
101
  ? `Component.__o`
77
102
  : `Component`;
78
- // @ts-ignore TODO: `tranverse` first argument type should be fixed
79
- (0, traverse_1.default)(node, {
80
- enter({ node, parent }) {
103
+ (0, estree_walker_1.walk)(node, {
104
+ /**
105
+ * NOTE:
106
+ * force cast to Node of `estree-walker@3.x`,
107
+ * because `estree-walker@3.x` is not dual packages,
108
+ * so it's support only esm only ...
109
+ */
110
+ // @ts-ignore
111
+ enter(node, parent) {
81
112
  switch (node.type) {
82
113
  case 'Program':
83
114
  if (type === 'plain') {
@@ -105,62 +136,62 @@ function generateNode(generator, node, options, injector) {
105
136
  generator.push(`{`);
106
137
  generator.indent();
107
138
  propsCountStack.push(node.properties.length);
108
- if (parent.type === 'ArrayExpression') {
139
+ if (parent != null && parent.type === 'ArrayExpression') {
109
140
  const lastIndex = itemsCountStack.length - 1;
110
141
  const currentCount = parent.elements.length - itemsCountStack[lastIndex];
111
142
  pathStack.push(currentCount.toString());
112
143
  itemsCountStack[lastIndex] = --itemsCountStack[lastIndex];
113
144
  }
114
145
  break;
115
- case 'ObjectProperty':
116
- if (isJSONablePrimitiveLiteral(node.value) &&
117
- (node.key.type === 'StringLiteral' ||
118
- node.key.type === 'Identifier')) {
119
- // prettier-ignore
120
- const name = node.key.type === 'StringLiteral'
121
- ? node.key.value
122
- : node.key.name;
123
- if (node.value.type === 'StringLiteral' ||
124
- node.value.type === 'TemplateLiteral') {
125
- const value = getValue(node.value);
126
- generator.push(`${JSON.stringify(name)}: `);
127
- pathStack.push(name);
128
- const { code, map } = (0, codegen_1.generateMessageFunction)(value, options, pathStack);
129
- sourceMap && map != null && codeMaps.set(value, map);
130
- generator.push(`${code}`, node.value, value);
131
- skipStack.push(false);
132
- }
133
- else {
134
- const value = getValue(node.value);
135
- if (forceStringify) {
136
- const strValue = JSON.stringify(value);
146
+ case 'Property':
147
+ if (node != null) {
148
+ if (isJSONablePrimitiveLiteral(node.value) &&
149
+ (node.key.type === 'Literal' || node.key.type === 'Identifier')) {
150
+ // prettier-ignore
151
+ const name = node.key.type === 'Literal'
152
+ ? String(node.key.value)
153
+ : node.key.name;
154
+ if ((node.value.type === 'Literal' && (0, shared_1.isString)(node.value.value)) ||
155
+ node.value.type === 'TemplateLiteral') {
156
+ const value = getValue(node.value);
137
157
  generator.push(`${JSON.stringify(name)}: `);
138
158
  pathStack.push(name);
139
- const { code, map } = (0, codegen_1.generateMessageFunction)(strValue, options, pathStack);
140
- sourceMap && map != null && codeMaps.set(strValue, map);
141
- generator.push(`${code}`, node.value, strValue);
159
+ const { code, map } = (0, codegen_1.generateMessageFunction)(value, options, pathStack);
160
+ sourceMap && map != null && codeMaps.set(value, map);
161
+ generator.push(`${code}`, node.value, value);
162
+ skipStack.push(false);
142
163
  }
143
164
  else {
144
- generator.push(`${JSON.stringify(name)}: ${JSON.stringify(value)}`);
145
- pathStack.push(name);
165
+ const value = getValue(node.value);
166
+ if (forceStringify) {
167
+ const strValue = JSON.stringify(value);
168
+ generator.push(`${JSON.stringify(name)}: `);
169
+ pathStack.push(name);
170
+ const { code, map } = (0, codegen_1.generateMessageFunction)(strValue, options, pathStack);
171
+ sourceMap && map != null && codeMaps.set(strValue, map);
172
+ generator.push(`${code}`, node.value, strValue);
173
+ }
174
+ else {
175
+ generator.push(`${JSON.stringify(name)}: ${JSON.stringify(value)}`);
176
+ pathStack.push(name);
177
+ }
178
+ skipStack.push(false);
146
179
  }
147
- skipStack.push(false);
148
180
  }
149
- }
150
- else if ((node.value.type === 'ObjectExpression' ||
151
- node.value.type === 'ArrayExpression') &&
152
- (node.key.type === 'StringLiteral' ||
153
- node.key.type === 'Identifier')) {
154
- // prettier-ignore
155
- const name = node.key.type === 'StringLiteral'
156
- ? node.key.value
157
- : node.key.name;
158
- generator.push(`${JSON.stringify(name)}: `);
159
- pathStack.push(name);
160
- }
161
- else {
162
- // for Regex, function, etc.
163
- skipStack.push(true);
181
+ else if ((node.value.type === 'ObjectExpression' ||
182
+ node.value.type === 'ArrayExpression') &&
183
+ (node.key.type === 'Literal' || node.key.type === 'Identifier')) {
184
+ // prettier-ignore
185
+ const name = node.key.type === 'Literal'
186
+ ? String(node.key.value)
187
+ : node.key.name;
188
+ generator.push(`${JSON.stringify(name)}: `);
189
+ pathStack.push(name);
190
+ }
191
+ else {
192
+ // for Regex, function, etc.
193
+ skipStack.push(true);
194
+ }
164
195
  }
165
196
  const lastIndex = propsCountStack.length - 1;
166
197
  propsCountStack[lastIndex] = --propsCountStack[lastIndex];
@@ -168,7 +199,7 @@ function generateNode(generator, node, options, injector) {
168
199
  case 'ArrayExpression':
169
200
  generator.push(`[`);
170
201
  generator.indent();
171
- if (parent.type === 'ArrayExpression') {
202
+ if (parent != null && parent.type === 'ArrayExpression') {
172
203
  const lastIndex = itemsCountStack.length - 1;
173
204
  const currentCount = parent.elements.length - itemsCountStack[lastIndex];
174
205
  pathStack.push(currentCount.toString());
@@ -177,32 +208,37 @@ function generateNode(generator, node, options, injector) {
177
208
  itemsCountStack.push(node.elements.length);
178
209
  break;
179
210
  default:
180
- if (isJSONablePrimitiveLiteral(node)) {
211
+ if (node != null && parent != null) {
181
212
  if (parent.type === 'ArrayExpression') {
182
213
  const lastIndex = itemsCountStack.length - 1;
183
214
  const currentCount = parent.elements.length - itemsCountStack[lastIndex];
184
215
  pathStack.push(currentCount.toString());
185
- if (node.type === 'StringLiteral' ||
186
- node.type === 'TemplateLiteral') {
187
- const value = getValue(node);
188
- const { code, map } = (0, codegen_1.generateMessageFunction)(value, options, pathStack);
189
- sourceMap && map != null && codeMaps.set(value, map);
190
- generator.push(`${code}`, node, value);
191
- skipStack.push(false);
192
- }
193
- else {
194
- const value = getValue(node);
195
- if (forceStringify) {
196
- const strValue = JSON.stringify(value);
197
- const { code, map } = (0, codegen_1.generateMessageFunction)(strValue, options, pathStack);
198
- sourceMap && map != null && codeMaps.set(strValue, map);
199
- generator.push(`${code}`, node, strValue);
216
+ if (isJSONablePrimitiveLiteral(node)) {
217
+ if ((node.type === 'Literal' && (0, shared_1.isString)(node.value)) ||
218
+ node.type === 'TemplateLiteral') {
219
+ const value = getValue(node);
220
+ const { code, map } = (0, codegen_1.generateMessageFunction)(value, options, pathStack);
221
+ sourceMap && map != null && codeMaps.set(value, map);
222
+ generator.push(`${code}`, node, value);
200
223
  }
201
224
  else {
202
- generator.push(`${JSON.stringify(value)}`);
225
+ const value = getValue(node);
226
+ if (forceStringify) {
227
+ const strValue = JSON.stringify(value);
228
+ const { code, map } = (0, codegen_1.generateMessageFunction)(strValue, options, pathStack);
229
+ sourceMap && map != null && codeMaps.set(strValue, map);
230
+ generator.push(`${code}`, node, strValue);
231
+ }
232
+ else {
233
+ generator.push(`${JSON.stringify(value)}`);
234
+ }
203
235
  }
204
236
  skipStack.push(false);
205
237
  }
238
+ else {
239
+ // for Regex, function, etc.
240
+ skipStack.push(true);
241
+ }
206
242
  itemsCountStack[lastIndex] = --itemsCountStack[lastIndex];
207
243
  }
208
244
  }
@@ -212,7 +248,14 @@ function generateNode(generator, node, options, injector) {
212
248
  break;
213
249
  }
214
250
  },
215
- exit({ node, parent }) {
251
+ /**
252
+ * NOTE:
253
+ * force cast to Node of `estree-walker@3.x`,
254
+ * because `estree-walker@3.x` is not dual packages,
255
+ * so it's support only esm only ...
256
+ */
257
+ // @ts-ignore
258
+ leave(node, parent) {
216
259
  switch (node.type) {
217
260
  case 'Program':
218
261
  if (type === 'sfc') {
@@ -235,14 +278,14 @@ function generateNode(generator, node, options, injector) {
235
278
  }
236
279
  generator.deindent();
237
280
  generator.push(`}`);
238
- if (parent.type === 'ArrayExpression') {
281
+ if (parent != null && parent.type === 'ArrayExpression') {
239
282
  if (itemsCountStack[itemsCountStack.length - 1] !== 0) {
240
283
  pathStack.pop();
241
284
  generator.pushline(`,`);
242
285
  }
243
286
  }
244
287
  break;
245
- case 'ObjectProperty':
288
+ case 'Property':
246
289
  if (propsCountStack[propsCountStack.length - 1] !== 0) {
247
290
  pathStack.pop();
248
291
  if (!skipStack.pop()) {
@@ -257,7 +300,7 @@ function generateNode(generator, node, options, injector) {
257
300
  }
258
301
  generator.deindent();
259
302
  generator.push(`]`);
260
- if (parent.type === 'ArrayExpression') {
303
+ if (parent != null && parent.type === 'ArrayExpression') {
261
304
  if (itemsCountStack[itemsCountStack.length - 1] !== 0) {
262
305
  pathStack.pop();
263
306
  if (!skipStack.pop()) {
@@ -266,25 +309,22 @@ function generateNode(generator, node, options, injector) {
266
309
  }
267
310
  }
268
311
  break;
269
- default:
270
- if (isJSONablePrimitiveLiteral(node)) {
271
- if (parent.type === 'ArrayExpression') {
272
- if (itemsCountStack[itemsCountStack.length - 1] !== 0) {
273
- pathStack.pop();
274
- if (!skipStack.pop()) {
275
- generator.pushline(`,`);
276
- }
312
+ case 'Literal':
313
+ if (parent != null && parent.type === 'ArrayExpression') {
314
+ if (itemsCountStack[itemsCountStack.length - 1] !== 0) {
315
+ pathStack.pop();
316
+ if (!skipStack.pop()) {
317
+ generator.pushline(`,`);
277
318
  }
278
- else {
279
- if (!skipStack.pop()) {
280
- generator.pushline(`,`);
281
- }
319
+ }
320
+ else {
321
+ if (!skipStack.pop()) {
322
+ generator.pushline(`,`);
282
323
  }
283
324
  }
284
325
  }
285
- else {
286
- // ...
287
- }
326
+ break;
327
+ default:
288
328
  break;
289
329
  }
290
330
  }
@@ -292,19 +332,39 @@ function generateNode(generator, node, options, injector) {
292
332
  return codeMaps;
293
333
  }
294
334
  function isJSONablePrimitiveLiteral(node) {
295
- return (node.type === 'NullLiteral' ||
296
- node.type === 'BooleanLiteral' ||
297
- node.type === 'NumericLiteral' ||
298
- node.type === 'StringLiteral' ||
335
+ return ((node.type === 'Literal' &&
336
+ ((0, shared_1.isString)(node.value) ||
337
+ (0, shared_1.isNumber)(node.value) ||
338
+ (0, shared_1.isBoolean)(node.value) ||
339
+ node.value === null)) ||
299
340
  node.type === 'TemplateLiteral');
341
+ // NOTE: the following code is same the above code
342
+ /*
343
+ if (node.type === 'Literal') {
344
+ if (
345
+ isString(node.value) ||
346
+ isNumber(node.value) ||
347
+ isBoolean(node.value) ||
348
+ node.value === null
349
+ ) {
350
+ return true
351
+ } else if (isRegExp(node.value)) {
352
+ return false
353
+ } else {
354
+ return false
355
+ }
356
+ } else if (node.type === 'TemplateLiteral') {
357
+ return true
358
+ } else {
359
+ return false
360
+ }
361
+ */
300
362
  }
301
363
  function getValue(node) {
302
364
  // prettier-ignore
303
- return node.type === 'StringLiteral'
365
+ return node.type === 'Literal'
304
366
  ? node.value
305
- : node.type === 'NullLiteral'
306
- ? null
307
- : node.type === 'TemplateLiteral'
308
- ? node.quasis.map(quasi => quasi.value.cooked).join('')
309
- : node.value;
367
+ : node.type === 'TemplateLiteral'
368
+ ? node.quasis.map(quasi => quasi.value.cooked).join('')
369
+ : undefined;
310
370
  }
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": "5.0.1",
4
+ "version": "5.1.1",
5
5
  "author": {
6
6
  "name": "kazuya kawaguchi",
7
7
  "email": "kawakazu80@gmail.com"
@@ -18,16 +18,18 @@
18
18
  }
19
19
  },
20
20
  "dependencies": {
21
- "@babel/parser": "^7.21.2",
22
- "@babel/traverse": "^7.21.2",
23
21
  "@intlify/message-compiler": "next",
24
22
  "@intlify/shared": "next",
23
+ "acorn": "^8.8.2",
24
+ "esquery": "^1.5.0",
25
+ "estree-walker": "^2.0.2",
25
26
  "jsonc-eslint-parser": "^1.0.1",
26
27
  "source-map": "0.6.1",
27
28
  "yaml-eslint-parser": "^0.3.2"
28
29
  },
29
30
  "devDependencies": {
30
- "@babel/types": "^7.21.2"
31
+ "@types/esquery": "^1.0.2",
32
+ "@types/estree": "^1.0.0"
31
33
  },
32
34
  "engines": {
33
35
  "node": ">= 12"