vue-i18n-extract-plugin 1.0.70 → 1.0.72
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/visitors.js +90 -4
- package/package.json +1 -1
package/lib/visitors.js
CHANGED
|
@@ -56,6 +56,7 @@ function getPropKey(propNode) {
|
|
|
56
56
|
return null;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
// 将静态属性转换为动态属性,如 <div title="xxx" /> => <div :title="$t('hashed')" />
|
|
59
60
|
function transformDirectiveIfNeeded(path, parentPath) {
|
|
60
61
|
let hasCreateVNode = false;
|
|
61
62
|
// 属性值情况,如 title: "xxx"
|
|
@@ -152,6 +153,77 @@ function generateJSXElement(name, id, msg) {
|
|
|
152
153
|
return t.jsxElement(openingElement, null, [], true);
|
|
153
154
|
}
|
|
154
155
|
|
|
156
|
+
function unwrapVueCacheIfNeeded(path) {
|
|
157
|
+
const assignPath = path.parentPath;
|
|
158
|
+
if (!assignPath || !assignPath.isAssignmentExpression({ operator: "=" })) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const logicalPath = assignPath.parentPath;
|
|
163
|
+
if (!logicalPath || !logicalPath.isLogicalExpression({ operator: "||" })) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const { left, right } = logicalPath.node;
|
|
168
|
+
|
|
169
|
+
// 校验 left: _cache[x]
|
|
170
|
+
const isCacheMember =
|
|
171
|
+
t.isMemberExpression(left) &&
|
|
172
|
+
(t.isIdentifier(left.object, { name: "_cache" }) ||
|
|
173
|
+
(t.isIdentifier(left.object) && left.object.name.startsWith("_cache")));
|
|
174
|
+
|
|
175
|
+
// 校验 right: (_cache[x] = createTextVNode(...))
|
|
176
|
+
const isSameAssignment =
|
|
177
|
+
right === assignPath.node &&
|
|
178
|
+
t.isMemberExpression(assignPath.node.left) &&
|
|
179
|
+
t.isCallExpression(assignPath.node.right);
|
|
180
|
+
|
|
181
|
+
if (!isCacheMember || !isSameAssignment) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// 用 createTextVNode(...) 替换整个 _cache || (...)
|
|
186
|
+
logicalPath.replaceWith(assignPath.node.right);
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function unwrapVueSlotArrayCache(path) {
|
|
191
|
+
// 1. 找 ArrayExpression
|
|
192
|
+
const arrayPath = path.findParent(p => p.isArrayExpression());
|
|
193
|
+
if (!arrayPath) return false;
|
|
194
|
+
|
|
195
|
+
// 2. array 是 assignment 的 right
|
|
196
|
+
const assignPath = arrayPath.parentPath;
|
|
197
|
+
if (!assignPath?.isAssignmentExpression({ operator: "=" })) return false;
|
|
198
|
+
|
|
199
|
+
// 3. assignment 在 LogicalExpression || 中
|
|
200
|
+
const logicalPath = assignPath.parentPath;
|
|
201
|
+
if (!logicalPath?.isLogicalExpression({ operator: "||" })) return false;
|
|
202
|
+
|
|
203
|
+
// 4. logical 在 SpreadElement 中
|
|
204
|
+
const spreadPath = logicalPath.parentPath;
|
|
205
|
+
if (!spreadPath?.isSpreadElement()) return false;
|
|
206
|
+
|
|
207
|
+
// 5. 校验 _cache[x]
|
|
208
|
+
const left = logicalPath.node.left;
|
|
209
|
+
const isCache =
|
|
210
|
+
t.isMemberExpression(left) &&
|
|
211
|
+
t.isIdentifier(left.object) &&
|
|
212
|
+
left.object.name.startsWith("_cache");
|
|
213
|
+
|
|
214
|
+
if (!isCache) return false;
|
|
215
|
+
|
|
216
|
+
// unwrap:用 array.elements 替换 spread(...)
|
|
217
|
+
spreadPath.replaceWithMultiple(arrayPath.node.elements);
|
|
218
|
+
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function isDynamicTextExpression(node) {
|
|
223
|
+
// 只要不是 StringLiteral,100% 是动态文本
|
|
224
|
+
return !t.isStringLiteral(node);
|
|
225
|
+
}
|
|
226
|
+
|
|
155
227
|
function createI18nVisitor(option, i18nMap) {
|
|
156
228
|
const excludedCall = [...option.excludedCall, ...EXCLUDED_CALL];
|
|
157
229
|
|
|
@@ -189,7 +261,19 @@ function createI18nVisitor(option, i18nMap) {
|
|
|
189
261
|
path.node.arguments.push(t.stringLiteral(keyText));
|
|
190
262
|
}
|
|
191
263
|
},
|
|
264
|
+
CallExpression(path) {
|
|
265
|
+
if (!isVNodeCall(path, "_createTextVNode")) return;
|
|
266
|
+
|
|
267
|
+
const args = path.node.arguments;
|
|
268
|
+
if (!args.length) return;
|
|
192
269
|
|
|
270
|
+
const content = args[0];
|
|
271
|
+
|
|
272
|
+
// 是否动态文本
|
|
273
|
+
if (isDynamicTextExpression(content)) {
|
|
274
|
+
args[1] = t.numericLiteral(1); // PatchFlags.TEXT createTextVNode(" " + toDisplayString$1(text)) => createTextVNode(" " + toDisplayString$1(text), 1)
|
|
275
|
+
}
|
|
276
|
+
},
|
|
193
277
|
StringLiteral(path) {
|
|
194
278
|
if (option.extractFromText === false) return;
|
|
195
279
|
if (!shouldTransform(path)) return;
|
|
@@ -255,10 +339,12 @@ function createI18nVisitor(option, i18nMap) {
|
|
|
255
339
|
|
|
256
340
|
// 判断是否createTextVNode或MemberExpression(如 Vue.createTextVNode)
|
|
257
341
|
if (isVNodeCall(parentPath, "_createTextVNode")) {
|
|
258
|
-
//
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
342
|
+
// createTextVNode强制补充第二个参数 1
|
|
343
|
+
parentPath.node.arguments = [callExpression, t.numericLiteral(1)];
|
|
344
|
+
// 先尝试 [...(_cache2[4] || (_cache2[4] = [ createTextVNode(...) ]))]
|
|
345
|
+
if (!unwrapVueSlotArrayCache(parentPath)) {
|
|
346
|
+
// 再尝试拆 _cache2[0] || (_cache2[0] = createTextVNode(...))
|
|
347
|
+
unwrapVueCacheIfNeeded(parentPath);
|
|
262
348
|
}
|
|
263
349
|
// 是否 vue.createElementVNode(...),且该 StringLiteral 是第三个参数
|
|
264
350
|
} else if (isVNodeCall(parentPath, "_createElementVNode")) {
|