@blocklet/pages-kit-block-studio 0.4.31 → 0.4.33
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/components/create-resource.js +2 -2
- package/lib/cjs/constants/new-block-template/index.js +2 -14
- package/lib/cjs/middlewares/init-block-studio-router.js +15 -21
- package/lib/cjs/middlewares/init-resource-router.js +34 -42
- package/lib/cjs/plugins/vite-plugin-block-studio.js +107 -86
- package/lib/cjs/plugins/vite-plugin-html-transform.js +13 -24
- package/lib/cjs/plugins/vite-plugin-remote-script-localizer.js +87 -103
- package/lib/cjs/tsconfig.tsbuildinfo +1 -1
- package/lib/cjs/utils/build-lib.js +62 -74
- package/lib/cjs/utils/generate-wrapper-code.js +366 -120
- package/lib/cjs/utils/helper.js +9 -19
- package/lib/esm/components/create-resource.js +2 -2
- package/lib/esm/constants/new-block-template/index.js +2 -14
- package/lib/esm/middlewares/init-block-studio-router.js +15 -21
- package/lib/esm/middlewares/init-resource-router.js +34 -42
- package/lib/esm/plugins/vite-plugin-block-studio.js +107 -86
- package/lib/esm/plugins/vite-plugin-html-transform.js +13 -24
- package/lib/esm/plugins/vite-plugin-remote-script-localizer.js +87 -103
- package/lib/esm/tsconfig.tsbuildinfo +1 -1
- package/lib/esm/utils/build-lib.js +62 -74
- package/lib/esm/utils/generate-wrapper-code.js +366 -120
- package/lib/esm/utils/helper.js +9 -19
- package/lib/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
/* eslint-disable no-console */
|
|
11
2
|
import { createHash } from 'crypto';
|
|
12
3
|
import { mkdir, rm, writeFile } from 'fs/promises';
|
|
@@ -15,22 +6,22 @@ export function initRemoteScriptLocalizerPlugin(options = {}) {
|
|
|
15
6
|
const { tempDir = 'temp/remote-scripts', maxConcurrent = 5, timeout = 30000 } = options;
|
|
16
7
|
let initialized = false;
|
|
17
8
|
const downloadQueue = [];
|
|
18
|
-
const initTempDir = () =>
|
|
9
|
+
const initTempDir = async () => {
|
|
19
10
|
try {
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
12
|
+
await mkdir(tempDir, { recursive: true });
|
|
22
13
|
initialized = true;
|
|
23
14
|
}
|
|
24
15
|
catch (error) {
|
|
25
16
|
console.error('Failed to initialize temp directory:', error);
|
|
26
17
|
throw error;
|
|
27
18
|
}
|
|
28
|
-
}
|
|
29
|
-
const downloadWithTimeout = (url, ms) =>
|
|
19
|
+
};
|
|
20
|
+
const downloadWithTimeout = async (url, ms) => {
|
|
30
21
|
const controller = new AbortController();
|
|
31
22
|
const timeoutId = setTimeout(() => controller.abort(), ms);
|
|
32
23
|
try {
|
|
33
|
-
const response =
|
|
24
|
+
const response = await fetch(url, { signal: controller.signal });
|
|
34
25
|
clearTimeout(timeoutId);
|
|
35
26
|
return response;
|
|
36
27
|
}
|
|
@@ -38,48 +29,48 @@ export function initRemoteScriptLocalizerPlugin(options = {}) {
|
|
|
38
29
|
clearTimeout(timeoutId);
|
|
39
30
|
throw error;
|
|
40
31
|
}
|
|
41
|
-
}
|
|
42
|
-
const downloadScript = (url) =>
|
|
43
|
-
var _a;
|
|
32
|
+
};
|
|
33
|
+
const downloadScript = async (url) => {
|
|
44
34
|
try {
|
|
45
|
-
const response =
|
|
35
|
+
const response = await downloadWithTimeout(url, timeout);
|
|
46
36
|
if (!response.ok) {
|
|
47
37
|
throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
|
|
48
38
|
}
|
|
49
|
-
const content =
|
|
39
|
+
const content = await response.text();
|
|
50
40
|
const hash = createHash('md5').update(url).digest('hex').slice(0, 8);
|
|
51
|
-
const filename = `${hash}-${
|
|
41
|
+
const filename = `${hash}-${url
|
|
52
42
|
.split('/')
|
|
53
|
-
.pop()
|
|
43
|
+
.pop()
|
|
44
|
+
?.replace(/[^a-zA-Z0-9.-]/g, '_') || 'script.js'}`;
|
|
54
45
|
const localPath = path.join(tempDir, filename);
|
|
55
|
-
|
|
46
|
+
await writeFile(localPath, content, 'utf-8');
|
|
56
47
|
return localPath;
|
|
57
48
|
}
|
|
58
49
|
catch (error) {
|
|
59
50
|
console.error(`Error downloading script from ${url}:`, error);
|
|
60
51
|
throw error;
|
|
61
52
|
}
|
|
62
|
-
}
|
|
63
|
-
const processDownloads = (urls) =>
|
|
53
|
+
};
|
|
54
|
+
const processDownloads = async (urls) => {
|
|
64
55
|
const results = new Map();
|
|
65
56
|
// Process downloads in chunks to limit concurrency
|
|
66
57
|
for (let i = 0; i < urls.length; i += maxConcurrent) {
|
|
67
58
|
const chunk = urls.slice(i, i + maxConcurrent);
|
|
68
|
-
const promises = chunk.map((url) =>
|
|
59
|
+
const promises = chunk.map(async (url) => {
|
|
69
60
|
try {
|
|
70
|
-
const localPath =
|
|
61
|
+
const localPath = await downloadScript(url);
|
|
71
62
|
results.set(url, localPath);
|
|
72
63
|
}
|
|
73
64
|
catch (error) {
|
|
74
65
|
console.warn(`Failed to download ${url}:`, error);
|
|
75
66
|
}
|
|
76
|
-
})
|
|
67
|
+
});
|
|
77
68
|
downloadQueue.push(...promises);
|
|
78
69
|
// eslint-disable-next-line no-await-in-loop
|
|
79
|
-
|
|
70
|
+
await Promise.all(promises);
|
|
80
71
|
}
|
|
81
72
|
return results;
|
|
82
|
-
}
|
|
73
|
+
};
|
|
83
74
|
return {
|
|
84
75
|
name: 'remote-script-localizer',
|
|
85
76
|
enforce: 'pre',
|
|
@@ -93,83 +84,76 @@ export function initRemoteScriptLocalizerPlugin(options = {}) {
|
|
|
93
84
|
console.log('[remote-script-localizer] load:', id);
|
|
94
85
|
return null; // 让其他插件继续处理
|
|
95
86
|
},
|
|
96
|
-
transform(code, id) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
codeLength: code.length,
|
|
103
|
-
});
|
|
104
|
-
// 检查文件类型
|
|
105
|
-
const isJS = /\.[jt]sx?$/.test(id);
|
|
106
|
-
const isHTML = /\.html$/.test(id);
|
|
107
|
-
if (!isJS && !isHTML)
|
|
108
|
-
return null;
|
|
109
|
-
// 匹配多种远程脚本模式,包括模板字符串中的内容
|
|
110
|
-
const patterns = [
|
|
111
|
-
// 动态导入
|
|
112
|
-
/import\s*\(\s*['"]https?:\/\/[^'"]+['"]\s*\)/g,
|
|
113
|
-
// HTML script 标签 (包括转义的版本)
|
|
114
|
-
/<script[^>]*src=["'](https?:\/\/[^"']+)["'][^>]*>(?:<\\\/script>)?/g,
|
|
115
|
-
// 模板字符串中的 script 标签
|
|
116
|
-
/`[^`]*<script[^>]*src=["'](https?:\/\/[^"']+)["'][^>]*>(?:<\\\/script>)?[^`]*`/g,
|
|
117
|
-
// HTML link 标签
|
|
118
|
-
/<link[^>]*href=["'](https?:\/\/[^"']+)["'][^>]*>/g,
|
|
119
|
-
];
|
|
120
|
-
let hasRemoteUrls = false;
|
|
121
|
-
let newCode = code;
|
|
122
|
-
const urls = new Set();
|
|
123
|
-
// 收集所有远程 URL
|
|
124
|
-
patterns.forEach((pattern) => {
|
|
125
|
-
var _a, _b;
|
|
126
|
-
const matches = code.matchAll(pattern);
|
|
127
|
-
for (const match of matches) {
|
|
128
|
-
hasRemoteUrls = true;
|
|
129
|
-
// 提取 URL(处理不同的匹配组)
|
|
130
|
-
const url = match[1] || ((_b = (_a = match[0].match(/['"]https?:\/\/[^'"]+['"]/)) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.slice(1, -1));
|
|
131
|
-
if (url)
|
|
132
|
-
urls.add(url);
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
if (hasRemoteUrls) {
|
|
136
|
-
console.log(`[remote-script-localizer] Found remote URLs in ${id}:`, [...urls]);
|
|
137
|
-
const downloadResults = yield processDownloads([...urls]);
|
|
138
|
-
downloadResults.forEach((localPath, url) => {
|
|
139
|
-
// 替换模板字符串中的 script 标签
|
|
140
|
-
newCode = newCode.replace(new RegExp(`<script([^>]*)src=["']${url}["']([^>]*)>(?:<\\\\/script>)?`, 'g'), `<script$1src="/${localPath}"$2></script>`);
|
|
141
|
-
// 替换其他情况
|
|
142
|
-
newCode = newCode.replace(new RegExp(`(['"\`])${url}\\1`, 'g'), `$1/${localPath}$1`);
|
|
143
|
-
console.log(`[remote-script-localizer] Localized: ${url} -> ${localPath}`);
|
|
144
|
-
});
|
|
145
|
-
return {
|
|
146
|
-
code: newCode,
|
|
147
|
-
map: null,
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
return null;
|
|
87
|
+
async transform(code, id) {
|
|
88
|
+
// 添加调试日志
|
|
89
|
+
console.log('[remote-script-localizer] transform:', {
|
|
90
|
+
id,
|
|
91
|
+
isVirtual: id.includes('\0'),
|
|
92
|
+
codeLength: code.length,
|
|
151
93
|
});
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
94
|
+
// 检查文件类型
|
|
95
|
+
const isJS = /\.[jt]sx?$/.test(id);
|
|
96
|
+
const isHTML = /\.html$/.test(id);
|
|
97
|
+
if (!isJS && !isHTML)
|
|
98
|
+
return null;
|
|
99
|
+
// 匹配多种远程脚本模式,包括模板字符串中的内容
|
|
100
|
+
const patterns = [
|
|
101
|
+
// 动态导入
|
|
102
|
+
/import\s*\(\s*['"]https?:\/\/[^'"]+['"]\s*\)/g,
|
|
103
|
+
// HTML script 标签 (包括转义的版本)
|
|
104
|
+
/<script[^>]*src=["'](https?:\/\/[^"']+)["'][^>]*>(?:<\\\/script>)?/g,
|
|
105
|
+
// 模板字符串中的 script 标签
|
|
106
|
+
/`[^`]*<script[^>]*src=["'](https?:\/\/[^"']+)["'][^>]*>(?:<\\\/script>)?[^`]*`/g,
|
|
107
|
+
// HTML link 标签
|
|
108
|
+
/<link[^>]*href=["'](https?:\/\/[^"']+)["'][^>]*>/g,
|
|
109
|
+
];
|
|
110
|
+
let hasRemoteUrls = false;
|
|
111
|
+
let newCode = code;
|
|
112
|
+
const urls = new Set();
|
|
113
|
+
// 收集所有远程 URL
|
|
114
|
+
patterns.forEach((pattern) => {
|
|
115
|
+
const matches = code.matchAll(pattern);
|
|
116
|
+
for (const match of matches) {
|
|
117
|
+
hasRemoteUrls = true;
|
|
118
|
+
// 提取 URL(处理不同的匹配组)
|
|
119
|
+
const url = match[1] || match[0].match(/['"]https?:\/\/[^'"]+['"]/)?.[0]?.slice(1, -1);
|
|
120
|
+
if (url)
|
|
121
|
+
urls.add(url);
|
|
157
122
|
}
|
|
158
123
|
});
|
|
124
|
+
if (hasRemoteUrls) {
|
|
125
|
+
console.log(`[remote-script-localizer] Found remote URLs in ${id}:`, [...urls]);
|
|
126
|
+
const downloadResults = await processDownloads([...urls]);
|
|
127
|
+
downloadResults.forEach((localPath, url) => {
|
|
128
|
+
// 替换模板字符串中的 script 标签
|
|
129
|
+
newCode = newCode.replace(new RegExp(`<script([^>]*)src=["']${url}["']([^>]*)>(?:<\\\\/script>)?`, 'g'), `<script$1src="/${localPath}"$2></script>`);
|
|
130
|
+
// 替换其他情况
|
|
131
|
+
newCode = newCode.replace(new RegExp(`(['"\`])${url}\\1`, 'g'), `$1/${localPath}$1`);
|
|
132
|
+
console.log(`[remote-script-localizer] Localized: ${url} -> ${localPath}`);
|
|
133
|
+
});
|
|
134
|
+
return {
|
|
135
|
+
code: newCode,
|
|
136
|
+
map: null,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
159
140
|
},
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
141
|
+
async buildStart() {
|
|
142
|
+
if (!initialized) {
|
|
143
|
+
await initTempDir();
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
async buildEnd() {
|
|
147
|
+
// Wait for any remaining downloads to complete
|
|
148
|
+
await Promise.all(downloadQueue);
|
|
149
|
+
// Clean up temp directory
|
|
150
|
+
try {
|
|
151
|
+
// await rm(tempDir, { recursive: true, force: true });
|
|
152
|
+
// console.log('Cleaned up temporary remote scripts directory');
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
console.error('Failed to clean up temp directory:', error);
|
|
156
|
+
}
|
|
173
157
|
},
|
|
174
158
|
};
|
|
175
159
|
}
|