@intlayer/babel 9.3.0 → 9.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -24
- package/dist/cjs/_virtual/_rolldown/runtime.cjs +1 -2
- package/dist/cjs/babel-plugin-intlayer-extract.cjs.map +1 -1
- package/dist/cjs/babel-plugin-intlayer-field-rename.cjs +66 -8
- package/dist/cjs/babel-plugin-intlayer-field-rename.cjs.map +1 -1
- package/dist/cjs/babel-plugin-intlayer-optimize.cjs +9 -5
- package/dist/cjs/babel-plugin-intlayer-optimize.cjs.map +1 -1
- package/dist/cjs/babel-plugin-intlayer-purge.cjs.map +1 -1
- package/dist/cjs/babel-plugin-intlayer-usage-analyzer.cjs +142 -54
- package/dist/cjs/babel-plugin-intlayer-usage-analyzer.cjs.map +1 -1
- package/dist/cjs/babelParser.cjs.map +1 -1
- package/dist/cjs/extractContent/babelProcessor.cjs +57 -57
- package/dist/cjs/extractContent/babelProcessor.cjs.map +1 -1
- package/dist/cjs/extractContent/contentWriter.cjs +3 -2
- package/dist/cjs/extractContent/contentWriter.cjs.map +1 -1
- package/dist/cjs/extractContent/extractContent.cjs +7 -6
- package/dist/cjs/extractContent/extractContent.cjs.map +1 -1
- package/dist/cjs/extractContent/index.cjs +0 -1
- package/dist/cjs/extractContent/processTsxFile.cjs.map +1 -1
- package/dist/cjs/extractContent/utils/constants.cjs +0 -14
- package/dist/cjs/extractContent/utils/constants.cjs.map +1 -1
- package/dist/cjs/extractContent/utils/detectPackageName.cjs.map +1 -1
- package/dist/cjs/extractContent/utils/extractDictionaryInfo.cjs +5 -3
- package/dist/cjs/extractContent/utils/extractDictionaryInfo.cjs.map +1 -1
- package/dist/cjs/extractContent/utils/extractDictionaryKey.cjs.map +1 -1
- package/dist/cjs/extractContent/utils/generateKey.cjs +0 -1
- package/dist/cjs/extractContent/utils/generateKey.cjs.map +1 -1
- package/dist/cjs/extractContent/utils/getExistingIntlayerInfo.cjs.map +1 -1
- package/dist/cjs/extractContent/utils/index.cjs +1 -4
- package/dist/cjs/extractContent/utils/resolveDictionaryKey.cjs.map +1 -1
- package/dist/cjs/extractScriptBlocks.cjs.map +1 -1
- package/dist/cjs/getExtractPluginOptions.cjs +4 -2
- package/dist/cjs/getExtractPluginOptions.cjs.map +1 -1
- package/dist/cjs/getOptimizePluginOptions.cjs.map +1 -1
- package/dist/cjs/getPurgePluginOptions.cjs.map +1 -1
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/transformers.cjs.map +1 -1
- package/dist/esm/babel-plugin-intlayer-field-rename.mjs +67 -9
- package/dist/esm/babel-plugin-intlayer-field-rename.mjs.map +1 -1
- package/dist/esm/babel-plugin-intlayer-optimize.mjs +9 -5
- package/dist/esm/babel-plugin-intlayer-optimize.mjs.map +1 -1
- package/dist/esm/babel-plugin-intlayer-usage-analyzer.mjs +142 -54
- package/dist/esm/babel-plugin-intlayer-usage-analyzer.mjs.map +1 -1
- package/dist/esm/extractContent/babelProcessor.mjs +51 -51
- package/dist/esm/extractContent/babelProcessor.mjs.map +1 -1
- package/dist/esm/extractContent/contentWriter.mjs +3 -2
- package/dist/esm/extractContent/contentWriter.mjs.map +1 -1
- package/dist/esm/extractContent/extractContent.mjs +5 -4
- package/dist/esm/extractContent/extractContent.mjs.map +1 -1
- package/dist/esm/extractContent/index.mjs +2 -2
- package/dist/esm/extractContent/utils/constants.mjs +1 -13
- package/dist/esm/extractContent/utils/constants.mjs.map +1 -1
- package/dist/esm/extractContent/utils/extractDictionaryInfo.mjs +5 -3
- package/dist/esm/extractContent/utils/extractDictionaryInfo.mjs.map +1 -1
- package/dist/esm/extractContent/utils/getExistingIntlayerInfo.mjs.map +1 -1
- package/dist/esm/extractContent/utils/index.mjs +2 -3
- package/dist/esm/getExtractPluginOptions.mjs +4 -2
- package/dist/esm/getExtractPluginOptions.mjs.map +1 -1
- package/dist/esm/index.mjs +3 -3
- package/dist/types/babel-plugin-intlayer-field-rename.d.ts.map +1 -1
- package/dist/types/babel-plugin-intlayer-usage-analyzer.d.ts +16 -1
- package/dist/types/babel-plugin-intlayer-usage-analyzer.d.ts.map +1 -1
- package/dist/types/extractContent/babelProcessor.d.ts.map +1 -1
- package/dist/types/extractContent/extractContent.d.ts.map +1 -1
- package/dist/types/extractContent/index.d.ts +2 -2
- package/dist/types/extractContent/utils/constants.d.ts +1 -7
- package/dist/types/extractContent/utils/constants.d.ts.map +1 -1
- package/dist/types/extractContent/utils/index.d.ts +2 -3
- package/dist/types/index.d.ts +3 -3
- package/package.json +9 -10
- package/dist/cjs/extractContent/utils/shouldExtract.cjs +0 -39
- package/dist/cjs/extractContent/utils/shouldExtract.cjs.map +0 -1
- package/dist/esm/extractContent/utils/shouldExtract.mjs +0 -37
- package/dist/esm/extractContent/utils/shouldExtract.mjs.map +0 -1
- package/dist/types/extractContent/utils/shouldExtract.d.ts +0 -15
- package/dist/types/extractContent/utils/shouldExtract.d.ts.map +0 -1
|
@@ -53,6 +53,21 @@ const preserveNestedDictionaryFields = (pruneContext, nestedDictionaryReferences
|
|
|
53
53
|
for (const nestedField of nestedFields) currentFieldUsage.add(nestedField);
|
|
54
54
|
}
|
|
55
55
|
};
|
|
56
|
+
/**
|
|
57
|
+
* Methods the runtime attaches to a resolved content object rather than fields
|
|
58
|
+
* declared in a `.content` file.
|
|
59
|
+
*
|
|
60
|
+
* `vanilla-intlayer`'s `useIntlayer` / `useDictionary` assign `onChange` onto
|
|
61
|
+
* the content they return, so `useIntlayer('app').onChange(cb)` is a
|
|
62
|
+
* subscription — not a read of a field named `onChange`. Without this list the
|
|
63
|
+
* analyser records `onChange` as the only consumed field and the purge pass
|
|
64
|
+
* strips every real field from the compiled dictionary.
|
|
65
|
+
*
|
|
66
|
+
* The analyser looks *through* these calls: the callback parameter is analysed
|
|
67
|
+
* as a fresh content root, and the call result is analysed again because the
|
|
68
|
+
* helpers return the content object for chaining.
|
|
69
|
+
*/
|
|
70
|
+
const CHAINABLE_RUNTIME_METHOD_NAMES = /* @__PURE__ */ new Set(["onChange"]);
|
|
56
71
|
/** Canonical intlayer caller names that trigger usage analysis. */
|
|
57
72
|
const INTLAYER_CALLER_NAMES = ["useIntlayer", "getIntlayer"];
|
|
58
73
|
/**
|
|
@@ -97,7 +112,6 @@ const recordFieldUsage = (pruneContext, dictionaryKey, fieldUsage) => {
|
|
|
97
112
|
* const result = useIntlayer('key') → records 'all' (untracked binding)
|
|
98
113
|
*/
|
|
99
114
|
const analyzeCallExpressionUsage = (babelTypes, pruneContext, callExpressionPath, dictionaryKey, currentSourceFilePath, isSfcFile) => {
|
|
100
|
-
const parentNode = callExpressionPath.parent;
|
|
101
115
|
/** Mark the dictionary key as having an untracked binding in this file. */
|
|
102
116
|
const markUntrackedBinding = () => {
|
|
103
117
|
const existingPaths = pruneContext.dictionaryKeysWithUntrackedBindings.get(dictionaryKey) ?? [];
|
|
@@ -225,32 +239,64 @@ const analyzeCallExpressionUsage = (babelTypes, pruneContext, callExpressionPath
|
|
|
225
239
|
}
|
|
226
240
|
return true;
|
|
227
241
|
};
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if (
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
242
|
+
/**
|
|
243
|
+
* Returns the call path when `memberExprPath` is a chainable runtime helper
|
|
244
|
+
* being invoked (`content.onChange(cb)`), otherwise `undefined`.
|
|
245
|
+
*
|
|
246
|
+
* See {@link CHAINABLE_RUNTIME_METHOD_NAMES}: a bare `content.onChange`
|
|
247
|
+
* reference that is never called is treated as an ordinary field access, so
|
|
248
|
+
* only the invoked form is looked through.
|
|
249
|
+
*/
|
|
250
|
+
const getChainedRuntimeCallPath = (memberExprPath, fieldName) => {
|
|
251
|
+
if (!CHAINABLE_RUNTIME_METHOD_NAMES.has(fieldName)) return void 0;
|
|
252
|
+
if (!memberExprPath) return void 0;
|
|
253
|
+
const callPath = memberExprPath.parentPath;
|
|
254
|
+
if (!callPath) return void 0;
|
|
255
|
+
if (!callPath.isCallExpression() && !callPath.isOptionalCallExpression()) return;
|
|
256
|
+
if (callPath.node.callee !== memberExprPath.node) return;
|
|
257
|
+
return callPath;
|
|
258
|
+
};
|
|
259
|
+
/**
|
|
260
|
+
* Analyses the callbacks handed to a chainable runtime helper.
|
|
261
|
+
*
|
|
262
|
+
* The callback receives the freshly-resolved content root, so its parameter
|
|
263
|
+
* is walked exactly like `const content = useIntlayer('key')` — either as a
|
|
264
|
+
* plain binding or as a destructuring pattern.
|
|
265
|
+
*/
|
|
266
|
+
const analyzeChainedCallbackArguments = (callPath) => {
|
|
267
|
+
const argumentPaths = callPath.get("arguments");
|
|
268
|
+
for (const argumentPath of argumentPaths) {
|
|
269
|
+
if (!argumentPath.isArrowFunctionExpression() && !argumentPath.isFunctionExpression()) continue;
|
|
270
|
+
const [firstParameterPath] = argumentPath.get("params");
|
|
271
|
+
if (!firstParameterPath) continue;
|
|
272
|
+
if (firstParameterPath.isIdentifier()) {
|
|
273
|
+
const parameterBinding = argumentPath.scope.getBinding(firstParameterPath.node.name);
|
|
274
|
+
if (!parameterBinding) {
|
|
275
|
+
markUntrackedBinding();
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
const accessedFieldNames = /* @__PURE__ */ new Set();
|
|
279
|
+
if (analyzeContentBindingReferences(parameterBinding, accessedFieldNames)) markUntrackedBinding();
|
|
280
|
+
else recordFieldUsage(pruneContext, dictionaryKey, accessedFieldNames);
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
if (firstParameterPath.isObjectPattern()) {
|
|
284
|
+
const accessedFieldNames = /* @__PURE__ */ new Set();
|
|
285
|
+
if (collectFieldsFromObjectPattern(firstParameterPath.node, argumentPath, accessedFieldNames)) recordFieldUsage(pruneContext, dictionaryKey, accessedFieldNames);
|
|
286
|
+
else recordFieldUsage(pruneContext, dictionaryKey, "all");
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
249
289
|
markUntrackedBinding();
|
|
250
|
-
return;
|
|
251
290
|
}
|
|
252
|
-
|
|
253
|
-
|
|
291
|
+
};
|
|
292
|
+
/**
|
|
293
|
+
* Walks every reference of a local binding holding the content root,
|
|
294
|
+
* collecting the top-level fields it reads into `accessedTopLevelFieldNames`.
|
|
295
|
+
*
|
|
296
|
+
* @returns `true` when a reference escaped static tracking, meaning the whole
|
|
297
|
+
* dictionary must be kept.
|
|
298
|
+
*/
|
|
299
|
+
const analyzeContentBindingReferences = (variableBinding, accessedTopLevelFieldNames) => {
|
|
254
300
|
for (const variableReferencePath of variableBinding.referencePaths) {
|
|
255
301
|
const referenceParentNode = variableReferencePath.parent;
|
|
256
302
|
if ((babelTypes.isMemberExpression(referenceParentNode) || babelTypes.isOptionalMemberExpression(referenceParentNode)) && referenceParentNode.object === variableReferencePath.node) {
|
|
@@ -259,17 +305,18 @@ const analyzeCallExpressionUsage = (babelTypes, pruneContext, callExpressionPath
|
|
|
259
305
|
if (!memberExpressionNode.computed && babelTypes.isIdentifier(memberExpressionNode.property)) fieldName = memberExpressionNode.property.name;
|
|
260
306
|
else if (memberExpressionNode.computed && babelTypes.isStringLiteral(memberExpressionNode.property)) fieldName = memberExpressionNode.property.value;
|
|
261
307
|
if (fieldName) {
|
|
262
|
-
accessedTopLevelFieldNames.add(fieldName);
|
|
263
308
|
const memberExprPath = variableReferencePath.parentPath;
|
|
309
|
+
const chainedCallPath = getChainedRuntimeCallPath(memberExprPath, fieldName);
|
|
310
|
+
if (chainedCallPath) {
|
|
311
|
+
analyzeChainedCallbackArguments(chainedCallPath);
|
|
312
|
+
analyzeContentRoot(chainedCallPath);
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
accessedTopLevelFieldNames.add(fieldName);
|
|
264
316
|
if (memberExprPath) analyzeOpaqueUsage(memberExprPath, [fieldName]);
|
|
265
|
-
} else
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
}
|
|
269
|
-
} else if (babelTypes.isArrayExpression(referenceParentNode)) {
|
|
270
|
-
hasUntrackedReferenceAccess = true;
|
|
271
|
-
break;
|
|
272
|
-
} else if ((babelTypes.isCallExpression(referenceParentNode) || babelTypes.isOptionalCallExpression(referenceParentNode)) && referenceParentNode.callee === variableReferencePath.node) {
|
|
317
|
+
} else return true;
|
|
318
|
+
} else if (babelTypes.isArrayExpression(referenceParentNode)) return true;
|
|
319
|
+
else if ((babelTypes.isCallExpression(referenceParentNode) || babelTypes.isOptionalCallExpression(referenceParentNode)) && referenceParentNode.callee === variableReferencePath.node) {
|
|
273
320
|
const callExprPath = variableReferencePath.parentPath;
|
|
274
321
|
const callParent = callExprPath?.parent;
|
|
275
322
|
if (callParent && (babelTypes.isMemberExpression(callParent) || babelTypes.isOptionalMemberExpression(callParent)) && callParent.object === callExprPath?.node) {
|
|
@@ -278,30 +325,71 @@ const analyzeCallExpressionUsage = (babelTypes, pruneContext, callExpressionPath
|
|
|
278
325
|
if (!memberExpr.computed && babelTypes.isIdentifier(memberExpr.property)) fieldName = memberExpr.property.name;
|
|
279
326
|
else if (memberExpr.computed && babelTypes.isStringLiteral(memberExpr.property)) fieldName = memberExpr.property.value;
|
|
280
327
|
if (fieldName) {
|
|
281
|
-
accessedTopLevelFieldNames.add(fieldName);
|
|
282
328
|
const memberExprPath = callExprPath?.parentPath;
|
|
329
|
+
const chainedCallPath = getChainedRuntimeCallPath(memberExprPath, fieldName);
|
|
330
|
+
if (chainedCallPath) {
|
|
331
|
+
analyzeChainedCallbackArguments(chainedCallPath);
|
|
332
|
+
analyzeContentRoot(chainedCallPath);
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
accessedTopLevelFieldNames.add(fieldName);
|
|
283
336
|
if (memberExprPath) analyzeOpaqueUsage(memberExprPath, [fieldName]);
|
|
284
|
-
} else
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
337
|
+
} else return true;
|
|
338
|
+
} else if (callParent && babelTypes.isVariableDeclarator(callParent) && babelTypes.isObjectPattern(callParent.id) && callExprPath && collectFieldsFromObjectPattern(callParent.id, callExprPath, accessedTopLevelFieldNames)) {} else return true;
|
|
339
|
+
} else return true;
|
|
340
|
+
}
|
|
341
|
+
return false;
|
|
342
|
+
};
|
|
343
|
+
/**
|
|
344
|
+
* Analyses how the content root referenced by `rootPath` is consumed.
|
|
345
|
+
*
|
|
346
|
+
* `rootPath` is the `useIntlayer('key')` call itself, or any expression that
|
|
347
|
+
* evaluates back to the same content object — currently the result of a
|
|
348
|
+
* chainable runtime helper such as `.onChange(…)`.
|
|
349
|
+
*/
|
|
350
|
+
const analyzeContentRoot = (rootPath) => {
|
|
351
|
+
const parentNode = rootPath.parent;
|
|
352
|
+
if (babelTypes.isVariableDeclarator(parentNode) && babelTypes.isObjectPattern(parentNode.id)) {
|
|
353
|
+
const accessedFieldNames = /* @__PURE__ */ new Set();
|
|
354
|
+
if (collectFieldsFromObjectPattern(parentNode.id, rootPath, accessedFieldNames)) recordFieldUsage(pruneContext, dictionaryKey, accessedFieldNames);
|
|
355
|
+
else recordFieldUsage(pruneContext, dictionaryKey, "all");
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
if ((babelTypes.isMemberExpression(parentNode) || babelTypes.isOptionalMemberExpression(parentNode)) && parentNode.object === rootPath.node) {
|
|
359
|
+
let fieldName;
|
|
360
|
+
if (!parentNode.computed && babelTypes.isIdentifier(parentNode.property)) fieldName = parentNode.property.name;
|
|
361
|
+
else if (parentNode.computed && babelTypes.isStringLiteral(parentNode.property)) fieldName = parentNode.property.value;
|
|
362
|
+
if (fieldName) {
|
|
363
|
+
const memberExprPath = rootPath.parentPath;
|
|
364
|
+
const chainedCallPath = getChainedRuntimeCallPath(memberExprPath, fieldName);
|
|
365
|
+
if (chainedCallPath) {
|
|
366
|
+
analyzeChainedCallbackArguments(chainedCallPath);
|
|
367
|
+
analyzeContentRoot(chainedCallPath);
|
|
368
|
+
return;
|
|
291
369
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
370
|
+
recordFieldUsage(pruneContext, dictionaryKey, /* @__PURE__ */ new Set([fieldName]));
|
|
371
|
+
if (memberExprPath) analyzeOpaqueUsage(memberExprPath, [fieldName]);
|
|
372
|
+
} else markUntrackedBinding();
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
if (babelTypes.isVariableDeclarator(parentNode) && babelTypes.isIdentifier(parentNode.id)) {
|
|
376
|
+
const variableName = parentNode.id.name;
|
|
377
|
+
const variableBinding = rootPath.scope.getBinding(variableName);
|
|
378
|
+
if (!variableBinding) {
|
|
379
|
+
markUntrackedBinding();
|
|
380
|
+
return;
|
|
295
381
|
}
|
|
382
|
+
const accessedTopLevelFieldNames = /* @__PURE__ */ new Set();
|
|
383
|
+
if (analyzeContentBindingReferences(variableBinding, accessedTopLevelFieldNames)) markUntrackedBinding();
|
|
384
|
+
else if (isSfcFile) deferFrameworkAnalysis(variableName);
|
|
385
|
+
else if (variableBinding.referencePaths.length === 0) markUntrackedBinding();
|
|
386
|
+
else recordFieldUsage(pruneContext, dictionaryKey, accessedTopLevelFieldNames);
|
|
387
|
+
return;
|
|
296
388
|
}
|
|
297
|
-
if (
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
return;
|
|
302
|
-
}
|
|
303
|
-
if (babelTypes.isExpressionStatement(parentNode)) return;
|
|
304
|
-
markUntrackedBinding();
|
|
389
|
+
if (babelTypes.isExpressionStatement(parentNode)) return;
|
|
390
|
+
markUntrackedBinding();
|
|
391
|
+
};
|
|
392
|
+
analyzeContentRoot(callExpressionPath);
|
|
305
393
|
};
|
|
306
394
|
/**
|
|
307
395
|
* Reads a fully-static string from an AST node. Returns `undefined` for
|
|
@@ -645,5 +733,5 @@ const makeUsageAnalyzerBabelPlugin = (pruneContext, options) => ({ types: babelT
|
|
|
645
733
|
};
|
|
646
734
|
|
|
647
735
|
//#endregion
|
|
648
|
-
export { DEFAULT_COMPAT_CALLERS, INTLAYER_CALLER_NAMES, createPruneContext, makeUsageAnalyzerBabelPlugin, preserveNestedDictionaryFields };
|
|
736
|
+
export { CHAINABLE_RUNTIME_METHOD_NAMES, DEFAULT_COMPAT_CALLERS, INTLAYER_CALLER_NAMES, createPruneContext, makeUsageAnalyzerBabelPlugin, preserveNestedDictionaryFields };
|
|
649
737
|
//# sourceMappingURL=babel-plugin-intlayer-usage-analyzer.mjs.map
|