@deot/docs-playground 1.1.9 → 1.2.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 +13 -4
- package/dist/{compile-no-AB7-B.js → compile-D33div4Y.js} +1 -1
- package/dist/{css-D47JLekg.js → css-sV_dM9Hl.js} +19 -7
- package/dist/index.js +68 -180
- package/package.json +4 -10
- package/dist/compile-yveCpyT3.cjs +0 -322
- package/dist/css-DGNVJsLz.cjs +0 -858
- package/dist/index.cjs +0 -4320
package/README.md
CHANGED
|
@@ -53,7 +53,7 @@ const files = ref({
|
|
|
53
53
|
| `id` | `string` | `''` | 标题锚点 id;未传时从 `title` 自动生成。仅挂在内联 runtime 标题上,弹窗不重复。 |
|
|
54
54
|
| `expandable` | `true \| number` | `undefined` | 开启预览高度展开;未传不显示控件;`true` 展开到剩余视口;正数为目标高度(px)。 |
|
|
55
55
|
| `previewScroller` | `boolean` | `false` | 在 iframe 内用 `@deot/vc` Scroller 替换原生滚动条;开启后会动态探测 `Scroller`,不存在则回退原生滚动。 |
|
|
56
|
-
| `local` | `boolean` | `true` |
|
|
56
|
+
| `local` | `boolean` | `true` | 在当前文档编译并挂载。业务模块通过运行时 ESM 加载,可通过 import map 逐个覆盖;预览使用所选 Vue 运行时挂载。 |
|
|
57
57
|
| `options` | `PlaygroundOptions` | `{}` | 传给 Vue REPL store 的实例级选项;`cdnURL` 会同时作用于预览样式和默认 import map。 |
|
|
58
58
|
| `previewOptions` | `SandboxProps['previewOptions']` | `undefined` | 传给当前 iframe 的 preview 选项。 |
|
|
59
59
|
| `locale` | `Language` | `en-US` | 界面语言;未传入时使用上层 Locale Provider。 |
|
|
@@ -154,16 +154,25 @@ const handleMessage = async () => {
|
|
|
154
154
|
|
|
155
155
|
## 运行环境
|
|
156
156
|
|
|
157
|
-
- iframe 运行时通过公共 CDN 加载 Vue 和默认 import map 中的依赖;local
|
|
157
|
+
- iframe 运行时通过公共 CDN 加载 Vue 和默认 import map 中的依赖;local 运行时默认复用宿主 Vue 和 vue-router,业务包通过 ESM 加载,需要网络访问或配置可访问的本地 ESM 地址。
|
|
158
|
+
- iframe 模式初始化时会补齐宿主页缺失的 `globalThis.process` 和 `process.env`,兼容 `@vue/repl` 的 JSX/TSX 编译;已有对象及环境值保持不变,不模拟其他 Node API。
|
|
158
159
|
- 默认 CDN 为 `https://cdn.jsdelivr.net/npm`;未使用 launch 时可通过 `options.cdnURL` 调整默认节点。launch 已选点时统一使用 `$docs.runtime.cdn`,优先于实例 `cdnURL`。
|
|
159
160
|
- jsDelivr npm、旧 `unpkg.com` 和 `esm.unpkg.com` 地址在实际加载时转换,再经过可选 `$docs.resolve.cdn({ url })`。jsDelivr 转换入口使用 `/+esm`,ESM UNPKG 使用包或文件入口。预览 CSS、import map、裸包回退和 Sass 共用该规则;原始映射与缓存不被改写。
|
|
160
|
-
-
|
|
161
|
+
- 直接渲染时,未配置的 npm 模块(含作用域包、版本和子路径)自动通过上述 ESM 规则加载,无需预先登记包名。组件包的传递依赖也适用,预览文件和远程模块中的 `import()` 在调用时加载。可用 `options.builtinImportMap.imports` 指定依赖的版本和 URL;显式 URL 加载失败会直接报错。
|
|
161
162
|
- Vue SFC 的 `<style lang="scss">` / `lang="sass"` 以及独立 `.scss` / `.sass` 文件会在浏览器里编译;`_partial.scss` 只作为 `@use` 依赖。
|
|
162
|
-
- local 模式按模块识别显式 URL 覆盖,即使地址与内置默认相同也会加载该 URL
|
|
163
|
+
- local 模式按模块识别显式 URL 覆盖,即使地址与内置默认相同也会加载该 URL。组件包和工具包统一经运行时加载器读取 ESM,不复用宿主的业务包副本。远程模块的 Vue 导入统一绑定到所选运行时;覆盖 `vue` 时,编译产物、挂载、组件引用、注入和 vue-router 使用对应的远程运行时。不同预览的覆盖互不影响,各预览独立执行远程模块。
|
|
163
164
|
- local 模式在当前页面按 URL 缓存外部模块的下载和转换成果,并合并并发请求;切换文档时可复用,最多保留最近使用的 128 个模块。各预览仍独立执行模块并解析依赖覆盖;失败的加载不缓存,同源模块实时读取,刷新页面会清空缓存。
|
|
164
165
|
- 每个 Playground 实例都使用自己的 preview 配置和 iframe 消息来源校验。
|
|
165
166
|
- `local` 默认开启:同一份 `files` 在当前文档里编译。直接渲染不撑开预览高度,`expandable` 固定为关闭,`docs:playground.run` 不会申请临时高度;`<DocsLink>` 仍通过 `docs:navigate` 通知。`local: false` 改回 iframe Sandbox。
|
|
166
167
|
|
|
168
|
+
## 运行时模块加载
|
|
169
|
+
|
|
170
|
+
加载器按模块说明符解析依赖,不识别组件名,不维护可选依赖白名单。静态导入在挂载前准备,动态导入在实际调用时准备;组件库内部的可选依赖沿用组件自身的加载时机。因此普通示例不会因加载组件包而预先下载所有动态依赖,也无需给组件额外增加异步包装。
|
|
171
|
+
|
|
172
|
+
显式模块地址优先于默认 CDN。CDN 返回的带版本依赖地址会保留版本;同名显式覆盖可以替换该依赖。失败后可再次调用动态导入或刷新预览重试,错误包含请求地址与原因;模块自身的执行异常继续报错。
|
|
173
|
+
|
|
174
|
+
依赖须能作为浏览器 ESM 执行。若 CDN 转换产物无法正常运行,可通过现有模块配置指定包的原始 ESM 文件,无需增加包名适配。加载器不猜测 npm 包对应的全局变量名,也不向 `window` 写入依赖;若库自身优先读取已有全局实现,该行为由库保留。已在宿主页其他位置执行的原生 `import()` 不受接管,iframe Sandbox 继续使用自己的 import map 机制。
|
|
175
|
+
|
|
167
176
|
## 仓库内 examples
|
|
168
177
|
|
|
169
178
|
在 monorepo 根目录执行 `npm run dev` 可预览 [`packages/playground/examples`](examples/) 下的单文件与多文件 Playground 示例。
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as transformScript, c as createFileIndex, h as resolveEntry, m as normalizeVirtualPath, s as collectReachableFilenames, t as collectCss, u as getExtension, v as compileScssSource, y as extractScssExports } from "./css-
|
|
1
|
+
import { a as transformScript, c as createFileIndex, h as resolveEntry, m as normalizeVirtualPath, s as collectReachableFilenames, t as collectCss, u as getExtension, v as compileScssSource, y as extractScssExports } from "./css-sV_dM9Hl.js";
|
|
2
2
|
import { compileString } from "sass";
|
|
3
3
|
//#region packages/playground/src/core/runtime/local/compile/scss.ts
|
|
4
4
|
/**
|
|
@@ -457,12 +457,14 @@ var isInsideRoot = (filename, root) => {
|
|
|
457
457
|
/**
|
|
458
458
|
* 静态 import / export-from / import() 的模块说明符。
|
|
459
459
|
* @param code 源码文本。
|
|
460
|
+
* @param includeDynamic 是否收集动态导入;local 运行时在调用时单独加载。
|
|
460
461
|
* @returns 按出现顺序收集到的说明符。
|
|
461
462
|
*/
|
|
462
|
-
var listImportSpecifiers = (code) => {
|
|
463
|
+
var listImportSpecifiers = (code, includeDynamic = true) => {
|
|
463
464
|
const result = [];
|
|
464
465
|
const source = String(code || "");
|
|
465
|
-
|
|
466
|
+
const re = includeDynamic ? /(?:\bfrom\s+|import\s*\(\s*|import\s+)['"]([^'"]+)['"]/gu : /(?:\bfrom\s+|import\s+)['"]([^'"]+)['"]/gu;
|
|
467
|
+
for (const match of source.matchAll(re)) if (match[1]) result.push(match[1]);
|
|
466
468
|
return result;
|
|
467
469
|
};
|
|
468
470
|
var isRelativeSpecifier = (id) => id === "." || id === ".." || id.startsWith("./") || id.startsWith("../") || id.startsWith("/");
|
|
@@ -489,12 +491,12 @@ var collectReachableFilenames = (files, entry) => {
|
|
|
489
491
|
visit(entry);
|
|
490
492
|
return ordered;
|
|
491
493
|
};
|
|
492
|
-
var collectBareSpecifiers = (files, filenames) => {
|
|
494
|
+
var collectBareSpecifiers = (files, filenames, includeDynamic = true) => {
|
|
493
495
|
const index = createFileIndex(files);
|
|
494
496
|
const result = [];
|
|
495
497
|
const seen = /* @__PURE__ */ new Set();
|
|
496
498
|
filenames.forEach((filename) => {
|
|
497
|
-
listImportSpecifiers(index.get(normalizeVirtualPath(filename)) || "").forEach((specifier) => {
|
|
499
|
+
listImportSpecifiers(index.get(normalizeVirtualPath(filename)) || "", includeDynamic).forEach((specifier) => {
|
|
498
500
|
if (!specifier || isRelativeSpecifier(specifier) || seen.has(specifier) || /\.(?:css|scss|sass)(?:[?#]|$)/.test(specifier)) return;
|
|
499
501
|
seen.add(specifier);
|
|
500
502
|
result.push(specifier);
|
|
@@ -504,7 +506,15 @@ var collectBareSpecifiers = (files, filenames) => {
|
|
|
504
506
|
};
|
|
505
507
|
//#endregion
|
|
506
508
|
//#region packages/playground/src/core/runtime/local/compile/script.ts
|
|
507
|
-
var { babelParse, walkIdentifiers, MagicString } = VueCompiler;
|
|
509
|
+
var { babelParse, walk, walkIdentifiers, MagicString } = VueCompiler;
|
|
510
|
+
var rewriteDynamicImports = (code) => {
|
|
511
|
+
if (!code.includes("import")) return code;
|
|
512
|
+
const source = new MagicString(code);
|
|
513
|
+
walk(babelParse(code, { sourceType: "module" }), { enter(node) {
|
|
514
|
+
if (node.type === "ImportExpression" || node.type === "CallExpression" && node.callee?.type === "Import") source.overwrite(node.start, node.start + 6, "__docs_import");
|
|
515
|
+
} });
|
|
516
|
+
return source.toString();
|
|
517
|
+
};
|
|
508
518
|
var rewriteJsxAttributes = (code) => {
|
|
509
519
|
const replacements = [];
|
|
510
520
|
for (const match of code.matchAll(/\b([\w-]+:[\w-]+)\s*=\s*\{/g)) {
|
|
@@ -583,15 +593,17 @@ var transformScript = (code, filename, options = {}) => {
|
|
|
583
593
|
try {
|
|
584
594
|
const script = wantTs ? removeImportedTypeExports(code) : code;
|
|
585
595
|
const source = options.jsx ? `import { h as __docs_h, Fragment as __docs_Fragment } from 'vue';\n${rewriteJsxAttributes(script)}` : script;
|
|
586
|
-
|
|
596
|
+
const result = transform(source, {
|
|
587
597
|
transforms,
|
|
598
|
+
preserveDynamicImport: true,
|
|
588
599
|
disableESTransforms: true,
|
|
589
600
|
production: true,
|
|
590
601
|
jsxRuntime: "classic",
|
|
591
602
|
jsxPragma: "__docs_h",
|
|
592
603
|
jsxFragmentPragma: "__docs_Fragment",
|
|
593
604
|
filePath: filename
|
|
594
|
-
})
|
|
605
|
+
});
|
|
606
|
+
return `${rewriteImportMeta(options.esm ? result.code : rewriteDynamicImports(result.code), filename)}\n//# sourceURL=playground://${filename}`;
|
|
595
607
|
} catch (error) {
|
|
596
608
|
const message = error instanceof Error ? error.message : String(error);
|
|
597
609
|
throw new Error(`[Playground] 脚本转换失败 ${filename}: ${message}`, { cause: error });
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { A as DEFAULT_ENTRY, C as createBuiltinStyles, D as resolveCdnURL, E as normalizeCdnURL, O as resolveNpmImport, S as createBuiltinImports, T as isCdnEsmURL, _ as bindPlaygroundScss, a as transformScript, b as whenSassReady, c as createFileIndex, d as isIgnoredFilename, f as isInsideRoot, g as resolveModulePath, i as rewriteImportMeta, j as NEW_SFC_CODE, k as DEFAULT_CDN_URL, l as getCommonRoot, m as normalizeVirtualPath, n as injectStyle, o as collectBareSpecifiers, p as isRelativeSpecifier, r as removeStyle, s as collectReachableFilenames, w as createCdnResolver, x as cdnModuleName } from "./css-
|
|
1
|
+
import { A as DEFAULT_ENTRY, C as createBuiltinStyles, D as resolveCdnURL, E as normalizeCdnURL, O as resolveNpmImport, S as createBuiltinImports, T as isCdnEsmURL, _ as bindPlaygroundScss, a as transformScript, b as whenSassReady, c as createFileIndex, d as isIgnoredFilename, f as isInsideRoot, g as resolveModulePath, i as rewriteImportMeta, j as NEW_SFC_CODE, k as DEFAULT_CDN_URL, l as getCommonRoot, m as normalizeVirtualPath, n as injectStyle, o as collectBareSpecifiers, p as isRelativeSpecifier, r as removeStyle, s as collectReachableFilenames, w as createCdnResolver, x as cdnModuleName } from "./css-sV_dM9Hl.js";
|
|
2
2
|
import * as Vue from "vue";
|
|
3
3
|
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineAsyncComponent, defineComponent, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, openBlock, ref, renderList, shallowRef, toDisplayString, unref, vModelText, vShow, watch, withCtx, withDirectives, withKeys, withModifiers } from "vue";
|
|
4
|
-
import * as Vc from "@deot/vc";
|
|
5
4
|
import { Clipboard, Dropdown, DropdownItem, DropdownMenu, Message, Popconfirm, Portal, Scroller, TransitionFade } from "@deot/vc";
|
|
6
5
|
import { provideLocale, useLocale } from "@deot/docs-locale";
|
|
7
6
|
import hljs from "highlight.js";
|
|
@@ -15,9 +14,6 @@ import { init, parse } from "es-module-lexer";
|
|
|
15
14
|
import { transform } from "sucrase";
|
|
16
15
|
import * as VueCompiler from "@vue/compiler-sfc/dist/compiler-sfc.esm-browser.js";
|
|
17
16
|
import * as VueRouter from "vue-router";
|
|
18
|
-
import * as Pinia from "pinia";
|
|
19
|
-
import * as VcComponents from "@deot/vc-components";
|
|
20
|
-
import * as VcHooks from "@deot/vc-hooks";
|
|
21
17
|
//#region \0rolldown/runtime.js
|
|
22
18
|
var __defProp = Object.defineProperty;
|
|
23
19
|
var __exportAll = (all, no_symbols) => {
|
|
@@ -2270,6 +2266,9 @@ var createRuntimeImports = (cdnURL, builtinImportMap) => ({
|
|
|
2270
2266
|
...createRuntimeImportOverrides(builtinImportMap)
|
|
2271
2267
|
});
|
|
2272
2268
|
var createRuntimeStore = (files, entry, options) => {
|
|
2269
|
+
const host = globalThis;
|
|
2270
|
+
const replProcess = host.process ??= {};
|
|
2271
|
+
replProcess.env ??= {};
|
|
2273
2272
|
const { cdnURL, builtinImportMap, ...storeOptions } = options;
|
|
2274
2273
|
const replFiles = ref(Object.fromEntries(Object.entries(files).map(([filename, code]) => {
|
|
2275
2274
|
const file = createReplFile(filename, code);
|
|
@@ -2698,56 +2697,6 @@ var formatPlaygroundRuntimeError = (error) => {
|
|
|
2698
2697
|
return text;
|
|
2699
2698
|
};
|
|
2700
2699
|
//#endregion
|
|
2701
|
-
//#region packages/playground/src/core/runtime/local/builtins.ts
|
|
2702
|
-
var loaders = {
|
|
2703
|
-
"vue": () => import("vue"),
|
|
2704
|
-
"vue-router": () => import("vue-router"),
|
|
2705
|
-
"pinia": async () => Pinia,
|
|
2706
|
-
"@deot/helper": () => import("@deot/helper"),
|
|
2707
|
-
"@deot/helper-cache": () => import("@deot/helper-cache"),
|
|
2708
|
-
"@deot/helper-device": () => import("@deot/helper-device"),
|
|
2709
|
-
"@deot/helper-dom": () => import("@deot/helper-dom"),
|
|
2710
|
-
"@deot/helper-emitter": () => import("@deot/helper-emitter"),
|
|
2711
|
-
"@deot/helper-fp": () => import("@deot/helper-fp"),
|
|
2712
|
-
"@deot/helper-is": () => import("@deot/helper-is"),
|
|
2713
|
-
"@deot/helper-load": () => import("@deot/helper-load"),
|
|
2714
|
-
"@deot/helper-resize": () => import("@deot/helper-resize"),
|
|
2715
|
-
"@deot/helper-route": () => import("@deot/helper-route"),
|
|
2716
|
-
"@deot/helper-scheduler": () => import("@deot/helper-scheduler"),
|
|
2717
|
-
"@deot/helper-shared": () => import("@deot/helper-shared"),
|
|
2718
|
-
"@deot/helper-unicode": () => import("@deot/helper-unicode"),
|
|
2719
|
-
"@deot/helper-utils": () => import("@deot/helper-utils"),
|
|
2720
|
-
"@deot/helper-validator": () => import("@deot/helper-validator"),
|
|
2721
|
-
"@deot/helper-wheel": () => import("@deot/helper-wheel"),
|
|
2722
|
-
"@deot/http-client": () => import("@deot/http-client"),
|
|
2723
|
-
"@deot/http-core": () => import("@deot/http-core"),
|
|
2724
|
-
"@deot/http-hooks": () => import("@deot/http-hooks"),
|
|
2725
|
-
"@deot/http": () => import("@deot/http"),
|
|
2726
|
-
"@deot/vc": async () => Vc,
|
|
2727
|
-
"@deot/vc-components": async () => VcComponents,
|
|
2728
|
-
"@deot/vc-hooks": async () => VcHooks,
|
|
2729
|
-
"@deot/vc-locale": () => import("@deot/vc-locale"),
|
|
2730
|
-
"lodash-es": () => import("lodash-es"),
|
|
2731
|
-
"echarts": () => import("echarts"),
|
|
2732
|
-
"photoswipe": () => import("photoswipe"),
|
|
2733
|
-
"jszip": () => import("jszip"),
|
|
2734
|
-
"jspdf": () => import("jspdf"),
|
|
2735
|
-
"dayjs": async () => (await import("dayjs")).default
|
|
2736
|
-
};
|
|
2737
|
-
var cache = /* @__PURE__ */ new Map();
|
|
2738
|
-
/** 直接渲染可从宿主包注入的说明符;与 Vue 无关的大型依赖按需加载。 */
|
|
2739
|
-
var localBuiltinIds = new Set(Object.keys(loaders));
|
|
2740
|
-
var ensureLocalBuiltin = (id) => {
|
|
2741
|
-
const loader = loaders[id];
|
|
2742
|
-
if (!loader) return Promise.reject(/* @__PURE__ */ new Error(`[Playground] 没有本地模块 "${id}"`));
|
|
2743
|
-
let pending = cache.get(id);
|
|
2744
|
-
if (!pending) {
|
|
2745
|
-
pending = loader();
|
|
2746
|
-
cache.set(id, pending);
|
|
2747
|
-
}
|
|
2748
|
-
return pending;
|
|
2749
|
-
};
|
|
2750
|
-
//#endregion
|
|
2751
2700
|
//#region packages/playground/src/core/runtime/local/modules.ts
|
|
2752
2701
|
var SKIP_COPY_KEYS = /* @__PURE__ */ new Set([
|
|
2753
2702
|
"prototype",
|
|
@@ -2817,15 +2766,10 @@ var resolveHostModule = (id, modules) => {
|
|
|
2817
2766
|
}
|
|
2818
2767
|
return null;
|
|
2819
2768
|
};
|
|
2820
|
-
var
|
|
2821
|
-
|
|
2769
|
+
var HOST_MODULES = /* @__PURE__ */ new Set([
|
|
2770
|
+
"vue",
|
|
2822
2771
|
"vue/server-renderer",
|
|
2823
|
-
"vue-router"
|
|
2824
|
-
"pinia",
|
|
2825
|
-
"@deot/vc",
|
|
2826
|
-
"@deot/vc-components",
|
|
2827
|
-
"@deot/vc-hooks",
|
|
2828
|
-
"@deot/vc-locale"
|
|
2772
|
+
"vue-router"
|
|
2829
2773
|
]);
|
|
2830
2774
|
var messageOf = (error) => error instanceof Error ? error.message : String(error);
|
|
2831
2775
|
/**
|
|
@@ -2845,13 +2789,13 @@ var resolveImportTarget = (id, imports) => {
|
|
|
2845
2789
|
cursor = parent;
|
|
2846
2790
|
}
|
|
2847
2791
|
};
|
|
2848
|
-
var
|
|
2849
|
-
if (!
|
|
2792
|
+
var usesHostRuntime = (id, imports, overrides = new Set(Object.keys(imports))) => {
|
|
2793
|
+
if (!HOST_MODULES.has(id)) return false;
|
|
2850
2794
|
if (overrides.has(id)) return false;
|
|
2851
|
-
return
|
|
2795
|
+
return id === "vue" || !overrides.has("vue");
|
|
2852
2796
|
};
|
|
2853
2797
|
/**
|
|
2854
|
-
*
|
|
2798
|
+
* Vue 运行时默认注入宿主副本,其他模块按显式 URL 或默认 CDN 加载。
|
|
2855
2799
|
* @param specifiers 本次预览用到的裸模块说明符。
|
|
2856
2800
|
* @param imports 合并后的 import map。
|
|
2857
2801
|
* @param builtins 宿主 Vue 与 vue-router。
|
|
@@ -2868,43 +2812,18 @@ var loadLocalModules = async (specifiers, imports, builtins, loader, overrides =
|
|
|
2868
2812
|
};
|
|
2869
2813
|
const errors = [];
|
|
2870
2814
|
const targets = /* @__PURE__ */ new Set();
|
|
2871
|
-
const
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
else {
|
|
2876
|
-
let cursor = specifier;
|
|
2877
|
-
while (true) {
|
|
2878
|
-
const slash = cursor.lastIndexOf("/");
|
|
2879
|
-
if (slash <= 0) break;
|
|
2880
|
-
const parent = cursor.slice(0, slash);
|
|
2881
|
-
if (prefersLocalBuiltin(parent, imports, overrides)) {
|
|
2882
|
-
localIds.add(parent);
|
|
2883
|
-
local = true;
|
|
2884
|
-
break;
|
|
2885
|
-
}
|
|
2886
|
-
cursor = parent;
|
|
2887
|
-
}
|
|
2888
|
-
}
|
|
2889
|
-
const target = resolveImportTarget(specifier, imports);
|
|
2890
|
-
if (target && prefersLocalBuiltin(target, imports, overrides)) localIds.add(target);
|
|
2891
|
-
else if (target) targets.add(target);
|
|
2892
|
-
else if (!local && !localIds.has(specifier)) {
|
|
2893
|
-
imports[specifier] = resolveNpmImport(specifier);
|
|
2894
|
-
targets.add(specifier);
|
|
2895
|
-
}
|
|
2896
|
-
});
|
|
2897
|
-
await Promise.all([...localIds].map(async (id) => {
|
|
2898
|
-
if (id === "vue" || id === "vue-router") return;
|
|
2899
|
-
if (id === "vue/server-renderer") {
|
|
2900
|
-
modules[id] = builtins.vue;
|
|
2901
|
-
return;
|
|
2815
|
+
for (const specifier of specifiers) {
|
|
2816
|
+
if (usesHostRuntime(specifier, imports, overrides)) {
|
|
2817
|
+
if (specifier === "vue/server-renderer") modules[specifier] = builtins.vue;
|
|
2818
|
+
continue;
|
|
2902
2819
|
}
|
|
2903
|
-
|
|
2904
|
-
|
|
2820
|
+
const target = resolveImportTarget(specifier, imports) || specifier;
|
|
2821
|
+
imports[target] ||= resolveNpmImport(target);
|
|
2822
|
+
targets.add(target);
|
|
2823
|
+
}
|
|
2905
2824
|
for (const id of targets) {
|
|
2906
2825
|
const url = imports[id];
|
|
2907
|
-
if (!url ||
|
|
2826
|
+
if (!url || usesHostRuntime(id, imports, overrides)) continue;
|
|
2908
2827
|
try {
|
|
2909
2828
|
modules[id] = await loader(url);
|
|
2910
2829
|
} catch (error) {
|
|
@@ -3040,7 +2959,11 @@ var linkPlayground = (compiled, files, options = {}) => {
|
|
|
3040
2959
|
cache.set(key, module.exports);
|
|
3041
2960
|
visiting.add(key);
|
|
3042
2961
|
try {
|
|
3043
|
-
new Function("require", "module", "exports", mod.js)(requireFn(key), module, module.exports)
|
|
2962
|
+
new Function("require", "module", "exports", "__docs_import", mod.js)(requireFn(key), module, module.exports, async (id) => {
|
|
2963
|
+
if (isRelativeSpecifier(id) || resolveHostModule(id, modules)) return requireFn(key)(id);
|
|
2964
|
+
if (options.loadModule) return toHostModule(await options.loadModule(id));
|
|
2965
|
+
return requireFn(key)(id);
|
|
2966
|
+
});
|
|
3044
2967
|
cache.set(key, module.exports);
|
|
3045
2968
|
return module.exports;
|
|
3046
2969
|
} catch (error) {
|
|
@@ -3080,7 +3003,6 @@ var linkPlayground = (compiled, files, options = {}) => {
|
|
|
3080
3003
|
};
|
|
3081
3004
|
//#endregion
|
|
3082
3005
|
//#region packages/playground/src/core/runtime/local/remote.ts
|
|
3083
|
-
var HOST_VUE = /* @__PURE__ */ new Set(["vue", "vue/server-renderer"]);
|
|
3084
3006
|
var moduleUrl = (url) => new URL(url, globalThis.location?.href).href;
|
|
3085
3007
|
var REMOTE_SOURCE_CACHE_LIMIT = 128;
|
|
3086
3008
|
var sourceCache = /* @__PURE__ */ new Map();
|
|
@@ -3125,54 +3047,25 @@ var readRemoteSource = (url) => {
|
|
|
3125
3047
|
* @param imports 合并后的 import map。
|
|
3126
3048
|
* @param builtins 宿主 Vue 与 vue-router。
|
|
3127
3049
|
* @param overrides 显式配置的模块名,与自动补齐的默认地址区分。
|
|
3128
|
-
* @param importModule 浏览器原生 ESM 加载器。
|
|
3129
3050
|
* @param cdnURL 没有 launch 选点结果时使用的实例 CDN。
|
|
3130
3051
|
* @returns 按 URL 加载并执行远程模块的加载器。
|
|
3131
3052
|
*/
|
|
3132
|
-
var createRemoteLoader = (imports, builtins, overrides = new Set(Object.keys(imports)),
|
|
3133
|
-
/* @vite-ignore */
|
|
3134
|
-
url
|
|
3135
|
-
), cdnURL) => {
|
|
3053
|
+
var createRemoteLoader = (imports, builtins, overrides = new Set(Object.keys(imports)), cdnURL) => {
|
|
3136
3054
|
const resolve = createCdnResolver(cdnURL);
|
|
3137
3055
|
const resolveUrl = (url) => resolve(moduleUrl(url));
|
|
3138
3056
|
const hostModules = {
|
|
3139
3057
|
"vue": builtins.vue,
|
|
3058
|
+
"vue/server-renderer": builtins.vue,
|
|
3140
3059
|
"vue-router": builtins.vueRouter
|
|
3141
3060
|
};
|
|
3142
|
-
const pendingBuiltins = /* @__PURE__ */ new Set();
|
|
3143
3061
|
const sources = /* @__PURE__ */ new Map();
|
|
3144
3062
|
const pendingSources = /* @__PURE__ */ new Map();
|
|
3145
3063
|
const evaluated = /* @__PURE__ */ new Map();
|
|
3146
|
-
const nativeModules = /* @__PURE__ */ new Map();
|
|
3147
|
-
const loadNative = (url) => {
|
|
3148
|
-
let pending = nativeModules.get(url);
|
|
3149
|
-
if (!pending) {
|
|
3150
|
-
pending = importModule(url).then((module) => {
|
|
3151
|
-
const exports = toHostModule(module);
|
|
3152
|
-
evaluated.set(url, exports);
|
|
3153
|
-
return exports;
|
|
3154
|
-
});
|
|
3155
|
-
nativeModules.set(url, pending);
|
|
3156
|
-
}
|
|
3157
|
-
return pending;
|
|
3158
|
-
};
|
|
3159
|
-
const localBuiltinId = (id) => {
|
|
3160
|
-
if (imports[id] && !prefersLocalBuiltin(id, imports, overrides)) return null;
|
|
3161
|
-
if (prefersLocalBuiltin(id, imports, overrides)) return id;
|
|
3162
|
-
let cursor = id;
|
|
3163
|
-
while (true) {
|
|
3164
|
-
const slash = cursor.lastIndexOf("/");
|
|
3165
|
-
if (slash <= 0) return null;
|
|
3166
|
-
const parent = cursor.slice(0, slash);
|
|
3167
|
-
if (prefersLocalBuiltin(parent, imports, overrides)) return parent;
|
|
3168
|
-
cursor = parent;
|
|
3169
|
-
}
|
|
3170
|
-
};
|
|
3171
3064
|
const dependencySpecifier = (from, specifier) => {
|
|
3172
3065
|
if (isRelativeSpecifier(specifier) || /^https?:\/\//.test(specifier)) {
|
|
3173
3066
|
const url = new URL(specifier, from);
|
|
3174
3067
|
const name = cdnModuleName(url.href);
|
|
3175
|
-
if (name && (
|
|
3068
|
+
if (name && (overrides.has(name) || usesHostRuntime(name, imports, overrides))) return name;
|
|
3176
3069
|
return url.href;
|
|
3177
3070
|
}
|
|
3178
3071
|
return specifier;
|
|
@@ -3180,35 +3073,21 @@ var createRemoteLoader = (imports, builtins, overrides = new Set(Object.keys(imp
|
|
|
3180
3073
|
const dependencyUrl = (from, id) => {
|
|
3181
3074
|
const specifier = dependencySpecifier(from, id);
|
|
3182
3075
|
if (/^https?:\/\//.test(specifier)) return resolveUrl(specifier);
|
|
3183
|
-
if (imports[specifier] && !
|
|
3184
|
-
if (
|
|
3185
|
-
let cursor = specifier;
|
|
3186
|
-
while (cursor) {
|
|
3187
|
-
if (localBuiltinIds.has(cursor) && prefersLocalBuiltin(cursor, imports, overrides)) {
|
|
3188
|
-
pendingBuiltins.add(cursor);
|
|
3189
|
-
return null;
|
|
3190
|
-
}
|
|
3191
|
-
const slash = cursor.lastIndexOf("/");
|
|
3192
|
-
if (slash <= 0) break;
|
|
3193
|
-
cursor = cursor.slice(0, slash);
|
|
3194
|
-
}
|
|
3076
|
+
if (imports[specifier] && !usesHostRuntime(specifier, imports, overrides)) return resolveUrl(imports[specifier]);
|
|
3077
|
+
if (usesHostRuntime(specifier, imports, overrides)) return null;
|
|
3195
3078
|
const target = imports[specifier] ? specifier : resolveImportTarget(specifier, imports);
|
|
3196
|
-
if (!target)
|
|
3197
|
-
imports[specifier] = resolveNpmImport(specifier);
|
|
3198
|
-
return resolveUrl(imports[specifier]);
|
|
3199
|
-
}
|
|
3079
|
+
if (!target) return resolveUrl(resolveNpmImport(specifier));
|
|
3200
3080
|
return resolveUrl(imports[target]);
|
|
3201
3081
|
};
|
|
3202
3082
|
const crawl = async (url, visited = /* @__PURE__ */ new Set()) => {
|
|
3203
|
-
if (!overrides.size && isCdnEsmURL(url)) {
|
|
3204
|
-
await loadNative(url);
|
|
3205
|
-
return;
|
|
3206
|
-
}
|
|
3207
3083
|
if (visited.has(url)) return;
|
|
3208
3084
|
visited.add(url);
|
|
3209
3085
|
let pending = pendingSources.get(url);
|
|
3210
3086
|
if (!pending) {
|
|
3211
|
-
pending = readRemoteSource(url)
|
|
3087
|
+
pending = readRemoteSource(url).catch((error) => {
|
|
3088
|
+
pendingSources.delete(url);
|
|
3089
|
+
throw error;
|
|
3090
|
+
});
|
|
3212
3091
|
pendingSources.set(url, pending);
|
|
3213
3092
|
}
|
|
3214
3093
|
const source = await pending;
|
|
@@ -3220,12 +3099,10 @@ var createRemoteLoader = (imports, builtins, overrides = new Set(Object.keys(imp
|
|
|
3220
3099
|
};
|
|
3221
3100
|
const requireFrom = (from) => (specifier) => {
|
|
3222
3101
|
const id = dependencySpecifier(from, specifier);
|
|
3223
|
-
if (
|
|
3224
|
-
const builtinId = localBuiltinId(id);
|
|
3225
|
-
if (builtinId) return toHostModule(hostModules[builtinId]);
|
|
3102
|
+
if (usesHostRuntime(id, imports, overrides)) return toHostModule(hostModules[id]);
|
|
3226
3103
|
if (isRelativeSpecifier(id) || /^https?:\/\//.test(id)) return evaluate(dependencyUrl(from, id));
|
|
3227
3104
|
const target = imports[id] ? id : resolveImportTarget(id, imports);
|
|
3228
|
-
if (!target
|
|
3105
|
+
if (!target) return evaluate(dependencyUrl(from, id));
|
|
3229
3106
|
const loaded = evaluate(resolveUrl(imports[target]));
|
|
3230
3107
|
if (target === id) return loaded;
|
|
3231
3108
|
if (!resolveHostModule(id, { [target]: loaded }))
|
|
@@ -3237,18 +3114,19 @@ var createRemoteLoader = (imports, builtins, overrides = new Set(Object.keys(imp
|
|
|
3237
3114
|
if (evaluated.has(url)) return evaluated.get(url);
|
|
3238
3115
|
const source = sources.get(url);
|
|
3239
3116
|
if (!source) throw new Error(`[Playground] 远程模块尚未下载: ${url}`);
|
|
3240
|
-
const module = { exports: {}
|
|
3117
|
+
const module = { exports: Object.defineProperty({}, "__esModule", {
|
|
3118
|
+
value: true,
|
|
3119
|
+
writable: true
|
|
3120
|
+
}) };
|
|
3241
3121
|
evaluated.set(url, module.exports);
|
|
3242
3122
|
const runner = source.run;
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
return requireFrom(url)(id);
|
|
3251
|
-
});
|
|
3123
|
+
try {
|
|
3124
|
+
runner(requireFrom(url), module, module.exports, (id) => loadModule(id, url));
|
|
3125
|
+
} catch (error) {
|
|
3126
|
+
evaluated.delete(url);
|
|
3127
|
+
throw error;
|
|
3128
|
+
}
|
|
3129
|
+
module.exports.__esModule = true;
|
|
3252
3130
|
evaluated.set(url, module.exports);
|
|
3253
3131
|
return module.exports;
|
|
3254
3132
|
};
|
|
@@ -3259,16 +3137,23 @@ var createRemoteLoader = (imports, builtins, overrides = new Set(Object.keys(imp
|
|
|
3259
3137
|
if (pending) return pending;
|
|
3260
3138
|
const task = (async () => {
|
|
3261
3139
|
await crawl(url);
|
|
3262
|
-
await Promise.all([...pendingBuiltins].map(async (id) => {
|
|
3263
|
-
if (id === "vue" || id === "vue-router") return;
|
|
3264
|
-
hostModules[id] = await ensureLocalBuiltin(id);
|
|
3265
|
-
}));
|
|
3266
3140
|
return evaluate(url);
|
|
3267
|
-
})()
|
|
3141
|
+
})().catch((error) => {
|
|
3142
|
+
loading.delete(url);
|
|
3143
|
+
throw new Error(`[Playground] 无法加载模块 (${url}): ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
3144
|
+
});
|
|
3268
3145
|
loading.set(url, task);
|
|
3269
3146
|
return task;
|
|
3270
3147
|
};
|
|
3271
|
-
|
|
3148
|
+
const loadModule = async (id, from = globalThis.location?.href) => {
|
|
3149
|
+
const url = dependencyUrl(from, id);
|
|
3150
|
+
if (url) await load(url);
|
|
3151
|
+
return requireFrom(from)(id);
|
|
3152
|
+
};
|
|
3153
|
+
return {
|
|
3154
|
+
load,
|
|
3155
|
+
loadModule
|
|
3156
|
+
};
|
|
3272
3157
|
};
|
|
3273
3158
|
//#endregion
|
|
3274
3159
|
//#region packages/playground/src/core/runtime/local/local-sandbox.vue?vue&type=script&setup=true&lang.ts
|
|
@@ -3414,7 +3299,7 @@ var local_sandbox_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
|
|
|
3414
3299
|
publishError();
|
|
3415
3300
|
destroyPreview();
|
|
3416
3301
|
try {
|
|
3417
|
-
const { compilePlayground } = await import("./compile-
|
|
3302
|
+
const { compilePlayground } = await import("./compile-D33div4Y.js");
|
|
3418
3303
|
/* istanbul ignore if -- 并发编译时只保留最后一次 */
|
|
3419
3304
|
if (current !== version) return;
|
|
3420
3305
|
const compiled = await compilePlayground(props.files, { entry: props.entry });
|
|
@@ -3427,13 +3312,13 @@ var local_sandbox_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
|
|
|
3427
3312
|
}
|
|
3428
3313
|
const imports = createRuntimeImports(props.options.cdnURL, props.options.builtinImportMap);
|
|
3429
3314
|
const overrides = new Set(Object.keys(createRuntimeImportOverrides(props.options.builtinImportMap)));
|
|
3430
|
-
const specifiers = collectBareSpecifiers(props.files, collectReachableFilenames(props.files, compiled.entry));
|
|
3315
|
+
const specifiers = collectBareSpecifiers(props.files, collectReachableFilenames(props.files, compiled.entry), false);
|
|
3431
3316
|
specifiers.push("vue");
|
|
3432
3317
|
if (props.previewScroller === true) specifiers.push("@deot/vc");
|
|
3433
3318
|
const remote = createRemoteLoader(imports, {
|
|
3434
3319
|
vue: Vue,
|
|
3435
3320
|
vueRouter: VueRouter
|
|
3436
|
-
}, overrides,
|
|
3321
|
+
}, overrides, props.options.cdnURL);
|
|
3437
3322
|
const loaded = await loadLocalModules(specifiers, imports, {
|
|
3438
3323
|
vue: Vue,
|
|
3439
3324
|
vueRouter: VueRouter
|
|
@@ -3445,7 +3330,10 @@ var local_sandbox_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
|
|
|
3445
3330
|
publishError();
|
|
3446
3331
|
return;
|
|
3447
3332
|
}
|
|
3448
|
-
const linked = linkPlayground(compiled, props.files, {
|
|
3333
|
+
const linked = linkPlayground(compiled, props.files, {
|
|
3334
|
+
modules: loaded.modules,
|
|
3335
|
+
loadModule: remote.loadModule
|
|
3336
|
+
});
|
|
3449
3337
|
/* istanbul ignore if -- 并发编译时只保留最后一次 */
|
|
3450
3338
|
if (current !== version) return;
|
|
3451
3339
|
if (linked.errors.length || !linked.component) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deot/docs-playground",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"main": "dist/index.js",
|
|
5
6
|
"types": "dist/index.d.ts",
|
|
6
7
|
"exports": {
|
|
@@ -18,8 +19,8 @@
|
|
|
18
19
|
"access": "public"
|
|
19
20
|
},
|
|
20
21
|
"dependencies": {
|
|
21
|
-
"@deot/docs-locale": "^1.
|
|
22
|
-
"@deot/docs-theme": "^1.
|
|
22
|
+
"@deot/docs-locale": "^1.2.0",
|
|
23
|
+
"@deot/docs-theme": "^1.2.0",
|
|
23
24
|
"@deot/helper": "^1.1.21",
|
|
24
25
|
"@deot/http": "^1.1.10",
|
|
25
26
|
"@deot/vc": "^1.2.3",
|
|
@@ -30,15 +31,8 @@
|
|
|
30
31
|
"@vue/compiler-sfc": "^3.5.43",
|
|
31
32
|
"@vue/repl": "^4.7.2",
|
|
32
33
|
"codemirror": "^6.0.2",
|
|
33
|
-
"dayjs": "^1.11.23",
|
|
34
|
-
"echarts": "^6.1.0",
|
|
35
34
|
"es-module-lexer": "^3.0.3",
|
|
36
35
|
"highlight.js": "^11.12.0",
|
|
37
|
-
"jspdf": "^4.2.1",
|
|
38
|
-
"jszip": "^3.10.2",
|
|
39
|
-
"lodash-es": "^4.18.1",
|
|
40
|
-
"photoswipe": "^5.4.4",
|
|
41
|
-
"pinia": "^4.0.3",
|
|
42
36
|
"sass": "^1.105.1",
|
|
43
37
|
"sucrase": "^3.35.1",
|
|
44
38
|
"vue-router": "^5.4.0"
|