@vitarx/plugin-vite 1.0.0-beta.0 → 1.0.0-beta.1
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/passes/directives/index.d.ts +1 -1
- package/dist/passes/directives/index.js +1 -1
- package/dist/passes/directives/vIf.d.ts +13 -6
- package/dist/passes/directives/vIf.js +24 -22
- package/dist/passes/jsx/processJSXElement.js +4 -2
- package/dist/transform.js +3 -0
- package/dist/utils/jsx-helpers.d.ts +4 -0
- package/dist/utils/jsx-helpers.js +12 -9
- package/package.json +1 -1
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* v-if 链处理器
|
|
3
|
-
* 处理 Fragment 中的 v-if/v-else-if/v-else 链
|
|
3
|
+
* 处理 Fragment/Element 中的 v-if/v-else-if/v-else 链
|
|
4
4
|
* @module passes/directives/vIf
|
|
5
5
|
*/
|
|
6
6
|
import type { NodePath } from '@babel/traverse';
|
|
7
7
|
import * as t from '@babel/types';
|
|
8
8
|
import { TransformContext } from '../../context.js';
|
|
9
|
+
type TransformJSXElementFn = (node: t.JSXElement, ctx: TransformContext, handleVIf: boolean) => t.Expression | null;
|
|
10
|
+
type JSXContainerPath = NodePath<t.JSXFragment | t.JSXElement>;
|
|
9
11
|
/**
|
|
10
|
-
*
|
|
12
|
+
* 处理子元素数组中的 v-if 链
|
|
13
|
+
* 收集并转换 v-if/v-else-if/v-else 链为 branch 调用
|
|
14
|
+
* @param children - 子元素数组(会被原地修改)
|
|
15
|
+
* @param ctx - 转换上下文
|
|
16
|
+
* @param transformJSXElement - JSX 元素转换函数
|
|
17
|
+
* @returns 处理后的子元素数组(链节点已替换为 branch 调用,nullLiteral 已移除)
|
|
11
18
|
*/
|
|
12
|
-
|
|
19
|
+
export declare function transformChildrenVIfChains(children: t.Node[], ctx: TransformContext, transformJSXElement: TransformJSXElementFn): t.Node[];
|
|
13
20
|
/**
|
|
14
|
-
* 处理 Fragment 中的 v-if 链
|
|
15
|
-
* @param path - JSX Fragment 路径
|
|
21
|
+
* 处理 Fragment/Element 中的 v-if 链
|
|
22
|
+
* @param path - JSX Fragment 或 Element 路径
|
|
16
23
|
* @param ctx - 转换上下文
|
|
17
24
|
* @param transformJSXElement - JSX 元素转换函数
|
|
18
25
|
*/
|
|
19
|
-
export declare function processVIfChain(path:
|
|
26
|
+
export declare function processVIfChain(path: JSXContainerPath, ctx: TransformContext, transformJSXElement: TransformJSXElementFn): void;
|
|
20
27
|
export {};
|
|
@@ -2,29 +2,44 @@ import * as t from '@babel/types';
|
|
|
2
2
|
import { isJSXElement, isJSXText } from '@babel/types';
|
|
3
3
|
import { collectFragmentVIfChains, createArrowFunction, createBranch, isWhitespaceJSXText, removeVIfChainDirectives } from '../../utils/index.js';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* 处理子元素数组中的 v-if 链
|
|
6
|
+
* 收集并转换 v-if/v-else-if/v-else 链为 branch 调用
|
|
7
|
+
* @param children - 子元素数组(会被原地修改)
|
|
7
8
|
* @param ctx - 转换上下文
|
|
8
9
|
* @param transformJSXElement - JSX 元素转换函数
|
|
10
|
+
* @returns 处理后的子元素数组(链节点已替换为 branch 调用,nullLiteral 已移除)
|
|
9
11
|
*/
|
|
10
|
-
export function
|
|
11
|
-
const children = path.node.children;
|
|
12
|
+
export function transformChildrenVIfChains(children, ctx, transformJSXElement) {
|
|
12
13
|
const chains = collectFragmentVIfChains(children);
|
|
13
14
|
if (chains.length === 0)
|
|
14
|
-
return;
|
|
15
|
-
// 从后向前处理链,避免索引偏移问题
|
|
15
|
+
return children;
|
|
16
16
|
for (let c = chains.length - 1; c >= 0; c--) {
|
|
17
17
|
processVIfChainItem(chains[c], children, ctx, transformJSXElement);
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
return children.filter(child => {
|
|
20
|
+
if (t.isNullLiteral(child))
|
|
21
|
+
return false;
|
|
22
|
+
return !(isJSXText(child) && isWhitespaceJSXText(child));
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 处理 Fragment/Element 中的 v-if 链
|
|
27
|
+
* @param path - JSX Fragment 或 Element 路径
|
|
28
|
+
* @param ctx - 转换上下文
|
|
29
|
+
* @param transformJSXElement - JSX 元素转换函数
|
|
30
|
+
*/
|
|
31
|
+
export function processVIfChain(path, ctx, transformJSXElement) {
|
|
32
|
+
const children = path.node.children;
|
|
33
|
+
const processed = transformChildrenVIfChains(children, ctx, transformJSXElement);
|
|
34
|
+
if (processed !== children) {
|
|
35
|
+
path.node.children = processed;
|
|
36
|
+
}
|
|
21
37
|
}
|
|
22
38
|
/**
|
|
23
39
|
* 处理单个 v-if 链
|
|
24
40
|
*/
|
|
25
41
|
function processVIfChainItem(chain, children, ctx, transformJSXElement) {
|
|
26
42
|
const { nodes, conditions, endIndex } = chain;
|
|
27
|
-
// 计算链在 children 中的起始位置
|
|
28
43
|
let start = -1;
|
|
29
44
|
for (let i = 0; i < children.length; i++) {
|
|
30
45
|
const child = children[i];
|
|
@@ -33,7 +48,6 @@ function processVIfChainItem(chain, children, ctx, transformJSXElement) {
|
|
|
33
48
|
break;
|
|
34
49
|
}
|
|
35
50
|
}
|
|
36
|
-
// 移除指令并转换节点
|
|
37
51
|
const branches = [];
|
|
38
52
|
for (const node of nodes) {
|
|
39
53
|
removeVIfChainDirectives(node);
|
|
@@ -42,9 +56,7 @@ function processVIfChainItem(chain, children, ctx, transformJSXElement) {
|
|
|
42
56
|
branches.push(createArrowFunction(transformedNode));
|
|
43
57
|
}
|
|
44
58
|
}
|
|
45
|
-
// 生成 branch 调用
|
|
46
59
|
const branchCall = createBranch({ conditions, branches }, ctx);
|
|
47
|
-
// 替换链的第一个节点,其他节点标记为 null
|
|
48
60
|
if (start >= 0) {
|
|
49
61
|
children[start] = branchCall;
|
|
50
62
|
for (let k = start + 1; k <= endIndex; k++) {
|
|
@@ -52,13 +64,3 @@ function processVIfChainItem(chain, children, ctx, transformJSXElement) {
|
|
|
52
64
|
}
|
|
53
65
|
}
|
|
54
66
|
}
|
|
55
|
-
/**
|
|
56
|
-
* 清理已处理的子节点
|
|
57
|
-
*/
|
|
58
|
-
function cleanupProcessedChildren(path, children) {
|
|
59
|
-
path.node.children = children.filter(child => {
|
|
60
|
-
if (t.isNullLiteral(child))
|
|
61
|
-
return false;
|
|
62
|
-
return !(isJSXText(child) && isWhitespaceJSXText(child));
|
|
63
|
-
});
|
|
64
|
-
}
|
|
@@ -3,7 +3,7 @@ import { isJSXElement } from '@babel/types';
|
|
|
3
3
|
import { addWarning, markImport } from '../../context.js';
|
|
4
4
|
import { createError, createWarning } from '../../error.js';
|
|
5
5
|
import { addPureComment, createArrowFunction, createBranch, createCreateViewCall, filterEffectiveChildren, getAlias, getDevLocInfo, getDirectiveValue, getJSXAttributeByName, getJSXElementName, hasEffectiveChildren, isNativeElement, isVElse, isVIf, isVIfChain, removeVIfChainDirectives } from '../../utils/index.js';
|
|
6
|
-
import { processDirectives } from '../directives/index.js';
|
|
6
|
+
import { processDirectives, transformChildrenVIfChains } from '../directives/index.js';
|
|
7
7
|
import { processProps } from '../props/index.js';
|
|
8
8
|
import { processChildren } from './processChildren.js';
|
|
9
9
|
/**
|
|
@@ -123,8 +123,10 @@ function processElementChildren(node, props, ctx) {
|
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
|
+
// 处理子元素中的 v-if 链(确保嵌套链在 transformJSXElement 递归调用时被正确处理)
|
|
127
|
+
const chainProcessed = transformChildrenVIfChains(children, ctx, transformJSXElement);
|
|
126
128
|
// 处理子元素
|
|
127
|
-
const processedChildren = processChildren(
|
|
129
|
+
const processedChildren = processChildren(chainProcessed, ctx);
|
|
128
130
|
const childrenValue = processedChildren.length === 1 ? processedChildren[0] : t.arrayExpression(processedChildren);
|
|
129
131
|
// 添加 children 属性
|
|
130
132
|
if (props) {
|
package/dist/transform.js
CHANGED
|
@@ -26,10 +26,13 @@ export declare function isNativeElement(name: string): boolean;
|
|
|
26
26
|
export declare function getJSXAttributeByName(node: JSXElement, name: string): JSXAttribute | undefined;
|
|
27
27
|
/**
|
|
28
28
|
* 检查元素是否具有指定指令
|
|
29
|
+
* v-if/v-else-if/v-else 仅支持 JSXIdentifier 格式(v-if),不支持命名空间格式(v:if)
|
|
30
|
+
* 其他指令(如 v-show)支持 v-xxx:arg 命名空间格式
|
|
29
31
|
*/
|
|
30
32
|
export declare function hasDirective(node: JSXElement, directiveName: string): boolean;
|
|
31
33
|
/**
|
|
32
34
|
* 获取指令的值
|
|
35
|
+
* v-if/v-else-if/v-else 仅支持 JSXIdentifier 格式(v-if),不支持命名空间格式(v:if)
|
|
33
36
|
*/
|
|
34
37
|
export declare function getDirectiveValue(node: JSXElement, directiveName: string): Expression | null;
|
|
35
38
|
/**
|
|
@@ -54,6 +57,7 @@ export declare function isVElse(node: JSXElement): boolean;
|
|
|
54
57
|
export declare function removeVDirectives(node: JSXElement): void;
|
|
55
58
|
/**
|
|
56
59
|
* 移除元素上的 v-if 链指令(v-if、v-else-if、v-else)
|
|
60
|
+
* 仅处理 JSXIdentifier 格式,不支持命名空间格式(v:if)
|
|
57
61
|
*/
|
|
58
62
|
export declare function removeVIfChainDirectives(node: JSXElement): void;
|
|
59
63
|
/**
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
import * as t from '@babel/types';
|
|
6
6
|
import { isJSXElement, isJSXText } from '@babel/types';
|
|
7
7
|
import { DIRECTIVE_PREFIX, PURE_COMPILE_COMPONENTS } from '../constants/index.js';
|
|
8
|
-
import { isWhitespaceJSXText } from './ast-guards.js';
|
|
9
8
|
import { createError } from '../error.js';
|
|
9
|
+
import { isWhitespaceJSXText } from './ast-guards.js';
|
|
10
10
|
/**
|
|
11
11
|
* 获取 JSX 元素的名称
|
|
12
12
|
*/
|
|
@@ -45,14 +45,19 @@ export function getJSXAttributeByName(node, name) {
|
|
|
45
45
|
}
|
|
46
46
|
return undefined;
|
|
47
47
|
}
|
|
48
|
+
const V_IF_CHAIN_DIRECTIVES = new Set(['v-if', 'v-else-if', 'v-else']);
|
|
48
49
|
/**
|
|
49
50
|
* 检查元素是否具有指定指令
|
|
51
|
+
* v-if/v-else-if/v-else 仅支持 JSXIdentifier 格式(v-if),不支持命名空间格式(v:if)
|
|
52
|
+
* 其他指令(如 v-show)支持 v-xxx:arg 命名空间格式
|
|
50
53
|
*/
|
|
51
54
|
export function hasDirective(node, directiveName) {
|
|
52
55
|
for (const attr of node.openingElement.attributes) {
|
|
53
56
|
if (attr.type === 'JSXAttribute') {
|
|
54
57
|
const attrName = attr.name;
|
|
55
58
|
if (attrName.type === 'JSXNamespacedName') {
|
|
59
|
+
if (V_IF_CHAIN_DIRECTIVES.has(directiveName))
|
|
60
|
+
continue;
|
|
56
61
|
if (attrName.namespace.name === 'v' && attrName.name.name === directiveName.slice(2)) {
|
|
57
62
|
return true;
|
|
58
63
|
}
|
|
@@ -66,6 +71,7 @@ export function hasDirective(node, directiveName) {
|
|
|
66
71
|
}
|
|
67
72
|
/**
|
|
68
73
|
* 获取指令的值
|
|
74
|
+
* v-if/v-else-if/v-else 仅支持 JSXIdentifier 格式(v-if),不支持命名空间格式(v:if)
|
|
69
75
|
*/
|
|
70
76
|
export function getDirectiveValue(node, directiveName) {
|
|
71
77
|
for (const attr of node.openingElement.attributes) {
|
|
@@ -73,6 +79,8 @@ export function getDirectiveValue(node, directiveName) {
|
|
|
73
79
|
const attrName = attr.name;
|
|
74
80
|
let matches = false;
|
|
75
81
|
if (attrName.type === 'JSXNamespacedName') {
|
|
82
|
+
if (V_IF_CHAIN_DIRECTIVES.has(directiveName))
|
|
83
|
+
continue;
|
|
76
84
|
matches = attrName.namespace.name === 'v' && attrName.name.name === directiveName.slice(2);
|
|
77
85
|
}
|
|
78
86
|
else if (attrName.type === 'JSXIdentifier') {
|
|
@@ -129,19 +137,14 @@ export function removeVDirectives(node) {
|
|
|
129
137
|
}
|
|
130
138
|
/**
|
|
131
139
|
* 移除元素上的 v-if 链指令(v-if、v-else-if、v-else)
|
|
140
|
+
* 仅处理 JSXIdentifier 格式,不支持命名空间格式(v:if)
|
|
132
141
|
*/
|
|
133
142
|
export function removeVIfChainDirectives(node) {
|
|
134
|
-
const vIfChainDirectives = ['v-if', 'v-else-if', 'v-else'];
|
|
135
143
|
node.openingElement.attributes = node.openingElement.attributes.filter(attr => {
|
|
136
144
|
if (attr.type === 'JSXAttribute') {
|
|
137
145
|
const attrName = attr.name;
|
|
138
|
-
if (attrName.type === '
|
|
139
|
-
|
|
140
|
-
return !vIfChainDirectives.includes(`v-${attrName.name.name}`);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
else if (attrName.type === 'JSXIdentifier') {
|
|
144
|
-
return !vIfChainDirectives.includes(attrName.name);
|
|
146
|
+
if (attrName.type === 'JSXIdentifier') {
|
|
147
|
+
return !V_IF_CHAIN_DIRECTIVES.has(attrName.name);
|
|
145
148
|
}
|
|
146
149
|
}
|
|
147
150
|
return true;
|