@blocklet/pages-kit-block-studio 0.4.104 → 0.4.106
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/lib/cjs/plugins/vite-plugin-block-studio.js +20 -1
- package/lib/cjs/plugins/vite-plugin-import-transform.js +269 -0
- package/lib/cjs/tsconfig.tsbuildinfo +1 -1
- package/lib/cjs/utils/helper.js +10 -1
- package/lib/esm/plugins/vite-plugin-block-studio.js +20 -1
- package/lib/esm/plugins/vite-plugin-import-transform.js +233 -0
- package/lib/esm/tsconfig.tsbuildinfo +1 -1
- package/lib/esm/utils/helper.js +10 -1
- package/lib/types/plugins/vite-plugin-import-transform.d.ts +20 -0
- package/lib/types/tsconfig.tsbuildinfo +1 -1
- package/lib/types/utils/helper.d.ts +1 -1
- package/package.json +3 -3
|
@@ -56,8 +56,13 @@ const vite_plugin_node_polyfills_1 = require("vite-plugin-node-polyfills");
|
|
|
56
56
|
const vite_plugin_react_pages_1 = __importStar(require("vite-plugin-react-pages"));
|
|
57
57
|
const helper_1 = require("../utils/helper");
|
|
58
58
|
const vite_plugin_html_transform_1 = require("./vite-plugin-html-transform");
|
|
59
|
+
const vite_plugin_import_transform_1 = require("./vite-plugin-import-transform");
|
|
59
60
|
// const BUILTIN_MODULES_VAR = '__PAGES_KIT_BUILTIN_MODULES__';
|
|
60
61
|
// logger.log('BUILTIN_MODULES_VAR', BUILTIN_MODULES_VAR);
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
63
|
+
const isMatchAfterSlachExternals = (_id) => {
|
|
64
|
+
return false;
|
|
65
|
+
};
|
|
61
66
|
const defaultBlockExternals = {
|
|
62
67
|
// 核心 React 相关
|
|
63
68
|
react: '@blocklet/pages-kit/builtin/react',
|
|
@@ -90,6 +95,19 @@ const defaultBlockExternals = {
|
|
|
90
95
|
'react-scroll-to-bottom': '@blocklet/pages-kit/builtin/async/react-scroll-to-bottom',
|
|
91
96
|
'@blocklet/pages-kit': '@blocklet/pages-kit',
|
|
92
97
|
};
|
|
98
|
+
const importTransformConfig = {
|
|
99
|
+
transforms: [
|
|
100
|
+
{
|
|
101
|
+
find: [
|
|
102
|
+
// import {useTheme} from '@mui/material/styles' => import {useTheme} from '@mui/material'
|
|
103
|
+
{ source: '@mui/material/styles', type: 'ImportSpecifier' },
|
|
104
|
+
// import useTheme from '@mui/material/styles/useTheme' => import { useTheme } from '@mui/material'
|
|
105
|
+
{ source: '@mui/material/styles/*', type: 'ImportDefaultSpecifier' },
|
|
106
|
+
],
|
|
107
|
+
replace: { source: '@mui/material', type: 'ImportSpecifier' },
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
};
|
|
93
111
|
function initBlockStudioPlugins(options) {
|
|
94
112
|
const workingDir = options?.cwd || process.cwd();
|
|
95
113
|
const entryFilesPattern = options?.entryFilesPattern || (0, helper_1.getBlockEntryFilesPattern)();
|
|
@@ -162,6 +180,7 @@ function initBlockStudioPlugins(options) {
|
|
|
162
180
|
// return html;
|
|
163
181
|
// },
|
|
164
182
|
// },
|
|
183
|
+
(0, vite_plugin_import_transform_1.importTransformPlugin)(importTransformConfig),
|
|
165
184
|
options?.ignoreNodePolyfills
|
|
166
185
|
? undefined
|
|
167
186
|
: (0, vite_plugin_node_polyfills_1.nodePolyfills)({
|
|
@@ -205,7 +224,7 @@ function initBlockStudioPlugins(options) {
|
|
|
205
224
|
external: _config?.build?.rollupOptions?.external ||
|
|
206
225
|
((id) => {
|
|
207
226
|
// 是否匹配后缀
|
|
208
|
-
const isMatchAfterSlash =
|
|
227
|
+
const isMatchAfterSlash = isMatchAfterSlachExternals(id);
|
|
209
228
|
const skipList = [...Object.keys(externalMappings)];
|
|
210
229
|
if (skipList.some((item) => (isMatchAfterSlash && id.startsWith(`${item}/`)) || id === item)) {
|
|
211
230
|
return true;
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.importTransformPlugin = importTransformPlugin;
|
|
37
|
+
const ts = __importStar(require("typescript"));
|
|
38
|
+
/**
|
|
39
|
+
* 简化版的 import 转换 Vite 插件
|
|
40
|
+
* 用于在构建过程中修改导入语句的源路径和类型
|
|
41
|
+
*/
|
|
42
|
+
function importTransformPlugin(options = {}) {
|
|
43
|
+
const { transforms = [], include = /\.[jt]sx?$/, exclude = /node_modules/ } = options;
|
|
44
|
+
// 创建过滤函数,判断是否应处理该文件
|
|
45
|
+
const filter = (id) => {
|
|
46
|
+
// 排除 node_modules 目录
|
|
47
|
+
if (id.includes('node_modules'))
|
|
48
|
+
return false;
|
|
49
|
+
// 处理 include 规则
|
|
50
|
+
const testInclude = (pattern) => {
|
|
51
|
+
if (typeof pattern === 'string')
|
|
52
|
+
return id.includes(pattern);
|
|
53
|
+
return pattern.test(id);
|
|
54
|
+
};
|
|
55
|
+
// 处理 exclude 规则
|
|
56
|
+
const testExclude = (pattern) => {
|
|
57
|
+
if (typeof pattern === 'string')
|
|
58
|
+
return id.includes(pattern);
|
|
59
|
+
return pattern.test(id);
|
|
60
|
+
};
|
|
61
|
+
// 检查是否符合 include 规则
|
|
62
|
+
const shouldInclude = Array.isArray(include) ? include.some(testInclude) : testInclude(include);
|
|
63
|
+
// 检查是否符合 exclude 规则
|
|
64
|
+
const shouldExclude = Array.isArray(exclude) ? exclude.some(testExclude) : testExclude(exclude);
|
|
65
|
+
return shouldInclude && !shouldExclude;
|
|
66
|
+
};
|
|
67
|
+
return {
|
|
68
|
+
name: 'import-transform',
|
|
69
|
+
transform(code, id) {
|
|
70
|
+
// 如果不需要处理该文件,直接返回
|
|
71
|
+
if (!filter(id))
|
|
72
|
+
return null;
|
|
73
|
+
// 使用 TypeScript 解析源代码
|
|
74
|
+
const sourceFile = ts.createSourceFile(id, code, ts.ScriptTarget.Latest, true);
|
|
75
|
+
// 记录是否有改变
|
|
76
|
+
let hasChanged = false;
|
|
77
|
+
// 创建转换器
|
|
78
|
+
const transformer = (context) => {
|
|
79
|
+
const visit = (node) => {
|
|
80
|
+
// 仅处理导入声明
|
|
81
|
+
if (ts.isImportDeclaration(node)) {
|
|
82
|
+
const importPath = getImportPath(node);
|
|
83
|
+
if (!importPath)
|
|
84
|
+
return ts.visitEachChild(node, visit, context);
|
|
85
|
+
const importType = getImportType(node);
|
|
86
|
+
// 记录是否找到匹配的规则
|
|
87
|
+
let matched = false;
|
|
88
|
+
// 遍历所有转换规则
|
|
89
|
+
for (const transform of transforms) {
|
|
90
|
+
const finds = Array.isArray(transform.find) ? transform.find : [transform.find];
|
|
91
|
+
// 检查每个查找条件
|
|
92
|
+
for (const find of finds) {
|
|
93
|
+
// 检查源路径和导入类型是否匹配
|
|
94
|
+
if (!matchSourcePath(find.source, importPath)) {
|
|
95
|
+
// 路径不匹配,检查下一条
|
|
96
|
+
}
|
|
97
|
+
else if (find.type && find.type !== importType) {
|
|
98
|
+
// 类型不匹配,检查下一条
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
// 找到匹配的导入声明
|
|
102
|
+
matched = true;
|
|
103
|
+
hasChanged = true;
|
|
104
|
+
const replacePath = transform.replace.source;
|
|
105
|
+
const replaceType = transform.replace.type;
|
|
106
|
+
// 如果指定了替换类型
|
|
107
|
+
if (replaceType && replaceType !== importType) {
|
|
108
|
+
// 处理不同类型的导入转换
|
|
109
|
+
if (importType === 'ImportSpecifier' && replaceType === 'ImportDefaultSpecifier') {
|
|
110
|
+
// { X } -> default
|
|
111
|
+
const names = node.importClause?.namedBindings;
|
|
112
|
+
if (!names || !names.elements[0])
|
|
113
|
+
return ts.visitEachChild(node, visit, context);
|
|
114
|
+
const importName = names.elements[0].name.text;
|
|
115
|
+
return createDefaultImport(importName, replacePath);
|
|
116
|
+
}
|
|
117
|
+
if (importType === 'ImportDefaultSpecifier' && replaceType === 'ImportNamespaceSpecifier') {
|
|
118
|
+
// default -> * as X
|
|
119
|
+
const name = node.importClause?.name?.text;
|
|
120
|
+
if (!name)
|
|
121
|
+
return ts.visitEachChild(node, visit, context);
|
|
122
|
+
return createNamespaceImport(name, replacePath);
|
|
123
|
+
}
|
|
124
|
+
if (importType === 'ImportNamespaceSpecifier' && replaceType === 'ImportDefaultSpecifier') {
|
|
125
|
+
// * as X -> default
|
|
126
|
+
const binding = node.importClause?.namedBindings;
|
|
127
|
+
if (!binding)
|
|
128
|
+
return ts.visitEachChild(node, visit, context);
|
|
129
|
+
const name = binding.name.text;
|
|
130
|
+
return createDefaultImport(name, replacePath);
|
|
131
|
+
}
|
|
132
|
+
if (importType === 'ImportDefaultSpecifier' && replaceType === 'ImportSpecifier') {
|
|
133
|
+
// default -> { X }
|
|
134
|
+
const name = node.importClause?.name?.text;
|
|
135
|
+
if (!name)
|
|
136
|
+
return ts.visitEachChild(node, visit, context);
|
|
137
|
+
// 智能处理:检测是否需要使用别名
|
|
138
|
+
// 从路径中提取原始名称,如 '@mui/material/styles/useTheme' -> 'useTheme'
|
|
139
|
+
const originalName = extractNameFromPath(importPath);
|
|
140
|
+
// 如果能从路径中提取名称,使用它作为原始名称
|
|
141
|
+
if (originalName && originalName !== name) {
|
|
142
|
+
return createNamedImportWithAlias(originalName, name, replacePath);
|
|
143
|
+
}
|
|
144
|
+
// 退回到简单导入
|
|
145
|
+
return createNamedImport(name, replacePath);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
// 没有指定替换类型,智能推断最合适的转换
|
|
150
|
+
// 默认导入 -> 命名导入的智能转换(基于路径分析)
|
|
151
|
+
const isDefaultImport = importType === 'ImportDefaultSpecifier';
|
|
152
|
+
if (isDefaultImport && isComponentPath(importPath)) {
|
|
153
|
+
const name = node.importClause?.name?.text;
|
|
154
|
+
if (!name)
|
|
155
|
+
return ts.visitEachChild(node, visit, context);
|
|
156
|
+
// 从路径中提取组件名称
|
|
157
|
+
const componentName = extractNameFromPath(importPath);
|
|
158
|
+
if (componentName && componentName !== name) {
|
|
159
|
+
// 使用从路径中提取的组件名作为原始导入名
|
|
160
|
+
return createNamedImportWithAlias(componentName, name, replacePath);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// 只改变导入路径
|
|
165
|
+
if (replacePath !== importPath) {
|
|
166
|
+
return ts.factory.createImportDeclaration(undefined, node.importClause, ts.factory.createStringLiteral(replacePath));
|
|
167
|
+
}
|
|
168
|
+
// 找到匹配但无需转换,继续检查下一个规则
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// 如果已经找到匹配并转换了,就不再继续检查
|
|
173
|
+
if (matched)
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return ts.visitEachChild(node, visit, context);
|
|
178
|
+
};
|
|
179
|
+
return (node) => ts.visitNode(node, visit);
|
|
180
|
+
};
|
|
181
|
+
// 应用转换
|
|
182
|
+
const result = ts.transform(sourceFile, [transformer]);
|
|
183
|
+
// 如果有改变,打印转换后的代码
|
|
184
|
+
if (hasChanged) {
|
|
185
|
+
const printer = ts.createPrinter();
|
|
186
|
+
const transformedCode = printer.printFile(result.transformed[0]);
|
|
187
|
+
return { code: transformedCode };
|
|
188
|
+
}
|
|
189
|
+
// 没有变化,返回 null
|
|
190
|
+
return null;
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
exports.default = importTransformPlugin;
|
|
195
|
+
// 辅助函数:获取导入路径
|
|
196
|
+
function getImportPath(node) {
|
|
197
|
+
const { moduleSpecifier } = node;
|
|
198
|
+
if (ts.isStringLiteral(moduleSpecifier)) {
|
|
199
|
+
return moduleSpecifier.text;
|
|
200
|
+
}
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
// 辅助函数:获取导入类型
|
|
204
|
+
function getImportType(node) {
|
|
205
|
+
if (node.importClause) {
|
|
206
|
+
if (node.importClause.name) {
|
|
207
|
+
return 'ImportDefaultSpecifier';
|
|
208
|
+
}
|
|
209
|
+
if (node.importClause.namedBindings) {
|
|
210
|
+
if (ts.isNamespaceImport(node.importClause.namedBindings)) {
|
|
211
|
+
return 'ImportNamespaceSpecifier';
|
|
212
|
+
}
|
|
213
|
+
if (ts.isNamedImports(node.importClause.namedBindings)) {
|
|
214
|
+
return 'ImportSpecifier';
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return '';
|
|
219
|
+
}
|
|
220
|
+
// 辅助函数:创建默认导入
|
|
221
|
+
function createDefaultImport(name, path) {
|
|
222
|
+
return ts.factory.createImportDeclaration(undefined, ts.factory.createImportClause(false, ts.factory.createIdentifier(name), undefined), ts.factory.createStringLiteral(path));
|
|
223
|
+
}
|
|
224
|
+
// 辅助函数:创建命名空间导入
|
|
225
|
+
function createNamespaceImport(name, path) {
|
|
226
|
+
return ts.factory.createImportDeclaration(undefined, ts.factory.createImportClause(false, undefined, ts.factory.createNamespaceImport(ts.factory.createIdentifier(name))), ts.factory.createStringLiteral(path));
|
|
227
|
+
}
|
|
228
|
+
// 辅助函数:创建命名导入
|
|
229
|
+
function createNamedImport(name, path) {
|
|
230
|
+
return ts.factory.createImportDeclaration(undefined, ts.factory.createImportClause(false, undefined, ts.factory.createNamedImports([
|
|
231
|
+
ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier(name)),
|
|
232
|
+
])), ts.factory.createStringLiteral(path));
|
|
233
|
+
}
|
|
234
|
+
// 辅助函数:从路径中提取名称
|
|
235
|
+
function extractNameFromPath(path) {
|
|
236
|
+
// 处理类似 '@mui/material/styles/useTheme' 的路径
|
|
237
|
+
const segments = path.split('/');
|
|
238
|
+
const lastSegment = segments[segments.length - 1];
|
|
239
|
+
// 如果最后一段有意义的名称(不是index或为空),返回它
|
|
240
|
+
if (lastSegment && lastSegment !== 'index') {
|
|
241
|
+
return lastSegment;
|
|
242
|
+
}
|
|
243
|
+
return undefined;
|
|
244
|
+
}
|
|
245
|
+
// 辅助函数:创建带别名的命名导入
|
|
246
|
+
function createNamedImportWithAlias(originalName, aliasName, path) {
|
|
247
|
+
return ts.factory.createImportDeclaration(undefined, ts.factory.createImportClause(false, undefined, ts.factory.createNamedImports([
|
|
248
|
+
ts.factory.createImportSpecifier(false, ts.factory.createIdentifier(originalName), ts.factory.createIdentifier(aliasName)),
|
|
249
|
+
])), ts.factory.createStringLiteral(path));
|
|
250
|
+
}
|
|
251
|
+
// 辅助函数:检查是否是组件路径(含有组件名的子路径)
|
|
252
|
+
function isComponentPath(path) {
|
|
253
|
+
// 检查路径是否包含至少一个斜杠,且最后一段不是index
|
|
254
|
+
const segments = path.split('/');
|
|
255
|
+
return segments.length > 1 && segments[segments.length - 1] !== 'index';
|
|
256
|
+
}
|
|
257
|
+
// 辅助函数:检查源路径是否匹配(支持通配符)
|
|
258
|
+
function matchSourcePath(pattern, actualPath) {
|
|
259
|
+
// 处理精确匹配
|
|
260
|
+
if (pattern === actualPath)
|
|
261
|
+
return true;
|
|
262
|
+
// 处理通配符匹配
|
|
263
|
+
if (pattern.endsWith('/*')) {
|
|
264
|
+
const basePath = pattern.slice(0, -2); // 移除 '/*'
|
|
265
|
+
return actualPath.startsWith(`${basePath}/`);
|
|
266
|
+
}
|
|
267
|
+
// 可以在这里添加更多匹配逻辑,如正则表达式
|
|
268
|
+
return false;
|
|
269
|
+
}
|