vue-i18n-extract-plugin 1.0.50 → 1.0.51
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 +114 -4
- package/package.json +1 -1
package/lib/visitors.js
CHANGED
|
@@ -15,6 +15,84 @@ function isTFunction(node, option) {
|
|
|
15
15
|
);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
function isCreateTextVNodeCall(path) {
|
|
19
|
+
const node = path.node;
|
|
20
|
+
if (!path.isCallExpression()) return false;
|
|
21
|
+
|
|
22
|
+
const callee = node.callee;
|
|
23
|
+
return (
|
|
24
|
+
(t.isIdentifier(callee) && callee.name === "_createTextVNode") ||
|
|
25
|
+
(t.isMemberExpression(callee) &&
|
|
26
|
+
t.isIdentifier(callee.property) &&
|
|
27
|
+
callee.property.name === "_createTextVNode")
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function getPropKey(propNode) {
|
|
32
|
+
if (t.isIdentifier(propNode.key)) {
|
|
33
|
+
return propNode.key.name;
|
|
34
|
+
}
|
|
35
|
+
if (t.isStringLiteral(propNode.key)) {
|
|
36
|
+
return propNode.key.value; // .replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function transformDirectiveIfNeeded(path, parentPath) {
|
|
42
|
+
let hasCreateVNode = false;
|
|
43
|
+
// 属性值情况,如 title: "xxx"
|
|
44
|
+
if (parentPath.isObjectProperty()) {
|
|
45
|
+
const propKey = getPropKey(parentPath.node);
|
|
46
|
+
|
|
47
|
+
if (!propKey) return;
|
|
48
|
+
|
|
49
|
+
const vNodeCall = path.findParent(
|
|
50
|
+
p =>
|
|
51
|
+
p.isCallExpression() &&
|
|
52
|
+
(t.isIdentifier(p.node.callee, { name: "_createVNode" }) ||
|
|
53
|
+
(t.isMemberExpression(p.node.callee) &&
|
|
54
|
+
t.isIdentifier(p.node.callee.property, { name: "_createVNode" })))
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
if (vNodeCall) {
|
|
58
|
+
hasCreateVNode = true;
|
|
59
|
+
const args = vNodeCall.node.arguments;
|
|
60
|
+
// PatchFlag = 8 (PROPS), dynamicProps = ["title"]
|
|
61
|
+
const patchFlagIndex = 3;
|
|
62
|
+
const dynamicPropsIndex = 4;
|
|
63
|
+
|
|
64
|
+
// 确保第 3 个参数(children)存在,否则补 null
|
|
65
|
+
if (args.length === 2) {
|
|
66
|
+
args.push(t.nullLiteral()); // => 第三个参数
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 补齐参数数组长度到第 5 个参数(index: 4)
|
|
70
|
+
while (args.length <= dynamicPropsIndex) {
|
|
71
|
+
args.push(null);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 设置 patchFlag = 8
|
|
75
|
+
args[patchFlagIndex] = t.numericLiteral(8);
|
|
76
|
+
|
|
77
|
+
// 设置 dynamicProps = ["propKey"]
|
|
78
|
+
const existingDynamicProps = args[dynamicPropsIndex];
|
|
79
|
+
if (!existingDynamicProps || !t.isArrayExpression(existingDynamicProps)) {
|
|
80
|
+
args[dynamicPropsIndex] = t.arrayExpression([t.stringLiteral(propKey)]);
|
|
81
|
+
} else {
|
|
82
|
+
const existingKeys = new Set(
|
|
83
|
+
existingDynamicProps.elements
|
|
84
|
+
.filter(el => t.isStringLiteral(el))
|
|
85
|
+
.map(el => el.value)
|
|
86
|
+
);
|
|
87
|
+
if (!existingKeys.has(propKey)) {
|
|
88
|
+
existingDynamicProps.elements.push(t.stringLiteral(propKey));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return hasCreateVNode;
|
|
94
|
+
}
|
|
95
|
+
|
|
18
96
|
function shouldTransform(path) {
|
|
19
97
|
const parent = path.parentPath;
|
|
20
98
|
return !(
|
|
@@ -112,10 +190,42 @@ function createI18nVisitor(option, i18nMap) {
|
|
|
112
190
|
i18nMap[hashed] = value;
|
|
113
191
|
}
|
|
114
192
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
)
|
|
193
|
+
let callExpression;
|
|
194
|
+
|
|
195
|
+
// 判断是否createTextVNode或MemberExpression(如 Vue.createTextVNode)
|
|
196
|
+
if (isCreateTextVNodeCall(parentPath)) {
|
|
197
|
+
// _ctx.$t("hashed")
|
|
198
|
+
callExpression = t.callExpression(
|
|
199
|
+
t.memberExpression(
|
|
200
|
+
t.identifier("_ctx"),
|
|
201
|
+
t.identifier(option.translateKey)
|
|
202
|
+
),
|
|
203
|
+
[t.stringLiteral(hashed)]
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
// 如果 createTextVNode 参数只有一个,则补充第二个参数 1
|
|
207
|
+
const args = parentPath.node.arguments;
|
|
208
|
+
if (args.length === 1) {
|
|
209
|
+
parentPath.node.arguments = [callExpression, t.numericLiteral(1)];
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
const hasCreateVNode = transformDirectiveIfNeeded(path, parentPath);
|
|
213
|
+
if (hasCreateVNode) {
|
|
214
|
+
callExpression = t.callExpression(
|
|
215
|
+
t.memberExpression(
|
|
216
|
+
t.identifier("_ctx"),
|
|
217
|
+
t.identifier(option.translateKey)
|
|
218
|
+
),
|
|
219
|
+
[t.stringLiteral(hashed)]
|
|
220
|
+
);
|
|
221
|
+
} else {
|
|
222
|
+
// $t("hashed")
|
|
223
|
+
callExpression = t.callExpression(t.identifier(option.translateKey), [
|
|
224
|
+
t.stringLiteral(hashed)
|
|
225
|
+
]);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
119
229
|
// 如果是 JSX 属性值,需要包裹在 JSXExpressionContainer 中
|
|
120
230
|
if (parentPath.isJSXAttribute()) {
|
|
121
231
|
const jsxExpression = t.jsxExpressionContainer(callExpression);
|