@intlayer/babel 9.0.0-canary.2 → 9.0.0-canary.21
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/dist/cjs/babel-plugin-intlayer-extract.cjs +3 -2
- package/dist/cjs/babel-plugin-intlayer-extract.cjs.map +1 -1
- package/dist/cjs/babel-plugin-intlayer-field-rename.cjs +160 -99
- package/dist/cjs/babel-plugin-intlayer-field-rename.cjs.map +1 -1
- package/dist/cjs/babel-plugin-intlayer-minify.cjs +11 -28
- package/dist/cjs/babel-plugin-intlayer-minify.cjs.map +1 -1
- package/dist/cjs/babel-plugin-intlayer-optimize.cjs +143 -13
- package/dist/cjs/babel-plugin-intlayer-optimize.cjs.map +1 -1
- package/dist/cjs/babel-plugin-intlayer-purge.cjs +38 -96
- package/dist/cjs/babel-plugin-intlayer-purge.cjs.map +1 -1
- package/dist/cjs/babel-plugin-intlayer-usage-analyzer.cjs +151 -52
- package/dist/cjs/babel-plugin-intlayer-usage-analyzer.cjs.map +1 -1
- package/dist/cjs/babelParser.cjs +62 -0
- package/dist/cjs/babelParser.cjs.map +1 -0
- package/dist/cjs/extractContent/babelProcessor.cjs +144 -71
- package/dist/cjs/extractContent/babelProcessor.cjs.map +1 -1
- package/dist/cjs/extractContent/contentWriter.cjs +10 -14
- package/dist/cjs/extractContent/contentWriter.cjs.map +1 -1
- package/dist/cjs/extractContent/extractContent.cjs +3 -3
- package/dist/cjs/extractContent/extractContent.cjs.map +1 -1
- package/dist/cjs/extractContent/processTsxFile.cjs +4 -7
- package/dist/cjs/extractContent/processTsxFile.cjs.map +1 -1
- package/dist/cjs/extractContent/utils/constants.cjs +2 -2
- package/dist/cjs/extractContent/utils/constants.cjs.map +1 -1
- package/dist/cjs/extractContent/utils/detectPackageName.cjs +0 -1
- package/dist/cjs/extractContent/utils/detectPackageName.cjs.map +1 -1
- package/dist/cjs/extractContent/utils/extractDictionaryInfo.cjs +4 -4
- package/dist/cjs/extractContent/utils/extractDictionaryInfo.cjs.map +1 -1
- package/dist/cjs/extractContent/utils/extractDictionaryKey.cjs +2 -3
- package/dist/cjs/extractContent/utils/extractDictionaryKey.cjs.map +1 -1
- package/dist/cjs/extractContent/utils/generateKey.cjs.map +1 -1
- package/dist/cjs/extractContent/utils/getComponentName.cjs.map +1 -1
- package/dist/cjs/extractContent/utils/getExistingIntlayerInfo.cjs.map +1 -1
- package/dist/cjs/extractContent/utils/getOrGenerateKey.cjs.map +1 -1
- package/dist/cjs/extractContent/utils/resolveDictionaryKey.cjs +0 -1
- package/dist/cjs/extractContent/utils/resolveDictionaryKey.cjs.map +1 -1
- package/dist/cjs/extractContent/utils/shouldExtract.cjs +2 -0
- package/dist/cjs/extractContent/utils/shouldExtract.cjs.map +1 -1
- package/dist/cjs/extractScriptBlocks.cjs +0 -1
- package/dist/cjs/extractScriptBlocks.cjs.map +1 -1
- package/dist/cjs/getExtractPluginOptions.cjs +2 -2
- package/dist/cjs/getExtractPluginOptions.cjs.map +1 -1
- package/dist/cjs/getOptimizePluginOptions.cjs +2 -3
- package/dist/cjs/getOptimizePluginOptions.cjs.map +1 -1
- package/dist/cjs/getPurgePluginOptions.cjs +2 -3
- package/dist/cjs/getPurgePluginOptions.cjs.map +1 -1
- package/dist/cjs/index.cjs +3 -0
- package/dist/cjs/normalizedFilesList.cjs +30 -0
- package/dist/cjs/normalizedFilesList.cjs.map +1 -0
- package/dist/cjs/transformers.cjs +20 -2
- package/dist/cjs/transformers.cjs.map +1 -1
- package/dist/esm/babel-plugin-intlayer-extract.mjs +3 -2
- package/dist/esm/babel-plugin-intlayer-extract.mjs.map +1 -1
- package/dist/esm/babel-plugin-intlayer-field-rename.mjs +159 -100
- package/dist/esm/babel-plugin-intlayer-field-rename.mjs.map +1 -1
- package/dist/esm/babel-plugin-intlayer-minify.mjs +12 -29
- package/dist/esm/babel-plugin-intlayer-minify.mjs.map +1 -1
- package/dist/esm/babel-plugin-intlayer-optimize.mjs +140 -9
- package/dist/esm/babel-plugin-intlayer-optimize.mjs.map +1 -1
- package/dist/esm/babel-plugin-intlayer-purge.mjs +40 -97
- package/dist/esm/babel-plugin-intlayer-purge.mjs.map +1 -1
- package/dist/esm/babel-plugin-intlayer-usage-analyzer.mjs +151 -52
- package/dist/esm/babel-plugin-intlayer-usage-analyzer.mjs.map +1 -1
- package/dist/esm/babelParser.mjs +60 -0
- package/dist/esm/babelParser.mjs.map +1 -0
- package/dist/esm/extractContent/babelProcessor.mjs +144 -71
- package/dist/esm/extractContent/babelProcessor.mjs.map +1 -1
- package/dist/esm/extractContent/contentWriter.mjs +6 -10
- package/dist/esm/extractContent/contentWriter.mjs.map +1 -1
- package/dist/esm/extractContent/extractContent.mjs +1 -1
- package/dist/esm/extractContent/extractContent.mjs.map +1 -1
- package/dist/esm/extractContent/processTsxFile.mjs +3 -6
- package/dist/esm/extractContent/processTsxFile.mjs.map +1 -1
- package/dist/esm/extractContent/utils/constants.mjs +2 -2
- package/dist/esm/extractContent/utils/constants.mjs.map +1 -1
- package/dist/esm/extractContent/utils/detectPackageName.mjs.map +1 -1
- package/dist/esm/extractContent/utils/extractDictionaryInfo.mjs +1 -1
- package/dist/esm/extractContent/utils/extractDictionaryInfo.mjs.map +1 -1
- package/dist/esm/extractContent/utils/extractDictionaryKey.mjs +1 -1
- package/dist/esm/extractContent/utils/extractDictionaryKey.mjs.map +1 -1
- package/dist/esm/extractContent/utils/generateKey.mjs.map +1 -1
- package/dist/esm/extractContent/utils/getComponentName.mjs.map +1 -1
- package/dist/esm/extractContent/utils/getExistingIntlayerInfo.mjs.map +1 -1
- package/dist/esm/extractContent/utils/getOrGenerateKey.mjs.map +1 -1
- package/dist/esm/extractContent/utils/resolveDictionaryKey.mjs.map +1 -1
- package/dist/esm/extractContent/utils/shouldExtract.mjs +2 -0
- package/dist/esm/extractContent/utils/shouldExtract.mjs.map +1 -1
- package/dist/esm/extractScriptBlocks.mjs.map +1 -1
- package/dist/esm/getExtractPluginOptions.mjs +1 -1
- package/dist/esm/getExtractPluginOptions.mjs.map +1 -1
- package/dist/esm/getOptimizePluginOptions.mjs +1 -1
- package/dist/esm/getOptimizePluginOptions.mjs.map +1 -1
- package/dist/esm/getPurgePluginOptions.mjs +1 -1
- package/dist/esm/getPurgePluginOptions.mjs.map +1 -1
- package/dist/esm/index.mjs +3 -3
- package/dist/esm/normalizedFilesList.mjs +29 -0
- package/dist/esm/normalizedFilesList.mjs.map +1 -0
- package/dist/esm/transformers.mjs +20 -2
- package/dist/esm/transformers.mjs.map +1 -1
- package/dist/types/babel-plugin-intlayer-extract.d.ts +2 -3
- package/dist/types/babel-plugin-intlayer-extract.d.ts.map +1 -1
- package/dist/types/babel-plugin-intlayer-field-rename.d.ts +29 -11
- package/dist/types/babel-plugin-intlayer-field-rename.d.ts.map +1 -1
- package/dist/types/babel-plugin-intlayer-minify.d.ts +2 -3
- package/dist/types/babel-plugin-intlayer-minify.d.ts.map +1 -1
- package/dist/types/babel-plugin-intlayer-optimize.d.ts +34 -11
- package/dist/types/babel-plugin-intlayer-optimize.d.ts.map +1 -1
- package/dist/types/babel-plugin-intlayer-purge.d.ts +2 -3
- package/dist/types/babel-plugin-intlayer-purge.d.ts.map +1 -1
- package/dist/types/babel-plugin-intlayer-usage-analyzer.d.ts +35 -113
- package/dist/types/babel-plugin-intlayer-usage-analyzer.d.ts.map +1 -1
- package/dist/types/babelParser.d.ts +12 -0
- package/dist/types/babelParser.d.ts.map +1 -0
- package/dist/types/extractContent/babelProcessor.d.ts +5 -2
- package/dist/types/extractContent/babelProcessor.d.ts.map +1 -1
- package/dist/types/extractContent/contentWriter.d.ts +0 -1
- package/dist/types/extractContent/contentWriter.d.ts.map +1 -1
- package/dist/types/extractContent/extractContent.d.ts +1 -1
- package/dist/types/extractContent/extractContent.d.ts.map +1 -1
- package/dist/types/extractContent/index.d.ts +1 -1
- package/dist/types/extractContent/processTsxFile.d.ts +1 -1
- package/dist/types/extractContent/processTsxFile.d.ts.map +1 -1
- package/dist/types/extractContent/utils/constants.d.ts +3 -3
- package/dist/types/extractContent/utils/constants.d.ts.map +1 -1
- package/dist/types/extractContent/utils/detectPackageName.d.ts +0 -1
- package/dist/types/extractContent/utils/detectPackageName.d.ts.map +1 -1
- package/dist/types/extractContent/utils/extractDictionaryInfo.d.ts +0 -1
- package/dist/types/extractContent/utils/extractDictionaryInfo.d.ts.map +1 -1
- package/dist/types/extractContent/utils/extractDictionaryKey.d.ts.map +1 -1
- package/dist/types/extractContent/utils/generateKey.d.ts.map +1 -1
- package/dist/types/extractContent/utils/getComponentName.d.ts +0 -1
- package/dist/types/extractContent/utils/getComponentName.d.ts.map +1 -1
- package/dist/types/extractContent/utils/getExistingIntlayerInfo.d.ts +8 -5
- package/dist/types/extractContent/utils/getExistingIntlayerInfo.d.ts.map +1 -1
- package/dist/types/extractContent/utils/getOrGenerateKey.d.ts.map +1 -1
- package/dist/types/extractContent/utils/resolveDictionaryKey.d.ts +0 -1
- package/dist/types/extractContent/utils/resolveDictionaryKey.d.ts.map +1 -1
- package/dist/types/extractContent/utils/shouldExtract.d.ts +1 -0
- package/dist/types/extractContent/utils/shouldExtract.d.ts.map +1 -1
- package/dist/types/extractScriptBlocks.d.ts.map +1 -1
- package/dist/types/getExtractPluginOptions.d.ts +0 -1
- package/dist/types/getExtractPluginOptions.d.ts.map +1 -1
- package/dist/types/getOptimizePluginOptions.d.ts +0 -1
- package/dist/types/getOptimizePluginOptions.d.ts.map +1 -1
- package/dist/types/getPurgePluginOptions.d.ts +0 -1
- package/dist/types/getPurgePluginOptions.d.ts.map +1 -1
- package/dist/types/index.d.ts +6 -5
- package/dist/types/normalizedFilesList.d.ts +12 -0
- package/dist/types/normalizedFilesList.d.ts.map +1 -0
- package/dist/types/transformers.d.ts +7 -2
- package/dist/types/transformers.d.ts.map +1 -1
- package/package.json +31 -23
|
@@ -7,7 +7,7 @@ const createPruneContext = () => ({
|
|
|
7
7
|
hasUnparsableSourceFiles: false,
|
|
8
8
|
dictionaryKeysWithUntrackedBindings: /* @__PURE__ */ new Map(),
|
|
9
9
|
dictionaryKeyToFieldRenameMap: /* @__PURE__ */ new Map(),
|
|
10
|
-
|
|
10
|
+
dictionaryKeysWithOpaqueFields: /* @__PURE__ */ new Map(),
|
|
11
11
|
dictionariesSkippingFieldRename: /* @__PURE__ */ new Set(),
|
|
12
12
|
pendingFrameworkAnalysis: /* @__PURE__ */ new Map()
|
|
13
13
|
});
|
|
@@ -37,8 +37,11 @@ const recordFieldUsage = (pruneContext, dictionaryKey, fieldUsage) => {
|
|
|
37
37
|
pruneContext.dictionaryKeyToFieldUsageMap.set(dictionaryKey, "all");
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
if (existingUsage instanceof Set) {
|
|
41
|
+
for (const fieldName of fieldUsage) existingUsage.add(fieldName);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
pruneContext.dictionaryKeyToFieldUsageMap.set(dictionaryKey, new Set(fieldUsage));
|
|
42
45
|
};
|
|
43
46
|
/**
|
|
44
47
|
* Analyses how the result of a single `useIntlayer('key')` / `getIntlayer('key')`
|
|
@@ -59,14 +62,18 @@ const analyzeCallExpressionUsage = (babelTypes, pruneContext, callExpressionPath
|
|
|
59
62
|
if (!existingPaths.includes(currentSourceFilePath)) pruneContext.dictionaryKeysWithUntrackedBindings.set(dictionaryKey, [...existingPaths, currentSourceFilePath]);
|
|
60
63
|
recordFieldUsage(pruneContext, dictionaryKey, "all");
|
|
61
64
|
};
|
|
62
|
-
/** Record that
|
|
63
|
-
const markOpaqueField = (
|
|
64
|
-
const
|
|
65
|
+
/** Record that the content value at `fieldPath` is consumed opaquely. */
|
|
66
|
+
const markOpaqueField = (fieldPath, line) => {
|
|
67
|
+
const pathToOccurrence = pruneContext.dictionaryKeysWithOpaqueFields.get(dictionaryKey) ?? /* @__PURE__ */ new Map();
|
|
65
68
|
const location = line !== void 0 ? `${currentSourceFilePath}:${line}` : currentSourceFilePath;
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
const joinedFieldPath = fieldPath.join(".");
|
|
70
|
+
const occurrence = pathToOccurrence.get(joinedFieldPath) ?? {
|
|
71
|
+
fieldPath: [...fieldPath],
|
|
72
|
+
locations: []
|
|
73
|
+
};
|
|
74
|
+
if (!occurrence.locations.includes(location)) occurrence.locations.push(location);
|
|
75
|
+
pathToOccurrence.set(joinedFieldPath, occurrence);
|
|
76
|
+
pruneContext.dictionaryKeysWithOpaqueFields.set(dictionaryKey, pathToOccurrence);
|
|
70
77
|
};
|
|
71
78
|
/** Register a plain variable binding in an SFC file for a second-pass analysis. */
|
|
72
79
|
const deferFrameworkAnalysis = (variableName) => {
|
|
@@ -78,37 +85,101 @@ const analyzeCallExpressionUsage = (babelTypes, pruneContext, callExpressionPath
|
|
|
78
85
|
pruneContext.pendingFrameworkAnalysis.set(currentSourceFilePath, existing);
|
|
79
86
|
};
|
|
80
87
|
/**
|
|
81
|
-
* Analyses
|
|
82
|
-
*
|
|
88
|
+
* Analyses how the content value at `fieldPath` (currently referenced by
|
|
89
|
+
* `refPath`) is consumed, to detect opaque consumption (passing a dictionary
|
|
90
|
+
* value as-is to a prop or function argument).
|
|
83
91
|
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
92
|
+
* Member-access chains and destructuring are followed recursively with an
|
|
93
|
+
* extended field path, so the *terminal* consumption of a chain like
|
|
94
|
+
* `content.sections.hero` decides opacity — mirroring how far the
|
|
95
|
+
* source-code renamer can rewrite accesses. When the terminal consumption
|
|
96
|
+
* escapes static tracking, the deepest reached field path is marked opaque
|
|
97
|
+
* so the children of that value keep their original key names.
|
|
87
98
|
*/
|
|
88
|
-
const analyzeOpaqueUsage = (refPath,
|
|
99
|
+
const analyzeOpaqueUsage = (refPath, fieldPath) => {
|
|
89
100
|
const parentNode = refPath.parent;
|
|
90
|
-
|
|
91
|
-
if (babelTypes.
|
|
101
|
+
const parentPath = refPath.parentPath;
|
|
102
|
+
if (parentPath && (babelTypes.isMemberExpression(parentNode) || babelTypes.isOptionalMemberExpression(parentNode)) && parentNode.object === refPath.node) {
|
|
103
|
+
const memberNode = parentNode;
|
|
104
|
+
if (memberNode.computed && babelTypes.isNumericLiteral(memberNode.property)) {
|
|
105
|
+
analyzeOpaqueUsage(parentPath, fieldPath);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (!memberNode.computed && babelTypes.isIdentifier(memberNode.property)) {
|
|
109
|
+
analyzeOpaqueUsage(parentPath, [...fieldPath, memberNode.property.name]);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (memberNode.computed && babelTypes.isStringLiteral(memberNode.property)) {
|
|
113
|
+
analyzeOpaqueUsage(parentPath, [...fieldPath, memberNode.property.value]);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
markOpaqueField(fieldPath, refPath.node.loc?.start.line);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (babelTypes.isVariableDeclarator(parentNode) && babelTypes.isObjectPattern(parentNode.id) && parentNode.init === refPath.node) {
|
|
120
|
+
analyzeOpaqueDestructuring(parentNode.id, refPath, fieldPath);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
92
123
|
if (babelTypes.isArrayExpression(parentNode)) return;
|
|
93
|
-
markOpaqueField(
|
|
124
|
+
markOpaqueField(fieldPath, refPath.node.loc?.start.line);
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Analyses a destructuring pattern applied to the content value at
|
|
128
|
+
* `fieldPath`, recursively following each bound local variable's references
|
|
129
|
+
* via {@link analyzeOpaqueUsage}.
|
|
130
|
+
*
|
|
131
|
+
* Patterns the source-code renamer cannot rewrite (rest elements, dynamic
|
|
132
|
+
* computed keys, array patterns) mark the corresponding path opaque.
|
|
133
|
+
*/
|
|
134
|
+
const analyzeOpaqueDestructuring = (objectPattern, scopePath, fieldPath) => {
|
|
135
|
+
for (const property of objectPattern.properties) {
|
|
136
|
+
if (babelTypes.isRestElement(property)) {
|
|
137
|
+
markOpaqueField(fieldPath, property.loc?.start.line);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
if (!babelTypes.isObjectProperty(property)) continue;
|
|
141
|
+
if (property.computed && !babelTypes.isStringLiteral(property.key)) {
|
|
142
|
+
markOpaqueField(fieldPath, property.loc?.start.line);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
const keyName = babelTypes.isIdentifier(property.key) ? property.key.name : babelTypes.isStringLiteral(property.key) ? property.key.value : null;
|
|
146
|
+
if (!keyName) continue;
|
|
147
|
+
const childFieldPath = [...fieldPath, keyName];
|
|
148
|
+
const bindingTarget = babelTypes.isAssignmentPattern(property.value) ? property.value.left : property.value;
|
|
149
|
+
if (babelTypes.isObjectPattern(bindingTarget)) {
|
|
150
|
+
analyzeOpaqueDestructuring(bindingTarget, scopePath, childFieldPath);
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (babelTypes.isIdentifier(bindingTarget)) {
|
|
154
|
+
const localVarBinding = scopePath.scope.getBinding(bindingTarget.name);
|
|
155
|
+
if (!localVarBinding) continue;
|
|
156
|
+
for (const referencePath of localVarBinding.referencePaths) analyzeOpaqueUsage(referencePath, childFieldPath);
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
markOpaqueField(childFieldPath, property.loc?.start.line);
|
|
160
|
+
}
|
|
94
161
|
};
|
|
95
162
|
/**
|
|
96
163
|
* Helper to collect field names from an ObjectPattern (destructuring).
|
|
97
|
-
* Returns true if successful, false
|
|
164
|
+
* Returns true if successful, false when the accessed fields cannot be
|
|
165
|
+
* determined statically (rest element or dynamic computed key → 'all').
|
|
98
166
|
*/
|
|
99
167
|
const collectFieldsFromObjectPattern = (pattern, initPath, targetSet) => {
|
|
100
168
|
if (pattern.properties.some((prop) => babelTypes.isRestElement(prop))) return false;
|
|
101
169
|
for (const property of pattern.properties) {
|
|
170
|
+
if (!babelTypes.isObjectProperty(property)) continue;
|
|
171
|
+
if (property.computed && !babelTypes.isStringLiteral(property.key)) return false;
|
|
102
172
|
let fieldName;
|
|
103
|
-
if (
|
|
104
|
-
else if (babelTypes.
|
|
105
|
-
if (fieldName)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
173
|
+
if (!property.computed && babelTypes.isIdentifier(property.key)) fieldName = property.key.name;
|
|
174
|
+
else if (babelTypes.isStringLiteral(property.key)) fieldName = property.key.value;
|
|
175
|
+
if (!fieldName) continue;
|
|
176
|
+
targetSet.add(fieldName);
|
|
177
|
+
const bindingTarget = babelTypes.isAssignmentPattern(property.value) ? property.value.left : property.value;
|
|
178
|
+
if (babelTypes.isIdentifier(bindingTarget)) {
|
|
179
|
+
const variableBinding = initPath.scope.getBinding(bindingTarget.name);
|
|
180
|
+
if (variableBinding) for (const refPath of variableBinding.referencePaths) analyzeOpaqueUsage(refPath, [fieldName]);
|
|
181
|
+
} else if (babelTypes.isObjectPattern(bindingTarget)) analyzeOpaqueDestructuring(bindingTarget, initPath, [fieldName]);
|
|
182
|
+
else markOpaqueField([fieldName], property.loc?.start.line);
|
|
112
183
|
}
|
|
113
184
|
return true;
|
|
114
185
|
};
|
|
@@ -123,9 +194,9 @@ const analyzeCallExpressionUsage = (babelTypes, pruneContext, callExpressionPath
|
|
|
123
194
|
if (!parentNode.computed && babelTypes.isIdentifier(parentNode.property)) fieldName = parentNode.property.name;
|
|
124
195
|
else if (parentNode.computed && babelTypes.isStringLiteral(parentNode.property)) fieldName = parentNode.property.value;
|
|
125
196
|
if (fieldName) {
|
|
126
|
-
recordFieldUsage(pruneContext, dictionaryKey, new Set([fieldName]));
|
|
197
|
+
recordFieldUsage(pruneContext, dictionaryKey, /* @__PURE__ */ new Set([fieldName]));
|
|
127
198
|
const memberExprPath = callExpressionPath.parentPath;
|
|
128
|
-
if (memberExprPath) analyzeOpaqueUsage(memberExprPath, fieldName);
|
|
199
|
+
if (memberExprPath) analyzeOpaqueUsage(memberExprPath, [fieldName]);
|
|
129
200
|
} else markUntrackedBinding();
|
|
130
201
|
return;
|
|
131
202
|
}
|
|
@@ -148,7 +219,7 @@ const analyzeCallExpressionUsage = (babelTypes, pruneContext, callExpressionPath
|
|
|
148
219
|
if (fieldName) {
|
|
149
220
|
accessedTopLevelFieldNames.add(fieldName);
|
|
150
221
|
const memberExprPath = variableReferencePath.parentPath;
|
|
151
|
-
if (memberExprPath) analyzeOpaqueUsage(memberExprPath, fieldName);
|
|
222
|
+
if (memberExprPath) analyzeOpaqueUsage(memberExprPath, [fieldName]);
|
|
152
223
|
} else {
|
|
153
224
|
hasUntrackedReferenceAccess = true;
|
|
154
225
|
break;
|
|
@@ -167,7 +238,7 @@ const analyzeCallExpressionUsage = (babelTypes, pruneContext, callExpressionPath
|
|
|
167
238
|
if (fieldName) {
|
|
168
239
|
accessedTopLevelFieldNames.add(fieldName);
|
|
169
240
|
const memberExprPath = callExprPath?.parentPath;
|
|
170
|
-
if (memberExprPath) analyzeOpaqueUsage(memberExprPath, fieldName);
|
|
241
|
+
if (memberExprPath) analyzeOpaqueUsage(memberExprPath, [fieldName]);
|
|
171
242
|
} else {
|
|
172
243
|
hasUntrackedReferenceAccess = true;
|
|
173
244
|
break;
|
|
@@ -252,9 +323,9 @@ const readJsxAttributeString = (babelTypes, openingElement, attributeName) => {
|
|
|
252
323
|
};
|
|
253
324
|
/**
|
|
254
325
|
* Resolves the namespace (dictionary key) for a compat caller call-site from
|
|
255
|
-
*
|
|
256
|
-
*
|
|
257
|
-
*
|
|
326
|
+
* one `CallerValueSource`. Returns the static key, or `'__default__'` when the
|
|
327
|
+
* configured argument is absent (caller falls back to its default namespace),
|
|
328
|
+
* or `undefined` when the value is present but dynamic.
|
|
258
329
|
*/
|
|
259
330
|
const resolveCompatNamespace = (babelTypes, callArguments, source) => {
|
|
260
331
|
if (source.from === "fixed") return source.value;
|
|
@@ -285,13 +356,28 @@ const resolveCompatNamespace = (babelTypes, callArguments, source) => {
|
|
|
285
356
|
return readObjectProperty(babelTypes, optionsArgument, source.property);
|
|
286
357
|
};
|
|
287
358
|
/**
|
|
359
|
+
* Resolves the namespace from a list of `CallerValueSource`s, tried in
|
|
360
|
+
* declaration order. The first source yielding a static string wins.
|
|
361
|
+
* Returns `'__default__'` when every source reports an absent value, and
|
|
362
|
+
* `undefined` when the namespace is present somewhere but dynamic.
|
|
363
|
+
*/
|
|
364
|
+
const resolveNamespaceFromSources = (babelTypes, callArguments, sources) => {
|
|
365
|
+
let sawAbsentValue = false;
|
|
366
|
+
for (const source of sources) {
|
|
367
|
+
const resolved = resolveCompatNamespace(babelTypes, callArguments, source);
|
|
368
|
+
if (typeof resolved === "string" && resolved !== "__default__") return resolved;
|
|
369
|
+
if (resolved === "__default__") sawAbsentValue = true;
|
|
370
|
+
}
|
|
371
|
+
return sawAbsentValue ? "__default__" : void 0;
|
|
372
|
+
};
|
|
373
|
+
/**
|
|
288
374
|
* Resolves an optional `keyPrefix` for a compat caller. Returns the static
|
|
289
375
|
* prefix string, `null` when no prefix is configured/present, or `undefined`
|
|
290
376
|
* when a prefix is present but dynamic.
|
|
291
377
|
*/
|
|
292
|
-
const resolveCompatKeyPrefix = (babelTypes, callArguments,
|
|
293
|
-
if (!
|
|
294
|
-
const resolved =
|
|
378
|
+
const resolveCompatKeyPrefix = (babelTypes, callArguments, sources) => {
|
|
379
|
+
if (!sources || sources.length === 0) return null;
|
|
380
|
+
const resolved = resolveNamespaceFromSources(babelTypes, callArguments, sources);
|
|
295
381
|
if (resolved === "__default__") return null;
|
|
296
382
|
return resolved;
|
|
297
383
|
};
|
|
@@ -317,8 +403,8 @@ const unwrapAwait = (babelTypes, path) => {
|
|
|
317
403
|
* so renaming the compiled JSON keys would break runtime lookups. Pruning
|
|
318
404
|
* (top-level field removal) remains safe because it preserves field names.
|
|
319
405
|
*/
|
|
320
|
-
const analyzeNamespaceCallerUsage = (babelTypes, pruneContext, callArguments, callerConfig, isSfcFile, callExpressionPath) => {
|
|
321
|
-
const resolvedNamespace =
|
|
406
|
+
const analyzeNamespaceCallerUsage = (babelTypes, pruneContext, callArguments, callerConfig, isSfcFile, currentSourceFilePath, callExpressionPath, namespaceOverride) => {
|
|
407
|
+
const resolvedNamespace = namespaceOverride ?? resolveNamespaceFromSources(babelTypes, callArguments, callerConfig.namespaceSources);
|
|
322
408
|
if (resolvedNamespace === void 0) return;
|
|
323
409
|
const namespaceString = resolvedNamespace === "__default__" ? DEFAULT_COMPAT_NAMESPACE : resolvedNamespace;
|
|
324
410
|
const namespaceSegments = namespaceString.split(".");
|
|
@@ -333,13 +419,18 @@ const analyzeNamespaceCallerUsage = (babelTypes, pruneContext, callArguments, ca
|
|
|
333
419
|
recordFieldUsage(pruneContext, dictionaryKey, "all");
|
|
334
420
|
return;
|
|
335
421
|
}
|
|
422
|
+
if (callerConfig.translationFunction === "content") {
|
|
423
|
+
if (callExpressionPath) analyzeCallExpressionUsage(babelTypes, pruneContext, callExpressionPath, dictionaryKey, currentSourceFilePath, isSfcFile);
|
|
424
|
+
else recordFieldUsage(pruneContext, dictionaryKey, "all");
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
336
427
|
if (callerConfig.translationFunction === "self") {
|
|
337
428
|
const firstArg = callArguments[0];
|
|
338
429
|
if (!firstArg) {
|
|
339
430
|
recordFieldUsage(pruneContext, dictionaryKey, "all");
|
|
340
431
|
return;
|
|
341
432
|
}
|
|
342
|
-
if (callerConfig.
|
|
433
|
+
if (callerConfig.namespaceSources.some((source) => source.from === "path-first-segment")) {
|
|
343
434
|
let fullId;
|
|
344
435
|
const staticString = readStaticString(babelTypes, firstArg);
|
|
345
436
|
if (staticString !== void 0) fullId = staticString;
|
|
@@ -349,22 +440,22 @@ const analyzeNamespaceCallerUsage = (babelTypes, pruneContext, callArguments, ca
|
|
|
349
440
|
}
|
|
350
441
|
if (fullId !== void 0) {
|
|
351
442
|
const field = fullId.split(".")[1];
|
|
352
|
-
if (field !== void 0) recordFieldUsage(pruneContext, dictionaryKey, new Set([field]));
|
|
443
|
+
if (field !== void 0) recordFieldUsage(pruneContext, dictionaryKey, /* @__PURE__ */ new Set([field]));
|
|
353
444
|
else recordFieldUsage(pruneContext, dictionaryKey, "all");
|
|
354
445
|
return;
|
|
355
446
|
}
|
|
356
447
|
recordFieldUsage(pruneContext, dictionaryKey, "all");
|
|
357
448
|
return;
|
|
358
449
|
}
|
|
359
|
-
const segment = readStaticFirstSegment(babelTypes, firstArg);
|
|
450
|
+
const segment = callerConfig.flatKey ? readStaticString(babelTypes, firstArg) : readStaticFirstSegment(babelTypes, firstArg);
|
|
360
451
|
if (segment !== void 0) {
|
|
361
|
-
recordFieldUsage(pruneContext, dictionaryKey, new Set([segment]));
|
|
452
|
+
recordFieldUsage(pruneContext, dictionaryKey, /* @__PURE__ */ new Set([segment]));
|
|
362
453
|
return;
|
|
363
454
|
}
|
|
364
455
|
if (babelTypes.isObjectExpression(firstArg)) {
|
|
365
456
|
const idValue = readObjectProperty(babelTypes, firstArg, "id");
|
|
366
457
|
if (idValue !== void 0 && idValue !== "__default__") {
|
|
367
|
-
recordFieldUsage(pruneContext, dictionaryKey, new Set([firstPathSegment(idValue)]));
|
|
458
|
+
recordFieldUsage(pruneContext, dictionaryKey, /* @__PURE__ */ new Set([callerConfig.flatKey ? idValue : firstPathSegment(idValue)]));
|
|
368
459
|
return;
|
|
369
460
|
}
|
|
370
461
|
}
|
|
@@ -375,14 +466,14 @@ const analyzeNamespaceCallerUsage = (babelTypes, pruneContext, callArguments, ca
|
|
|
375
466
|
recordFieldUsage(pruneContext, dictionaryKey, "all");
|
|
376
467
|
return;
|
|
377
468
|
}
|
|
378
|
-
const explicitKeyPrefix = resolveCompatKeyPrefix(babelTypes, callArguments, callerConfig.
|
|
469
|
+
const explicitKeyPrefix = resolveCompatKeyPrefix(babelTypes, callArguments, callerConfig.keyPrefixSources);
|
|
379
470
|
if (explicitKeyPrefix === void 0) {
|
|
380
471
|
recordFieldUsage(pruneContext, dictionaryKey, "all");
|
|
381
472
|
return;
|
|
382
473
|
}
|
|
383
474
|
const effectivePrefix = namespacePrefix ?? explicitKeyPrefix;
|
|
384
475
|
if (effectivePrefix !== null) {
|
|
385
|
-
recordFieldUsage(pruneContext, dictionaryKey, new Set([firstPathSegment(effectivePrefix)]));
|
|
476
|
+
recordFieldUsage(pruneContext, dictionaryKey, /* @__PURE__ */ new Set([firstPathSegment(effectivePrefix)]));
|
|
386
477
|
return;
|
|
387
478
|
}
|
|
388
479
|
let translationBinding = null;
|
|
@@ -444,9 +535,10 @@ const makeUsageAnalyzerBabelPlugin = (pruneContext, options) => ({ types: babelT
|
|
|
444
535
|
const isSfcFile = currentSourceFilePath.endsWith(".vue") || currentSourceFilePath.endsWith(".svelte") || currentSourceFilePath.endsWith(".astro");
|
|
445
536
|
const intlayerCallerLocalNameMap = /* @__PURE__ */ new Map();
|
|
446
537
|
const compatCallerLocalNameMap = /* @__PURE__ */ new Map();
|
|
447
|
-
const
|
|
538
|
+
const fileImportSources = /* @__PURE__ */ new Set();
|
|
448
539
|
programPath.traverse({ ImportDeclaration: (importDeclarationPath) => {
|
|
449
540
|
const importSource = importDeclarationPath.node.source.value;
|
|
541
|
+
fileImportSources.add(importSource);
|
|
450
542
|
for (const importSpecifier of importDeclarationPath.node.specifiers) {
|
|
451
543
|
if (!babelTypes.isImportSpecifier(importSpecifier)) continue;
|
|
452
544
|
const importedName = babelTypes.isIdentifier(importSpecifier.imported) ? importSpecifier.imported.name : importSpecifier.imported.value;
|
|
@@ -458,6 +550,7 @@ const makeUsageAnalyzerBabelPlugin = (pruneContext, options) => ({ types: babelT
|
|
|
458
550
|
if (compatCaller) compatCallerLocalNameMap.set(importSpecifier.local.name, compatCaller);
|
|
459
551
|
}
|
|
460
552
|
} });
|
|
553
|
+
const methodCompatCallers = compatCallers.filter((caller) => caller.matchAsMethod && (!caller.requiresImport || caller.importSources.some((source) => fileImportSources.has(source))));
|
|
461
554
|
const hasNativeCallers = intlayerCallerLocalNameMap.size > 0;
|
|
462
555
|
const hasCompatCallers = compatCallerLocalNameMap.size > 0 || methodCompatCallers.length > 0;
|
|
463
556
|
if (!hasNativeCallers && !hasCompatCallers) return;
|
|
@@ -482,12 +575,12 @@ const makeUsageAnalyzerBabelPlugin = (pruneContext, options) => ({ types: babelT
|
|
|
482
575
|
}
|
|
483
576
|
const importedCompatCaller = compatCallerLocalNameMap.get(localCallerName);
|
|
484
577
|
if (importedCompatCaller && !isMethodCall) {
|
|
485
|
-
analyzeNamespaceCallerUsage(babelTypes, pruneContext, callExpressionPath.node.arguments, importedCompatCaller, isSfcFile, callExpressionPath);
|
|
578
|
+
analyzeNamespaceCallerUsage(babelTypes, pruneContext, callExpressionPath.node.arguments, importedCompatCaller, isSfcFile, currentSourceFilePath, callExpressionPath);
|
|
486
579
|
return;
|
|
487
580
|
}
|
|
488
581
|
if (isMethodCall) {
|
|
489
582
|
const methodCaller = methodCompatCallers.find((caller) => caller.callerName === localCallerName);
|
|
490
|
-
if (methodCaller) analyzeNamespaceCallerUsage(babelTypes, pruneContext, callExpressionPath.node.arguments, methodCaller, isSfcFile, callExpressionPath);
|
|
583
|
+
if (methodCaller) analyzeNamespaceCallerUsage(babelTypes, pruneContext, callExpressionPath.node.arguments, methodCaller, isSfcFile, currentSourceFilePath, callExpressionPath);
|
|
491
584
|
}
|
|
492
585
|
},
|
|
493
586
|
JSXOpeningElement: (jsxOpeningElementPath) => {
|
|
@@ -496,7 +589,13 @@ const makeUsageAnalyzerBabelPlugin = (pruneContext, options) => ({ types: babelT
|
|
|
496
589
|
const jsxCaller = compatCallerLocalNameMap.get(nameNode.name);
|
|
497
590
|
if (!jsxCaller?.jsxIdAttribute) return;
|
|
498
591
|
const idNode = readJsxAttributeString(babelTypes, jsxOpeningElementPath.node, jsxCaller.jsxIdAttribute);
|
|
499
|
-
|
|
592
|
+
let namespaceOverride;
|
|
593
|
+
if (jsxCaller.jsxNamespaceAttribute) {
|
|
594
|
+
const namespaceNode = readJsxAttributeString(babelTypes, jsxOpeningElementPath.node, jsxCaller.jsxNamespaceAttribute);
|
|
595
|
+
if (!namespaceNode) return;
|
|
596
|
+
namespaceOverride = namespaceNode.value;
|
|
597
|
+
}
|
|
598
|
+
analyzeNamespaceCallerUsage(babelTypes, pruneContext, idNode ? [idNode] : [], jsxCaller, isSfcFile, currentSourceFilePath, void 0, namespaceOverride);
|
|
500
599
|
}
|
|
501
600
|
});
|
|
502
601
|
} } }
|