@vitarx/plugin-vite 1.0.1 → 1.0.2-alpha.0

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.
@@ -1,5 +1,6 @@
1
1
  /**
2
2
  * JSX 相关工具函数
3
+ * 提供 JSX 元素的各种操作和判断方法
3
4
  * @module utils/jsx-helpers
4
5
  */
5
6
  import * as t from '@babel/types';
@@ -9,22 +10,30 @@ import { createError } from '../error.js';
9
10
  import { isWhitespaceJSXText } from './ast-guards.js';
10
11
  /**
11
12
  * 获取 JSX 元素的名称
13
+ * @param node - JSX 元素节点
14
+ * @returns 元素名称(Identifier)或 null(MemberExpression)
12
15
  */
13
16
  export function getJSXElementName(node) {
14
17
  const nameNode = node.openingElement.name;
18
+ // 只处理简单标识符,MemberExpression 返回 null
15
19
  return nameNode.type === 'JSXIdentifier' ? nameNode.name : null;
16
20
  }
17
21
  /**
18
22
  * 将 JSX 元素名称节点转换为 createView 的类型表达式
19
23
  * JSXIdentifier → Identifier(组件)或 StringLiteral(原生元素)
20
24
  * JSXMemberExpression → MemberExpression(如 Obj.Key → Obj.Key)
25
+ * @param node - JSX 元素节点
26
+ * @returns 类型表达式或 null
21
27
  */
22
28
  export function resolveJSXElementType(node) {
23
29
  const nameNode = node.openingElement.name;
30
+ // 处理简单标识符(如 <div> 或 <Component>)
24
31
  if (nameNode.type === 'JSXIdentifier') {
25
32
  const name = nameNode.name;
33
+ // 原生元素转为字符串,组件转为标识符
26
34
  return isNativeElement(name) ? t.stringLiteral(name) : t.identifier(name);
27
35
  }
36
+ // 处理成员表达式(如 <Obj.Key>)
28
37
  if (nameNode.type === 'JSXMemberExpression') {
29
38
  return jsxMemberExprToMemberExpr(nameNode);
30
39
  }
@@ -33,8 +42,11 @@ export function resolveJSXElementType(node) {
33
42
  /**
34
43
  * 递归转换 JSXMemberExpression 为 MemberExpression
35
44
  * Obj.Key → Obj.Key, A.B.C → A.B.C
45
+ * @param node - JSXMemberExpression 节点
46
+ * @returns MemberExpression 节点
36
47
  */
37
48
  function jsxMemberExprToMemberExpr(node) {
49
+ // 递归处理对象部分
38
50
  const object = node.object.type === 'JSXMemberExpression'
39
51
  ? jsxMemberExprToMemberExpr(node.object)
40
52
  : t.identifier(node.object.name);
@@ -42,18 +54,27 @@ function jsxMemberExprToMemberExpr(node) {
42
54
  }
43
55
  /**
44
56
  * 判断名称是否为纯编译组件
57
+ * 纯编译组件在编译时完全展开,不会生成运行时调用
58
+ * @param name - 元素名称
59
+ * @returns 是否为纯编译组件
45
60
  */
46
61
  export function isPureCompileComponent(name) {
47
62
  return PURE_COMPILE_COMPONENTS.includes(name);
48
63
  }
49
64
  /**
50
65
  * 判断名称是否为组件(首字母大写)
66
+ * 遵循 React/Vue 的组件命名约定
67
+ * @param name - 元素名称
68
+ * @returns 是否为组件
51
69
  */
52
70
  export function isComponent(name) {
53
71
  return name.length > 0 && name[0] === name[0].toUpperCase();
54
72
  }
55
73
  /**
56
74
  * 判断名称是否为原生元素
75
+ * 原生元素使用小写字母开头
76
+ * @param name - 元素名称
77
+ * @returns 是否为原生元素
57
78
  */
58
79
  export function isNativeElement(name) {
59
80
  return !isComponent(name);
@@ -7,14 +7,14 @@ import type { LVal, ObjectPattern } from '@babel/types';
7
7
  /**
8
8
  * 从绑定模式中收集变量名
9
9
  * 支持标识符、对象模式、数组模式
10
- * @param pattern - 绑定模式
11
- * @param variables - 变量名集合
10
+ * @param pattern - 绑定模式节点
11
+ * @param variables - 存储变量名的集合
12
12
  */
13
13
  export declare function collectPatternBindings(pattern: LVal, variables: Set<string>): void;
14
14
  /**
15
15
  * 从对象解构模式中收集变量名
16
16
  * 专门用于 toRefs 解构场景
17
- * @param pattern - 对象模式
18
- * @param variables - 变量名集合
17
+ * @param pattern - 对象模式节点
18
+ * @param variables - 存储变量名的集合
19
19
  */
20
20
  export declare function collectObjectPatternBindings(pattern: ObjectPattern, variables: Set<string>): void;
@@ -1,26 +1,32 @@
1
1
  /**
2
2
  * 从绑定模式中收集变量名
3
3
  * 支持标识符、对象模式、数组模式
4
- * @param pattern - 绑定模式
5
- * @param variables - 变量名集合
4
+ * @param pattern - 绑定模式节点
5
+ * @param variables - 存储变量名的集合
6
6
  */
7
7
  export function collectPatternBindings(pattern, variables) {
8
+ // 处理简单标识符
8
9
  if (pattern.type === 'Identifier') {
9
10
  variables.add(pattern.name);
10
11
  }
11
12
  else if (pattern.type === 'ObjectPattern') {
13
+ // 处理对象解构模式
12
14
  for (const prop of pattern.properties) {
13
15
  if (prop.type === 'RestElement') {
16
+ // 处理剩余运算符(...rest)
14
17
  collectPatternBindings(prop.argument, variables);
15
18
  }
16
19
  else {
20
+ // 处理普通属性,递归收集 value
17
21
  collectPatternBindings(prop.value, variables);
18
22
  }
19
23
  }
20
24
  }
21
25
  else if (pattern.type === 'ArrayPattern') {
26
+ // 处理数组解构模式
22
27
  for (const elem of pattern.elements) {
23
28
  if (elem) {
29
+ // 递归处理每个非空元素
24
30
  collectPatternBindings(elem, variables);
25
31
  }
26
32
  }
@@ -29,18 +35,21 @@ export function collectPatternBindings(pattern, variables) {
29
35
  /**
30
36
  * 从对象解构模式中收集变量名
31
37
  * 专门用于 toRefs 解构场景
32
- * @param pattern - 对象模式
33
- * @param variables - 变量名集合
38
+ * @param pattern - 对象模式节点
39
+ * @param variables - 存储变量名的集合
34
40
  */
35
41
  export function collectObjectPatternBindings(pattern, variables) {
36
42
  for (const prop of pattern.properties) {
37
43
  if (prop.type === 'RestElement') {
44
+ // 处理剩余运算符
38
45
  collectPatternBindings(prop.argument, variables);
39
46
  }
40
47
  else if (prop.value.type === 'Identifier') {
48
+ // 处理简单标识符属性
41
49
  variables.add(prop.value.name);
42
50
  }
43
51
  else if (prop.value.type === 'ObjectPattern') {
52
+ // 处理嵌套对象解构,递归收集
44
53
  collectObjectPatternBindings(prop.value, variables);
45
54
  }
46
55
  }
@@ -15,14 +15,22 @@ export interface VIfChainInfo {
15
15
  }
16
16
  /**
17
17
  * 验证 v-if 链的合法性
18
+ * 检查语法错误,如顺序不当、v-else 不是最后一个等
19
+ * @param children - v-if 链的元素数组
18
20
  */
19
21
  export declare function validateVIfChain(children: t.JSXElement[]): void;
20
22
  /**
21
23
  * 从 JSX 元素数组收集 v-if 链信息
24
+ * 要求所有元素都属于 v-if 链(之前已验证)
25
+ * @param nodes - JSX 元素数组
26
+ * @returns v-if 链信息对象
22
27
  */
23
28
  export declare function collectVIfChainInfo(nodes: t.JSXElement[]): VIfChainInfo;
24
29
  /**
25
30
  * 收集 Fragment 中的 v-if 链
31
+ * 从 Fragment 的子元素中识别多个独立的 v-if 链
32
+ * @param children - Fragment 的子节点数组
33
+ * @returns v-if 链信息数组
26
34
  */
27
35
  export declare function collectFragmentVIfChains(children: t.Node[]): Array<VIfChainInfo & {
28
36
  endIndex: number;
@@ -10,24 +10,31 @@ import { isWhitespaceJSXText } from './ast-guards.js';
10
10
  import { getDirectiveValue, hasDirective, isVElse, isVElseIf, isVIf, isVIfChain } from './jsx-helpers.js';
11
11
  /**
12
12
  * 验证 v-if 链的合法性
13
+ * 检查语法错误,如顺序不当、v-else 不是最后一个等
14
+ * @param children - v-if 链的元素数组
13
15
  */
14
16
  export function validateVIfChain(children) {
15
17
  if (children.length === 0)
16
18
  return;
19
+ // 第一个元素必须有 v-if 指令
17
20
  if (!hasDirective(children[0], 'v-if')) {
18
21
  throw createError('E008', children[0], 'First element must have v-if directive');
19
22
  }
23
+ // 验证后续元素
20
24
  for (let i = 1; i < children.length; i++) {
21
25
  const child = children[i];
22
26
  const prevChild = children[i - 1];
23
27
  const hasVElseIf = hasDirective(child, 'v-else-if');
24
28
  const hasVElse = hasDirective(child, 'v-else');
29
+ // 后续元素必须是 v-else-if 或 v-else
25
30
  if (!hasVElseIf && !hasVElse) {
26
31
  throw createError('E008', child, 'Elements after v-if must have v-else-if or v-else directive');
27
32
  }
33
+ // v-else 必须是最后一个元素
28
34
  if (hasVElse && i !== children.length - 1) {
29
35
  throw createError('E008', child, 'v-else must be the last element');
30
36
  }
37
+ // v-else-if 不能接在 v-else 后面
31
38
  if (hasVElseIf && hasDirective(prevChild, 'v-else')) {
32
39
  throw createError('E008', child, 'v-else-if cannot follow v-else');
33
40
  }
@@ -35,54 +42,72 @@ export function validateVIfChain(children) {
35
42
  }
36
43
  /**
37
44
  * 从 JSX 元素数组收集 v-if 链信息
45
+ * 要求所有元素都属于 v-if 链(之前已验证)
46
+ * @param nodes - JSX 元素数组
47
+ * @returns v-if 链信息对象
38
48
  */
39
49
  export function collectVIfChainInfo(nodes) {
40
50
  const conditions = [];
51
+ // 遍历每个节点,收集对应的条件
41
52
  for (const node of nodes) {
42
53
  const vIfValue = getDirectiveValue(node, 'v-if');
43
54
  if (vIfValue) {
55
+ // v-if 直接使用其条件表达式
44
56
  conditions.push(vIfValue);
45
57
  continue;
46
58
  }
47
59
  const vElseIfValue = getDirectiveValue(node, 'v-else-if');
48
60
  if (vElseIfValue) {
61
+ // v-else-if 直接使用其条件表达式
49
62
  conditions.push(vElseIfValue);
50
63
  continue;
51
64
  }
52
65
  if (hasDirective(node, 'v-else')) {
66
+ // v-else 使用 true 作为条件(默认情况)
53
67
  conditions.push(t.booleanLiteral(true));
54
68
  continue;
55
69
  }
70
+ // 理论上不会走到这里,因为之前已验证
56
71
  throw createError('E008', node, 'Element missing v-if/v-else-if/v-else directive');
57
72
  }
58
73
  return { nodes, conditions, startIndex: 0, endIndex: nodes.length - 1 };
59
74
  }
60
75
  /**
61
76
  * 收集 Fragment 中的 v-if 链
77
+ * 从 Fragment 的子元素中识别多个独立的 v-if 链
78
+ * @param children - Fragment 的子节点数组
79
+ * @returns v-if 链信息数组
62
80
  */
63
81
  export function collectFragmentVIfChains(children) {
64
82
  const chains = [];
65
83
  let i = 0;
84
+ // 遍历所有子节点
66
85
  while (i < children.length) {
67
86
  const child = children[i];
87
+ // 跳过文本节点
68
88
  if (isJSXText(child)) {
69
89
  i++;
70
90
  continue;
71
91
  }
92
+ // 跳过非 JSXElement 节点
72
93
  if (!isJSXElement(child)) {
73
94
  i++;
74
95
  continue;
75
96
  }
97
+ // 跳过不属于 v-if 链的元素
76
98
  if (!isVIfChain(child)) {
77
99
  i++;
78
100
  continue;
79
101
  }
102
+ // 处理 v-if 开头的链
80
103
  if (isVIf(child)) {
81
104
  const chain = collectSingleChainFromFragment(children, i);
82
105
  chains.push(chain);
106
+ // 跳到链结束的下一个位置
83
107
  i = chain.endIndex + 1;
84
108
  }
85
109
  else if (isVElseIf(child) || isVElse(child)) {
110
+ // v-else-if 或 v-else 不能单独出现
86
111
  throw createError(isVElse(child) ? 'E003' : 'E004', child);
87
112
  }
88
113
  else {
@@ -93,33 +118,44 @@ export function collectFragmentVIfChains(children) {
93
118
  }
94
119
  /**
95
120
  * 从 Fragment 收集单个 v-if 链
121
+ * 从 v-if 开始,收集后续连续的 v-else-if 和 v-else
122
+ * @param children - Fragment 的子节点数组
123
+ * @param startIndex - v-if 起始索引
124
+ * @returns 单个 v-if 链信息
96
125
  */
97
126
  function collectSingleChainFromFragment(children, startIndex) {
98
127
  const nodes = [children[startIndex]];
99
128
  const conditions = [getDirectiveValue(nodes[0], 'v-if')];
100
129
  let j = startIndex + 1;
130
+ // 继续收集后续的 v-else-if 和 v-else
101
131
  while (j < children.length) {
102
132
  const nextChild = children[j];
133
+ // 跳过空白文本节点(允许链元素间有空白)
103
134
  if (isJSXText(nextChild) && isWhitespaceJSXText(nextChild)) {
104
135
  j++;
105
136
  continue;
106
137
  }
138
+ // 遇到非 JSXElement,链结束
107
139
  if (!isJSXElement(nextChild))
108
140
  break;
141
+ // 遇到不属于 v-if 链的元素,链结束
109
142
  if (!isVIfChain(nextChild))
110
143
  break;
111
144
  if (isVElseIf(nextChild)) {
145
+ // 收集 v-else-if
112
146
  nodes.push(nextChild);
113
147
  conditions.push(getDirectiveValue(nextChild, 'v-else-if'));
114
148
  j++;
115
149
  }
116
150
  else if (isVElse(nextChild)) {
151
+ // 收集 v-else 并结束链
117
152
  nodes.push(nextChild);
118
153
  conditions.push(t.booleanLiteral(true));
119
154
  j++;
120
155
  break;
121
156
  }
122
157
  else {
158
+ // 其他情况,链结束
123
159
  break;
124
160
  }
125
161
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitarx/plugin-vite",
3
- "version": "1.0.1",
3
+ "version": "1.0.2-alpha.0",
4
4
  "description": "The official plugin for Vitarx support in Vite.",
5
5
  "author": "ZhuChongLin <8210856@qq.com>",
6
6
  "license": "MIT",