@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.
@@ -2,5 +2,5 @@
2
2
  * 指令处理模块
3
3
  * @module passes/directives
4
4
  */
5
- export { processVIfChain } from './vIf.js';
5
+ export { processVIfChain, transformChildrenVIfChains } from './vIf.js';
6
6
  export { processDirectives } from './processDirectives.js';
@@ -2,5 +2,5 @@
2
2
  * 指令处理模块
3
3
  * @module passes/directives
4
4
  */
5
- export { processVIfChain } from './vIf.js';
5
+ export { processVIfChain, transformChildrenVIfChains } from './vIf.js';
6
6
  export { processDirectives } from './processDirectives.js';
@@ -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
- * JSX 元素转换函数类型
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
- type TransformJSXElementFn = (node: t.JSXElement, ctx: TransformContext, handleVIf: boolean) => t.Expression | null;
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: NodePath<t.JSXFragment>, ctx: TransformContext, transformJSXElement: TransformJSXElementFn): void;
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
- * 处理 Fragment 中的 v-if 链
6
- * @param path - JSX Fragment 路径
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 processVIfChain(path, ctx, transformJSXElement) {
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
- cleanupProcessedChildren(path, children);
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(children, ctx);
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
@@ -84,6 +84,9 @@ function transformAST(ast, ctx) {
84
84
  ctx.processedNodes.add(path.node);
85
85
  processPureCompileComponent(path, ctx);
86
86
  }
87
+ else {
88
+ processVIfChain(path, ctx, transformJSXElement);
89
+ }
87
90
  },
88
91
  exit(path) {
89
92
  if (ctx.processedNodes.has(path.node))
@@ -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 === 'JSXNamespacedName') {
139
- if (attrName.namespace.name === 'v') {
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitarx/plugin-vite",
3
- "version": "1.0.0-beta.0",
3
+ "version": "1.0.0-beta.1",
4
4
  "description": "The official plugin for Vitarx support in Vite.",
5
5
  "author": "ZhuChongLin <8210856@qq.com>",
6
6
  "license": "MIT",