@actview/plugin-babel 1.0.7 → 2.1.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.
- package/README.md +25 -3
- package/dist/index.d.ts +13 -4
- package/dist/index.js +82 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,10 +42,32 @@ const result = babel.transformSync(code, {
|
|
|
42
42
|
| 导出 | 说明 |
|
|
43
43
|
|---|---|
|
|
44
44
|
| `defineComponentPlugin`(默认导出同) | Babel 插件工厂:组件 → `defineComponent` 转换 |
|
|
45
|
-
| `createBabelTransform(plugin)` | 宿主壳工厂:模块级创建一次 ConfigItem,返回 `(code, filename) => { code, map } \| null` |
|
|
45
|
+
| `createBabelTransform(plugin, options?)` | 宿主壳工厂:模块级创建一次 ConfigItem,返回 `(code, filename) => { code, map } \| null` |
|
|
46
46
|
| `createBabelItem(plugin)` | 把插件工厂预编译为 ConfigItem(Babel 8 同步) |
|
|
47
|
-
| `transformWithBabel(code, filename, pluginItem)` | 统一参数的 `transformSync` |
|
|
48
|
-
|
|
|
47
|
+
| `transformWithBabel(code, filename, pluginItem, options?)` | 统一参数的 `transformSync` |
|
|
48
|
+
| `isExcludedTransform(filename, options?)` | 排除判定:node_modules 硬排除 / 未命中 include / 命中 exclude |
|
|
49
|
+
| 类型:`BabelPlugin` / `BabelHostResult` / `BabelTransformOptions` | 宿主壳类型 |
|
|
50
|
+
|
|
51
|
+
## 排除规则(node_modules 硬排除)
|
|
52
|
+
|
|
53
|
+
宿主壳**硬排除 node_modules 下的文件**(返回 `null` 不转换):依赖是第三方代码,属依赖管线(esbuild 预构建),不是源码管线——`babel-loader` / `@rollup/plugin-babel` 同款默认。`BabelTransformOptions`:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
{
|
|
57
|
+
include?: Array<string | RegExp>, // 白名单:命中任一才转换(默认不过滤;node_modules 硬排除优先)
|
|
58
|
+
exclude?: Array<string | RegExp>, // 黑名单:命中任一即跳过(优先于 include)
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**源码分发库包 / 主题包(node_modules 下)需要现场编译时**,不在插件层开洞,而是在宿主构建配置里做**路径转换**,让文件解析路径脱离 node_modules 段、进入源码管线:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
// vite.config.ts
|
|
66
|
+
resolve: {
|
|
67
|
+
alias: { 'my-lib': 'node_modules/my-lib/src' }, // 路径不再含 node_modules 段 → 正常转换
|
|
68
|
+
},
|
|
69
|
+
optimizeDeps: { exclude: ['my-lib'] }, // 不预构建,保持源码形态
|
|
70
|
+
```
|
|
49
71
|
|
|
50
72
|
## 依赖关系
|
|
51
73
|
|
package/dist/index.d.ts
CHANGED
|
@@ -21,15 +21,24 @@ interface BabelHostResult {
|
|
|
21
21
|
code: string;
|
|
22
22
|
map: unknown;
|
|
23
23
|
}
|
|
24
|
+
/** 宿主壳排除规则(createBabelTransform / transformWithBabel 第二/四参) */
|
|
25
|
+
interface BabelTransformOptions {
|
|
26
|
+
/** 白名单:文件命中任一规则才转换(默认不过滤;node_modules 硬排除优先) */
|
|
27
|
+
include?: Array<string | RegExp>;
|
|
28
|
+
/** 黑名单:命中任一规则即跳过(优先级高于 include) */
|
|
29
|
+
exclude?: Array<string | RegExp>;
|
|
30
|
+
}
|
|
31
|
+
/** 是否应跳过转换:node_modules 硬排除 / 未命中 include / 命中 exclude */
|
|
32
|
+
declare function isExcludedTransform(filename: string, options?: BabelTransformOptions): boolean;
|
|
24
33
|
/** 把插件工厂预编译为 ConfigItem(Babel 8 同步版本,可跨多次 transformSync 复用) */
|
|
25
34
|
declare function createBabelItem(plugin: BabelPlugin): PluginItem;
|
|
26
|
-
/** 统一参数的 transformSync
|
|
27
|
-
declare function transformWithBabel(code: string, filename: string, pluginItem: PluginItem): BabelHostResult | null;
|
|
35
|
+
/** 统一参数的 transformSync:排除命中或失败返回 null,成功返回 { code, map } */
|
|
36
|
+
declare function transformWithBabel(code: string, filename: string, pluginItem: PluginItem, options?: BabelTransformOptions): BabelHostResult | null;
|
|
28
37
|
/**
|
|
29
38
|
* 静态插件的便捷工厂:模块级调用一次,ConfigItem 只创建一次。
|
|
30
39
|
* 适用于插件对象不随文件变化的场景(如 defineComponentPlugin)。
|
|
31
40
|
*/
|
|
32
|
-
declare function createBabelTransform(plugin: BabelPlugin | BabelPlugin[]): (code: string, filename: string) => BabelHostResult | null;
|
|
41
|
+
declare function createBabelTransform(plugin: BabelPlugin | BabelPlugin[], options?: BabelTransformOptions): (code: string, filename: string) => BabelHostResult | null;
|
|
33
42
|
|
|
34
43
|
declare function solidPlugin(): {
|
|
35
44
|
visitor: {
|
|
@@ -40,4 +49,4 @@ declare function solidPlugin(): {
|
|
|
40
49
|
};
|
|
41
50
|
};
|
|
42
51
|
|
|
43
|
-
export { type BabelHostResult, createBabelItem, createBabelTransform, defineComponentPlugin as default, defineComponentPlugin, solidPlugin, transformWithBabel };
|
|
52
|
+
export { type BabelHostResult, type BabelTransformOptions, createBabelItem, createBabelTransform, defineComponentPlugin as default, defineComponentPlugin, isExcludedTransform, solidPlugin, transformWithBabel };
|
package/dist/index.js
CHANGED
|
@@ -130,9 +130,10 @@ function defineComponentPlugin() {
|
|
|
130
130
|
if (!node.id) return;
|
|
131
131
|
const name = node.id.name;
|
|
132
132
|
if (!/^[A-Z]/.test(name)) return;
|
|
133
|
+
assertNoSetupStyleEarlyReturns(path, name);
|
|
133
134
|
const fn = t.functionExpression(null, node.params, node.body, false, false);
|
|
134
135
|
if (node.typeParameters) fn.typeParameters = node.typeParameters;
|
|
135
|
-
const wrapped = wrapComponentFn(fn, name);
|
|
136
|
+
const wrapped = wrapComponentFn(fn, name, path);
|
|
136
137
|
if (!wrapped) return;
|
|
137
138
|
const call = wrapped;
|
|
138
139
|
hasTransformed = true;
|
|
@@ -153,11 +154,12 @@ function defineComponentPlugin() {
|
|
|
153
154
|
const init = node.init;
|
|
154
155
|
const isFn = t.isFunctionExpression(init) || t.isArrowFunctionExpression(init);
|
|
155
156
|
if (!isFn) return;
|
|
156
|
-
const
|
|
157
|
+
const initPath = path.get("init");
|
|
158
|
+
assertNoSetupStyleEarlyReturns(initPath, id.name);
|
|
159
|
+
const wrapped = wrapComponentFn(init, id.name, initPath);
|
|
157
160
|
if (!wrapped) return;
|
|
158
161
|
const call = wrapped;
|
|
159
162
|
hasTransformed = true;
|
|
160
|
-
const initPath = path.get("init");
|
|
161
163
|
wrapEarlyReturns(initPath);
|
|
162
164
|
node.init = call;
|
|
163
165
|
},
|
|
@@ -184,18 +186,19 @@ function defineComponentPlugin() {
|
|
|
184
186
|
;
|
|
185
187
|
fn.typeParameters = decl.typeParameters;
|
|
186
188
|
}
|
|
187
|
-
const
|
|
189
|
+
const declPath = path.get("declaration");
|
|
190
|
+
assertNoSetupStyleEarlyReturns(declPath);
|
|
191
|
+
const wrapped = wrapComponentFn(fn, void 0, path);
|
|
188
192
|
if (!wrapped) return;
|
|
189
193
|
const call = wrapped;
|
|
190
194
|
hasTransformed = true;
|
|
191
|
-
const declPath = path.get("declaration");
|
|
192
195
|
wrapEarlyReturns(declPath);
|
|
193
196
|
path.node.declaration = call;
|
|
194
197
|
}
|
|
195
198
|
}
|
|
196
199
|
};
|
|
197
200
|
}
|
|
198
|
-
function wrapComponentFn(fn, name) {
|
|
201
|
+
function wrapComponentFn(fn, name, fnPath) {
|
|
199
202
|
const body = fn.body;
|
|
200
203
|
const isExprBody = !t.isBlockStatement(body);
|
|
201
204
|
let last = null;
|
|
@@ -214,7 +217,13 @@ function wrapComponentFn(fn, name) {
|
|
|
214
217
|
const isJsxCall = t.isCallExpression(ret) && t.isIdentifier(ret.callee) && /^_?jsx/.test(ret.callee.name);
|
|
215
218
|
const isNullRet = t.isNullLiteral(ret);
|
|
216
219
|
const isCondRet = isRenderExpr(ret);
|
|
217
|
-
if (!isJsx && !isJsxCall && !isNullRet && !isCondRet)
|
|
220
|
+
if (!isJsx && !isJsxCall && !isNullRet && !isCondRet) {
|
|
221
|
+
const returnsFn = t.isArrowFunctionExpression(ret) || t.isFunctionExpression(ret);
|
|
222
|
+
if (returnsFn && (name !== void 0 || containsRenderNode(ret))) {
|
|
223
|
+
throw buildSetupStyleError(fnPath, name);
|
|
224
|
+
}
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
218
227
|
if (isJsx) walkJSX(ret);
|
|
219
228
|
if (isExprBody) {
|
|
220
229
|
fn.body = t.blockStatement([
|
|
@@ -229,6 +238,54 @@ function wrapComponentFn(fn, name) {
|
|
|
229
238
|
if (name) args.push(t.stringLiteral(name));
|
|
230
239
|
return t.callExpression(t.identifier("defineComponent"), args);
|
|
231
240
|
}
|
|
241
|
+
function assertNoSetupStyleEarlyReturns(fnPath, name) {
|
|
242
|
+
const body = fnPath.node.body;
|
|
243
|
+
if (!t.isBlockStatement(body)) return;
|
|
244
|
+
const stmts = body.body;
|
|
245
|
+
const trailing = stmts.length ? stmts[stmts.length - 1] : null;
|
|
246
|
+
fnPath.traverse({
|
|
247
|
+
ReturnStatement(retPath) {
|
|
248
|
+
if (retPath.getFunctionParent() !== fnPath) return;
|
|
249
|
+
if (trailing && retPath.node === trailing) return;
|
|
250
|
+
const arg = retPath.node.argument;
|
|
251
|
+
if (t.isArrowFunctionExpression(arg) || t.isFunctionExpression(arg)) {
|
|
252
|
+
throw buildSetupStyleError(retPath, name);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
function buildSetupStyleError(fnPath, name) {
|
|
258
|
+
const label = name ? `\u7EC4\u4EF6 ${name}` : "\u7EC4\u4EF6\u51FD\u6570";
|
|
259
|
+
const msg = `[actview] \u5DF2\u5E9F\u5F03\u7684 setup \u98CE\u683C\uFF1A${label}\u4F53\u5185 return \u4E86\u6E32\u67D3\u51FD\u6570\uFF08() => JSX / function () { JSX }\uFF09\u3002
|
|
260
|
+
ActView \u53EA\u652F\u6301\u7B80\u5199\u7EC4\u4EF6\u2014\u2014\u76F4\u63A5 return JSX\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u5305\u88C5 render \u51FD\u6570\uFF1A
|
|
261
|
+
|
|
262
|
+
\u2717 function App() { return () => <div /> }
|
|
263
|
+
\u2713 function App() { return <div /> }
|
|
264
|
+
`;
|
|
265
|
+
try {
|
|
266
|
+
return fnPath.buildCodeFrameError(msg);
|
|
267
|
+
} catch {
|
|
268
|
+
return new Error(msg);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
function containsRenderNode(node, seen = /* @__PURE__ */ new Set()) {
|
|
272
|
+
if (!node || typeof node !== "object" || seen.has(node)) return false;
|
|
273
|
+
seen.add(node);
|
|
274
|
+
if (t.isJSXElement(node) || t.isJSXFragment(node)) return true;
|
|
275
|
+
if (t.isCallExpression(node) && t.isIdentifier(node.callee) && /^_?jsx/.test(node.callee.name)) {
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
for (const k in node) {
|
|
279
|
+
if (k === "leadingComments" || k === "trailingComments") continue;
|
|
280
|
+
const v = node[k];
|
|
281
|
+
if (Array.isArray(v)) {
|
|
282
|
+
if (v.some((c) => containsRenderNode(c, seen))) return true;
|
|
283
|
+
} else if (v !== null && typeof v === "object") {
|
|
284
|
+
if (containsRenderNode(v, seen)) return true;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
232
289
|
function wrapEarlyReturns(fnPath) {
|
|
233
290
|
fnPath.traverse({
|
|
234
291
|
ReturnStatement(innerPath) {
|
|
@@ -380,10 +437,24 @@ function buildSolidMark(el, state) {
|
|
|
380
437
|
|
|
381
438
|
// src/babel-host.ts
|
|
382
439
|
import * as babel from "@babel/core";
|
|
440
|
+
var NODE_MODULES_RE = /(^|[\\/])node_modules[\\/]/;
|
|
441
|
+
function matchesRule(rule, filename) {
|
|
442
|
+
return typeof rule === "string" ? filename.includes(rule) : rule.test(filename);
|
|
443
|
+
}
|
|
444
|
+
function isExcludedTransform(filename, options) {
|
|
445
|
+
const norm = filename.replace(/\\/g, "/");
|
|
446
|
+
if (NODE_MODULES_RE.test(norm)) return true;
|
|
447
|
+
if (options?.include?.length && !options.include.some((r) => matchesRule(r, norm))) {
|
|
448
|
+
return true;
|
|
449
|
+
}
|
|
450
|
+
if (options?.exclude?.some((r) => matchesRule(r, norm))) return true;
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
383
453
|
function createBabelItem(plugin) {
|
|
384
454
|
return babel.createConfigItemSync(plugin, { type: "plugin" });
|
|
385
455
|
}
|
|
386
|
-
function transformWithBabel(code, filename, pluginItem) {
|
|
456
|
+
function transformWithBabel(code, filename, pluginItem, options) {
|
|
457
|
+
if (isExcludedTransform(filename, options)) return null;
|
|
387
458
|
const result = babel.transformSync(code, {
|
|
388
459
|
filename,
|
|
389
460
|
plugins: [pluginItem],
|
|
@@ -396,9 +467,10 @@ function transformWithBabel(code, filename, pluginItem) {
|
|
|
396
467
|
if (!result) return null;
|
|
397
468
|
return { code: result.code || code, map: result.map };
|
|
398
469
|
}
|
|
399
|
-
function createBabelTransform(plugin) {
|
|
470
|
+
function createBabelTransform(plugin, options) {
|
|
400
471
|
const items = (Array.isArray(plugin) ? plugin : [plugin]).map((p) => createBabelItem(p));
|
|
401
472
|
return (code, filename) => {
|
|
473
|
+
if (isExcludedTransform(filename, options)) return null;
|
|
402
474
|
const result = babel.transformSync(code, {
|
|
403
475
|
filename,
|
|
404
476
|
plugins: items,
|
|
@@ -713,6 +785,7 @@ export {
|
|
|
713
785
|
createBabelTransform,
|
|
714
786
|
defineComponentPlugin as default,
|
|
715
787
|
defineComponentPlugin,
|
|
788
|
+
isExcludedTransform,
|
|
716
789
|
solidPlugin,
|
|
717
790
|
transformWithBabel
|
|
718
791
|
};
|