@intlify/bundle-utils 5.0.0 → 5.1.0

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,38 @@ 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
+ console.log('astExportDefaultWithObject', astExportDefaultWithObject);
47
+ if (!allowDynamic) {
48
+ if (!astExportDefaultWithObject.length) {
49
+ throw new Error(`You need to define an object as the locale message with 'export default'.`);
50
+ }
51
+ }
52
+ else {
53
+ const astExportDefault = (0, esquery_1.default)(ast, 'Program:has(ExportDefaultDeclaration)');
54
+ if (!astExportDefault.length) {
55
+ throw new Error(`You need to define 'export default' that will return the locale messages.`);
56
+ }
57
+ console.log('astExportDefault', astExportDefault);
58
+ if (!astExportDefaultWithObject.length) {
59
+ /**
60
+ * NOTE:
61
+ * If `allowDynamic` is `true`, do not transform the code by this function, return it as is.
62
+ * This means that the user **must transform locale messages ownself**.
63
+ * Especially at the production, you need to do locale messages pre-compiling.
64
+ */
65
+ return {
66
+ ast,
67
+ code: value,
68
+ map: inSourceMap
69
+ };
70
+ }
44
71
  }
45
72
  const codeMaps = generateNode(generator, ast, options, injector);
46
73
  const { code, map } = generator.context();
@@ -55,7 +82,7 @@ function generate(targetSource, { type = 'plain', bridge = false, exportESM = fa
55
82
  ? (0, codegen_1.mapLinesColumns)(map.toJSON(), codeMaps, inSourceMap) || null // eslint-disable-line @typescript-eslint/no-explicit-any
56
83
  : null;
57
84
  return {
58
- ast: ast,
85
+ ast,
59
86
  code,
60
87
  map: newMap != null ? newMap : undefined
61
88
  };
@@ -75,9 +102,15 @@ function generateNode(generator, node, options, injector) {
75
102
  : useClassComponent
76
103
  ? `Component.__o`
77
104
  : `Component`;
78
- // @ts-ignore TODO: `tranverse` first argument type should be fixed
79
- (0, traverse_1.default)(node, {
80
- enter({ node, parent }) {
105
+ (0, estree_walker_1.walk)(node, {
106
+ /**
107
+ * NOTE:
108
+ * force cast to Node of `estree-walker@3.x`,
109
+ * because `estree-walker@3.x` is not dual packages,
110
+ * so it's support only esm only ...
111
+ */
112
+ // @ts-ignore
113
+ enter(node, parent) {
81
114
  switch (node.type) {
82
115
  case 'Program':
83
116
  if (type === 'plain') {
@@ -105,62 +138,62 @@ function generateNode(generator, node, options, injector) {
105
138
  generator.push(`{`);
106
139
  generator.indent();
107
140
  propsCountStack.push(node.properties.length);
108
- if (parent.type === 'ArrayExpression') {
141
+ if (parent != null && parent.type === 'ArrayExpression') {
109
142
  const lastIndex = itemsCountStack.length - 1;
110
143
  const currentCount = parent.elements.length - itemsCountStack[lastIndex];
111
144
  pathStack.push(currentCount.toString());
112
145
  itemsCountStack[lastIndex] = --itemsCountStack[lastIndex];
113
146
  }
114
147
  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);
148
+ case 'Property':
149
+ if (node != null) {
150
+ if (isJSONablePrimitiveLiteral(node.value) &&
151
+ (node.key.type === 'Literal' || node.key.type === 'Identifier')) {
152
+ // prettier-ignore
153
+ const name = node.key.type === 'Literal'
154
+ ? String(node.key.value)
155
+ : node.key.name;
156
+ if ((node.value.type === 'Literal' && (0, shared_1.isString)(node.value.value)) ||
157
+ node.value.type === 'TemplateLiteral') {
158
+ const value = getValue(node.value);
137
159
  generator.push(`${JSON.stringify(name)}: `);
138
160
  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);
161
+ const { code, map } = (0, codegen_1.generateMessageFunction)(value, options, pathStack);
162
+ sourceMap && map != null && codeMaps.set(value, map);
163
+ generator.push(`${code}`, node.value, value);
164
+ skipStack.push(false);
142
165
  }
143
166
  else {
144
- generator.push(`${JSON.stringify(name)}: ${JSON.stringify(value)}`);
145
- pathStack.push(name);
167
+ const value = getValue(node.value);
168
+ if (forceStringify) {
169
+ const strValue = JSON.stringify(value);
170
+ generator.push(`${JSON.stringify(name)}: `);
171
+ pathStack.push(name);
172
+ const { code, map } = (0, codegen_1.generateMessageFunction)(strValue, options, pathStack);
173
+ sourceMap && map != null && codeMaps.set(strValue, map);
174
+ generator.push(`${code}`, node.value, strValue);
175
+ }
176
+ else {
177
+ generator.push(`${JSON.stringify(name)}: ${JSON.stringify(value)}`);
178
+ pathStack.push(name);
179
+ }
180
+ skipStack.push(false);
146
181
  }
147
- skipStack.push(false);
148
182
  }
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);
183
+ else if ((node.value.type === 'ObjectExpression' ||
184
+ node.value.type === 'ArrayExpression') &&
185
+ (node.key.type === 'Literal' || node.key.type === 'Identifier')) {
186
+ // prettier-ignore
187
+ const name = node.key.type === 'Literal'
188
+ ? String(node.key.value)
189
+ : node.key.name;
190
+ generator.push(`${JSON.stringify(name)}: `);
191
+ pathStack.push(name);
192
+ }
193
+ else {
194
+ // for Regex, function, etc.
195
+ skipStack.push(true);
196
+ }
164
197
  }
165
198
  const lastIndex = propsCountStack.length - 1;
166
199
  propsCountStack[lastIndex] = --propsCountStack[lastIndex];
@@ -168,7 +201,7 @@ function generateNode(generator, node, options, injector) {
168
201
  case 'ArrayExpression':
169
202
  generator.push(`[`);
170
203
  generator.indent();
171
- if (parent.type === 'ArrayExpression') {
204
+ if (parent != null && parent.type === 'ArrayExpression') {
172
205
  const lastIndex = itemsCountStack.length - 1;
173
206
  const currentCount = parent.elements.length - itemsCountStack[lastIndex];
174
207
  pathStack.push(currentCount.toString());
@@ -177,32 +210,37 @@ function generateNode(generator, node, options, injector) {
177
210
  itemsCountStack.push(node.elements.length);
178
211
  break;
179
212
  default:
180
- if (isJSONablePrimitiveLiteral(node)) {
213
+ if (node != null && parent != null) {
181
214
  if (parent.type === 'ArrayExpression') {
182
215
  const lastIndex = itemsCountStack.length - 1;
183
216
  const currentCount = parent.elements.length - itemsCountStack[lastIndex];
184
217
  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);
218
+ if (isJSONablePrimitiveLiteral(node)) {
219
+ if ((node.type === 'Literal' && (0, shared_1.isString)(node.value)) ||
220
+ node.type === 'TemplateLiteral') {
221
+ const value = getValue(node);
222
+ const { code, map } = (0, codegen_1.generateMessageFunction)(value, options, pathStack);
223
+ sourceMap && map != null && codeMaps.set(value, map);
224
+ generator.push(`${code}`, node, value);
200
225
  }
201
226
  else {
202
- generator.push(`${JSON.stringify(value)}`);
227
+ const value = getValue(node);
228
+ if (forceStringify) {
229
+ const strValue = JSON.stringify(value);
230
+ const { code, map } = (0, codegen_1.generateMessageFunction)(strValue, options, pathStack);
231
+ sourceMap && map != null && codeMaps.set(strValue, map);
232
+ generator.push(`${code}`, node, strValue);
233
+ }
234
+ else {
235
+ generator.push(`${JSON.stringify(value)}`);
236
+ }
203
237
  }
204
238
  skipStack.push(false);
205
239
  }
240
+ else {
241
+ // for Regex, function, etc.
242
+ skipStack.push(true);
243
+ }
206
244
  itemsCountStack[lastIndex] = --itemsCountStack[lastIndex];
207
245
  }
208
246
  }
@@ -212,7 +250,14 @@ function generateNode(generator, node, options, injector) {
212
250
  break;
213
251
  }
214
252
  },
215
- exit({ node, parent }) {
253
+ /**
254
+ * NOTE:
255
+ * force cast to Node of `estree-walker@3.x`,
256
+ * because `estree-walker@3.x` is not dual packages,
257
+ * so it's support only esm only ...
258
+ */
259
+ // @ts-ignore
260
+ leave(node, parent) {
216
261
  switch (node.type) {
217
262
  case 'Program':
218
263
  if (type === 'sfc') {
@@ -235,14 +280,14 @@ function generateNode(generator, node, options, injector) {
235
280
  }
236
281
  generator.deindent();
237
282
  generator.push(`}`);
238
- if (parent.type === 'ArrayExpression') {
283
+ if (parent != null && parent.type === 'ArrayExpression') {
239
284
  if (itemsCountStack[itemsCountStack.length - 1] !== 0) {
240
285
  pathStack.pop();
241
286
  generator.pushline(`,`);
242
287
  }
243
288
  }
244
289
  break;
245
- case 'ObjectProperty':
290
+ case 'Property':
246
291
  if (propsCountStack[propsCountStack.length - 1] !== 0) {
247
292
  pathStack.pop();
248
293
  if (!skipStack.pop()) {
@@ -257,7 +302,7 @@ function generateNode(generator, node, options, injector) {
257
302
  }
258
303
  generator.deindent();
259
304
  generator.push(`]`);
260
- if (parent.type === 'ArrayExpression') {
305
+ if (parent != null && parent.type === 'ArrayExpression') {
261
306
  if (itemsCountStack[itemsCountStack.length - 1] !== 0) {
262
307
  pathStack.pop();
263
308
  if (!skipStack.pop()) {
@@ -266,25 +311,22 @@ function generateNode(generator, node, options, injector) {
266
311
  }
267
312
  }
268
313
  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
- }
314
+ case 'Literal':
315
+ if (parent != null && parent.type === 'ArrayExpression') {
316
+ if (itemsCountStack[itemsCountStack.length - 1] !== 0) {
317
+ pathStack.pop();
318
+ if (!skipStack.pop()) {
319
+ generator.pushline(`,`);
277
320
  }
278
- else {
279
- if (!skipStack.pop()) {
280
- generator.pushline(`,`);
281
- }
321
+ }
322
+ else {
323
+ if (!skipStack.pop()) {
324
+ generator.pushline(`,`);
282
325
  }
283
326
  }
284
327
  }
285
- else {
286
- // ...
287
- }
328
+ break;
329
+ default:
288
330
  break;
289
331
  }
290
332
  }
@@ -292,19 +334,39 @@ function generateNode(generator, node, options, injector) {
292
334
  return codeMaps;
293
335
  }
294
336
  function isJSONablePrimitiveLiteral(node) {
295
- return (node.type === 'NullLiteral' ||
296
- node.type === 'BooleanLiteral' ||
297
- node.type === 'NumericLiteral' ||
298
- node.type === 'StringLiteral' ||
337
+ return ((node.type === 'Literal' &&
338
+ ((0, shared_1.isString)(node.value) ||
339
+ (0, shared_1.isNumber)(node.value) ||
340
+ (0, shared_1.isBoolean)(node.value) ||
341
+ node.value === null)) ||
299
342
  node.type === 'TemplateLiteral');
343
+ // NOTE: the following code is same the above code
344
+ /*
345
+ if (node.type === 'Literal') {
346
+ if (
347
+ isString(node.value) ||
348
+ isNumber(node.value) ||
349
+ isBoolean(node.value) ||
350
+ node.value === null
351
+ ) {
352
+ return true
353
+ } else if (isRegExp(node.value)) {
354
+ return false
355
+ } else {
356
+ return false
357
+ }
358
+ } else if (node.type === 'TemplateLiteral') {
359
+ return true
360
+ } else {
361
+ return false
362
+ }
363
+ */
300
364
  }
301
365
  function getValue(node) {
302
366
  // prettier-ignore
303
- return node.type === 'StringLiteral'
367
+ return node.type === 'Literal'
304
368
  ? node.value
305
- : node.type === 'NullLiteral'
306
- ? null
307
- : node.type === 'TemplateLiteral'
308
- ? node.quasis.map(quasi => quasi.value.cooked).join('')
309
- : node.value;
369
+ : node.type === 'TemplateLiteral'
370
+ ? node.quasis.map(quasi => quasi.value.cooked).join('')
371
+ : undefined;
310
372
  }
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.0",
4
+ "version": "5.1.0",
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"