@deot/docs-playground 1.1.2 → 1.1.3
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 +2 -0
- package/dist/cdn-Czve5_9b.cjs +94 -0
- package/dist/cdn-DEvdGJu2.js +53 -0
- package/dist/compile-Bw7v7QE-.js +333 -0
- package/dist/compile-DSMuM8zl.cjs +333 -0
- package/dist/files-C5UMzYxA.js +178 -0
- package/dist/files-D5LNOtjp.cjs +192 -0
- package/dist/index.cjs +195 -1029
- package/dist/index.d.ts +4 -2
- package/dist/index.js +152 -965
- package/dist/index.style.css +1 -1
- package/dist/linker-B--sjERT.cjs +167 -0
- package/dist/linker-JHdz37DK.js +166 -0
- package/dist/local-sandbox-B8IJ5jWb.js +431 -0
- package/dist/local-sandbox-DnkKrBhf.cjs +428 -0
- package/dist/modules-CInmL-8h.cjs +217 -0
- package/dist/modules-DlLJF_vd.js +211 -0
- package/dist/remote-CKMzn1J3.cjs +106 -0
- package/dist/remote-DfXAsO9n.js +106 -0
- package/dist/rolldown-runtime-C0BPl7ul.cjs +43 -0
- package/dist/script-5Xzzx7u5.cjs +57 -0
- package/dist/script-xKUjE8pf.js +46 -0
- package/dist/scss-Co2it4vB.js +215 -0
- package/dist/scss-DaIqB_qT.cjs +233 -0
- package/dist/store-BF7z-oaO.cjs +964 -0
- package/dist/store-D8vwi-HV.js +767 -0
- package/package.json +20 -9
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { n as createBuiltinImports } from "./cdn-DEvdGJu2.js";
|
|
2
|
+
//#region packages/playground/src/core/runtime/local/builtins.ts
|
|
3
|
+
var loaders = {
|
|
4
|
+
"vue": () => import("vue"),
|
|
5
|
+
"vue-router": () => import("vue-router"),
|
|
6
|
+
"pinia": () => import("pinia"),
|
|
7
|
+
"@deot/helper": () => import("@deot/helper"),
|
|
8
|
+
"@deot/helper-cache": () => import("@deot/helper-cache"),
|
|
9
|
+
"@deot/helper-device": () => import("@deot/helper-device"),
|
|
10
|
+
"@deot/helper-dom": () => import("@deot/helper-dom"),
|
|
11
|
+
"@deot/helper-emitter": () => import("@deot/helper-emitter"),
|
|
12
|
+
"@deot/helper-fp": () => import("@deot/helper-fp"),
|
|
13
|
+
"@deot/helper-is": () => import("@deot/helper-is"),
|
|
14
|
+
"@deot/helper-load": () => import("@deot/helper-load"),
|
|
15
|
+
"@deot/helper-resize": () => import("@deot/helper-resize"),
|
|
16
|
+
"@deot/helper-route": () => import("@deot/helper-route"),
|
|
17
|
+
"@deot/helper-scheduler": () => import("@deot/helper-scheduler"),
|
|
18
|
+
"@deot/helper-shared": () => import("@deot/helper-shared"),
|
|
19
|
+
"@deot/helper-unicode": () => import("@deot/helper-unicode"),
|
|
20
|
+
"@deot/helper-utils": () => import("@deot/helper-utils"),
|
|
21
|
+
"@deot/helper-validator": () => import("@deot/helper-validator"),
|
|
22
|
+
"@deot/helper-wheel": () => import("@deot/helper-wheel"),
|
|
23
|
+
"@deot/http-client": () => import("@deot/http-client"),
|
|
24
|
+
"@deot/http-core": () => import("@deot/http-core"),
|
|
25
|
+
"@deot/http-hooks": () => import("@deot/http-hooks"),
|
|
26
|
+
"@deot/http": () => import("@deot/http"),
|
|
27
|
+
"@deot/vc": () => import("@deot/vc"),
|
|
28
|
+
"@deot/vc-components": () => import("@deot/vc-components"),
|
|
29
|
+
"@deot/vc-hooks": () => import("@deot/vc-hooks"),
|
|
30
|
+
"@deot/vc-locale": () => import("@deot/vc-locale"),
|
|
31
|
+
"lodash-es": () => import("lodash-es"),
|
|
32
|
+
"echarts": () => import("echarts"),
|
|
33
|
+
"photoswipe": () => import("photoswipe"),
|
|
34
|
+
"jszip": () => import("jszip"),
|
|
35
|
+
"jspdf": () => import("jspdf"),
|
|
36
|
+
"dayjs": async () => (await import("dayjs")).default
|
|
37
|
+
};
|
|
38
|
+
var cache = /* @__PURE__ */ new Map();
|
|
39
|
+
/** 直接渲染可从宿主包注入的说明符。用到时再加载,避免预览启动时执行全部副作用。 */
|
|
40
|
+
var localBuiltinIds = new Set(Object.keys(loaders));
|
|
41
|
+
var ensureLocalBuiltin = (id) => {
|
|
42
|
+
const loader = loaders[id];
|
|
43
|
+
if (!loader) return Promise.reject(/* @__PURE__ */ new Error(`[Playground] 没有本地模块 "${id}"`));
|
|
44
|
+
let pending = cache.get(id);
|
|
45
|
+
if (!pending) {
|
|
46
|
+
pending = loader();
|
|
47
|
+
cache.set(id, pending);
|
|
48
|
+
}
|
|
49
|
+
return pending;
|
|
50
|
+
};
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region packages/playground/src/core/runtime/local/modules.ts
|
|
53
|
+
var SKIP_COPY_KEYS = /* @__PURE__ */ new Set([
|
|
54
|
+
"prototype",
|
|
55
|
+
"caller",
|
|
56
|
+
"arguments"
|
|
57
|
+
]);
|
|
58
|
+
var toHostModule = (ns) => {
|
|
59
|
+
if (ns == null || typeof ns !== "object" && typeof ns !== "function") return {
|
|
60
|
+
__esModule: true,
|
|
61
|
+
default: ns
|
|
62
|
+
};
|
|
63
|
+
const source = ns;
|
|
64
|
+
const mod = { __esModule: true };
|
|
65
|
+
const assignKey = (key) => {
|
|
66
|
+
if (SKIP_COPY_KEYS.has(key) || key === "__esModule") return;
|
|
67
|
+
try {
|
|
68
|
+
mod[key] = source[key];
|
|
69
|
+
} catch {}
|
|
70
|
+
};
|
|
71
|
+
try {
|
|
72
|
+
Object.keys(source).forEach(assignKey);
|
|
73
|
+
} catch {}
|
|
74
|
+
try {
|
|
75
|
+
Object.getOwnPropertyNames(source).forEach(assignKey);
|
|
76
|
+
} catch {}
|
|
77
|
+
if (!("default" in mod) || mod.default === void 0) mod.default = source.default !== void 0 ? source.default : source;
|
|
78
|
+
return mod;
|
|
79
|
+
};
|
|
80
|
+
var lookupHostModule = (id, modules) => {
|
|
81
|
+
if (Object.prototype.hasOwnProperty.call(modules, id)) return toHostModule(modules[id]);
|
|
82
|
+
return null;
|
|
83
|
+
};
|
|
84
|
+
var pickNestedExport = (rootMod, rest) => {
|
|
85
|
+
if (!rest) return void 0;
|
|
86
|
+
const parts = rest.split("/").filter(Boolean);
|
|
87
|
+
let current = rootMod;
|
|
88
|
+
for (const part of parts) {
|
|
89
|
+
if (current == null || typeof current !== "object" && typeof current !== "function") return;
|
|
90
|
+
const record = current;
|
|
91
|
+
if (!(part in record)) return void 0;
|
|
92
|
+
current = record[part];
|
|
93
|
+
}
|
|
94
|
+
return current;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* 先精确匹配,再从右往左剥路径,把剩余段当成导出属性。
|
|
98
|
+
* 模块表只来自当前 Playground,不写入全局注册表。
|
|
99
|
+
* @param id 裸模块说明符。
|
|
100
|
+
* @param modules 当前 Playground 的模块表。
|
|
101
|
+
* @returns 可被 `require` 使用的模块;找不到时返回 null。
|
|
102
|
+
*/
|
|
103
|
+
var resolveHostModule = (id, modules) => {
|
|
104
|
+
const exact = lookupHostModule(id, modules);
|
|
105
|
+
if (exact) return exact;
|
|
106
|
+
let cursor = id;
|
|
107
|
+
while (true) {
|
|
108
|
+
const slash = cursor.lastIndexOf("/");
|
|
109
|
+
if (slash <= 0) break;
|
|
110
|
+
const parent = cursor.slice(0, slash);
|
|
111
|
+
const rest = id.slice(parent.length + 1);
|
|
112
|
+
const rootMod = lookupHostModule(parent, modules);
|
|
113
|
+
if (rootMod) {
|
|
114
|
+
const nested = pickNestedExport(rootMod, rest);
|
|
115
|
+
if (nested !== void 0) return toHostModule(nested);
|
|
116
|
+
}
|
|
117
|
+
cursor = parent;
|
|
118
|
+
}
|
|
119
|
+
return null;
|
|
120
|
+
};
|
|
121
|
+
var HOST_VUE_SPECIFIERS = /* @__PURE__ */ new Set(["vue", "vue/server-renderer"]);
|
|
122
|
+
var messageOf = (error) => error instanceof Error ? error.message : String(error);
|
|
123
|
+
/**
|
|
124
|
+
* 找到 import map 里能覆盖该说明符的键。子路径没有独立 URL 时回退到父包。
|
|
125
|
+
* @param id 裸模块说明符。
|
|
126
|
+
* @param imports 合并后的 import map。
|
|
127
|
+
* @returns 命中的 import map 键;没有地址时返回 null。
|
|
128
|
+
*/
|
|
129
|
+
var resolveImportTarget = (id, imports) => {
|
|
130
|
+
if (imports[id]) return id;
|
|
131
|
+
let cursor = id;
|
|
132
|
+
while (true) {
|
|
133
|
+
const slash = cursor.lastIndexOf("/");
|
|
134
|
+
if (slash <= 0) return null;
|
|
135
|
+
const parent = cursor.slice(0, slash);
|
|
136
|
+
if (imports[parent]) return parent;
|
|
137
|
+
cursor = parent;
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
var prefersLocalBuiltin = (id, imports, cdnURL) => {
|
|
141
|
+
if (!localBuiltinIds.has(id) && !HOST_VUE_SPECIFIERS.has(id)) return false;
|
|
142
|
+
const url = imports[id];
|
|
143
|
+
if (!url) return true;
|
|
144
|
+
return url === createBuiltinImports(cdnURL)[id];
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* 内置依赖先注入宿主副本。import map 里与默认 CDN 不同的地址会覆盖,包括 `vue`。
|
|
148
|
+
* @param specifiers 本次预览用到的裸模块说明符。
|
|
149
|
+
* @param imports 合并后的 import map。
|
|
150
|
+
* @param builtins 宿主 Vue 与 vue-router。
|
|
151
|
+
* @param builtins.vue 当前页面的 Vue 模块。
|
|
152
|
+
* @param builtins.vueRouter 打包进来的 vue-router,可被 import map 覆盖。
|
|
153
|
+
* @param loader 按 URL 加载远程模块。
|
|
154
|
+
* @param cdnURL 当前 CDN 根,用来识别默认地址。
|
|
155
|
+
* @returns 模块表和加载错误。
|
|
156
|
+
*/
|
|
157
|
+
var loadLocalModules = async (specifiers, imports, builtins, loader, cdnURL) => {
|
|
158
|
+
const modules = {
|
|
159
|
+
"vue": builtins.vue,
|
|
160
|
+
"vue-router": builtins.vueRouter
|
|
161
|
+
};
|
|
162
|
+
const errors = [];
|
|
163
|
+
const targets = /* @__PURE__ */ new Set();
|
|
164
|
+
const localIds = /* @__PURE__ */ new Set();
|
|
165
|
+
specifiers.forEach((specifier) => {
|
|
166
|
+
if (prefersLocalBuiltin(specifier, imports, cdnURL)) localIds.add(specifier);
|
|
167
|
+
else {
|
|
168
|
+
let cursor = specifier;
|
|
169
|
+
while (true) {
|
|
170
|
+
const slash = cursor.lastIndexOf("/");
|
|
171
|
+
if (slash <= 0) break;
|
|
172
|
+
const parent = cursor.slice(0, slash);
|
|
173
|
+
if (prefersLocalBuiltin(parent, imports, cdnURL)) {
|
|
174
|
+
localIds.add(parent);
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
cursor = parent;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (specifier === "vue-router") {
|
|
181
|
+
if (imports["vue-router"]) targets.add("vue-router");
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const target = resolveImportTarget(specifier, imports);
|
|
185
|
+
if (target && prefersLocalBuiltin(target, imports, cdnURL)) localIds.add(target);
|
|
186
|
+
else if (target) targets.add(target);
|
|
187
|
+
});
|
|
188
|
+
await Promise.all([...localIds].map(async (id) => {
|
|
189
|
+
if (id === "vue" || id === "vue-router") return;
|
|
190
|
+
if (id === "vue/server-renderer") {
|
|
191
|
+
modules[id] = builtins.vue;
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
modules[id] = await ensureLocalBuiltin(id);
|
|
195
|
+
}));
|
|
196
|
+
for (const id of targets) {
|
|
197
|
+
const url = imports[id];
|
|
198
|
+
if (!url || prefersLocalBuiltin(id, imports, cdnURL)) continue;
|
|
199
|
+
try {
|
|
200
|
+
modules[id] = await loader(url);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
errors.push(`[Playground] 无法加载模块 "${id}" (${url}): ${messageOf(error)}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
modules,
|
|
207
|
+
errors
|
|
208
|
+
};
|
|
209
|
+
};
|
|
210
|
+
//#endregion
|
|
211
|
+
export { loadLocalModules, localBuiltinIds as n, prefersLocalBuiltin, resolveHostModule, resolveImportTarget, ensureLocalBuiltin as t, toHostModule };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
const require_files = require("./files-D5LNOtjp.cjs");
|
|
2
|
+
const require_script = require("./script-5Xzzx7u5.cjs");
|
|
3
|
+
const require_modules = require("./modules-CInmL-8h.cjs");
|
|
4
|
+
let sucrase = require("sucrase");
|
|
5
|
+
//#region packages/playground/src/core/runtime/local/remote.ts
|
|
6
|
+
var HOST_VUE = /* @__PURE__ */ new Set(["vue", "vue/server-renderer"]);
|
|
7
|
+
/**
|
|
8
|
+
* 把 CDN 上的 ESM 先拉完整张依赖图,再在当前页面里执行。
|
|
9
|
+
* 裸导入走同一份 import map。与默认 CDN 不同的 `vue` 地址会远程加载。
|
|
10
|
+
* @param imports 合并后的 import map。
|
|
11
|
+
* @param builtins 宿主 Vue 与 vue-router。
|
|
12
|
+
* @param cdnURL 当前 CDN 根,用来识别默认地址。
|
|
13
|
+
* @returns 按 URL 加载并执行远程模块的加载器。
|
|
14
|
+
*/
|
|
15
|
+
var createRemoteLoader = (imports, builtins, cdnURL) => {
|
|
16
|
+
const hostModules = {
|
|
17
|
+
"vue": builtins.vue,
|
|
18
|
+
"vue-router": builtins.vueRouter
|
|
19
|
+
};
|
|
20
|
+
const pendingBuiltins = /* @__PURE__ */ new Set();
|
|
21
|
+
const texts = /* @__PURE__ */ new Map();
|
|
22
|
+
const evaluated = /* @__PURE__ */ new Map();
|
|
23
|
+
const crawled = /* @__PURE__ */ new Set();
|
|
24
|
+
const localBuiltinId = (id) => {
|
|
25
|
+
if (imports[id] && !require_modules.prefersLocalBuiltin(id, imports, cdnURL)) return null;
|
|
26
|
+
if (require_modules.prefersLocalBuiltin(id, imports, cdnURL)) return id;
|
|
27
|
+
let cursor = id;
|
|
28
|
+
while (true) {
|
|
29
|
+
const slash = cursor.lastIndexOf("/");
|
|
30
|
+
if (slash <= 0) return null;
|
|
31
|
+
const parent = cursor.slice(0, slash);
|
|
32
|
+
if (require_modules.prefersLocalBuiltin(parent, imports, cdnURL)) return parent;
|
|
33
|
+
cursor = parent;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const dependencyUrl = (from, specifier) => {
|
|
37
|
+
if (require_files.isRelativeSpecifier(specifier)) return new URL(specifier, from).href;
|
|
38
|
+
if (imports[specifier] && !require_modules.prefersLocalBuiltin(specifier, imports, cdnURL)) return imports[specifier];
|
|
39
|
+
if (HOST_VUE.has(specifier) && require_modules.prefersLocalBuiltin(specifier, imports, cdnURL)) return null;
|
|
40
|
+
let cursor = specifier;
|
|
41
|
+
while (cursor) {
|
|
42
|
+
if (require_modules.localBuiltinIds.has(cursor) && require_modules.prefersLocalBuiltin(cursor, imports, cdnURL)) {
|
|
43
|
+
pendingBuiltins.add(cursor);
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const slash = cursor.lastIndexOf("/");
|
|
47
|
+
if (slash <= 0) break;
|
|
48
|
+
cursor = cursor.slice(0, slash);
|
|
49
|
+
}
|
|
50
|
+
const target = imports[specifier] ? specifier : require_modules.resolveImportTarget(specifier, imports);
|
|
51
|
+
if (!target || !imports[target]) return null;
|
|
52
|
+
return imports[target];
|
|
53
|
+
};
|
|
54
|
+
const crawl = async (url) => {
|
|
55
|
+
if (crawled.has(url)) return;
|
|
56
|
+
crawled.add(url);
|
|
57
|
+
const response = await fetch(url);
|
|
58
|
+
if (!response.ok) throw new Error(`${response.status} ${url}`);
|
|
59
|
+
const text = await response.text();
|
|
60
|
+
texts.set(url, text);
|
|
61
|
+
const source = text.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
62
|
+
await Promise.all(require_files.listImportSpecifiers(source).map(async (specifier) => {
|
|
63
|
+
const next = dependencyUrl(url, specifier);
|
|
64
|
+
if (next) await crawl(next);
|
|
65
|
+
}));
|
|
66
|
+
};
|
|
67
|
+
const requireFrom = (from) => (id) => {
|
|
68
|
+
if (HOST_VUE.has(id) && require_modules.prefersLocalBuiltin(id, imports, cdnURL)) return require_modules.toHostModule(builtins.vue);
|
|
69
|
+
const builtinId = localBuiltinId(id);
|
|
70
|
+
if (builtinId) return require_modules.toHostModule(hostModules[builtinId]);
|
|
71
|
+
if (require_files.isRelativeSpecifier(id)) return evaluate(new URL(id, from).href);
|
|
72
|
+
const target = imports[id] ? id : require_modules.resolveImportTarget(id, imports);
|
|
73
|
+
if (!target || !imports[target]) throw new Error(`[Playground] 未注册的模块 "${id}"`);
|
|
74
|
+
const loaded = evaluate(imports[target]);
|
|
75
|
+
if (target === id) return loaded;
|
|
76
|
+
if (!require_modules.resolveHostModule(id, { [target]: loaded }))
|
|
77
|
+
/* istanbul ignore next -- 父包没有对应导出时才拒绝 */
|
|
78
|
+
throw new Error(`[Playground] 未注册的模块 "${id}"`);
|
|
79
|
+
return loaded;
|
|
80
|
+
};
|
|
81
|
+
const evaluate = (url) => {
|
|
82
|
+
if (evaluated.has(url)) return evaluated.get(url);
|
|
83
|
+
const text = texts.get(url);
|
|
84
|
+
if (text == null) throw new Error(`[Playground] 远程模块尚未下载: ${url}`);
|
|
85
|
+
const cjs = (0, sucrase.transform)(require_script.rewriteImportMeta(text, url), {
|
|
86
|
+
transforms: ["imports"],
|
|
87
|
+
production: true,
|
|
88
|
+
filePath: url
|
|
89
|
+
}).code;
|
|
90
|
+
const module = { exports: {} };
|
|
91
|
+
evaluated.set(url, module.exports);
|
|
92
|
+
new Function("require", "module", "exports", cjs)(requireFrom(url), module, module.exports);
|
|
93
|
+
evaluated.set(url, module.exports);
|
|
94
|
+
return module.exports;
|
|
95
|
+
};
|
|
96
|
+
return { load: async (url) => {
|
|
97
|
+
await crawl(url);
|
|
98
|
+
await Promise.all([...pendingBuiltins].map(async (id) => {
|
|
99
|
+
if (id === "vue" || id === "vue-router") return;
|
|
100
|
+
hostModules[id] = await require_modules.ensureLocalBuiltin(id);
|
|
101
|
+
}));
|
|
102
|
+
return evaluate(url);
|
|
103
|
+
} };
|
|
104
|
+
};
|
|
105
|
+
//#endregion
|
|
106
|
+
exports.createRemoteLoader = createRemoteLoader;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { isRelativeSpecifier, listImportSpecifiers } from "./files-C5UMzYxA.js";
|
|
2
|
+
import { t as rewriteImportMeta } from "./script-xKUjE8pf.js";
|
|
3
|
+
import { n as localBuiltinIds, prefersLocalBuiltin, resolveHostModule, resolveImportTarget, t as ensureLocalBuiltin, toHostModule } from "./modules-DlLJF_vd.js";
|
|
4
|
+
import { transform } from "sucrase";
|
|
5
|
+
//#region packages/playground/src/core/runtime/local/remote.ts
|
|
6
|
+
var HOST_VUE = /* @__PURE__ */ new Set(["vue", "vue/server-renderer"]);
|
|
7
|
+
/**
|
|
8
|
+
* 把 CDN 上的 ESM 先拉完整张依赖图,再在当前页面里执行。
|
|
9
|
+
* 裸导入走同一份 import map。与默认 CDN 不同的 `vue` 地址会远程加载。
|
|
10
|
+
* @param imports 合并后的 import map。
|
|
11
|
+
* @param builtins 宿主 Vue 与 vue-router。
|
|
12
|
+
* @param cdnURL 当前 CDN 根,用来识别默认地址。
|
|
13
|
+
* @returns 按 URL 加载并执行远程模块的加载器。
|
|
14
|
+
*/
|
|
15
|
+
var createRemoteLoader = (imports, builtins, cdnURL) => {
|
|
16
|
+
const hostModules = {
|
|
17
|
+
"vue": builtins.vue,
|
|
18
|
+
"vue-router": builtins.vueRouter
|
|
19
|
+
};
|
|
20
|
+
const pendingBuiltins = /* @__PURE__ */ new Set();
|
|
21
|
+
const texts = /* @__PURE__ */ new Map();
|
|
22
|
+
const evaluated = /* @__PURE__ */ new Map();
|
|
23
|
+
const crawled = /* @__PURE__ */ new Set();
|
|
24
|
+
const localBuiltinId = (id) => {
|
|
25
|
+
if (imports[id] && !prefersLocalBuiltin(id, imports, cdnURL)) return null;
|
|
26
|
+
if (prefersLocalBuiltin(id, imports, cdnURL)) return id;
|
|
27
|
+
let cursor = id;
|
|
28
|
+
while (true) {
|
|
29
|
+
const slash = cursor.lastIndexOf("/");
|
|
30
|
+
if (slash <= 0) return null;
|
|
31
|
+
const parent = cursor.slice(0, slash);
|
|
32
|
+
if (prefersLocalBuiltin(parent, imports, cdnURL)) return parent;
|
|
33
|
+
cursor = parent;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const dependencyUrl = (from, specifier) => {
|
|
37
|
+
if (isRelativeSpecifier(specifier)) return new URL(specifier, from).href;
|
|
38
|
+
if (imports[specifier] && !prefersLocalBuiltin(specifier, imports, cdnURL)) return imports[specifier];
|
|
39
|
+
if (HOST_VUE.has(specifier) && prefersLocalBuiltin(specifier, imports, cdnURL)) return null;
|
|
40
|
+
let cursor = specifier;
|
|
41
|
+
while (cursor) {
|
|
42
|
+
if (localBuiltinIds.has(cursor) && prefersLocalBuiltin(cursor, imports, cdnURL)) {
|
|
43
|
+
pendingBuiltins.add(cursor);
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const slash = cursor.lastIndexOf("/");
|
|
47
|
+
if (slash <= 0) break;
|
|
48
|
+
cursor = cursor.slice(0, slash);
|
|
49
|
+
}
|
|
50
|
+
const target = imports[specifier] ? specifier : resolveImportTarget(specifier, imports);
|
|
51
|
+
if (!target || !imports[target]) return null;
|
|
52
|
+
return imports[target];
|
|
53
|
+
};
|
|
54
|
+
const crawl = async (url) => {
|
|
55
|
+
if (crawled.has(url)) return;
|
|
56
|
+
crawled.add(url);
|
|
57
|
+
const response = await fetch(url);
|
|
58
|
+
if (!response.ok) throw new Error(`${response.status} ${url}`);
|
|
59
|
+
const text = await response.text();
|
|
60
|
+
texts.set(url, text);
|
|
61
|
+
const source = text.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
62
|
+
await Promise.all(listImportSpecifiers(source).map(async (specifier) => {
|
|
63
|
+
const next = dependencyUrl(url, specifier);
|
|
64
|
+
if (next) await crawl(next);
|
|
65
|
+
}));
|
|
66
|
+
};
|
|
67
|
+
const requireFrom = (from) => (id) => {
|
|
68
|
+
if (HOST_VUE.has(id) && prefersLocalBuiltin(id, imports, cdnURL)) return toHostModule(builtins.vue);
|
|
69
|
+
const builtinId = localBuiltinId(id);
|
|
70
|
+
if (builtinId) return toHostModule(hostModules[builtinId]);
|
|
71
|
+
if (isRelativeSpecifier(id)) return evaluate(new URL(id, from).href);
|
|
72
|
+
const target = imports[id] ? id : resolveImportTarget(id, imports);
|
|
73
|
+
if (!target || !imports[target]) throw new Error(`[Playground] 未注册的模块 "${id}"`);
|
|
74
|
+
const loaded = evaluate(imports[target]);
|
|
75
|
+
if (target === id) return loaded;
|
|
76
|
+
if (!resolveHostModule(id, { [target]: loaded }))
|
|
77
|
+
/* istanbul ignore next -- 父包没有对应导出时才拒绝 */
|
|
78
|
+
throw new Error(`[Playground] 未注册的模块 "${id}"`);
|
|
79
|
+
return loaded;
|
|
80
|
+
};
|
|
81
|
+
const evaluate = (url) => {
|
|
82
|
+
if (evaluated.has(url)) return evaluated.get(url);
|
|
83
|
+
const text = texts.get(url);
|
|
84
|
+
if (text == null) throw new Error(`[Playground] 远程模块尚未下载: ${url}`);
|
|
85
|
+
const cjs = transform(rewriteImportMeta(text, url), {
|
|
86
|
+
transforms: ["imports"],
|
|
87
|
+
production: true,
|
|
88
|
+
filePath: url
|
|
89
|
+
}).code;
|
|
90
|
+
const module = { exports: {} };
|
|
91
|
+
evaluated.set(url, module.exports);
|
|
92
|
+
new Function("require", "module", "exports", cjs)(requireFrom(url), module, module.exports);
|
|
93
|
+
evaluated.set(url, module.exports);
|
|
94
|
+
return module.exports;
|
|
95
|
+
};
|
|
96
|
+
return { load: async (url) => {
|
|
97
|
+
await crawl(url);
|
|
98
|
+
await Promise.all([...pendingBuiltins].map(async (id) => {
|
|
99
|
+
if (id === "vue" || id === "vue-router") return;
|
|
100
|
+
hostModules[id] = await ensureLocalBuiltin(id);
|
|
101
|
+
}));
|
|
102
|
+
return evaluate(url);
|
|
103
|
+
} };
|
|
104
|
+
};
|
|
105
|
+
//#endregion
|
|
106
|
+
export { createRemoteLoader };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __exportAll = (all, no_symbols) => {
|
|
9
|
+
let target = {};
|
|
10
|
+
for (var name in all) __defProp(target, name, {
|
|
11
|
+
get: all[name],
|
|
12
|
+
enumerable: true
|
|
13
|
+
});
|
|
14
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
15
|
+
return target;
|
|
16
|
+
};
|
|
17
|
+
var __copyProps = (to, from, except, desc) => {
|
|
18
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
19
|
+
key = keys[i];
|
|
20
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
21
|
+
get: ((k) => from[k]).bind(null, key),
|
|
22
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return to;
|
|
26
|
+
};
|
|
27
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
28
|
+
value: mod,
|
|
29
|
+
enumerable: true
|
|
30
|
+
}) : target, mod));
|
|
31
|
+
//#endregion
|
|
32
|
+
Object.defineProperty(exports, "__exportAll", {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
get: function() {
|
|
35
|
+
return __exportAll;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
Object.defineProperty(exports, "__toESM", {
|
|
39
|
+
enumerable: true,
|
|
40
|
+
get: function() {
|
|
41
|
+
return __toESM;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
let sucrase = require("sucrase");
|
|
2
|
+
//#region packages/playground/src/core/runtime/local/compile/script.ts
|
|
3
|
+
/**
|
|
4
|
+
* files 里的 `import.meta.env` 没有 Vite 注入,接到开发态占位对象上。
|
|
5
|
+
* @param code 源码文本。
|
|
6
|
+
* @param filename 当前虚拟文件名。
|
|
7
|
+
* @returns 替换 `import.meta` 之后的源码。
|
|
8
|
+
*/
|
|
9
|
+
var rewriteImportMeta = (code, filename) => {
|
|
10
|
+
if (!code.includes("import.meta")) return code;
|
|
11
|
+
const meta = {
|
|
12
|
+
url: `playground://${filename}`,
|
|
13
|
+
env: {
|
|
14
|
+
MODE: "development",
|
|
15
|
+
DEV: true,
|
|
16
|
+
PROD: false,
|
|
17
|
+
SSR: false
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
return `var import_meta = ${JSON.stringify(meta)};\n${code.replaceAll("import.meta", "import_meta")}`;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* 将 TS / ESM 转成可被 `new Function('require','module','exports', code)` 执行的 CJS。
|
|
24
|
+
* @param code 源码文本。
|
|
25
|
+
* @param filename 当前虚拟文件名,用来判断是否按 TypeScript 转换。
|
|
26
|
+
* @param options 转换选项。
|
|
27
|
+
* @param options.typescript 是否启用 TypeScript 转换。
|
|
28
|
+
* @returns 可执行的 CJS 文本。
|
|
29
|
+
*/
|
|
30
|
+
var transformScript = (code, filename, options = {}) => {
|
|
31
|
+
const transforms = ["imports"];
|
|
32
|
+
if (options.typescript === true || options.typescript !== false && (filename.endsWith(".ts") || filename.endsWith(".tsx"))) transforms.unshift("typescript");
|
|
33
|
+
try {
|
|
34
|
+
const withMeta = rewriteImportMeta(code, filename);
|
|
35
|
+
return `${(0, sucrase.transform)(withMeta, {
|
|
36
|
+
transforms,
|
|
37
|
+
production: true,
|
|
38
|
+
filePath: filename
|
|
39
|
+
}).code}\n//# sourceURL=playground://${filename}`;
|
|
40
|
+
} catch (error) {
|
|
41
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
42
|
+
throw new Error(`[Playground] 脚本转换失败 ${filename}: ${message}`, { cause: error });
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
//#endregion
|
|
46
|
+
Object.defineProperty(exports, "rewriteImportMeta", {
|
|
47
|
+
enumerable: true,
|
|
48
|
+
get: function() {
|
|
49
|
+
return rewriteImportMeta;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
Object.defineProperty(exports, "transformScript", {
|
|
53
|
+
enumerable: true,
|
|
54
|
+
get: function() {
|
|
55
|
+
return transformScript;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { transform } from "sucrase";
|
|
2
|
+
//#region packages/playground/src/core/runtime/local/compile/script.ts
|
|
3
|
+
/**
|
|
4
|
+
* files 里的 `import.meta.env` 没有 Vite 注入,接到开发态占位对象上。
|
|
5
|
+
* @param code 源码文本。
|
|
6
|
+
* @param filename 当前虚拟文件名。
|
|
7
|
+
* @returns 替换 `import.meta` 之后的源码。
|
|
8
|
+
*/
|
|
9
|
+
var rewriteImportMeta = (code, filename) => {
|
|
10
|
+
if (!code.includes("import.meta")) return code;
|
|
11
|
+
const meta = {
|
|
12
|
+
url: `playground://${filename}`,
|
|
13
|
+
env: {
|
|
14
|
+
MODE: "development",
|
|
15
|
+
DEV: true,
|
|
16
|
+
PROD: false,
|
|
17
|
+
SSR: false
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
return `var import_meta = ${JSON.stringify(meta)};\n${code.replaceAll("import.meta", "import_meta")}`;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* 将 TS / ESM 转成可被 `new Function('require','module','exports', code)` 执行的 CJS。
|
|
24
|
+
* @param code 源码文本。
|
|
25
|
+
* @param filename 当前虚拟文件名,用来判断是否按 TypeScript 转换。
|
|
26
|
+
* @param options 转换选项。
|
|
27
|
+
* @param options.typescript 是否启用 TypeScript 转换。
|
|
28
|
+
* @returns 可执行的 CJS 文本。
|
|
29
|
+
*/
|
|
30
|
+
var transformScript = (code, filename, options = {}) => {
|
|
31
|
+
const transforms = ["imports"];
|
|
32
|
+
if (options.typescript === true || options.typescript !== false && (filename.endsWith(".ts") || filename.endsWith(".tsx"))) transforms.unshift("typescript");
|
|
33
|
+
try {
|
|
34
|
+
const withMeta = rewriteImportMeta(code, filename);
|
|
35
|
+
return `${transform(withMeta, {
|
|
36
|
+
transforms,
|
|
37
|
+
production: true,
|
|
38
|
+
filePath: filename
|
|
39
|
+
}).code}\n//# sourceURL=playground://${filename}`;
|
|
40
|
+
} catch (error) {
|
|
41
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
42
|
+
throw new Error(`[Playground] 脚本转换失败 ${filename}: ${message}`, { cause: error });
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
//#endregion
|
|
46
|
+
export { transformScript as n, rewriteImportMeta as t };
|