@wsxjs/wsx-vite-plugin 0.0.6 → 0.0.8
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/LICENSE +21 -0
- package/dist/index.d.mts +6 -26
- package/dist/index.d.ts +6 -26
- package/dist/index.js +367 -43
- package/dist/index.mjs +357 -43
- package/package.json +58 -50
- package/src/babel-plugin-wsx-state.ts +260 -0
- package/src/babel-plugin-wsx-style.ts +149 -0
- package/src/index.ts +2 -1
- package/src/vite-plugin-wsx-babel.ts +218 -0
- package/src/vite-plugin-wsx.ts +0 -166
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 WSX Framework Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,39 +1,19 @@
|
|
|
1
1
|
import { Plugin } from 'vite';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Vite Plugin for WSX
|
|
4
|
+
* Vite Plugin for WSX with Babel decorator support
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* - 支持TypeScript编译
|
|
9
|
-
* - 完全隔离,不影响主项目React配置
|
|
6
|
+
* Uses Babel to preprocess decorators before esbuild transformation
|
|
7
|
+
* This ensures decorators work correctly even with esbuild's limitations
|
|
10
8
|
*/
|
|
11
9
|
|
|
12
10
|
interface WSXPluginOptions {
|
|
13
|
-
/**
|
|
14
|
-
* JSX工厂函数名
|
|
15
|
-
* @default 'h'
|
|
16
|
-
*/
|
|
17
11
|
jsxFactory?: string;
|
|
18
|
-
/**
|
|
19
|
-
* JSX Fragment函数名
|
|
20
|
-
* @default 'Fragment'
|
|
21
|
-
*/
|
|
22
12
|
jsxFragment?: string;
|
|
23
|
-
/**
|
|
24
|
-
* 是否启用调试日志
|
|
25
|
-
* @default false
|
|
26
|
-
*/
|
|
27
13
|
debug?: boolean;
|
|
28
|
-
/**
|
|
29
|
-
* 文件扩展名
|
|
30
|
-
* @default ['.wsx']
|
|
31
|
-
*/
|
|
32
14
|
extensions?: string[];
|
|
15
|
+
autoStyleInjection?: boolean;
|
|
33
16
|
}
|
|
34
|
-
|
|
35
|
-
* WSX Vite插件
|
|
36
|
-
*/
|
|
37
|
-
declare function vitePluginWSX(options?: WSXPluginOptions): Plugin;
|
|
17
|
+
declare function vitePluginWSXWithBabel(options?: WSXPluginOptions): Plugin;
|
|
38
18
|
|
|
39
|
-
export {
|
|
19
|
+
export { vitePluginWSXWithBabel as wsx };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,39 +1,19 @@
|
|
|
1
1
|
import { Plugin } from 'vite';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Vite Plugin for WSX
|
|
4
|
+
* Vite Plugin for WSX with Babel decorator support
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* - 支持TypeScript编译
|
|
9
|
-
* - 完全隔离,不影响主项目React配置
|
|
6
|
+
* Uses Babel to preprocess decorators before esbuild transformation
|
|
7
|
+
* This ensures decorators work correctly even with esbuild's limitations
|
|
10
8
|
*/
|
|
11
9
|
|
|
12
10
|
interface WSXPluginOptions {
|
|
13
|
-
/**
|
|
14
|
-
* JSX工厂函数名
|
|
15
|
-
* @default 'h'
|
|
16
|
-
*/
|
|
17
11
|
jsxFactory?: string;
|
|
18
|
-
/**
|
|
19
|
-
* JSX Fragment函数名
|
|
20
|
-
* @default 'Fragment'
|
|
21
|
-
*/
|
|
22
12
|
jsxFragment?: string;
|
|
23
|
-
/**
|
|
24
|
-
* 是否启用调试日志
|
|
25
|
-
* @default false
|
|
26
|
-
*/
|
|
27
13
|
debug?: boolean;
|
|
28
|
-
/**
|
|
29
|
-
* 文件扩展名
|
|
30
|
-
* @default ['.wsx']
|
|
31
|
-
*/
|
|
32
14
|
extensions?: string[];
|
|
15
|
+
autoStyleInjection?: boolean;
|
|
33
16
|
}
|
|
34
|
-
|
|
35
|
-
* WSX Vite插件
|
|
36
|
-
*/
|
|
37
|
-
declare function vitePluginWSX(options?: WSXPluginOptions): Plugin;
|
|
17
|
+
declare function vitePluginWSXWithBabel(options?: WSXPluginOptions): Plugin;
|
|
38
18
|
|
|
39
|
-
export {
|
|
19
|
+
export { vitePluginWSXWithBabel as wsx };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,104 +17,426 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
21
31
|
var index_exports = {};
|
|
22
32
|
__export(index_exports, {
|
|
23
|
-
wsx: () =>
|
|
33
|
+
wsx: () => vitePluginWSXWithBabel
|
|
24
34
|
});
|
|
25
35
|
module.exports = __toCommonJS(index_exports);
|
|
26
36
|
|
|
27
|
-
// src/vite-plugin-wsx.ts
|
|
37
|
+
// src/vite-plugin-wsx-babel.ts
|
|
28
38
|
var import_esbuild = require("esbuild");
|
|
39
|
+
var import_core = require("@babel/core");
|
|
40
|
+
var import_fs = require("fs");
|
|
41
|
+
var import_path = require("path");
|
|
42
|
+
|
|
43
|
+
// src/babel-plugin-wsx-state.ts
|
|
44
|
+
var tModule = __toESM(require("@babel/types"));
|
|
45
|
+
function babelPluginWSXState() {
|
|
46
|
+
const t = tModule;
|
|
47
|
+
return {
|
|
48
|
+
name: "babel-plugin-wsx-state",
|
|
49
|
+
visitor: {
|
|
50
|
+
ClassDeclaration(path) {
|
|
51
|
+
const classBody = path.node.body;
|
|
52
|
+
const stateProperties = [];
|
|
53
|
+
console.info(
|
|
54
|
+
`[Babel Plugin WSX State] Processing class ${path.node.id?.name || "anonymous"}, members: ${classBody.body.length}`
|
|
55
|
+
);
|
|
56
|
+
for (const member of classBody.body) {
|
|
57
|
+
console.info(
|
|
58
|
+
` - Member type: ${member.type}, key: ${member.type === "ClassProperty" || member.type === "ClassPrivateProperty" ? member.key?.name : "N/A"}`
|
|
59
|
+
);
|
|
60
|
+
if ((member.type === "ClassProperty" || member.type === "ClassPrivateProperty") && member.key.type === "Identifier") {
|
|
61
|
+
console.info(
|
|
62
|
+
` - Property: ${member.key.name}, decorators: ${member.decorators?.length || 0}, hasValue: ${!!member.value}`
|
|
63
|
+
);
|
|
64
|
+
if (member.decorators && member.decorators.length > 0) {
|
|
65
|
+
member.decorators.forEach((decorator) => {
|
|
66
|
+
if (decorator.expression.type === "Identifier") {
|
|
67
|
+
console.info(` Decorator: ${decorator.expression.name}`);
|
|
68
|
+
} else if (decorator.expression.type === "CallExpression" && decorator.expression.callee.type === "Identifier") {
|
|
69
|
+
console.debug(
|
|
70
|
+
` Decorator: ${decorator.expression.callee.name}()`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
const hasStateDecorator = member.decorators?.some(
|
|
76
|
+
(decorator) => {
|
|
77
|
+
if (decorator.expression.type === "Identifier" && decorator.expression.name === "state") {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
if (decorator.expression.type === "CallExpression" && decorator.expression.callee.type === "Identifier" && decorator.expression.callee.name === "state") {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
if (hasStateDecorator && member.value) {
|
|
87
|
+
const key = member.key.name;
|
|
88
|
+
const initialValue = member.value;
|
|
89
|
+
const isObject = initialValue.type === "ObjectExpression" || initialValue.type === "ArrayExpression";
|
|
90
|
+
stateProperties.push({
|
|
91
|
+
key,
|
|
92
|
+
initialValue,
|
|
93
|
+
isObject
|
|
94
|
+
});
|
|
95
|
+
if (member.decorators) {
|
|
96
|
+
member.decorators = member.decorators.filter(
|
|
97
|
+
(decorator) => {
|
|
98
|
+
if (decorator.expression.type === "Identifier" && decorator.expression.name === "state") {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
if (decorator.expression.type === "CallExpression" && decorator.expression.callee.type === "Identifier" && decorator.expression.callee.name === "state") {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
member.value = void 0;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (stateProperties.length === 0) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
let constructor = classBody.body.find(
|
|
116
|
+
(member) => member.type === "ClassMethod" && member.kind === "constructor"
|
|
117
|
+
);
|
|
118
|
+
if (!constructor) {
|
|
119
|
+
constructor = t.classMethod(
|
|
120
|
+
"constructor",
|
|
121
|
+
t.identifier("constructor"),
|
|
122
|
+
[],
|
|
123
|
+
t.blockStatement([])
|
|
124
|
+
);
|
|
125
|
+
classBody.body.unshift(constructor);
|
|
126
|
+
}
|
|
127
|
+
const statements = [];
|
|
128
|
+
const hasSuper = constructor.body.body.some(
|
|
129
|
+
(stmt) => stmt.type === "ExpressionStatement" && stmt.expression.type === "CallExpression" && stmt.expression.callee.type === "Super"
|
|
130
|
+
);
|
|
131
|
+
if (!hasSuper) {
|
|
132
|
+
statements.push(t.expressionStatement(t.callExpression(t.super(), [])));
|
|
133
|
+
}
|
|
134
|
+
for (const { key, initialValue, isObject } of stateProperties) {
|
|
135
|
+
if (isObject) {
|
|
136
|
+
statements.push(
|
|
137
|
+
t.expressionStatement(
|
|
138
|
+
t.assignmentExpression(
|
|
139
|
+
"=",
|
|
140
|
+
t.memberExpression(t.thisExpression(), t.identifier(key)),
|
|
141
|
+
t.callExpression(
|
|
142
|
+
t.memberExpression(
|
|
143
|
+
t.thisExpression(),
|
|
144
|
+
t.identifier("reactive")
|
|
145
|
+
),
|
|
146
|
+
[initialValue]
|
|
147
|
+
)
|
|
148
|
+
)
|
|
149
|
+
)
|
|
150
|
+
);
|
|
151
|
+
} else {
|
|
152
|
+
const getterId = t.identifier(`_get${key}`);
|
|
153
|
+
const setterId = t.identifier(`_set${key}`);
|
|
154
|
+
statements.push(
|
|
155
|
+
t.variableDeclaration("const", [
|
|
156
|
+
t.variableDeclarator(
|
|
157
|
+
t.arrayPattern([getterId, setterId]),
|
|
158
|
+
t.callExpression(
|
|
159
|
+
t.memberExpression(
|
|
160
|
+
t.thisExpression(),
|
|
161
|
+
t.identifier("useState")
|
|
162
|
+
),
|
|
163
|
+
[t.stringLiteral(key), initialValue]
|
|
164
|
+
)
|
|
165
|
+
)
|
|
166
|
+
])
|
|
167
|
+
);
|
|
168
|
+
statements.push(
|
|
169
|
+
t.expressionStatement(
|
|
170
|
+
t.callExpression(
|
|
171
|
+
t.memberExpression(
|
|
172
|
+
t.identifier("Object"),
|
|
173
|
+
t.identifier("defineProperty")
|
|
174
|
+
),
|
|
175
|
+
[
|
|
176
|
+
t.thisExpression(),
|
|
177
|
+
t.stringLiteral(key),
|
|
178
|
+
t.objectExpression([
|
|
179
|
+
t.objectProperty(t.identifier("get"), getterId),
|
|
180
|
+
t.objectProperty(t.identifier("set"), setterId),
|
|
181
|
+
t.objectProperty(
|
|
182
|
+
t.identifier("enumerable"),
|
|
183
|
+
t.booleanLiteral(true)
|
|
184
|
+
),
|
|
185
|
+
t.objectProperty(
|
|
186
|
+
t.identifier("configurable"),
|
|
187
|
+
t.booleanLiteral(true)
|
|
188
|
+
)
|
|
189
|
+
])
|
|
190
|
+
]
|
|
191
|
+
)
|
|
192
|
+
)
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
constructor.body.body.push(...statements);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// src/babel-plugin-wsx-style.ts
|
|
203
|
+
var tModule2 = __toESM(require("@babel/types"));
|
|
204
|
+
function hasStylesImport(program) {
|
|
205
|
+
for (const node of program.body) {
|
|
206
|
+
if (node.type === "ImportDeclaration") {
|
|
207
|
+
const source = node.source.value;
|
|
208
|
+
if (typeof source === "string" && (source.endsWith(".css?inline") || source.endsWith(".css"))) {
|
|
209
|
+
const defaultSpecifier = node.specifiers.find(
|
|
210
|
+
(spec) => spec.type === "ImportDefaultSpecifier"
|
|
211
|
+
);
|
|
212
|
+
if (defaultSpecifier) {
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
function hasAutoStylesProperty(classBody) {
|
|
221
|
+
for (const member of classBody.body) {
|
|
222
|
+
if ((member.type === "ClassProperty" || member.type === "ClassPrivateProperty") && member.key.type === "Identifier" && member.key.name === "_autoStyles") {
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
function babelPluginWSXStyle() {
|
|
229
|
+
const t = tModule2;
|
|
230
|
+
return {
|
|
231
|
+
name: "babel-plugin-wsx-style",
|
|
232
|
+
visitor: {
|
|
233
|
+
Program(path, state) {
|
|
234
|
+
const { cssFileExists, cssFilePath, componentName } = state.opts;
|
|
235
|
+
if (!cssFileExists) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
if (hasStylesImport(path.node)) {
|
|
239
|
+
console.info(
|
|
240
|
+
`[Babel Plugin WSX Style] Skipping ${componentName}: styles already manually imported`
|
|
241
|
+
);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
console.info(
|
|
245
|
+
`[Babel Plugin WSX Style] Injecting CSS import for ${componentName}: ${cssFilePath}`
|
|
246
|
+
);
|
|
247
|
+
const importStatement = t.importDeclaration(
|
|
248
|
+
[t.importDefaultSpecifier(t.identifier("styles"))],
|
|
249
|
+
t.stringLiteral(cssFilePath)
|
|
250
|
+
);
|
|
251
|
+
let insertIndex = 0;
|
|
252
|
+
for (let i = 0; i < path.node.body.length; i++) {
|
|
253
|
+
const node = path.node.body[i];
|
|
254
|
+
if (node.type === "ImportDeclaration") {
|
|
255
|
+
insertIndex = i + 1;
|
|
256
|
+
} else {
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
path.node.body.splice(insertIndex, 0, importStatement);
|
|
261
|
+
},
|
|
262
|
+
ClassDeclaration(path, state) {
|
|
263
|
+
const { cssFileExists } = state.opts;
|
|
264
|
+
if (!cssFileExists) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
const classBody = path.node.body;
|
|
268
|
+
if (hasAutoStylesProperty(classBody)) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
const autoStylesProperty = t.classProperty(
|
|
272
|
+
t.identifier("_autoStyles"),
|
|
273
|
+
t.identifier("styles"),
|
|
274
|
+
null,
|
|
275
|
+
// typeAnnotation
|
|
276
|
+
[],
|
|
277
|
+
// decorators
|
|
278
|
+
false,
|
|
279
|
+
// computed
|
|
280
|
+
false
|
|
281
|
+
// static
|
|
282
|
+
);
|
|
283
|
+
classBody.body.unshift(autoStylesProperty);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// src/vite-plugin-wsx-babel.ts
|
|
29
290
|
function getJSXFactoryImportPath(_options) {
|
|
30
291
|
return "@wsxjs/wsx-core";
|
|
31
292
|
}
|
|
32
|
-
function
|
|
293
|
+
function vitePluginWSXWithBabel(options = {}) {
|
|
33
294
|
const {
|
|
34
295
|
jsxFactory = "h",
|
|
35
296
|
jsxFragment = "Fragment",
|
|
36
297
|
debug = false,
|
|
37
|
-
extensions = [".wsx"]
|
|
298
|
+
extensions = [".wsx"],
|
|
299
|
+
autoStyleInjection = true
|
|
38
300
|
} = options;
|
|
39
301
|
return {
|
|
40
|
-
name: "vite-plugin-wsx",
|
|
302
|
+
name: "vite-plugin-wsx-babel",
|
|
41
303
|
enforce: "pre",
|
|
42
|
-
// 确保在 React 插件之前执行
|
|
43
|
-
// 处理 .wsx 文件加载
|
|
44
|
-
load(id) {
|
|
45
|
-
const isWSXFile = extensions.some((ext) => id.endsWith(ext));
|
|
46
|
-
if (!isWSXFile) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
if (debug) {
|
|
50
|
-
console.log(`[WSX Plugin] Loading: ${id}`);
|
|
51
|
-
}
|
|
52
|
-
return null;
|
|
53
|
-
},
|
|
54
|
-
// 在transform阶段处理文件
|
|
55
304
|
async transform(code, id) {
|
|
56
305
|
const isWSXFile = extensions.some((ext) => id.endsWith(ext));
|
|
57
306
|
if (!isWSXFile) {
|
|
58
307
|
return null;
|
|
59
308
|
}
|
|
60
309
|
if (debug) {
|
|
61
|
-
console.log(`[WSX Plugin] Processing: ${id}`);
|
|
310
|
+
console.log(`[WSX Plugin Babel] Processing: ${id}`);
|
|
311
|
+
}
|
|
312
|
+
let cssFileExists = false;
|
|
313
|
+
let cssFilePath = "";
|
|
314
|
+
let componentName = "";
|
|
315
|
+
if (autoStyleInjection) {
|
|
316
|
+
const fileDir = (0, import_path.dirname)(id);
|
|
317
|
+
const fileName = (0, import_path.basename)(id, extensions.find((ext) => id.endsWith(ext)) || "");
|
|
318
|
+
const cssFilePathWithoutQuery = (0, import_path.join)(fileDir, `${fileName}.css`);
|
|
319
|
+
cssFileExists = (0, import_fs.existsSync)(cssFilePathWithoutQuery);
|
|
320
|
+
componentName = fileName;
|
|
321
|
+
if (cssFileExists) {
|
|
322
|
+
cssFilePath = `./${fileName}.css?inline`;
|
|
323
|
+
}
|
|
324
|
+
if (cssFileExists) {
|
|
325
|
+
console.log(
|
|
326
|
+
`[WSX Plugin Babel] Found CSS file for auto-injection: ${cssFilePathWithoutQuery}, will inject: ${cssFilePath}`
|
|
327
|
+
);
|
|
328
|
+
}
|
|
62
329
|
}
|
|
63
330
|
let transformedCode = code;
|
|
64
331
|
const hasWSXCoreImport = code.includes('from "@wsxjs/wsx-core"');
|
|
65
332
|
const hasJSXInImport = hasWSXCoreImport && (new RegExp(`[{,]\\s*${jsxFactory}\\s*[},]`).test(code) || new RegExp(`[{,]\\s*${jsxFragment}\\s*[},]`).test(code));
|
|
66
|
-
if (debug) {
|
|
67
|
-
console.log(`[WSX Plugin] Checking JSX imports for: ${id}`);
|
|
68
|
-
console.log(` - hasWSXCoreImport: ${hasWSXCoreImport}`);
|
|
69
|
-
console.log(` - hasJSXInImport: ${hasJSXInImport}`);
|
|
70
|
-
console.log(` - has < character: ${code.includes("<")}`);
|
|
71
|
-
console.log(` - has Fragment: ${code.includes("Fragment")}`);
|
|
72
|
-
}
|
|
73
333
|
if ((code.includes("<") || code.includes("Fragment")) && !hasJSXInImport) {
|
|
74
334
|
const importPath = getJSXFactoryImportPath(options);
|
|
75
335
|
const importStatement = `import { ${jsxFactory}, ${jsxFragment} } from "${importPath}";
|
|
336
|
+
`;
|
|
337
|
+
transformedCode = importStatement + transformedCode;
|
|
338
|
+
}
|
|
339
|
+
try {
|
|
340
|
+
const babelResult = (0, import_core.transformSync)(transformedCode, {
|
|
341
|
+
filename: id,
|
|
342
|
+
// Pass the actual filename so Babel knows it's .wsx
|
|
343
|
+
presets: [
|
|
344
|
+
[
|
|
345
|
+
"@babel/preset-typescript",
|
|
346
|
+
{
|
|
347
|
+
isTSX: true,
|
|
348
|
+
// Enable JSX syntax
|
|
349
|
+
allExtensions: true
|
|
350
|
+
// Process all extensions, including .wsx
|
|
351
|
+
}
|
|
352
|
+
]
|
|
353
|
+
],
|
|
354
|
+
plugins: [
|
|
355
|
+
// CRITICAL: Style injection plugin must run FIRST
|
|
356
|
+
// This ensures _autoStyles property exists before state transformations
|
|
357
|
+
...autoStyleInjection && cssFileExists ? [
|
|
358
|
+
[
|
|
359
|
+
babelPluginWSXStyle,
|
|
360
|
+
{
|
|
361
|
+
cssFileExists,
|
|
362
|
+
cssFilePath,
|
|
363
|
+
componentName
|
|
364
|
+
}
|
|
365
|
+
]
|
|
366
|
+
] : [],
|
|
367
|
+
// State decorator transformation runs after style injection
|
|
368
|
+
babelPluginWSXState,
|
|
369
|
+
[
|
|
370
|
+
"@babel/plugin-proposal-decorators",
|
|
371
|
+
{
|
|
372
|
+
version: "2023-05",
|
|
373
|
+
decoratorsBeforeExport: true
|
|
374
|
+
}
|
|
375
|
+
],
|
|
376
|
+
[
|
|
377
|
+
"@babel/plugin-proposal-class-properties",
|
|
378
|
+
{
|
|
379
|
+
loose: false
|
|
380
|
+
}
|
|
381
|
+
],
|
|
382
|
+
"@babel/plugin-transform-class-static-block"
|
|
383
|
+
// Support static class blocks
|
|
384
|
+
]
|
|
385
|
+
// parserOpts not needed - @babel/preset-typescript and plugins handle it
|
|
386
|
+
});
|
|
387
|
+
if (babelResult && babelResult.code) {
|
|
388
|
+
transformedCode = babelResult.code;
|
|
389
|
+
if (debug) {
|
|
390
|
+
console.log(`[WSX Plugin Babel] Decorators preprocessed: ${id}`);
|
|
391
|
+
if (transformedCode.includes("this.reactive") || transformedCode.includes("this.useState")) {
|
|
392
|
+
console.log(
|
|
393
|
+
`[WSX Plugin Babel] Generated reactive code found in: ${id}
|
|
394
|
+
` + transformedCode.split("\n").filter(
|
|
395
|
+
(line) => line.includes("this.reactive") || line.includes("this.useState")
|
|
396
|
+
).join("\n")
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
} catch (error) {
|
|
402
|
+
console.warn(
|
|
403
|
+
`[WSX Plugin Babel] Babel transform failed for ${id}, falling back to esbuild only:`,
|
|
404
|
+
error
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
const hasJSXAfterBabel = transformedCode.includes('from "@wsxjs/wsx-core"') && (new RegExp(`[{,]\\s*${jsxFactory}\\s*[},]`).test(transformedCode) || new RegExp(`[{,]\\s*${jsxFragment}\\s*[},]`).test(transformedCode));
|
|
408
|
+
if ((transformedCode.includes("<") || transformedCode.includes("Fragment")) && !hasJSXAfterBabel) {
|
|
409
|
+
const importPath = getJSXFactoryImportPath(options);
|
|
410
|
+
const importStatement = `import { ${jsxFactory}, ${jsxFragment} } from "${importPath}";
|
|
76
411
|
`;
|
|
77
412
|
transformedCode = importStatement + transformedCode;
|
|
78
413
|
if (debug) {
|
|
79
|
-
console.log(
|
|
414
|
+
console.log(
|
|
415
|
+
`[WSX Plugin Babel] Re-added JSX imports after Babel transform: ${id}`
|
|
416
|
+
);
|
|
80
417
|
}
|
|
81
418
|
}
|
|
82
419
|
try {
|
|
83
420
|
const result = await (0, import_esbuild.transform)(transformedCode, {
|
|
84
|
-
loader: "
|
|
421
|
+
loader: "jsx",
|
|
422
|
+
// Already TypeScript-transformed by Babel
|
|
85
423
|
jsx: "transform",
|
|
86
424
|
jsxFactory,
|
|
87
425
|
jsxFragment,
|
|
88
426
|
target: "es2020",
|
|
89
427
|
format: "esm"
|
|
90
|
-
// Esbuild supports decorators natively with tsx loader
|
|
91
428
|
});
|
|
92
|
-
if (debug) {
|
|
93
|
-
console.log(`[WSX Plugin] JSX transformed: ${id}`);
|
|
94
|
-
}
|
|
95
429
|
return {
|
|
96
430
|
code: result.code,
|
|
97
431
|
map: null
|
|
98
432
|
};
|
|
99
433
|
} catch (error) {
|
|
100
|
-
console.error(`[WSX Plugin] Transform error for ${id}:`, error);
|
|
434
|
+
console.error(`[WSX Plugin Babel] Transform error for ${id}:`, error);
|
|
101
435
|
throw error;
|
|
102
436
|
}
|
|
103
|
-
},
|
|
104
|
-
// We handle JSX transformation directly in the transform hook
|
|
105
|
-
// No need to modify global esbuild config
|
|
106
|
-
// 构建开始时的日志
|
|
107
|
-
buildStart() {
|
|
108
|
-
if (debug) {
|
|
109
|
-
console.log(`[WSX Plugin] Build started with extensions: ${extensions.join(", ")}`);
|
|
110
|
-
console.log(`[WSX Plugin] JSX Factory: ${jsxFactory}, Fragment: ${jsxFragment}`);
|
|
111
|
-
}
|
|
112
437
|
}
|
|
113
438
|
};
|
|
114
439
|
}
|
|
115
|
-
var vite_plugin_wsx_default = vitePluginWSX;
|
|
116
440
|
// Annotate the CommonJS export names for ESM import in node:
|
|
117
441
|
0 && (module.exports = {
|
|
118
442
|
wsx
|