@deot/docs-playground 1.1.3 → 1.1.5
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 +1 -0
- package/dist/{compile-DSMuM8zl.cjs → compile-29EUKPOy.cjs} +29 -40
- package/dist/{compile-Bw7v7QE-.js → compile-CM_OyqYN.js} +21 -32
- package/dist/css-DleINdoA.js +580 -0
- package/dist/css-DpqJBQ5c.cjs +786 -0
- package/dist/index.cjs +1925 -101
- package/dist/index.js +1879 -47
- package/dist/index.style.css +1 -1
- package/package.json +21 -20
- package/dist/cdn-Czve5_9b.cjs +0 -94
- package/dist/cdn-DEvdGJu2.js +0 -53
- package/dist/files-C5UMzYxA.js +0 -178
- package/dist/files-D5LNOtjp.cjs +0 -192
- package/dist/linker-B--sjERT.cjs +0 -167
- package/dist/linker-JHdz37DK.js +0 -166
- package/dist/local-sandbox-B8IJ5jWb.js +0 -431
- package/dist/local-sandbox-DnkKrBhf.cjs +0 -428
- package/dist/modules-CInmL-8h.cjs +0 -217
- package/dist/modules-DlLJF_vd.js +0 -211
- package/dist/remote-CKMzn1J3.cjs +0 -106
- package/dist/remote-DfXAsO9n.js +0 -106
- package/dist/rolldown-runtime-C0BPl7ul.cjs +0 -43
- package/dist/script-5Xzzx7u5.cjs +0 -57
- package/dist/script-xKUjE8pf.js +0 -46
- package/dist/scss-Co2it4vB.js +0 -215
- package/dist/scss-DaIqB_qT.cjs +0 -233
- package/dist/store-BF7z-oaO.cjs +0 -964
- package/dist/store-D8vwi-HV.js +0 -767
package/dist/index.cjs
CHANGED
|
@@ -1,19 +1,30 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
3
|
-
const require_cdn = require("./cdn-Czve5_9b.cjs");
|
|
4
|
-
const require_store = require("./store-BF7z-oaO.cjs");
|
|
5
|
-
const require_scss = require("./scss-DaIqB_qT.cjs");
|
|
2
|
+
const require_css = require("./css-DpqJBQ5c.cjs");
|
|
6
3
|
let vue = require("vue");
|
|
4
|
+
vue = require_css.__toESM(vue);
|
|
7
5
|
let _deot_vc = require("@deot/vc");
|
|
6
|
+
_deot_vc = require_css.__toESM(_deot_vc);
|
|
8
7
|
let _deot_docs_locale = require("@deot/docs-locale");
|
|
9
8
|
let highlight_js = require("highlight.js");
|
|
10
|
-
highlight_js =
|
|
9
|
+
highlight_js = require_css.__toESM(highlight_js);
|
|
11
10
|
let _vue_repl = require("@vue/repl");
|
|
12
11
|
let codemirror = require("codemirror");
|
|
13
12
|
let _codemirror_lang_css = require("@codemirror/lang-css");
|
|
14
13
|
let _codemirror_lang_javascript = require("@codemirror/lang-javascript");
|
|
15
14
|
let _codemirror_lang_vue = require("@codemirror/lang-vue");
|
|
16
15
|
let _codemirror_view = require("@codemirror/view");
|
|
16
|
+
let es_module_lexer = require("es-module-lexer");
|
|
17
|
+
let sucrase = require("sucrase");
|
|
18
|
+
let _vue_compiler_sfc_dist_compiler_sfc_esm_browser_js = require("@vue/compiler-sfc/dist/compiler-sfc.esm-browser.js");
|
|
19
|
+
_vue_compiler_sfc_dist_compiler_sfc_esm_browser_js = require_css.__toESM(_vue_compiler_sfc_dist_compiler_sfc_esm_browser_js);
|
|
20
|
+
let vue_router = require("vue-router");
|
|
21
|
+
vue_router = require_css.__toESM(vue_router);
|
|
22
|
+
let pinia = require("pinia");
|
|
23
|
+
pinia = require_css.__toESM(pinia);
|
|
24
|
+
let _deot_vc_components = require("@deot/vc-components");
|
|
25
|
+
_deot_vc_components = require_css.__toESM(_deot_vc_components);
|
|
26
|
+
let _deot_vc_hooks = require("@deot/vc-hooks");
|
|
27
|
+
_deot_vc_hooks = require_css.__toESM(_deot_vc_hooks);
|
|
17
28
|
//#region packages/playground/src/highlight.ts
|
|
18
29
|
var vueHighlight = (api) => ({
|
|
19
30
|
subLanguage: "xml",
|
|
@@ -121,7 +132,7 @@ var PLAYGROUND_ICONS = {
|
|
|
121
132
|
};
|
|
122
133
|
//#endregion
|
|
123
134
|
//#region packages/playground/src/icon/icon.vue?vue&type=script&setup=true&lang.ts
|
|
124
|
-
var _hoisted_1$
|
|
135
|
+
var _hoisted_1$8 = ["fill", "stroke"];
|
|
125
136
|
var _hoisted_2$7 = ["d"];
|
|
126
137
|
//#endregion
|
|
127
138
|
//#region packages/playground/src/icon/icon.vue
|
|
@@ -153,7 +164,7 @@ var icon_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
153
164
|
"stroke-linecap": "round",
|
|
154
165
|
"stroke-linejoin": "round",
|
|
155
166
|
"aria-hidden": "true"
|
|
156
|
-
}, [(0, vue.createElementVNode)("path", { d: icon.value.path }, null, 8, _hoisted_2$7)], 12, _hoisted_1$
|
|
167
|
+
}, [(0, vue.createElementVNode)("path", { d: icon.value.path }, null, 8, _hoisted_2$7)], 12, _hoisted_1$8);
|
|
157
168
|
};
|
|
158
169
|
}
|
|
159
170
|
});
|
|
@@ -162,7 +173,7 @@ var icon_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
162
173
|
var github_default = "pre code.hljs{display:block;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#005cc5}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-code,.hljs-comment,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{font-weight:700;color:#005cc5}.hljs-bullet{color:#735c0f}.hljs-emphasis{font-style:italic;color:#24292e}.hljs-strong{font-weight:700;color:#24292e}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}[data-doc-theme=dark] .hljs,[data-vc-theme=dark] .hljs{color:#c9d1d9;background:#0d1117}[data-doc-theme=dark] .hljs-doctag,[data-doc-theme=dark] .hljs-keyword,[data-doc-theme=dark] .hljs-meta .hljs-keyword,[data-doc-theme=dark] .hljs-template-tag,[data-doc-theme=dark] .hljs-template-variable,[data-doc-theme=dark] .hljs-type,[data-doc-theme=dark] .hljs-variable.language_,[data-vc-theme=dark] .hljs-doctag,[data-vc-theme=dark] .hljs-keyword,[data-vc-theme=dark] .hljs-meta .hljs-keyword,[data-vc-theme=dark] .hljs-template-tag,[data-vc-theme=dark] .hljs-template-variable,[data-vc-theme=dark] .hljs-type,[data-vc-theme=dark] .hljs-variable.language_{color:#ff7b72}[data-doc-theme=dark] .hljs-title,[data-doc-theme=dark] .hljs-title.class_,[data-doc-theme=dark] .hljs-title.function_,[data-vc-theme=dark] .hljs-title,[data-vc-theme=dark] .hljs-title.class_,[data-vc-theme=dark] .hljs-title.function_{color:#d2a8ff}[data-doc-theme=dark] .hljs-attr,[data-doc-theme=dark] .hljs-literal,[data-doc-theme=dark] .hljs-number,[data-doc-theme=dark] .hljs-variable,[data-vc-theme=dark] .hljs-attr,[data-vc-theme=dark] .hljs-literal,[data-vc-theme=dark] .hljs-number,[data-vc-theme=dark] .hljs-variable{color:#79c0ff}[data-doc-theme=dark] .hljs-regexp,[data-doc-theme=dark] .hljs-string,[data-vc-theme=dark] .hljs-regexp,[data-vc-theme=dark] .hljs-string{color:#a5d6ff}[data-doc-theme=dark] .hljs-code,[data-doc-theme=dark] .hljs-comment,[data-vc-theme=dark] .hljs-code,[data-vc-theme=dark] .hljs-comment{color:#8b949e}[data-doc-theme=dark] .hljs-name,[data-doc-theme=dark] .hljs-selector-tag,[data-vc-theme=dark] .hljs-name,[data-vc-theme=dark] .hljs-selector-tag{color:#7ee787}";
|
|
163
174
|
//#endregion
|
|
164
175
|
//#region packages/playground/src/core/code-preview/code-preview.scss?inline
|
|
165
|
-
var code_preview_default$1 = ".docs-code-preview{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;min-height:0;overflow:hidden;background:var(--docs-background-color-soft,var(--vc-background-color,#f7f8fa));border-radius:8px}.docs-code-preview__language{z-index:1;min-width:28px;padding:0 8px;font-size:12px;line-height:18px;white-space:nowrap;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transition:opacity .15s
|
|
176
|
+
var code_preview_default$1 = ".docs-code-preview{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;min-height:0;overflow:hidden;background:var(--docs-background-color-soft,var(--vc-background-color,#f7f8fa));border-radius:8px}.docs-code-preview__language{z-index:1;min-width:28px;padding:0 8px;font-size:12px;line-height:18px;white-space:nowrap;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transition:opacity .15s;transition:opacity .15s}.docs-code-preview__copy,.docs-code-preview__language{position:absolute;top:6px;right:12px;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;height:28px;color:var(--docs-foreground-color-mute,var(--vc-color-dark-extralight,#71717a));-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.docs-code-preview__copy{z-index:2;width:28px;padding:0;pointer-events:none;cursor:pointer;background:var(--docs-background-color-soft,var(--vc-background-color,#f7f8fa));border:1px solid var(--docs-border-color,var(--vc-color-light-deeper,#d4d4d8));border-radius:8px;opacity:0;-webkit-transition:opacity .15s,background-color .15s;transition:opacity .15s,background-color .15s}.docs-code-preview__copy:hover{background:var(--docs-background-color,var(--vc-background-color-light,#fff))}.docs-code-preview__copy:focus-visible{pointer-events:auto;opacity:1}.docs-code-preview:has(.docs-code-preview__copy:focus-visible) .docs-code-preview__language,.docs-code-preview:hover .docs-code-preview__language{opacity:0}.docs-code-preview:has(.docs-code-preview__copy:focus-visible) .docs-code-preview__copy,.docs-code-preview:hover .docs-code-preview__copy{pointer-events:auto;opacity:1}.docs-code-preview__scroller{width:100%;height:100%;min-width:0;min-height:0;-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.docs-code-preview__code{width:-webkit-max-content;width:-moz-max-content;width:max-content;margin:0}.docs-code-preview__code,.docs-code-preview__code code.hljs{min-width:100%;min-height:100%;overflow:visible;background:var(--docs-background-color-soft,var(--vc-background-color,#f7f8fa))}.docs-code-preview__code code.hljs{display:block;padding:12px 96px 12px 24px;-webkit-box-sizing:border-box;box-sizing:border-box}";
|
|
166
177
|
//#endregion
|
|
167
178
|
//#region packages/playground/src/core/code-preview/style.ts
|
|
168
179
|
var CODE_PREVIEW_STYLE_ID = "docs-code-preview-style";
|
|
@@ -179,7 +190,7 @@ var ensureCodePreviewStyle = () => {
|
|
|
179
190
|
};
|
|
180
191
|
//#endregion
|
|
181
192
|
//#region packages/playground/src/core/code-preview/code-preview.vue?vue&type=script&setup=true&lang.ts
|
|
182
|
-
var _hoisted_1$
|
|
193
|
+
var _hoisted_1$7 = { class: "docs-code-preview" };
|
|
183
194
|
var _hoisted_2$6 = ["title"];
|
|
184
195
|
var _hoisted_3$6 = { class: "docs-code-preview__code" };
|
|
185
196
|
var _hoisted_4$6 = ["innerHTML"];
|
|
@@ -213,7 +224,7 @@ var code_preview_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
213
224
|
const highlightLanguage = (0, vue.computed)(() => props.language || resolveHighlightLanguage(props.filename));
|
|
214
225
|
const highlightedCode = (0, vue.computed)(() => highlightCodeByLanguage(props.code, highlightLanguage.value));
|
|
215
226
|
return (_ctx, _cache) => {
|
|
216
|
-
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$
|
|
227
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$7, [
|
|
217
228
|
languageLabel.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
218
229
|
key: 0,
|
|
219
230
|
class: "docs-code-preview__language",
|
|
@@ -253,7 +264,7 @@ var code_preview_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
253
264
|
});
|
|
254
265
|
//#endregion
|
|
255
266
|
//#region packages/playground/src/core/files-preview/files-preview.vue?vue&type=script&setup=true&lang.ts
|
|
256
|
-
var _hoisted_1$
|
|
267
|
+
var _hoisted_1$6 = { class: "docs-playground-files" };
|
|
257
268
|
var _hoisted_2$5 = { class: "docs-playground-files__tabs-row" };
|
|
258
269
|
var _hoisted_3$5 = ["data-filename", "onClick"];
|
|
259
270
|
var _hoisted_4$5 = {
|
|
@@ -282,7 +293,7 @@ var files_preview_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
282
293
|
if (filename !== props.activeFilename) emit("active-change", filename);
|
|
283
294
|
};
|
|
284
295
|
return (_ctx, _cache) => {
|
|
285
|
-
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$
|
|
296
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$6, [(0, vue.createElementVNode)("div", _hoisted_2$5, [(0, vue.createVNode)((0, vue.unref)(_deot_vc.Scroller), {
|
|
286
297
|
class: "docs-playground-files__scroller",
|
|
287
298
|
"auto-resize": true,
|
|
288
299
|
native: false,
|
|
@@ -427,7 +438,7 @@ var Drag = class {
|
|
|
427
438
|
};
|
|
428
439
|
//#endregion
|
|
429
440
|
//#region packages/playground/src/editor/editor.vue?vue&type=script&setup=true&lang.ts
|
|
430
|
-
var _hoisted_1$
|
|
441
|
+
var _hoisted_1$5 = { class: "docs-playground-editor" };
|
|
431
442
|
var _hoisted_2$4 = ["title"];
|
|
432
443
|
var _hoisted_3$4 = { class: "docs-playground-editor__files" };
|
|
433
444
|
var _hoisted_4$4 = [
|
|
@@ -439,7 +450,7 @@ var _hoisted_5$4 = ["onKeydown"];
|
|
|
439
450
|
var _hoisted_6$3 = ["title"];
|
|
440
451
|
var _hoisted_7$3 = ["title", "aria-label"];
|
|
441
452
|
var _hoisted_8$2 = ["title", "aria-label"];
|
|
442
|
-
var _hoisted_9$
|
|
453
|
+
var _hoisted_9$1 = { class: "docs-playground-editor__actions" };
|
|
443
454
|
var _hoisted_10$1 = ["title"];
|
|
444
455
|
var _hoisted_11$1 = ["title", "disabled"];
|
|
445
456
|
var _hoisted_12$1 = {
|
|
@@ -571,7 +582,7 @@ var editor_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
571
582
|
const filename = nextFilename();
|
|
572
583
|
editorFiles.value = {
|
|
573
584
|
...editorFiles.value,
|
|
574
|
-
[filename]:
|
|
585
|
+
[filename]: require_css.NEW_SFC_CODE
|
|
575
586
|
};
|
|
576
587
|
activeFilename.value = filename;
|
|
577
588
|
notifyFilesChange({
|
|
@@ -677,7 +688,7 @@ var editor_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
677
688
|
editor.value?.destroy();
|
|
678
689
|
});
|
|
679
690
|
return (_ctx, _cache) => {
|
|
680
|
-
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$
|
|
691
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$5, [(0, vue.createVNode)((0, vue.unref)(_deot_vc.TransitionFade), { onAfterLeave: handleHide }, {
|
|
681
692
|
default: (0, vue.withCtx)(() => [(0, vue.withDirectives)((0, vue.createElementVNode)("div", {
|
|
682
693
|
ref_key: "wrapper",
|
|
683
694
|
ref: wrapper,
|
|
@@ -755,7 +766,7 @@ var editor_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
755
766
|
], 64))], 42, _hoisted_4$4);
|
|
756
767
|
}), 128))]),
|
|
757
768
|
_: 1
|
|
758
|
-
}, 512), (0, vue.createElementVNode)("div", _hoisted_9$
|
|
769
|
+
}, 512), (0, vue.createElementVNode)("div", _hoisted_9$1, [(0, vue.createElementVNode)("button", {
|
|
759
770
|
type: "button",
|
|
760
771
|
title: (0, vue.unref)(t)("playground.editor.createFile"),
|
|
761
772
|
onClick: handleCreate
|
|
@@ -836,6 +847,316 @@ var resolvePlaygroundTitleId = (title, explicitId = "", isOccupied) => {
|
|
|
836
847
|
while (isOccupied(`${base}-${index}`)) index += 1;
|
|
837
848
|
return `${base}-${index}`;
|
|
838
849
|
};
|
|
850
|
+
//#endregion
|
|
851
|
+
//#region packages/playground/src/core/preview-scroll.ts
|
|
852
|
+
/** iframe 包装成功后挂在 `html` 上,供样式与 auto-height 识别。 */
|
|
853
|
+
var PREVIEW_SCROLL_HTML_CLASS = "docs-playground-preview-scroll";
|
|
854
|
+
/** Scroller 内容节点 class,auto-height 优先测量该节点。 */
|
|
855
|
+
var PREVIEW_SCROLL_CONTENT_CLASS = "docs-playground-preview-scroll__content";
|
|
856
|
+
/** 重评时先清掉 html class,避免 `await import` 期间仍套用 `height:100%`。 */
|
|
857
|
+
var PREVIEW_SCROLL_RESET_CODE = `document.documentElement.classList.remove("${PREVIEW_SCROLL_HTML_CLASS}");`;
|
|
858
|
+
/** 动态探测 `@deot/vc`;失败时为空对象,不阻断 DocsLink / 预览挂载。 */
|
|
859
|
+
var PREVIEW_SCROLLER_IMPORT_CODE = "const __docsVc=await import(\"@deot/vc\").catch(()=>({}))";
|
|
860
|
+
/**
|
|
861
|
+
* Vue 的 `mount` 闭包的是 `createApp(root)` 时的根组件,改 `app._component` 不会生效。
|
|
862
|
+
* 因此劫持 `app.mount`:等全部 useCode 注册完后,再 `createApp` 包一层 Scroller。
|
|
863
|
+
* 前导分号避免接在 `app.component(...)` 后被 ASI 解析成调用返回值。
|
|
864
|
+
*/
|
|
865
|
+
var PREVIEW_SCROLLER_USE_CODE = [
|
|
866
|
+
";(()=>{",
|
|
867
|
+
PREVIEW_SCROLL_RESET_CODE,
|
|
868
|
+
"const __DocsScroller=__docsVc&&__docsVc.Scroller;",
|
|
869
|
+
"if(!__DocsScroller)return;",
|
|
870
|
+
"const UserApp=app._component;",
|
|
871
|
+
"app.mount=(container,...rest)=>{",
|
|
872
|
+
"const next=_createApp({",
|
|
873
|
+
"name:\"DocsPreviewRoot\",",
|
|
874
|
+
"setup(){return()=>__docsH(__DocsScroller,{",
|
|
875
|
+
"height:\"100%\",",
|
|
876
|
+
"native:false,",
|
|
877
|
+
"autoResize:true,",
|
|
878
|
+
"showBar:true,",
|
|
879
|
+
`contentClass:"${PREVIEW_SCROLL_CONTENT_CLASS}"`,
|
|
880
|
+
"},{default:()=>__docsH(UserApp)})}",
|
|
881
|
+
"});",
|
|
882
|
+
"next.config.errorHandler=app.config.errorHandler;",
|
|
883
|
+
"if(app._context&&next._context){",
|
|
884
|
+
"if(app._context.components)Object.assign(next._context.components,app._context.components);",
|
|
885
|
+
"if(app._context.directives)Object.assign(next._context.directives,app._context.directives);",
|
|
886
|
+
"Object.assign(next._context.provides,app._context.provides);",
|
|
887
|
+
"next._context.mixins.push(...app._context.mixins);",
|
|
888
|
+
"}",
|
|
889
|
+
"window.__app__=next;",
|
|
890
|
+
`document.documentElement.classList.add("${PREVIEW_SCROLL_HTML_CLASS}");`,
|
|
891
|
+
"return next.mount(container,...rest)",
|
|
892
|
+
"}",
|
|
893
|
+
"})()"
|
|
894
|
+
].join("");
|
|
895
|
+
var PREVIEW_SCROLLER_STYLE = [
|
|
896
|
+
`html.${PREVIEW_SCROLL_HTML_CLASS},`,
|
|
897
|
+
`html.${PREVIEW_SCROLL_HTML_CLASS} body,`,
|
|
898
|
+
`html.${PREVIEW_SCROLL_HTML_CLASS} #app{`,
|
|
899
|
+
"height:100%;min-height:100%;margin:0;overflow:hidden",
|
|
900
|
+
"}",
|
|
901
|
+
`html.${PREVIEW_SCROLL_HTML_CLASS} #app>.vc-scroller{`,
|
|
902
|
+
"height:100%;max-height:100%;box-sizing:border-box",
|
|
903
|
+
"}"
|
|
904
|
+
].join("");
|
|
905
|
+
var resolveSandboxContainer = (sandbox) => sandbox?.container ? (0, vue.unref)(sandbox.container) : null;
|
|
906
|
+
var resolveSandboxMessageSource = (sandbox) => {
|
|
907
|
+
const exposed = sandbox?.messageSource ? (0, vue.unref)(sandbox.messageSource) : null;
|
|
908
|
+
if (exposed && typeof exposed.postMessage === "function") return exposed;
|
|
909
|
+
return (resolveSandboxContainer(sandbox)?.querySelector("iframe"))?.contentWindow ?? null;
|
|
910
|
+
};
|
|
911
|
+
/**
|
|
912
|
+
* iframe 的 contentWindow 在 jsdom 里可能是 null,仍要和旧的元素校验一致。
|
|
913
|
+
* 直接渲染会暴露真实的 messageSource。
|
|
914
|
+
* @param sandbox
|
|
915
|
+
* @param event
|
|
916
|
+
*/
|
|
917
|
+
var isSandboxMessage = (sandbox, event) => {
|
|
918
|
+
const explicit = sandbox?.messageSource ? (0, vue.unref)(sandbox.messageSource) : null;
|
|
919
|
+
if (explicit && typeof explicit.postMessage === "function") return event.source === explicit;
|
|
920
|
+
const iframe = resolveSandboxContainer(sandbox)?.querySelector("iframe");
|
|
921
|
+
return !!iframe && event.source === iframe.contentWindow;
|
|
922
|
+
};
|
|
923
|
+
var resolveScrollContent = (iframeDocument) => {
|
|
924
|
+
if (!iframeDocument.documentElement.classList.contains("docs-playground-preview-scroll")) return null;
|
|
925
|
+
return iframeDocument.querySelector(`.${PREVIEW_SCROLL_CONTENT_CLASS}`);
|
|
926
|
+
};
|
|
927
|
+
var useSandboxAutoHeight = (sandboxRef) => {
|
|
928
|
+
const height = (0, vue.ref)(24);
|
|
929
|
+
let container = null;
|
|
930
|
+
let iframe = null;
|
|
931
|
+
let containerObserver = null;
|
|
932
|
+
let contentObserver = null;
|
|
933
|
+
let scrollMountObserver = null;
|
|
934
|
+
let observedScrollNode = null;
|
|
935
|
+
let frameId = 0;
|
|
936
|
+
const cancelMeasure = () => {
|
|
937
|
+
if (!frameId) return;
|
|
938
|
+
cancelAnimationFrame(frameId);
|
|
939
|
+
frameId = 0;
|
|
940
|
+
};
|
|
941
|
+
const measureDocumentContent = (iframeWindow, iframeDocument) => {
|
|
942
|
+
const { body, documentElement } = iframeDocument;
|
|
943
|
+
const bodyStyle = iframeWindow.getComputedStyle(body);
|
|
944
|
+
const bodyMargins = (Number.parseFloat(bodyStyle.marginTop) || 0) + (Number.parseFloat(bodyStyle.marginBottom) || 0);
|
|
945
|
+
const rootTop = documentElement.getBoundingClientRect().top;
|
|
946
|
+
const bodyRect = body.getBoundingClientRect();
|
|
947
|
+
const collapsedTop = Math.max(0, bodyRect.top - rootTop);
|
|
948
|
+
let childrenBottom = 0;
|
|
949
|
+
for (const child of body.children) {
|
|
950
|
+
if (iframeWindow.getComputedStyle(child).position === "fixed") continue;
|
|
951
|
+
const rect = child.getBoundingClientRect();
|
|
952
|
+
const marginBottom = Number.parseFloat(iframeWindow.getComputedStyle(child).marginBottom) || 0;
|
|
953
|
+
childrenBottom = Math.max(childrenBottom, rect.bottom + marginBottom - rootTop);
|
|
954
|
+
}
|
|
955
|
+
const scrollHeight = Math.max(body.scrollHeight, documentElement.scrollHeight);
|
|
956
|
+
const overflowingHeight = scrollHeight > (iframe?.clientHeight || 0) + 1 ? scrollHeight : 0;
|
|
957
|
+
return Math.ceil(Math.max(body.offsetHeight + bodyMargins + collapsedTop, bodyRect.height + bodyMargins + collapsedTop, childrenBottom, overflowingHeight));
|
|
958
|
+
};
|
|
959
|
+
const measureScrollContent = (scrollContent) => {
|
|
960
|
+
const contentStyle = scrollContent.ownerDocument.defaultView?.getComputedStyle(scrollContent);
|
|
961
|
+
const margins = contentStyle ? (Number.parseFloat(contentStyle.marginTop) || 0) + (Number.parseFloat(contentStyle.marginBottom) || 0) : 0;
|
|
962
|
+
let childrenBottom = 0;
|
|
963
|
+
const rootTop = scrollContent.getBoundingClientRect().top;
|
|
964
|
+
for (const child of scrollContent.children) {
|
|
965
|
+
const rect = child.getBoundingClientRect();
|
|
966
|
+
const marginBottom = Number.parseFloat(scrollContent.ownerDocument.defaultView?.getComputedStyle(child).marginBottom || "0") || 0;
|
|
967
|
+
childrenBottom = Math.max(childrenBottom, rect.bottom + marginBottom - rootTop);
|
|
968
|
+
}
|
|
969
|
+
return Math.ceil(Math.max(scrollContent.scrollHeight + margins, scrollContent.offsetHeight + margins, childrenBottom + margins));
|
|
970
|
+
};
|
|
971
|
+
const isPendingPreviewApp = (iframeDocument) => {
|
|
972
|
+
const app = iframeDocument.getElementById("app");
|
|
973
|
+
return app ? app.childElementCount === 0 : !!iframe?.srcdoc;
|
|
974
|
+
};
|
|
975
|
+
const releaseBootstrapHeight = (target) => {
|
|
976
|
+
(0, vue.nextTick)(() => {
|
|
977
|
+
if (iframe === target) target.style.height = "100%";
|
|
978
|
+
});
|
|
979
|
+
};
|
|
980
|
+
const measureElementChildren = (root) => {
|
|
981
|
+
const view = root.ownerDocument.defaultView || window;
|
|
982
|
+
const rootTop = root.getBoundingClientRect().top;
|
|
983
|
+
let childrenBottom = 0;
|
|
984
|
+
for (const child of root.children) {
|
|
985
|
+
if (view.getComputedStyle(child).position === "fixed") continue;
|
|
986
|
+
const rect = child.getBoundingClientRect();
|
|
987
|
+
const marginBottom = Number.parseFloat(view.getComputedStyle(child).marginBottom) || 0;
|
|
988
|
+
childrenBottom = Math.max(childrenBottom, rect.bottom + marginBottom - rootTop);
|
|
989
|
+
}
|
|
990
|
+
const overflowingHeight = root.scrollHeight > root.clientHeight + 1 ? root.scrollHeight : 0;
|
|
991
|
+
const naturalHeight = root.classList.contains("docs-playground-local__mount--auto") ? root.offsetHeight : 0;
|
|
992
|
+
return Math.ceil(Math.max(childrenBottom, overflowingHeight, naturalHeight));
|
|
993
|
+
};
|
|
994
|
+
const measureLocalContainer = () => {
|
|
995
|
+
if (!container) return;
|
|
996
|
+
const scrollContent = container.querySelector(`.${PREVIEW_SCROLL_CONTENT_CLASS}`);
|
|
997
|
+
const mount = container.querySelector(".docs-playground-local__mount");
|
|
998
|
+
const target = scrollContent || mount;
|
|
999
|
+
if (!target || !scrollContent && target.childElementCount === 0) return;
|
|
1000
|
+
const contentHeight = scrollContent ? measureScrollContent(scrollContent) : measureElementChildren(target);
|
|
1001
|
+
const nextHeight = Math.max(contentHeight, 24);
|
|
1002
|
+
if (height.value !== nextHeight) height.value = nextHeight;
|
|
1003
|
+
};
|
|
1004
|
+
const isLocalContainer = (element) => element?.classList.contains("docs-playground-local") === true;
|
|
1005
|
+
const measure = () => {
|
|
1006
|
+
frameId = 0;
|
|
1007
|
+
if (isLocalContainer(container)) {
|
|
1008
|
+
measureLocalContainer();
|
|
1009
|
+
return;
|
|
1010
|
+
}
|
|
1011
|
+
if (!iframe) return;
|
|
1012
|
+
try {
|
|
1013
|
+
const iframeWindow = iframe.contentWindow;
|
|
1014
|
+
const iframeDocument = iframe.contentDocument;
|
|
1015
|
+
if (!iframeWindow || !iframeDocument?.body) return;
|
|
1016
|
+
const scrollContent = resolveScrollContent(iframeDocument);
|
|
1017
|
+
if (!scrollContent && isPendingPreviewApp(iframeDocument)) return;
|
|
1018
|
+
const contentHeight = scrollContent ? measureScrollContent(scrollContent) : measureDocumentContent(iframeWindow, iframeDocument);
|
|
1019
|
+
const nextHeight = Math.max(contentHeight, 24);
|
|
1020
|
+
if (height.value !== nextHeight) height.value = nextHeight;
|
|
1021
|
+
releaseBootstrapHeight(iframe);
|
|
1022
|
+
} catch {
|
|
1023
|
+
if (height.value !== 24) height.value = 24;
|
|
1024
|
+
}
|
|
1025
|
+
};
|
|
1026
|
+
const scheduleMeasure = () => {
|
|
1027
|
+
if (frameId) return;
|
|
1028
|
+
frameId = requestAnimationFrame(measure);
|
|
1029
|
+
};
|
|
1030
|
+
const disconnectContent = () => {
|
|
1031
|
+
contentObserver?.disconnect();
|
|
1032
|
+
contentObserver = null;
|
|
1033
|
+
scrollMountObserver?.disconnect();
|
|
1034
|
+
scrollMountObserver = null;
|
|
1035
|
+
observedScrollNode = null;
|
|
1036
|
+
cancelMeasure();
|
|
1037
|
+
};
|
|
1038
|
+
const observeContent = () => {
|
|
1039
|
+
disconnectContent();
|
|
1040
|
+
if (!iframe) return;
|
|
1041
|
+
try {
|
|
1042
|
+
const iframeWindow = iframe.contentWindow;
|
|
1043
|
+
const iframeDocument = iframe.contentDocument;
|
|
1044
|
+
const Observer = iframeWindow?.ResizeObserver;
|
|
1045
|
+
if (!iframeWindow || !iframeDocument?.body || !Observer) {
|
|
1046
|
+
scheduleMeasure();
|
|
1047
|
+
return;
|
|
1048
|
+
}
|
|
1049
|
+
const observer = new Observer(scheduleMeasure);
|
|
1050
|
+
observer.observe(iframeDocument.documentElement);
|
|
1051
|
+
observer.observe(iframeDocument.body);
|
|
1052
|
+
contentObserver = observer;
|
|
1053
|
+
const attachScrollContent = (node) => {
|
|
1054
|
+
if (!node || !contentObserver) return false;
|
|
1055
|
+
if (observedScrollNode === node) return true;
|
|
1056
|
+
if (observedScrollNode) contentObserver.unobserve(observedScrollNode);
|
|
1057
|
+
observedScrollNode = node;
|
|
1058
|
+
contentObserver.observe(node);
|
|
1059
|
+
return true;
|
|
1060
|
+
};
|
|
1061
|
+
const syncScrollContent = () => {
|
|
1062
|
+
attachScrollContent(resolveScrollContent(iframeDocument));
|
|
1063
|
+
scheduleMeasure();
|
|
1064
|
+
};
|
|
1065
|
+
scrollMountObserver = new MutationObserver(syncScrollContent);
|
|
1066
|
+
scrollMountObserver.observe(iframeDocument.documentElement, {
|
|
1067
|
+
attributes: true,
|
|
1068
|
+
attributeFilter: ["class"]
|
|
1069
|
+
});
|
|
1070
|
+
scrollMountObserver.observe(iframeDocument.body, {
|
|
1071
|
+
childList: true,
|
|
1072
|
+
subtree: true
|
|
1073
|
+
});
|
|
1074
|
+
syncScrollContent();
|
|
1075
|
+
} catch {
|
|
1076
|
+
if (height.value !== 24) height.value = 24;
|
|
1077
|
+
}
|
|
1078
|
+
};
|
|
1079
|
+
const handleIframeLoad = () => observeContent();
|
|
1080
|
+
const setIframe = (nextIframe) => {
|
|
1081
|
+
if (iframe === nextIframe) return;
|
|
1082
|
+
iframe?.removeEventListener("load", handleIframeLoad);
|
|
1083
|
+
disconnectContent();
|
|
1084
|
+
iframe = nextIframe;
|
|
1085
|
+
if (!iframe) {
|
|
1086
|
+
height.value = 24;
|
|
1087
|
+
return;
|
|
1088
|
+
}
|
|
1089
|
+
iframe.addEventListener("load", handleIframeLoad);
|
|
1090
|
+
iframe.style.height = `${Math.max(window.innerHeight, 24)}px`;
|
|
1091
|
+
observeContent();
|
|
1092
|
+
};
|
|
1093
|
+
const observeLocal = () => {
|
|
1094
|
+
disconnectContent();
|
|
1095
|
+
if (!container || typeof ResizeObserver === "undefined") {
|
|
1096
|
+
scheduleMeasure();
|
|
1097
|
+
return;
|
|
1098
|
+
}
|
|
1099
|
+
const observer = new ResizeObserver(scheduleMeasure);
|
|
1100
|
+
observer.observe(container);
|
|
1101
|
+
const mount = container.querySelector(".docs-playground-local__mount");
|
|
1102
|
+
if (mount) observer.observe(mount);
|
|
1103
|
+
contentObserver = observer;
|
|
1104
|
+
scrollMountObserver = new MutationObserver(() => {
|
|
1105
|
+
const nextMount = container?.querySelector(".docs-playground-local__mount");
|
|
1106
|
+
if (nextMount && contentObserver) {
|
|
1107
|
+
contentObserver.observe(nextMount);
|
|
1108
|
+
for (const child of nextMount.children) contentObserver.observe(child);
|
|
1109
|
+
}
|
|
1110
|
+
scheduleMeasure();
|
|
1111
|
+
});
|
|
1112
|
+
scrollMountObserver.observe(container, {
|
|
1113
|
+
childList: true,
|
|
1114
|
+
subtree: true
|
|
1115
|
+
});
|
|
1116
|
+
scheduleMeasure();
|
|
1117
|
+
};
|
|
1118
|
+
const syncIframe = () => {
|
|
1119
|
+
if (isLocalContainer(container)) {
|
|
1120
|
+
iframe?.removeEventListener("load", handleIframeLoad);
|
|
1121
|
+
iframe = null;
|
|
1122
|
+
observeLocal();
|
|
1123
|
+
return;
|
|
1124
|
+
}
|
|
1125
|
+
setIframe(container?.querySelector("iframe") || null);
|
|
1126
|
+
};
|
|
1127
|
+
const setContainer = (nextContainer) => {
|
|
1128
|
+
if (container === nextContainer) return;
|
|
1129
|
+
containerObserver?.disconnect();
|
|
1130
|
+
containerObserver = null;
|
|
1131
|
+
disconnectContent();
|
|
1132
|
+
iframe?.removeEventListener("load", handleIframeLoad);
|
|
1133
|
+
iframe = null;
|
|
1134
|
+
container = nextContainer;
|
|
1135
|
+
if (!container) {
|
|
1136
|
+
height.value = 24;
|
|
1137
|
+
return;
|
|
1138
|
+
}
|
|
1139
|
+
if (isLocalContainer(container)) {
|
|
1140
|
+
observeLocal();
|
|
1141
|
+
return;
|
|
1142
|
+
}
|
|
1143
|
+
containerObserver = new MutationObserver(syncIframe);
|
|
1144
|
+
containerObserver.observe(container, {
|
|
1145
|
+
childList: true,
|
|
1146
|
+
subtree: true
|
|
1147
|
+
});
|
|
1148
|
+
syncIframe();
|
|
1149
|
+
};
|
|
1150
|
+
(0, vue.watch)(() => resolveSandboxContainer(sandboxRef.value), setContainer, {
|
|
1151
|
+
flush: "post",
|
|
1152
|
+
immediate: true
|
|
1153
|
+
});
|
|
1154
|
+
(0, vue.onBeforeUnmount)(() => {
|
|
1155
|
+
setContainer(null);
|
|
1156
|
+
cancelMeasure();
|
|
1157
|
+
});
|
|
1158
|
+
return height;
|
|
1159
|
+
};
|
|
839
1160
|
var resolvePreviewBoxHeight = (contentHeight, verticalInset = 0, borderWidth = 1) => {
|
|
840
1161
|
const content = Number.isFinite(contentHeight) ? Math.max(0, contentHeight) : 0;
|
|
841
1162
|
const inset = Number.isFinite(verticalInset) ? Math.max(0, verticalInset) : 0;
|
|
@@ -914,6 +1235,68 @@ var scrollPlaygroundToViewportStart = (el) => {
|
|
|
914
1235
|
});
|
|
915
1236
|
};
|
|
916
1237
|
//#endregion
|
|
1238
|
+
//#region packages/playground/src/core/runtime/error-guard.ts
|
|
1239
|
+
var UNKNOWN_RUNTIME_ERROR = "运行时发生未知错误";
|
|
1240
|
+
var MODULE_SPECIFIER_RE = /Failed to resolve module specifier|Error resolving module specifier/u;
|
|
1241
|
+
var forwardSandboxRuntimeError = (event) => {
|
|
1242
|
+
if (!(event instanceof ErrorEvent) || event.error != null || !event.message) return;
|
|
1243
|
+
event.stopImmediatePropagation();
|
|
1244
|
+
if (event.message === "ResizeObserver loop limit exceeded" || event.message === "ResizeObserver loop completed with undelivered notifications.") return;
|
|
1245
|
+
window.parent.postMessage({
|
|
1246
|
+
action: "error",
|
|
1247
|
+
value: event.message
|
|
1248
|
+
}, "*");
|
|
1249
|
+
};
|
|
1250
|
+
var SANDBOX_RUNTIME_ERROR_CAPTURE_HTML = [
|
|
1251
|
+
"<script>",
|
|
1252
|
+
`window.addEventListener('error', ${forwardSandboxRuntimeError.toString()}, true);`,
|
|
1253
|
+
"<\/script>"
|
|
1254
|
+
].join("\n");
|
|
1255
|
+
var toRuntimeErrorMessage = (value, message) => {
|
|
1256
|
+
if (typeof value === "string" && value) return value;
|
|
1257
|
+
if (value instanceof Error && value.message) return value.message;
|
|
1258
|
+
if (value && typeof value === "object" && "message" in value) {
|
|
1259
|
+
const valueMessage = value.message;
|
|
1260
|
+
if (typeof valueMessage === "string" && valueMessage) return valueMessage;
|
|
1261
|
+
}
|
|
1262
|
+
if (typeof message === "string" && message) return message;
|
|
1263
|
+
if (value !== null && value !== void 0) try {
|
|
1264
|
+
return String(value);
|
|
1265
|
+
} catch {
|
|
1266
|
+
return UNKNOWN_RUNTIME_ERROR;
|
|
1267
|
+
}
|
|
1268
|
+
return UNKNOWN_RUNTIME_ERROR;
|
|
1269
|
+
};
|
|
1270
|
+
var normalizeRuntimeErrorMessage = (data) => {
|
|
1271
|
+
if (!data || typeof data !== "object") return false;
|
|
1272
|
+
const message = data;
|
|
1273
|
+
if (message.action !== "error") return false;
|
|
1274
|
+
message.value = toRuntimeErrorMessage(message.value, message.message);
|
|
1275
|
+
return true;
|
|
1276
|
+
};
|
|
1277
|
+
var toErrorText = (value) => {
|
|
1278
|
+
if (typeof value === "string" && value) return value;
|
|
1279
|
+
if (value instanceof Error && value.message) return value.message;
|
|
1280
|
+
return "";
|
|
1281
|
+
};
|
|
1282
|
+
var formatSandboxRuntimeError = (message, importMapTip) => {
|
|
1283
|
+
if (!MODULE_SPECIFIER_RE.test(message)) return message;
|
|
1284
|
+
return `${message.replace(/\. Relative references must.*$/u, "").replace(/\.$/u, "")}.\n${importMapTip}`;
|
|
1285
|
+
};
|
|
1286
|
+
var useSandboxRuntimeErrorGuard = (sandboxRef) => {
|
|
1287
|
+
const error = (0, vue.ref)("");
|
|
1288
|
+
if (typeof window === "undefined") return error;
|
|
1289
|
+
const handleMessage = (event) => {
|
|
1290
|
+
const source = resolveSandboxMessageSource(sandboxRef.value);
|
|
1291
|
+
if (!source || event.source !== source) return;
|
|
1292
|
+
if (!normalizeRuntimeErrorMessage(event.data)) return;
|
|
1293
|
+
error.value = event.data.value;
|
|
1294
|
+
};
|
|
1295
|
+
window.addEventListener("message", handleMessage, true);
|
|
1296
|
+
(0, vue.onBeforeUnmount)(() => window.removeEventListener("message", handleMessage, true));
|
|
1297
|
+
return error;
|
|
1298
|
+
};
|
|
1299
|
+
//#endregion
|
|
917
1300
|
//#region packages/playground/src/core/runtime/viewport.ts
|
|
918
1301
|
var DEFAULT_VIEWPORT_OPTIONS = ["auto", 375];
|
|
919
1302
|
var isValidViewport = (viewport) => {
|
|
@@ -1077,7 +1460,7 @@ var useSandboxTheme = (sandboxRef) => {
|
|
|
1077
1460
|
}
|
|
1078
1461
|
syncIframe();
|
|
1079
1462
|
};
|
|
1080
|
-
(0, vue.watch)(() =>
|
|
1463
|
+
(0, vue.watch)(() => resolveSandboxContainer(sandboxRef.value), setContainer, {
|
|
1081
1464
|
flush: "post",
|
|
1082
1465
|
immediate: true
|
|
1083
1466
|
});
|
|
@@ -1119,7 +1502,7 @@ function usePreviewHeightBridge(sandbox, maxHeight = () => Infinity) {
|
|
|
1119
1502
|
sync();
|
|
1120
1503
|
};
|
|
1121
1504
|
const handleMessage = async (event) => {
|
|
1122
|
-
const current =
|
|
1505
|
+
const current = resolveSandboxMessageSource(sandbox.value);
|
|
1123
1506
|
const data = event.data;
|
|
1124
1507
|
if (!current || event.source !== current || data?.action !== "docs:height" || typeof data.session !== "string") return;
|
|
1125
1508
|
if (data.operation === "start") {
|
|
@@ -1153,7 +1536,7 @@ function usePreviewHeightBridge(sandbox, maxHeight = () => Infinity) {
|
|
|
1153
1536
|
accepted
|
|
1154
1537
|
}, "*");
|
|
1155
1538
|
};
|
|
1156
|
-
(0, vue.watch)(() =>
|
|
1539
|
+
(0, vue.watch)(() => resolveSandboxMessageSource(sandbox.value), reset, { flush: "sync" });
|
|
1157
1540
|
if (typeof window !== "undefined") window.addEventListener("message", handleMessage);
|
|
1158
1541
|
(0, vue.onBeforeUnmount)(() => {
|
|
1159
1542
|
disposed = true;
|
|
@@ -1164,7 +1547,7 @@ function usePreviewHeightBridge(sandbox, maxHeight = () => Infinity) {
|
|
|
1164
1547
|
}
|
|
1165
1548
|
//#endregion
|
|
1166
1549
|
//#region packages/playground/src/core/runtime/toolbar.vue?vue&type=script&setup=true&lang.ts
|
|
1167
|
-
var _hoisted_1$
|
|
1550
|
+
var _hoisted_1$4 = { class: "docs-playground__tools" };
|
|
1168
1551
|
var _hoisted_2$3 = {
|
|
1169
1552
|
key: 0,
|
|
1170
1553
|
class: "docs-playground__tool-group"
|
|
@@ -1187,7 +1570,7 @@ var _hoisted_8$1 = {
|
|
|
1187
1570
|
class: "docs-playground__tool-divider",
|
|
1188
1571
|
"aria-hidden": "true"
|
|
1189
1572
|
};
|
|
1190
|
-
var _hoisted_9
|
|
1573
|
+
var _hoisted_9 = ["aria-label"];
|
|
1191
1574
|
var _hoisted_10 = [
|
|
1192
1575
|
"title",
|
|
1193
1576
|
"aria-label",
|
|
@@ -1254,7 +1637,7 @@ var toolbar_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1254
1637
|
if (!enabled) viewportMenuVisible.value = false;
|
|
1255
1638
|
});
|
|
1256
1639
|
return (_ctx, _cache) => {
|
|
1257
|
-
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$
|
|
1640
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$4, [
|
|
1258
1641
|
__props.showRuntimeActions ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [
|
|
1259
1642
|
__props.viewportOptions.length > 1 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$3, [(0, vue.createVNode)((0, vue.unref)(_deot_vc.Dropdown), {
|
|
1260
1643
|
modelValue: viewportMenuVisible.value,
|
|
@@ -1360,7 +1743,7 @@ var toolbar_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1360
1743
|
"aria-pressed": item === __props.activeView,
|
|
1361
1744
|
onClick: ($event) => emit("view-change", item)
|
|
1362
1745
|
}, (0, vue.toDisplayString)(getViewLabel(item)), 11, _hoisted_10);
|
|
1363
|
-
}), 128))], 8, _hoisted_9
|
|
1746
|
+
}), 128))], 8, _hoisted_9)) : (0, vue.createCommentVNode)("v-if", true),
|
|
1364
1747
|
__props.showClose && (__props.showRuntimeActions || showViews.value) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_11)) : (0, vue.createCommentVNode)("v-if", true),
|
|
1365
1748
|
__props.showClose ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
1366
1749
|
key: 3,
|
|
@@ -1379,8 +1762,540 @@ var toolbar_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1379
1762
|
}
|
|
1380
1763
|
});
|
|
1381
1764
|
//#endregion
|
|
1765
|
+
//#region packages/playground/src/import-map.ts
|
|
1766
|
+
/**
|
|
1767
|
+
* 站点级同步内存:`$docs.modules` / `$docs.styles` 与管理页 import、CSS 覆盖。
|
|
1768
|
+
*/
|
|
1769
|
+
var normalize = (value) => value.trim();
|
|
1770
|
+
var isSafePlaygroundHref = (href) => {
|
|
1771
|
+
const next = href.trim();
|
|
1772
|
+
if (!next) return false;
|
|
1773
|
+
if (/^https?:\/\//iu.test(next)) return true;
|
|
1774
|
+
return next.startsWith("/") && !next.startsWith("//");
|
|
1775
|
+
};
|
|
1776
|
+
var filterSafeHrefs = (value = {}) => Object.fromEntries(Object.entries(value).filter((entry) => typeof entry[1] === "string" && isSafePlaygroundHref(entry[1])));
|
|
1777
|
+
var sanitizeMap = (value = {}) => filterSafeHrefs(Object.fromEntries(Object.entries(value).map(([alias, url]) => [normalize(alias), normalize(url)]).filter(([alias]) => Boolean(alias))));
|
|
1778
|
+
var createMapStore = () => {
|
|
1779
|
+
let data = {};
|
|
1780
|
+
const snapshot = () => ({ ...data });
|
|
1781
|
+
const drop = (alias) => {
|
|
1782
|
+
if (data[alias] === void 0) return snapshot();
|
|
1783
|
+
const next = { ...data };
|
|
1784
|
+
delete next[alias];
|
|
1785
|
+
data = next;
|
|
1786
|
+
return snapshot();
|
|
1787
|
+
};
|
|
1788
|
+
return {
|
|
1789
|
+
get: snapshot,
|
|
1790
|
+
set: (value = {}) => {
|
|
1791
|
+
data = sanitizeMap(value);
|
|
1792
|
+
},
|
|
1793
|
+
apply: (alias, url) => {
|
|
1794
|
+
const nextAlias = normalize(alias);
|
|
1795
|
+
const nextUrl = normalize(url);
|
|
1796
|
+
if (!nextAlias) return snapshot();
|
|
1797
|
+
if (!isSafePlaygroundHref(nextUrl)) return drop(nextAlias);
|
|
1798
|
+
data = {
|
|
1799
|
+
...data,
|
|
1800
|
+
[nextAlias]: nextUrl
|
|
1801
|
+
};
|
|
1802
|
+
return snapshot();
|
|
1803
|
+
},
|
|
1804
|
+
remove: (alias) => {
|
|
1805
|
+
const nextAlias = normalize(alias);
|
|
1806
|
+
return nextAlias ? drop(nextAlias) : snapshot();
|
|
1807
|
+
}
|
|
1808
|
+
};
|
|
1809
|
+
};
|
|
1810
|
+
var siteModules = createMapStore();
|
|
1811
|
+
var siteStyles = createMapStore();
|
|
1812
|
+
var importOverrides = createMapStore();
|
|
1813
|
+
var styleOverrides = createMapStore();
|
|
1814
|
+
/**
|
|
1815
|
+
* 站点默认 import。合并时夹在内置 CDN 与实例 `builtinImportMap` 之间。
|
|
1816
|
+
*/
|
|
1817
|
+
var getPlaygroundSiteModules = siteModules.get;
|
|
1818
|
+
var setPlaygroundSiteModules = siteModules.set;
|
|
1819
|
+
/**
|
|
1820
|
+
* 站点默认预览 CSS。合并时夹在内置样式表与管理页覆盖之间。
|
|
1821
|
+
*/
|
|
1822
|
+
var getPlaygroundSiteStyles = siteStyles.get;
|
|
1823
|
+
var setPlaygroundSiteStyles = siteStyles.set;
|
|
1824
|
+
var getPlaygroundImportMapOverrides = importOverrides.get;
|
|
1825
|
+
var setPlaygroundImportMapOverrides = importOverrides.set;
|
|
1826
|
+
var applyPlaygroundImportMapOverride = importOverrides.apply;
|
|
1827
|
+
var removePlaygroundImportMapOverride = importOverrides.remove;
|
|
1828
|
+
var getPlaygroundStyleOverrides = styleOverrides.get;
|
|
1829
|
+
var setPlaygroundStyleOverrides = styleOverrides.set;
|
|
1830
|
+
var applyPlaygroundStyleOverride = styleOverrides.apply;
|
|
1831
|
+
var removePlaygroundStyleOverride = styleOverrides.remove;
|
|
1832
|
+
var clearPlaygroundMaps = () => {
|
|
1833
|
+
[
|
|
1834
|
+
siteModules,
|
|
1835
|
+
siteStyles,
|
|
1836
|
+
importOverrides,
|
|
1837
|
+
styleOverrides
|
|
1838
|
+
].forEach((store) => store.set());
|
|
1839
|
+
};
|
|
1840
|
+
//#endregion
|
|
1841
|
+
//#region packages/playground/src/preview-service.ts
|
|
1842
|
+
/** Preview iframe 内的高度服务;class 会被序列化到 iframe 执行。 */
|
|
1843
|
+
var PlaygroundService = class {
|
|
1844
|
+
target;
|
|
1845
|
+
vue;
|
|
1846
|
+
session;
|
|
1847
|
+
/* istanbul ignore next -- class 会被序列化到没有覆盖率运行时的 iframe。 */
|
|
1848
|
+
sequence = 0;
|
|
1849
|
+
/* istanbul ignore next -- class 会被序列化到没有覆盖率运行时的 iframe。 */
|
|
1850
|
+
disposed = false;
|
|
1851
|
+
manual;
|
|
1852
|
+
/* istanbul ignore next -- class 会被序列化到没有覆盖率运行时的 iframe。 */
|
|
1853
|
+
requests = /* @__PURE__ */ new Set();
|
|
1854
|
+
/* istanbul ignore next -- class 会被序列化到没有覆盖率运行时的 iframe。 */
|
|
1855
|
+
owners = /* @__PURE__ */ new Set();
|
|
1856
|
+
/**
|
|
1857
|
+
* @param target 当前预览窗口。
|
|
1858
|
+
* @param vue 与预览应用共用的 Vue 实例。
|
|
1859
|
+
*/
|
|
1860
|
+
/* istanbul ignore next -- class 会被序列化到没有覆盖率运行时的 iframe。 */
|
|
1861
|
+
constructor(target, vue) {
|
|
1862
|
+
this.target = target;
|
|
1863
|
+
this.vue = vue;
|
|
1864
|
+
this.session = `${Date.now()}-${Math.random()}`;
|
|
1865
|
+
this.dispose = this.dispose.bind(this);
|
|
1866
|
+
this.post("start");
|
|
1867
|
+
this.target.addEventListener("pagehide", this.dispose);
|
|
1868
|
+
}
|
|
1869
|
+
/**
|
|
1870
|
+
* 申请手动临时高度;新请求会替换上一个手动请求。
|
|
1871
|
+
* @param height iframe 最小高度。
|
|
1872
|
+
* @returns iframe 是否在超时前应用目标高度。
|
|
1873
|
+
*/
|
|
1874
|
+
enable(height) {
|
|
1875
|
+
this.validateHeight(height);
|
|
1876
|
+
this.manual?.release();
|
|
1877
|
+
this.manual = this.createRequest(height);
|
|
1878
|
+
return this.manual.ready;
|
|
1879
|
+
}
|
|
1880
|
+
/** 释放手动临时高度,不影响 `run` 创建的请求。 */
|
|
1881
|
+
disable() {
|
|
1882
|
+
this.manual?.release();
|
|
1883
|
+
this.manual = void 0;
|
|
1884
|
+
}
|
|
1885
|
+
/**
|
|
1886
|
+
* 创建等待高度后执行的事件处理函数。
|
|
1887
|
+
* @param height iframe 最小高度。
|
|
1888
|
+
* @param optionsOrHandler 可见状态配置,或最后一个 handler。
|
|
1889
|
+
* @param lastHandler 使用配置时的最后一个 handler。
|
|
1890
|
+
* @returns 保留 handler 参数和结果的异步事件处理函数。
|
|
1891
|
+
*/
|
|
1892
|
+
run(height, optionsOrHandler, lastHandler) {
|
|
1893
|
+
this.validateHeight(height);
|
|
1894
|
+
if (optionsOrHandler === void 0) return (visible) => {
|
|
1895
|
+
if (visible) return this.enable(height);
|
|
1896
|
+
this.disable();
|
|
1897
|
+
return Promise.resolve(void 0);
|
|
1898
|
+
};
|
|
1899
|
+
const visible = (typeof optionsOrHandler === "function" ? {} : optionsOrHandler).visible;
|
|
1900
|
+
if (visible !== void 0 && !this.vue.isRef(visible) && typeof visible !== "function") throw new TypeError("Playground visible must be a ref or getter");
|
|
1901
|
+
const handler = typeof optionsOrHandler === "function" ? optionsOrHandler : lastHandler ?? (this.vue.isRef(visible) ? () => {
|
|
1902
|
+
visible.value = true;
|
|
1903
|
+
} : void 0);
|
|
1904
|
+
if (typeof handler !== "function") throw new TypeError("Playground run requires a handler");
|
|
1905
|
+
let ownerDisposed = false;
|
|
1906
|
+
let current;
|
|
1907
|
+
let pending;
|
|
1908
|
+
const disposeOwner = () => {
|
|
1909
|
+
ownerDisposed = true;
|
|
1910
|
+
current?.release();
|
|
1911
|
+
this.owners.delete(disposeOwner);
|
|
1912
|
+
};
|
|
1913
|
+
this.owners.add(disposeOwner);
|
|
1914
|
+
if (this.vue.getCurrentScope()) this.vue.onScopeDispose(disposeOwner);
|
|
1915
|
+
return (...args) => {
|
|
1916
|
+
if (this.disposed || ownerDisposed) return Promise.resolve(void 0);
|
|
1917
|
+
if (pending) return pending;
|
|
1918
|
+
const request = current = this.createRequest(height);
|
|
1919
|
+
let executionFinished = false;
|
|
1920
|
+
const unlock = () => {
|
|
1921
|
+
if (executionFinished && request.released && current === request) {
|
|
1922
|
+
pending = void 0;
|
|
1923
|
+
current = void 0;
|
|
1924
|
+
}
|
|
1925
|
+
};
|
|
1926
|
+
request.closed.then(unlock);
|
|
1927
|
+
const execution = (async () => {
|
|
1928
|
+
try {
|
|
1929
|
+
if (!await request.ready || ownerDisposed || this.disposed) return void 0;
|
|
1930
|
+
if (visible) request.watch(visible);
|
|
1931
|
+
const result = await handler(...args);
|
|
1932
|
+
if (!visible || !this.vue.toValue(visible)) request.release();
|
|
1933
|
+
return result;
|
|
1934
|
+
} catch (error) {
|
|
1935
|
+
request.release();
|
|
1936
|
+
throw error;
|
|
1937
|
+
} finally {
|
|
1938
|
+
executionFinished = true;
|
|
1939
|
+
unlock();
|
|
1940
|
+
}
|
|
1941
|
+
})();
|
|
1942
|
+
pending = execution;
|
|
1943
|
+
return execution;
|
|
1944
|
+
};
|
|
1945
|
+
}
|
|
1946
|
+
/** 释放当前预览应用持有的全部高度和监听。 */
|
|
1947
|
+
/* istanbul ignore next -- 注入测试会从序列化后的 iframe class 调用该方法。 */
|
|
1948
|
+
dispose() {
|
|
1949
|
+
if (this.disposed) return;
|
|
1950
|
+
this.disposed = true;
|
|
1951
|
+
for (const disposeOwner of this.owners) disposeOwner();
|
|
1952
|
+
for (const request of this.requests) request.release();
|
|
1953
|
+
this.post("stop");
|
|
1954
|
+
this.target.removeEventListener("pagehide", this.dispose);
|
|
1955
|
+
if (this.target.$docsPlayground === this) delete this.target.$docsPlayground;
|
|
1956
|
+
}
|
|
1957
|
+
/** @param height iframe 最小高度。 */
|
|
1958
|
+
validateHeight(height) {
|
|
1959
|
+
if (!Number.isFinite(height) || height <= 0) throw new TypeError("Playground height must be a positive finite number");
|
|
1960
|
+
}
|
|
1961
|
+
/**
|
|
1962
|
+
* @param operation 请求操作。
|
|
1963
|
+
* @param id 请求标识。
|
|
1964
|
+
* @param height iframe 最小高度。
|
|
1965
|
+
*/
|
|
1966
|
+
/* istanbul ignore next -- 构造和销毁时会从序列化后的 iframe class 调用该方法。 */
|
|
1967
|
+
post(operation, id = 0, height = 0) {
|
|
1968
|
+
this.target.parent.postMessage({
|
|
1969
|
+
action: "docs:height",
|
|
1970
|
+
session: this.session,
|
|
1971
|
+
operation,
|
|
1972
|
+
id,
|
|
1973
|
+
height
|
|
1974
|
+
}, "*");
|
|
1975
|
+
}
|
|
1976
|
+
/**
|
|
1977
|
+
* @param height iframe 最小高度。
|
|
1978
|
+
* @returns 内部等待与释放句柄。
|
|
1979
|
+
*/
|
|
1980
|
+
createRequest(height) {
|
|
1981
|
+
this.validateHeight(height);
|
|
1982
|
+
const id = ++this.sequence;
|
|
1983
|
+
let released = false;
|
|
1984
|
+
let settled = false;
|
|
1985
|
+
let frame = 0;
|
|
1986
|
+
let timer = 0;
|
|
1987
|
+
let stopWatch;
|
|
1988
|
+
let resolveReady;
|
|
1989
|
+
let resolveClosed;
|
|
1990
|
+
const ready = new Promise((resolve) => {
|
|
1991
|
+
resolveReady = resolve;
|
|
1992
|
+
});
|
|
1993
|
+
const closed = new Promise((resolve) => {
|
|
1994
|
+
resolveClosed = resolve;
|
|
1995
|
+
});
|
|
1996
|
+
const stopWaiting = () => {
|
|
1997
|
+
this.target.cancelAnimationFrame(frame);
|
|
1998
|
+
if (timer) {
|
|
1999
|
+
this.target.clearTimeout(timer);
|
|
2000
|
+
timer = 0;
|
|
2001
|
+
}
|
|
2002
|
+
this.target.removeEventListener("message", onMessage);
|
|
2003
|
+
};
|
|
2004
|
+
const release = () => {
|
|
2005
|
+
if (released) return;
|
|
2006
|
+
released = true;
|
|
2007
|
+
stopWaiting();
|
|
2008
|
+
stopWatch?.();
|
|
2009
|
+
resolveReady(false);
|
|
2010
|
+
resolveClosed();
|
|
2011
|
+
this.requests.delete(request);
|
|
2012
|
+
this.post("release", id);
|
|
2013
|
+
};
|
|
2014
|
+
const check = () => {
|
|
2015
|
+
if (released) return;
|
|
2016
|
+
if (this.target.innerHeight >= height) {
|
|
2017
|
+
settled = true;
|
|
2018
|
+
stopWaiting();
|
|
2019
|
+
resolveReady(true);
|
|
2020
|
+
} else frame = this.target.requestAnimationFrame(check);
|
|
2021
|
+
};
|
|
2022
|
+
const onMessage = (event) => {
|
|
2023
|
+
const data = event.data;
|
|
2024
|
+
if (event.source !== this.target.parent || data?.action !== "docs:height:applied" || data.session !== this.session || data.id !== id || settled) return;
|
|
2025
|
+
if (!data.accepted) release();
|
|
2026
|
+
else check();
|
|
2027
|
+
};
|
|
2028
|
+
const request = {
|
|
2029
|
+
ready,
|
|
2030
|
+
closed,
|
|
2031
|
+
get released() {
|
|
2032
|
+
return released;
|
|
2033
|
+
},
|
|
2034
|
+
release,
|
|
2035
|
+
watch: (visible) => {
|
|
2036
|
+
stopWatch = this.vue.watch(() => this.vue.toValue(visible), (value) => {
|
|
2037
|
+
if (!value) release();
|
|
2038
|
+
}, { flush: "sync" });
|
|
2039
|
+
}
|
|
2040
|
+
};
|
|
2041
|
+
this.requests.add(request);
|
|
2042
|
+
if (this.disposed) release();
|
|
2043
|
+
else {
|
|
2044
|
+
this.target.addEventListener("message", onMessage);
|
|
2045
|
+
timer = this.target.setTimeout(() => {
|
|
2046
|
+
timer = 0;
|
|
2047
|
+
release();
|
|
2048
|
+
}, 2e3);
|
|
2049
|
+
this.post("enable", id, height);
|
|
2050
|
+
}
|
|
2051
|
+
return request;
|
|
2052
|
+
}
|
|
2053
|
+
};
|
|
2054
|
+
var PREVIEW_SERVICE_IMPORT_CODE = "import * as __docsPreviewVue from \"vue\"";
|
|
2055
|
+
var PREVIEW_SERVICE_USE_CODE = [
|
|
2056
|
+
`;const __docsPlayground=new (${PlaygroundService.toString()})(window,__docsPreviewVue);`,
|
|
2057
|
+
"app.provide(\"docs:playground\",__docsPlayground);",
|
|
2058
|
+
"window.$docsPlayground=__docsPlayground;",
|
|
2059
|
+
"app.mixin({beforeUnmount(){if(this===this.$root)__docsPlayground.dispose()}});"
|
|
2060
|
+
].join("");
|
|
2061
|
+
//#endregion
|
|
2062
|
+
//#region packages/playground/src/core/repl-modules.ts
|
|
2063
|
+
var { babelParse, MagicString, walkIdentifiers } = _vue_compiler_sfc_dist_compiler_sfc_esm_browser_js;
|
|
2064
|
+
var moduleSpecifier = (item) => item.type === "import-meta" || !item.specifier || item.type === "dynamic" && item.glob ? void 0 : item.specifier;
|
|
2065
|
+
/**
|
|
2066
|
+
* 发现自定义 ESM 的传递引用;缺失的 npm 包映射到 CDN,动态依赖只登记地址。
|
|
2067
|
+
* @param imports 当前预览的模块覆盖。
|
|
2068
|
+
* @param specifiers 源文件实际引用的模块。
|
|
2069
|
+
* @returns 补齐后的 import map。
|
|
2070
|
+
*/
|
|
2071
|
+
var resolveReplImports = async (imports, specifiers) => {
|
|
2072
|
+
const resolved = { ...imports };
|
|
2073
|
+
const visited = /* @__PURE__ */ new Set();
|
|
2074
|
+
const visit = async (specifier, importer) => {
|
|
2075
|
+
const url = require_css.isRelativeSpecifier(specifier) || /^https?:\/\//.test(specifier) ? new URL(specifier, importer || location.href).href : resolved[specifier] ||= require_css.resolveNpmImport(specifier);
|
|
2076
|
+
if (visited.has(url) || /\/\+esm(?:[?#]|$)/.test(url)) return;
|
|
2077
|
+
visited.add(url);
|
|
2078
|
+
const response = await fetch(url);
|
|
2079
|
+
if (!response.ok) throw new Error(`${response.status} ${url}`);
|
|
2080
|
+
const modules = (0, es_module_lexer.parse)(await response.text())[0];
|
|
2081
|
+
await Promise.all(modules.flatMap((item) => {
|
|
2082
|
+
const dependency = moduleSpecifier(item);
|
|
2083
|
+
return dependency ? [visit(dependency, url)] : [];
|
|
2084
|
+
}));
|
|
2085
|
+
};
|
|
2086
|
+
await Promise.all(specifiers.map((specifier) => visit(specifier)));
|
|
2087
|
+
return resolved;
|
|
2088
|
+
};
|
|
2089
|
+
var rewriteImportedExports = (code) => {
|
|
2090
|
+
const statements = babelParse(code, { sourceType: "module" }).program.body;
|
|
2091
|
+
const bindings = /* @__PURE__ */ new Map();
|
|
2092
|
+
const source = new MagicString(code);
|
|
2093
|
+
for (const statement of statements) {
|
|
2094
|
+
if (statement.type !== "ImportDeclaration") continue;
|
|
2095
|
+
for (const spec of statement.specifiers) {
|
|
2096
|
+
if (spec.type === "ImportNamespaceSpecifier") continue;
|
|
2097
|
+
const imported = spec.type === "ImportDefaultSpecifier" ? "default" : spec.imported.type === "Identifier" ? spec.imported.name : JSON.stringify(spec.imported.value);
|
|
2098
|
+
bindings.set(spec.local.name, {
|
|
2099
|
+
imported,
|
|
2100
|
+
source: statement.source.value,
|
|
2101
|
+
rename: (name) => source.overwrite(spec.local.start, spec.local.end, spec.type === "ImportSpecifier" && spec.imported.start === spec.local.start ? `${imported} as ${name}` : name)
|
|
2102
|
+
});
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
2106
|
+
const rewritten = /* @__PURE__ */ new Set();
|
|
2107
|
+
for (const statement of statements) {
|
|
2108
|
+
if (statement.type !== "ExportNamedDeclaration" || statement.source || statement.declaration) continue;
|
|
2109
|
+
const exports = statement.specifiers.map((spec) => {
|
|
2110
|
+
if (spec.type !== "ExportSpecifier") return "";
|
|
2111
|
+
const local = spec.local.name;
|
|
2112
|
+
const exported = spec.exported.type === "Identifier" ? spec.exported.name : JSON.stringify(spec.exported.value);
|
|
2113
|
+
const binding = bindings.get(local);
|
|
2114
|
+
if (!binding) return `export { ${local} as ${exported} };`;
|
|
2115
|
+
if (!aliases.has(local)) {
|
|
2116
|
+
const alias = `__docs_reexport_${aliases.size}__`;
|
|
2117
|
+
aliases.set(local, alias);
|
|
2118
|
+
binding.rename(alias);
|
|
2119
|
+
}
|
|
2120
|
+
return `export { ${binding.imported} as ${exported} } from ${JSON.stringify(binding.source)};`;
|
|
2121
|
+
});
|
|
2122
|
+
if (statement.specifiers.some((spec) => spec.type === "ExportSpecifier" && bindings.has(spec.local.name))) {
|
|
2123
|
+
source.overwrite(statement.start, statement.end, exports.join("\n"));
|
|
2124
|
+
rewritten.add(statement);
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
for (const statement of statements) {
|
|
2128
|
+
if (statement.type === "ImportDeclaration" || rewritten.has(statement)) continue;
|
|
2129
|
+
walkIdentifiers(statement, (id, parent) => {
|
|
2130
|
+
const alias = aliases.get(id.name);
|
|
2131
|
+
if (!alias) return;
|
|
2132
|
+
if (parent?.type === "ObjectProperty" && parent.shorthand) source.appendLeft(id.end, `: ${alias}`);
|
|
2133
|
+
else source.overwrite(id.start, id.end, alias);
|
|
2134
|
+
});
|
|
2135
|
+
}
|
|
2136
|
+
return source.toString();
|
|
2137
|
+
};
|
|
2138
|
+
/**
|
|
2139
|
+
* REPL 将 ./ 引用按 src 根目录解析,编译结果需要先转成文件表中的完整路径。
|
|
2140
|
+
* @param store iframe 预览的文件和编译结果。
|
|
2141
|
+
*/
|
|
2142
|
+
var bindReplModules = (store) => {
|
|
2143
|
+
(0, vue.watch)(() => Object.values(store.files).map((file) => [
|
|
2144
|
+
file.filename,
|
|
2145
|
+
file.code,
|
|
2146
|
+
file.compiled.js,
|
|
2147
|
+
file.compiled.ssr
|
|
2148
|
+
]), () => {
|
|
2149
|
+
const files = require_css.createFileIndex(Object.fromEntries(Object.entries(store.files).map(([name, file]) => [name, file.code])));
|
|
2150
|
+
const importMap = store.getImportMap();
|
|
2151
|
+
const imports = { ...importMap.imports };
|
|
2152
|
+
let importsChanged = false;
|
|
2153
|
+
for (const file of Object.values(store.files)) for (const output of ["js", "ssr"]) {
|
|
2154
|
+
if (!file.compiled[output]) continue;
|
|
2155
|
+
try {
|
|
2156
|
+
let code = /\.[jt]sx?$/.test(file.filename) ? require_css.transformScript(file.code, file.filename, {
|
|
2157
|
+
esm: true,
|
|
2158
|
+
jsx: /\.[jt]sx$/.test(file.filename)
|
|
2159
|
+
}) : require_css.rewriteImportMeta(file.compiled[output], file.filename);
|
|
2160
|
+
code = rewriteImportedExports(code);
|
|
2161
|
+
for (const item of [...(0, es_module_lexer.parse)(code)[0]].reverse()) {
|
|
2162
|
+
const specifier = moduleSpecifier(item);
|
|
2163
|
+
if (!specifier) continue;
|
|
2164
|
+
if (require_css.isRelativeSpecifier(specifier)) {
|
|
2165
|
+
const resolved = require_css.resolveModulePath(file.filename, specifier, files);
|
|
2166
|
+
if (!resolved) continue;
|
|
2167
|
+
const target = `./${resolved.replace(/^\/?src\//, "")}`;
|
|
2168
|
+
const text = item.type === "dynamic" ? JSON.stringify(target) : target;
|
|
2169
|
+
code = code.slice(0, item.start) + text + code.slice(item.end);
|
|
2170
|
+
} else if (!/^https?:\/\//.test(specifier) && !imports[specifier]) {
|
|
2171
|
+
imports[specifier] = require_css.resolveNpmImport(specifier);
|
|
2172
|
+
importsChanged = true;
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
if (file.compiled[output] !== code) file.compiled[output] = code;
|
|
2176
|
+
} catch (error) {
|
|
2177
|
+
store.errors.push(error instanceof Error ? error : String(error));
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
if (importsChanged) store.setImportMap({
|
|
2181
|
+
...importMap,
|
|
2182
|
+
imports
|
|
2183
|
+
});
|
|
2184
|
+
}, { immediate: true });
|
|
2185
|
+
};
|
|
2186
|
+
//#endregion
|
|
2187
|
+
//#region packages/playground/src/core/store.ts
|
|
2188
|
+
var DOCS_LINK_IMPORT_CODE = "import { h as __docsH } from \"vue\"";
|
|
2189
|
+
var DOCS_LINK_USE_CODE = [
|
|
2190
|
+
PREVIEW_SCROLL_RESET_CODE,
|
|
2191
|
+
"app.component(\"DocsLink\",{",
|
|
2192
|
+
"props:{to:{type:String,default:\"\"}},",
|
|
2193
|
+
"setup(props,{slots}){return()=>__docsH(\"a\",{",
|
|
2194
|
+
"href:props.to,",
|
|
2195
|
+
"style:{color:\"inherit\",textDecoration:\"none\"},",
|
|
2196
|
+
"onClick(event){event.preventDefault();window.parent.postMessage({action:\"docs:navigate\",to:props.to},\"*\")}",
|
|
2197
|
+
"},slots.default?.())}",
|
|
2198
|
+
"})"
|
|
2199
|
+
].join("");
|
|
2200
|
+
var escapeHtmlAttr = (value) => value.replace(/&/gu, "&").replace(/"/gu, """).replace(/'/gu, "'").replace(/</gu, "<").replace(/>/gu, ">");
|
|
2201
|
+
/**
|
|
2202
|
+
* runtime 画布色。`previewInset` 露出的 padding、iframe chrome 和 sandbox
|
|
2203
|
+
* `html`/`body` 必须共用这一变量,暗色下 `--docs-background-color` 与
|
|
2204
|
+
* `--vc-background-color-light` 不同,否则会出现色带割裂。
|
|
2205
|
+
*/
|
|
2206
|
+
var PLAYGROUND_RUNTIME_CANVAS_BACKGROUND = "var(--vc-background-color-light, var(--docs-background-color, #fff))";
|
|
2207
|
+
var createRuntimePreviewOptions = (cdnURL = require_css.DEFAULT_CDN_URL, options = {}) => {
|
|
2208
|
+
const previewScroller = options.previewScroller === true;
|
|
2209
|
+
const hrefs = Object.values({
|
|
2210
|
+
...require_css.createBuiltinStyles(cdnURL),
|
|
2211
|
+
...getPlaygroundSiteStyles(),
|
|
2212
|
+
...getPlaygroundStyleOverrides()
|
|
2213
|
+
});
|
|
2214
|
+
const styleBlocks = [
|
|
2215
|
+
`html,body{height:auto;min-height:0;background:${PLAYGROUND_RUNTIME_CANVAS_BACKGROUND}}`,
|
|
2216
|
+
"body{color:var(--vc-foreground-color,#080f20)}",
|
|
2217
|
+
...previewScroller ? [PREVIEW_SCROLLER_STYLE] : []
|
|
2218
|
+
];
|
|
2219
|
+
return {
|
|
2220
|
+
showRuntimeError: false,
|
|
2221
|
+
showRuntimeWarning: false,
|
|
2222
|
+
headHTML: [
|
|
2223
|
+
SANDBOX_RUNTIME_ERROR_CAPTURE_HTML,
|
|
2224
|
+
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">",
|
|
2225
|
+
...hrefs.map((href) => `<link rel="stylesheet" href="${escapeHtmlAttr(href)}">`),
|
|
2226
|
+
"<style>",
|
|
2227
|
+
...styleBlocks,
|
|
2228
|
+
"</style>"
|
|
2229
|
+
].join("\n"),
|
|
2230
|
+
customCode: {
|
|
2231
|
+
importCode: `${DOCS_LINK_IMPORT_CODE}\n${PREVIEW_SERVICE_IMPORT_CODE}`,
|
|
2232
|
+
useCode: `${DOCS_LINK_USE_CODE}\n${PREVIEW_SERVICE_USE_CODE}`
|
|
2233
|
+
}
|
|
2234
|
+
};
|
|
2235
|
+
};
|
|
2236
|
+
var toReplFilename = (filename) => filename.startsWith("src/") ? filename : `src/${filename}`;
|
|
2237
|
+
var createReplFile = (filename, code) => {
|
|
2238
|
+
const replFilename = toReplFilename(filename);
|
|
2239
|
+
return new _vue_repl.File(replFilename, code);
|
|
2240
|
+
};
|
|
2241
|
+
/**
|
|
2242
|
+
* 默认 CDN → 站点 modules → 实例 builtinImportMap → 管理页覆盖。
|
|
2243
|
+
* iframe import map 与直接渲染加载的是同一份地址表。
|
|
2244
|
+
* @param cdnURL
|
|
2245
|
+
* @param builtinImportMap
|
|
2246
|
+
*/
|
|
2247
|
+
var createRuntimeImports = (cdnURL = require_css.DEFAULT_CDN_URL, builtinImportMap) => ({
|
|
2248
|
+
...require_css.createBuiltinImports(cdnURL),
|
|
2249
|
+
...getPlaygroundSiteModules(),
|
|
2250
|
+
...filterSafeHrefs(builtinImportMap?.imports),
|
|
2251
|
+
...getPlaygroundImportMapOverrides()
|
|
2252
|
+
});
|
|
2253
|
+
var createRuntimeStore = (files, entry, options) => {
|
|
2254
|
+
const { cdnURL, builtinImportMap, ...storeOptions } = options;
|
|
2255
|
+
const replFiles = (0, vue.ref)(Object.fromEntries(Object.entries(files).map(([filename, code]) => {
|
|
2256
|
+
const file = createReplFile(filename, code);
|
|
2257
|
+
return [file.filename, file];
|
|
2258
|
+
})));
|
|
2259
|
+
const mainFile = (0, vue.ref)(toReplFilename(entry));
|
|
2260
|
+
const activeFilename = (0, vue.ref)(toReplFilename(entry));
|
|
2261
|
+
const imports = createRuntimeImports(cdnURL, builtinImportMap);
|
|
2262
|
+
const store = (0, _vue_repl.useStore)({
|
|
2263
|
+
...storeOptions,
|
|
2264
|
+
files: replFiles,
|
|
2265
|
+
mainFile,
|
|
2266
|
+
activeFilename,
|
|
2267
|
+
builtinImportMap: (0, vue.ref)({
|
|
2268
|
+
...builtinImportMap,
|
|
2269
|
+
imports
|
|
2270
|
+
}),
|
|
2271
|
+
template: (0, vue.ref)({
|
|
2272
|
+
welcomeSFC: files[entry],
|
|
2273
|
+
newSFC: require_css.NEW_SFC_CODE
|
|
2274
|
+
})
|
|
2275
|
+
});
|
|
2276
|
+
require_css.bindPlaygroundScss(store);
|
|
2277
|
+
bindReplModules(store);
|
|
2278
|
+
require_css.whenSassReady(files, () => {
|
|
2279
|
+
const specifiers = require_css.collectBareSpecifiers(files, Object.keys(files));
|
|
2280
|
+
if (!specifiers.length) {
|
|
2281
|
+
store.init();
|
|
2282
|
+
return;
|
|
2283
|
+
}
|
|
2284
|
+
store.loading = true;
|
|
2285
|
+
resolveReplImports(imports, specifiers).then((resolved) => {
|
|
2286
|
+
if (Object.keys(resolved).length !== Object.keys(imports).length) store.setImportMap({ imports: resolved }, true);
|
|
2287
|
+
store.init();
|
|
2288
|
+
}).catch((error) => {
|
|
2289
|
+
store.errors.push(error);
|
|
2290
|
+
}).finally(() => {
|
|
2291
|
+
store.loading = false;
|
|
2292
|
+
});
|
|
2293
|
+
});
|
|
2294
|
+
return store;
|
|
2295
|
+
};
|
|
2296
|
+
//#endregion
|
|
1382
2297
|
//#region packages/playground/src/core/runtime/alone/wrapper.vue?vue&type=script&setup=true&lang.ts
|
|
1383
|
-
var _hoisted_1$
|
|
2298
|
+
var _hoisted_1$3 = ["aria-label"];
|
|
1384
2299
|
var _hoisted_2$2 = { class: "docs-playground-popup__frame" };
|
|
1385
2300
|
var _hoisted_3$2 = { class: "docs-playground-popup__header" };
|
|
1386
2301
|
var _hoisted_4$2 = ["title"];
|
|
@@ -1425,7 +2340,7 @@ var wrapper_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1425
2340
|
"portal-fulfilled"
|
|
1426
2341
|
],
|
|
1427
2342
|
setup(__props, { emit: __emit }) {
|
|
1428
|
-
const LocalSandbox = (0, vue.defineAsyncComponent)(() => Promise.resolve().then(() =>
|
|
2343
|
+
const LocalSandbox = (0, vue.defineAsyncComponent)(() => Promise.resolve().then(() => local_sandbox_exports));
|
|
1429
2344
|
const props = __props;
|
|
1430
2345
|
const emit = __emit;
|
|
1431
2346
|
const { t } = (0, _deot_docs_locale.useLocale)();
|
|
@@ -1442,11 +2357,11 @@ var wrapper_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1442
2357
|
const temporaryHeight = usePreviewHeightBridge(sandboxRef, availableHeight);
|
|
1443
2358
|
const sandboxKey = (0, vue.ref)(0);
|
|
1444
2359
|
const layoutTick = (0, vue.ref)(0);
|
|
1445
|
-
const runtimeError =
|
|
2360
|
+
const runtimeError = useSandboxRuntimeErrorGuard(sandboxRef);
|
|
1446
2361
|
useSandboxTheme(sandboxRef);
|
|
1447
|
-
const storeErrors = (0, vue.computed)(() => props.local ? localError.value.compile : (props.store?.errors || []).map(
|
|
2362
|
+
const storeErrors = (0, vue.computed)(() => props.local ? localError.value.compile : (props.store?.errors || []).map(toErrorText).filter(Boolean).join("\n"));
|
|
1448
2363
|
const errorText = (0, vue.computed)(() => {
|
|
1449
|
-
const runtime = props.local ? localError.value.runtime : runtimeError.value ?
|
|
2364
|
+
const runtime = props.local ? localError.value.runtime : runtimeError.value ? formatSandboxRuntimeError(runtimeError.value, t("playground.runtime.importMapTip")) : "";
|
|
1450
2365
|
return [storeErrors.value, runtime].filter(Boolean).join("\n\n");
|
|
1451
2366
|
});
|
|
1452
2367
|
const layout = (0, vue.computed)(() => {
|
|
@@ -1469,7 +2384,7 @@ var wrapper_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1469
2384
|
const canvasStyle = (0, vue.computed)(() => ({
|
|
1470
2385
|
width: `${layout.value.canvasWidth}px`,
|
|
1471
2386
|
height: `${layout.value.canvasHeight}px`,
|
|
1472
|
-
background:
|
|
2387
|
+
background: PLAYGROUND_RUNTIME_CANVAS_BACKGROUND
|
|
1473
2388
|
}));
|
|
1474
2389
|
const handleRefresh = () => {
|
|
1475
2390
|
runtimeError.value = "";
|
|
@@ -1501,7 +2416,7 @@ var wrapper_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1501
2416
|
layoutTick.value++;
|
|
1502
2417
|
};
|
|
1503
2418
|
const handleBridgeMessage = (event) => {
|
|
1504
|
-
if (!
|
|
2419
|
+
if (!isSandboxMessage(sandboxRef.value, event)) return;
|
|
1505
2420
|
const data = event.data;
|
|
1506
2421
|
if (!data || data.action !== "docs:navigate" || typeof data.to !== "string") return;
|
|
1507
2422
|
emit("navigate", data.to);
|
|
@@ -1594,7 +2509,7 @@ var wrapper_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1594
2509
|
])) : (0, vue.createCommentVNode)("v-if", true)], 4)]),
|
|
1595
2510
|
_: 1
|
|
1596
2511
|
})])
|
|
1597
|
-
])], 4)], 8, _hoisted_1$
|
|
2512
|
+
])], 4)], 8, _hoisted_1$3);
|
|
1598
2513
|
};
|
|
1599
2514
|
}
|
|
1600
2515
|
});
|
|
@@ -1606,27 +2521,932 @@ var Alone = new _deot_vc.Portal(wrapper_default, {
|
|
|
1606
2521
|
multiple: false
|
|
1607
2522
|
});
|
|
1608
2523
|
//#endregion
|
|
2524
|
+
//#region packages/playground/src/core/runtime/local/playground.ts
|
|
2525
|
+
/**
|
|
2526
|
+
* 直接渲染与页面同文档,弹层不需要临时撑高。
|
|
2527
|
+
* `run` 仍返回可调用函数,但不会申请高度,也不会改动预览尺寸。
|
|
2528
|
+
* @param vue 宿主 Vue,只用其中的 `isRef`。
|
|
2529
|
+
* @returns 注入给预览的 `docs:playground`。
|
|
2530
|
+
*/
|
|
2531
|
+
var createLocalPlayground = (vue) => {
|
|
2532
|
+
const run = (_height, optionsOrHandler, lastHandler) => {
|
|
2533
|
+
const visible = (typeof optionsOrHandler === "function" || optionsOrHandler == null ? {} : optionsOrHandler).visible;
|
|
2534
|
+
const handler = typeof optionsOrHandler === "function" ? optionsOrHandler : typeof lastHandler === "function" ? lastHandler : vue.isRef(visible) ? () => {
|
|
2535
|
+
visible.value = true;
|
|
2536
|
+
} : void 0;
|
|
2537
|
+
return (...args) => {
|
|
2538
|
+
if (typeof handler !== "function") return void 0;
|
|
2539
|
+
return handler(...args);
|
|
2540
|
+
};
|
|
2541
|
+
};
|
|
2542
|
+
return {
|
|
2543
|
+
enable: () => Promise.resolve(true),
|
|
2544
|
+
disable() {},
|
|
2545
|
+
dispose() {},
|
|
2546
|
+
run
|
|
2547
|
+
};
|
|
2548
|
+
};
|
|
2549
|
+
//#endregion
|
|
2550
|
+
//#region packages/playground/src/core/runtime/local/port.ts
|
|
2551
|
+
/** 只在桥接 iframe 内部转发,保证父页面收到的 source 是该 iframe。 */
|
|
2552
|
+
var LOCAL_BRIDGE_CHANNEL = "docs:local-out";
|
|
2553
|
+
var BRIDGE_INSTALLER = `
|
|
2554
|
+
if (!window.__docsLocalBridge) {
|
|
2555
|
+
window.__docsLocalBridge = true;
|
|
2556
|
+
window.addEventListener('message', function (event) {
|
|
2557
|
+
var data = event.data;
|
|
2558
|
+
if (!data || data.channel !== ${JSON.stringify(LOCAL_BRIDGE_CHANNEL)}) return;
|
|
2559
|
+
window.parent.postMessage(data.payload, '*');
|
|
2560
|
+
});
|
|
2561
|
+
}
|
|
2562
|
+
`;
|
|
2563
|
+
var LOCAL_BRIDGE_SRCDOC = `<!doctype html><html><head></head><body><script>${BRIDGE_INSTALLER}<\/script></body></html>`;
|
|
2564
|
+
/**
|
|
2565
|
+
* 在同源空白 iframe 里安装转发脚本。调用发生在 iframe realm,父页面看到的 source 才是它。
|
|
2566
|
+
* @param iframe 用作消息身份的空白 iframe。
|
|
2567
|
+
* @returns 脚本是否已经装上。
|
|
2568
|
+
*/
|
|
2569
|
+
var installLocalBridge = (iframe) => {
|
|
2570
|
+
const win = iframe.contentWindow;
|
|
2571
|
+
if (!win || win.__docsLocalBridge) return Boolean(win?.__docsLocalBridge);
|
|
2572
|
+
win.eval(BRIDGE_INSTALLER);
|
|
2573
|
+
return Boolean(win.__docsLocalBridge);
|
|
2574
|
+
};
|
|
2575
|
+
/**
|
|
2576
|
+
* 满足 PlaygroundService 现有 Window 调用的预览窗口。
|
|
2577
|
+
* 出站消息经 iframe 转发,入站回复再交回服务,协议仍是 docs:height / docs:navigate。
|
|
2578
|
+
*/
|
|
2579
|
+
var LocalPreviewPort = class {
|
|
2580
|
+
iframe;
|
|
2581
|
+
parent;
|
|
2582
|
+
listeners = /* @__PURE__ */ new Map();
|
|
2583
|
+
constructor(iframe) {
|
|
2584
|
+
this.iframe = iframe;
|
|
2585
|
+
this.parent = { postMessage: (data) => {
|
|
2586
|
+
this.iframe.contentWindow?.postMessage({
|
|
2587
|
+
channel: LOCAL_BRIDGE_CHANNEL,
|
|
2588
|
+
payload: data
|
|
2589
|
+
}, "*");
|
|
2590
|
+
} };
|
|
2591
|
+
}
|
|
2592
|
+
get contentWindow() {
|
|
2593
|
+
return this.iframe.contentWindow;
|
|
2594
|
+
}
|
|
2595
|
+
get innerHeight() {
|
|
2596
|
+
const fromWindow = this.iframe.contentWindow?.innerHeight ?? 0;
|
|
2597
|
+
if (fromWindow > 0) return fromWindow;
|
|
2598
|
+
return this.iframe.clientHeight || this.iframe.parentElement?.clientHeight || 0;
|
|
2599
|
+
}
|
|
2600
|
+
addEventListener(type, listener) {
|
|
2601
|
+
const win = this.iframe.contentWindow;
|
|
2602
|
+
if (!win) return;
|
|
2603
|
+
if (type !== "message") {
|
|
2604
|
+
win.addEventListener(type, listener);
|
|
2605
|
+
return;
|
|
2606
|
+
}
|
|
2607
|
+
const wrapped = (event) => {
|
|
2608
|
+
const message = event;
|
|
2609
|
+
const data = message.data;
|
|
2610
|
+
if (data && data.channel === "docs:local-out") return;
|
|
2611
|
+
listener({
|
|
2612
|
+
data: message.data,
|
|
2613
|
+
source: this.parent
|
|
2614
|
+
});
|
|
2615
|
+
};
|
|
2616
|
+
this.listeners.set(listener, wrapped);
|
|
2617
|
+
win.addEventListener("message", wrapped);
|
|
2618
|
+
}
|
|
2619
|
+
removeEventListener(type, listener) {
|
|
2620
|
+
const win = this.iframe.contentWindow;
|
|
2621
|
+
if (!win) return;
|
|
2622
|
+
const wrapped = this.listeners.get(listener);
|
|
2623
|
+
if (wrapped) {
|
|
2624
|
+
this.listeners.delete(listener);
|
|
2625
|
+
win.removeEventListener(type, wrapped);
|
|
2626
|
+
return;
|
|
2627
|
+
}
|
|
2628
|
+
win.removeEventListener(type, listener);
|
|
2629
|
+
}
|
|
2630
|
+
requestAnimationFrame(callback) {
|
|
2631
|
+
return window.requestAnimationFrame(callback);
|
|
2632
|
+
}
|
|
2633
|
+
cancelAnimationFrame(handle) {
|
|
2634
|
+
window.cancelAnimationFrame(handle);
|
|
2635
|
+
}
|
|
2636
|
+
setTimeout(handler, timeout, ...args) {
|
|
2637
|
+
return window.setTimeout(handler, timeout, ...args);
|
|
2638
|
+
}
|
|
2639
|
+
clearTimeout(handle) {
|
|
2640
|
+
window.clearTimeout(handle);
|
|
2641
|
+
}
|
|
2642
|
+
};
|
|
2643
|
+
//#endregion
|
|
2644
|
+
//#region packages/playground/src/core/runtime/local/format-error.ts
|
|
2645
|
+
/**
|
|
2646
|
+
* 空 reject(例如弹层取消)不要渲染成红条。
|
|
2647
|
+
* @param error 运行时抛出的值。
|
|
2648
|
+
* @returns 可展示的错误文本;空取消返回空字符串。
|
|
2649
|
+
*/
|
|
2650
|
+
var formatPlaygroundRuntimeError = (error) => {
|
|
2651
|
+
if (error == null) return "";
|
|
2652
|
+
const raw = typeof error === "object" && "message" in error ? error.message : error;
|
|
2653
|
+
if (raw == null || raw === "") return "";
|
|
2654
|
+
const text = String(raw);
|
|
2655
|
+
if (text === "undefined" || text === "null") return "";
|
|
2656
|
+
return text;
|
|
2657
|
+
};
|
|
2658
|
+
//#endregion
|
|
2659
|
+
//#region packages/playground/src/core/runtime/local/builtins.ts
|
|
2660
|
+
var loaders = {
|
|
2661
|
+
"vue": () => import("vue"),
|
|
2662
|
+
"vue-router": () => import("vue-router"),
|
|
2663
|
+
"pinia": async () => pinia,
|
|
2664
|
+
"@deot/helper": () => import("@deot/helper"),
|
|
2665
|
+
"@deot/helper-cache": () => import("@deot/helper-cache"),
|
|
2666
|
+
"@deot/helper-device": () => import("@deot/helper-device"),
|
|
2667
|
+
"@deot/helper-dom": () => import("@deot/helper-dom"),
|
|
2668
|
+
"@deot/helper-emitter": () => import("@deot/helper-emitter"),
|
|
2669
|
+
"@deot/helper-fp": () => import("@deot/helper-fp"),
|
|
2670
|
+
"@deot/helper-is": () => import("@deot/helper-is"),
|
|
2671
|
+
"@deot/helper-load": () => import("@deot/helper-load"),
|
|
2672
|
+
"@deot/helper-resize": () => import("@deot/helper-resize"),
|
|
2673
|
+
"@deot/helper-route": () => import("@deot/helper-route"),
|
|
2674
|
+
"@deot/helper-scheduler": () => import("@deot/helper-scheduler"),
|
|
2675
|
+
"@deot/helper-shared": () => import("@deot/helper-shared"),
|
|
2676
|
+
"@deot/helper-unicode": () => import("@deot/helper-unicode"),
|
|
2677
|
+
"@deot/helper-utils": () => import("@deot/helper-utils"),
|
|
2678
|
+
"@deot/helper-validator": () => import("@deot/helper-validator"),
|
|
2679
|
+
"@deot/helper-wheel": () => import("@deot/helper-wheel"),
|
|
2680
|
+
"@deot/http-client": () => import("@deot/http-client"),
|
|
2681
|
+
"@deot/http-core": () => import("@deot/http-core"),
|
|
2682
|
+
"@deot/http-hooks": () => import("@deot/http-hooks"),
|
|
2683
|
+
"@deot/http": () => import("@deot/http"),
|
|
2684
|
+
"@deot/vc": async () => _deot_vc,
|
|
2685
|
+
"@deot/vc-components": async () => _deot_vc_components,
|
|
2686
|
+
"@deot/vc-hooks": async () => _deot_vc_hooks,
|
|
2687
|
+
"@deot/vc-locale": () => import("@deot/vc-locale"),
|
|
2688
|
+
"lodash-es": () => import("lodash-es"),
|
|
2689
|
+
"echarts": () => import("echarts"),
|
|
2690
|
+
"photoswipe": () => import("photoswipe"),
|
|
2691
|
+
"jszip": () => import("jszip"),
|
|
2692
|
+
"jspdf": () => import("jspdf"),
|
|
2693
|
+
"dayjs": async () => (await import("dayjs")).default
|
|
2694
|
+
};
|
|
2695
|
+
var cache = /* @__PURE__ */ new Map();
|
|
2696
|
+
/** 直接渲染可从宿主包注入的说明符;与 Vue 无关的大型依赖按需加载。 */
|
|
2697
|
+
var localBuiltinIds = new Set(Object.keys(loaders));
|
|
2698
|
+
var ensureLocalBuiltin = (id) => {
|
|
2699
|
+
const loader = loaders[id];
|
|
2700
|
+
if (!loader) return Promise.reject(/* @__PURE__ */ new Error(`[Playground] 没有本地模块 "${id}"`));
|
|
2701
|
+
let pending = cache.get(id);
|
|
2702
|
+
if (!pending) {
|
|
2703
|
+
pending = loader();
|
|
2704
|
+
cache.set(id, pending);
|
|
2705
|
+
}
|
|
2706
|
+
return pending;
|
|
2707
|
+
};
|
|
2708
|
+
//#endregion
|
|
2709
|
+
//#region packages/playground/src/core/runtime/local/modules.ts
|
|
2710
|
+
var SKIP_COPY_KEYS = /* @__PURE__ */ new Set([
|
|
2711
|
+
"prototype",
|
|
2712
|
+
"caller",
|
|
2713
|
+
"arguments"
|
|
2714
|
+
]);
|
|
2715
|
+
var toHostModule = (ns) => {
|
|
2716
|
+
if (ns == null || typeof ns !== "object" && typeof ns !== "function") return {
|
|
2717
|
+
__esModule: true,
|
|
2718
|
+
default: ns
|
|
2719
|
+
};
|
|
2720
|
+
const source = ns;
|
|
2721
|
+
const mod = { __esModule: true };
|
|
2722
|
+
const assignKey = (key) => {
|
|
2723
|
+
if (SKIP_COPY_KEYS.has(key) || key === "__esModule") return;
|
|
2724
|
+
try {
|
|
2725
|
+
mod[key] = source[key];
|
|
2726
|
+
} catch {}
|
|
2727
|
+
};
|
|
2728
|
+
try {
|
|
2729
|
+
Object.keys(source).forEach(assignKey);
|
|
2730
|
+
} catch {}
|
|
2731
|
+
try {
|
|
2732
|
+
Object.getOwnPropertyNames(source).forEach(assignKey);
|
|
2733
|
+
} catch {}
|
|
2734
|
+
if (!("default" in mod) || mod.default === void 0) mod.default = source.default !== void 0 ? source.default : source;
|
|
2735
|
+
return mod;
|
|
2736
|
+
};
|
|
2737
|
+
var lookupHostModule = (id, modules) => {
|
|
2738
|
+
if (Object.prototype.hasOwnProperty.call(modules, id)) return toHostModule(modules[id]);
|
|
2739
|
+
return null;
|
|
2740
|
+
};
|
|
2741
|
+
var pickNestedExport = (rootMod, rest) => {
|
|
2742
|
+
if (!rest) return void 0;
|
|
2743
|
+
const parts = rest.split("/").filter(Boolean);
|
|
2744
|
+
let current = rootMod;
|
|
2745
|
+
for (const part of parts) {
|
|
2746
|
+
if (current == null || typeof current !== "object" && typeof current !== "function") return;
|
|
2747
|
+
const record = current;
|
|
2748
|
+
if (!(part in record)) return void 0;
|
|
2749
|
+
current = record[part];
|
|
2750
|
+
}
|
|
2751
|
+
return current;
|
|
2752
|
+
};
|
|
2753
|
+
/**
|
|
2754
|
+
* 先精确匹配,再从右往左剥路径,把剩余段当成导出属性。
|
|
2755
|
+
* 模块表只来自当前 Playground,不写入全局注册表。
|
|
2756
|
+
* @param id 裸模块说明符。
|
|
2757
|
+
* @param modules 当前 Playground 的模块表。
|
|
2758
|
+
* @returns 可被 `require` 使用的模块;找不到时返回 null。
|
|
2759
|
+
*/
|
|
2760
|
+
var resolveHostModule = (id, modules) => {
|
|
2761
|
+
const exact = lookupHostModule(id, modules);
|
|
2762
|
+
if (exact) return exact;
|
|
2763
|
+
let cursor = id;
|
|
2764
|
+
while (true) {
|
|
2765
|
+
const slash = cursor.lastIndexOf("/");
|
|
2766
|
+
if (slash <= 0) break;
|
|
2767
|
+
const parent = cursor.slice(0, slash);
|
|
2768
|
+
const rest = id.slice(parent.length + 1);
|
|
2769
|
+
const rootMod = lookupHostModule(parent, modules);
|
|
2770
|
+
if (rootMod) {
|
|
2771
|
+
const nested = pickNestedExport(rootMod, rest);
|
|
2772
|
+
if (nested !== void 0) return toHostModule(nested);
|
|
2773
|
+
}
|
|
2774
|
+
cursor = parent;
|
|
2775
|
+
}
|
|
2776
|
+
return null;
|
|
2777
|
+
};
|
|
2778
|
+
var HOST_VUE_SPECIFIERS = /* @__PURE__ */ new Set(["vue", "vue/server-renderer"]);
|
|
2779
|
+
var messageOf = (error) => error instanceof Error ? error.message : String(error);
|
|
2780
|
+
/**
|
|
2781
|
+
* 找到 import map 里能覆盖该说明符的键。子路径没有独立 URL 时回退到父包。
|
|
2782
|
+
* @param id 裸模块说明符。
|
|
2783
|
+
* @param imports 合并后的 import map。
|
|
2784
|
+
* @returns 命中的 import map 键;没有地址时返回 null。
|
|
2785
|
+
*/
|
|
2786
|
+
var resolveImportTarget = (id, imports) => {
|
|
2787
|
+
if (imports[id]) return id;
|
|
2788
|
+
let cursor = id;
|
|
2789
|
+
while (true) {
|
|
2790
|
+
const slash = cursor.lastIndexOf("/");
|
|
2791
|
+
if (slash <= 0) return null;
|
|
2792
|
+
const parent = cursor.slice(0, slash);
|
|
2793
|
+
if (imports[parent]) return parent;
|
|
2794
|
+
cursor = parent;
|
|
2795
|
+
}
|
|
2796
|
+
};
|
|
2797
|
+
var prefersLocalBuiltin = (id, imports, cdnURL) => {
|
|
2798
|
+
if (!localBuiltinIds.has(id) && !HOST_VUE_SPECIFIERS.has(id)) return false;
|
|
2799
|
+
const url = imports[id];
|
|
2800
|
+
if (!url) return true;
|
|
2801
|
+
return url === require_css.createBuiltinImports(cdnURL)[id];
|
|
2802
|
+
};
|
|
2803
|
+
/**
|
|
2804
|
+
* 内置依赖先注入宿主副本。import map 里与默认 CDN 不同的地址会覆盖,包括 `vue`。
|
|
2805
|
+
* @param specifiers 本次预览用到的裸模块说明符。
|
|
2806
|
+
* @param imports 合并后的 import map。
|
|
2807
|
+
* @param builtins 宿主 Vue 与 vue-router。
|
|
2808
|
+
* @param builtins.vue 当前页面的 Vue 模块。
|
|
2809
|
+
* @param builtins.vueRouter 打包进来的 vue-router,可被 import map 覆盖。
|
|
2810
|
+
* @param loader 按 URL 加载远程模块。
|
|
2811
|
+
* @param cdnURL 当前 CDN 根,用来识别默认地址。
|
|
2812
|
+
* @returns 模块表和加载错误。
|
|
2813
|
+
*/
|
|
2814
|
+
var loadLocalModules = async (specifiers, imports, builtins, loader, cdnURL) => {
|
|
2815
|
+
const modules = {
|
|
2816
|
+
"vue": builtins.vue,
|
|
2817
|
+
"vue-router": builtins.vueRouter
|
|
2818
|
+
};
|
|
2819
|
+
const errors = [];
|
|
2820
|
+
const targets = /* @__PURE__ */ new Set();
|
|
2821
|
+
const localIds = /* @__PURE__ */ new Set();
|
|
2822
|
+
specifiers.forEach((specifier) => {
|
|
2823
|
+
let local = false;
|
|
2824
|
+
if (prefersLocalBuiltin(specifier, imports, cdnURL)) localIds.add(specifier);
|
|
2825
|
+
else {
|
|
2826
|
+
let cursor = specifier;
|
|
2827
|
+
while (true) {
|
|
2828
|
+
const slash = cursor.lastIndexOf("/");
|
|
2829
|
+
if (slash <= 0) break;
|
|
2830
|
+
const parent = cursor.slice(0, slash);
|
|
2831
|
+
if (prefersLocalBuiltin(parent, imports, cdnURL)) {
|
|
2832
|
+
localIds.add(parent);
|
|
2833
|
+
local = true;
|
|
2834
|
+
break;
|
|
2835
|
+
}
|
|
2836
|
+
cursor = parent;
|
|
2837
|
+
}
|
|
2838
|
+
}
|
|
2839
|
+
if (specifier === "vue-router") {
|
|
2840
|
+
if (imports["vue-router"]) targets.add("vue-router");
|
|
2841
|
+
return;
|
|
2842
|
+
}
|
|
2843
|
+
const target = resolveImportTarget(specifier, imports);
|
|
2844
|
+
if (target && prefersLocalBuiltin(target, imports, cdnURL)) localIds.add(target);
|
|
2845
|
+
else if (target) targets.add(target);
|
|
2846
|
+
else if (!local && !localIds.has(specifier)) {
|
|
2847
|
+
imports[specifier] = require_css.resolveNpmImport(specifier);
|
|
2848
|
+
targets.add(specifier);
|
|
2849
|
+
}
|
|
2850
|
+
});
|
|
2851
|
+
await Promise.all([...localIds].map(async (id) => {
|
|
2852
|
+
if (id === "vue" || id === "vue-router") return;
|
|
2853
|
+
if (id === "vue/server-renderer") {
|
|
2854
|
+
modules[id] = builtins.vue;
|
|
2855
|
+
return;
|
|
2856
|
+
}
|
|
2857
|
+
modules[id] = await ensureLocalBuiltin(id);
|
|
2858
|
+
}));
|
|
2859
|
+
for (const id of targets) {
|
|
2860
|
+
const url = imports[id];
|
|
2861
|
+
if (!url || prefersLocalBuiltin(id, imports, cdnURL)) continue;
|
|
2862
|
+
try {
|
|
2863
|
+
modules[id] = await loader(url);
|
|
2864
|
+
} catch (error) {
|
|
2865
|
+
errors.push(`[Playground] 无法加载模块 "${id}" (${url}): ${messageOf(error)}`);
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
return {
|
|
2869
|
+
modules,
|
|
2870
|
+
errors
|
|
2871
|
+
};
|
|
2872
|
+
};
|
|
2873
|
+
//#endregion
|
|
2874
|
+
//#region packages/playground/src/core/runtime/local/vue-guard.ts
|
|
2875
|
+
/**
|
|
2876
|
+
* 给 files 注入的 vue:同一份宿主 Vue,但 `createApp().mount` 不会卸掉页面。
|
|
2877
|
+
* 防护按本次 link 创建,多个 Playground 互不覆盖。
|
|
2878
|
+
* @param capture 本次链接收集到的根组件、局部组件和 provide。
|
|
2879
|
+
* @returns 带防护的 Vue 模块。
|
|
2880
|
+
*/
|
|
2881
|
+
var createGuardedVue = (capture) => {
|
|
2882
|
+
const createApp = (rootComponent, rootProps) => {
|
|
2883
|
+
const fakeApp = {
|
|
2884
|
+
_component: rootComponent,
|
|
2885
|
+
_props: rootProps,
|
|
2886
|
+
config: {
|
|
2887
|
+
errorHandler: null,
|
|
2888
|
+
warnHandler: null,
|
|
2889
|
+
globalProperties: {}
|
|
2890
|
+
},
|
|
2891
|
+
_context: {
|
|
2892
|
+
provides: Object.create(null),
|
|
2893
|
+
components: Object.create(null),
|
|
2894
|
+
directives: Object.create(null),
|
|
2895
|
+
mixins: []
|
|
2896
|
+
},
|
|
2897
|
+
use() {
|
|
2898
|
+
return fakeApp;
|
|
2899
|
+
},
|
|
2900
|
+
mixin(mixin) {
|
|
2901
|
+
fakeApp._context.mixins.push(mixin);
|
|
2902
|
+
return fakeApp;
|
|
2903
|
+
},
|
|
2904
|
+
component(name, component) {
|
|
2905
|
+
if (component) {
|
|
2906
|
+
fakeApp._context.components[name] = component;
|
|
2907
|
+
return fakeApp;
|
|
2908
|
+
}
|
|
2909
|
+
return fakeApp._context.components[name];
|
|
2910
|
+
},
|
|
2911
|
+
directive() {
|
|
2912
|
+
return fakeApp;
|
|
2913
|
+
},
|
|
2914
|
+
provide(key, value) {
|
|
2915
|
+
fakeApp._context.provides[key] = value;
|
|
2916
|
+
return fakeApp;
|
|
2917
|
+
},
|
|
2918
|
+
mount() {
|
|
2919
|
+
capture.components = { ...fakeApp._context.components };
|
|
2920
|
+
capture.provides = { ...fakeApp._context.provides };
|
|
2921
|
+
capture.mountedComponent = (0, vue.defineComponent)({
|
|
2922
|
+
name: "PlaygroundCapturedApp",
|
|
2923
|
+
components: fakeApp._context.components,
|
|
2924
|
+
setup() {
|
|
2925
|
+
Reflect.ownKeys(fakeApp._context.provides).forEach((key) => {
|
|
2926
|
+
(0, vue.provide)(key, fakeApp._context.provides[key]);
|
|
2927
|
+
});
|
|
2928
|
+
return () => (0, vue.h)(rootComponent, rootProps || null);
|
|
2929
|
+
}
|
|
2930
|
+
});
|
|
2931
|
+
return capture.mountedComponent;
|
|
2932
|
+
},
|
|
2933
|
+
unmount() {},
|
|
2934
|
+
onUnmount() {
|
|
2935
|
+
return fakeApp;
|
|
2936
|
+
}
|
|
2937
|
+
};
|
|
2938
|
+
return fakeApp;
|
|
2939
|
+
};
|
|
2940
|
+
return new Proxy(vue, { get(target, prop, receiver) {
|
|
2941
|
+
if (prop === "createApp" || prop === "createSSRApp") return createApp;
|
|
2942
|
+
if (prop === "default") return receiver;
|
|
2943
|
+
return Reflect.get(target, prop, receiver);
|
|
2944
|
+
} });
|
|
2945
|
+
};
|
|
2946
|
+
//#endregion
|
|
2947
|
+
//#region packages/playground/src/core/runtime/local/linker.ts
|
|
2948
|
+
/**
|
|
2949
|
+
* 在当前页面链接编译结果,返回入口组件。
|
|
2950
|
+
* 未覆盖 `vue` 时换成带防护的宿主实例,避免 `mount` 卸掉页面。
|
|
2951
|
+
* @param compiled 浏览器编译结果。
|
|
2952
|
+
* @param files 当前 Playground 文件表。
|
|
2953
|
+
* @param options 可选的宿主模块表。
|
|
2954
|
+
* @returns 入口组件、样式和链接错误。
|
|
2955
|
+
*/
|
|
2956
|
+
var linkPlayground = (compiled, files, options = {}) => {
|
|
2957
|
+
const errors = [...compiled.errors || []];
|
|
2958
|
+
if (!compiled.entry || errors.length) return {
|
|
2959
|
+
component: null,
|
|
2960
|
+
css: compiled.css || [],
|
|
2961
|
+
errors
|
|
2962
|
+
};
|
|
2963
|
+
const capture = {
|
|
2964
|
+
mountedComponent: null,
|
|
2965
|
+
components: {},
|
|
2966
|
+
provides: {}
|
|
2967
|
+
};
|
|
2968
|
+
const modules = { ...options.modules || {} };
|
|
2969
|
+
if (modules.vue == null || modules.vue === vue) modules.vue = createGuardedVue(capture);
|
|
2970
|
+
const fileIndex = require_css.createFileIndex(files);
|
|
2971
|
+
const root = require_css.getCommonRoot([...fileIndex.keys()]);
|
|
2972
|
+
const cache = /* @__PURE__ */ new Map();
|
|
2973
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
2974
|
+
const requireFn = (fromFilename) => (id) => {
|
|
2975
|
+
if (require_css.isRelativeSpecifier(id)) {
|
|
2976
|
+
const resolved = require_css.resolveModulePath(fromFilename, id, fileIndex);
|
|
2977
|
+
if (!resolved) throw new Error(`[Playground] 无法解析相对模块 "${id}"(来自 ${fromFilename})`);
|
|
2978
|
+
/* istanbul ignore if -- 公共根已包含全部 files,正常解析不会逃出 */
|
|
2979
|
+
if (!require_css.isInsideRoot(resolved, root)) throw new Error(`[Playground] 模块逃出虚拟根: ${resolved}`);
|
|
2980
|
+
return loadModule(resolved);
|
|
2981
|
+
}
|
|
2982
|
+
const host = resolveHostModule(id, modules);
|
|
2983
|
+
if (host) return host;
|
|
2984
|
+
throw new Error(`[Playground] 未注册的模块 "${id}"。请在 import map 中提供可加载的地址。`);
|
|
2985
|
+
};
|
|
2986
|
+
const loadModule = (filename) => {
|
|
2987
|
+
const key = require_css.normalizeVirtualPath(filename);
|
|
2988
|
+
if (cache.has(key)) return cache.get(key);
|
|
2989
|
+
if (visiting.has(key)) return cache.get(key);
|
|
2990
|
+
const mod = compiled.modules[key];
|
|
2991
|
+
if (!mod) throw new Error(`[Playground] 缺少编译模块: ${key}`);
|
|
2992
|
+
const module = { exports: {} };
|
|
2993
|
+
cache.set(key, module.exports);
|
|
2994
|
+
visiting.add(key);
|
|
2995
|
+
try {
|
|
2996
|
+
new Function("require", "module", "exports", mod.js)(requireFn(key), module, module.exports);
|
|
2997
|
+
cache.set(key, module.exports);
|
|
2998
|
+
return module.exports;
|
|
2999
|
+
} catch (error) {
|
|
3000
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3001
|
+
errors.push(`[Playground] 执行失败 ${key}: ${message}`);
|
|
3002
|
+
throw error;
|
|
3003
|
+
} finally {
|
|
3004
|
+
visiting.delete(key);
|
|
3005
|
+
}
|
|
3006
|
+
};
|
|
3007
|
+
try {
|
|
3008
|
+
const entryExports = loadModule(compiled.entry);
|
|
3009
|
+
let component = entryExports?.default ?? entryExports;
|
|
3010
|
+
if (capture.mountedComponent) component = capture.mountedComponent;
|
|
3011
|
+
/* istanbul ignore if -- 空入口在编译阶段已经报错 */
|
|
3012
|
+
if (!component) {
|
|
3013
|
+
errors.push("[Playground] 入口必须 export default 组件,或调用 createApp(App).mount()");
|
|
3014
|
+
return {
|
|
3015
|
+
component: null,
|
|
3016
|
+
css: compiled.css || [],
|
|
3017
|
+
errors
|
|
3018
|
+
};
|
|
3019
|
+
}
|
|
3020
|
+
return {
|
|
3021
|
+
component,
|
|
3022
|
+
css: compiled.css || [],
|
|
3023
|
+
errors
|
|
3024
|
+
};
|
|
3025
|
+
} catch (error) {
|
|
3026
|
+
if (!errors.length) errors.push(error instanceof Error ? error.message : String(error));
|
|
3027
|
+
return {
|
|
3028
|
+
component: null,
|
|
3029
|
+
css: compiled.css || [],
|
|
3030
|
+
errors
|
|
3031
|
+
};
|
|
3032
|
+
}
|
|
3033
|
+
};
|
|
3034
|
+
//#endregion
|
|
3035
|
+
//#region packages/playground/src/core/runtime/local/remote.ts
|
|
3036
|
+
var HOST_VUE = /* @__PURE__ */ new Set(["vue", "vue/server-renderer"]);
|
|
3037
|
+
/**
|
|
3038
|
+
* 把 CDN 上的 ESM 先拉完整张依赖图,再在当前页面里执行。
|
|
3039
|
+
* 裸导入优先走 import map,缺失的 npm 依赖回退到 CDN ESM;import() 按需加载。
|
|
3040
|
+
* @param imports 合并后的 import map。
|
|
3041
|
+
* @param builtins 宿主 Vue 与 vue-router。
|
|
3042
|
+
* @param cdnURL 当前 CDN 根,用来识别默认地址。
|
|
3043
|
+
* @param importModule 浏览器原生 ESM 加载器。
|
|
3044
|
+
* @returns 按 URL 加载并执行远程模块的加载器。
|
|
3045
|
+
*/
|
|
3046
|
+
var createRemoteLoader = (imports, builtins, cdnURL, importModule = (url) => import(
|
|
3047
|
+
/* @vite-ignore */
|
|
3048
|
+
url
|
|
3049
|
+
)) => {
|
|
3050
|
+
const hostModules = {
|
|
3051
|
+
"vue": builtins.vue,
|
|
3052
|
+
"vue-router": builtins.vueRouter
|
|
3053
|
+
};
|
|
3054
|
+
const pendingBuiltins = /* @__PURE__ */ new Set();
|
|
3055
|
+
const texts = /* @__PURE__ */ new Map();
|
|
3056
|
+
const evaluated = /* @__PURE__ */ new Map();
|
|
3057
|
+
const crawled = /* @__PURE__ */ new Set();
|
|
3058
|
+
const nativeModules = /* @__PURE__ */ new Map();
|
|
3059
|
+
const loadNative = (url) => {
|
|
3060
|
+
let pending = nativeModules.get(url);
|
|
3061
|
+
if (!pending) {
|
|
3062
|
+
pending = importModule(url).then((module) => {
|
|
3063
|
+
const exports = toHostModule(module);
|
|
3064
|
+
evaluated.set(url, exports);
|
|
3065
|
+
return exports;
|
|
3066
|
+
});
|
|
3067
|
+
nativeModules.set(url, pending);
|
|
3068
|
+
}
|
|
3069
|
+
return pending;
|
|
3070
|
+
};
|
|
3071
|
+
const localBuiltinId = (id) => {
|
|
3072
|
+
if (imports[id] && !prefersLocalBuiltin(id, imports, cdnURL)) return null;
|
|
3073
|
+
if (prefersLocalBuiltin(id, imports, cdnURL)) return id;
|
|
3074
|
+
let cursor = id;
|
|
3075
|
+
while (true) {
|
|
3076
|
+
const slash = cursor.lastIndexOf("/");
|
|
3077
|
+
if (slash <= 0) return null;
|
|
3078
|
+
const parent = cursor.slice(0, slash);
|
|
3079
|
+
if (prefersLocalBuiltin(parent, imports, cdnURL)) return parent;
|
|
3080
|
+
cursor = parent;
|
|
3081
|
+
}
|
|
3082
|
+
};
|
|
3083
|
+
const dependencyUrl = (from, specifier) => {
|
|
3084
|
+
if (require_css.isRelativeSpecifier(specifier) || /^https?:\/\//.test(specifier)) return new URL(specifier, from).href;
|
|
3085
|
+
if (imports[specifier] && !prefersLocalBuiltin(specifier, imports, cdnURL)) return imports[specifier];
|
|
3086
|
+
if (HOST_VUE.has(specifier) && prefersLocalBuiltin(specifier, imports, cdnURL)) return null;
|
|
3087
|
+
let cursor = specifier;
|
|
3088
|
+
while (cursor) {
|
|
3089
|
+
if (localBuiltinIds.has(cursor) && prefersLocalBuiltin(cursor, imports, cdnURL)) {
|
|
3090
|
+
pendingBuiltins.add(cursor);
|
|
3091
|
+
return null;
|
|
3092
|
+
}
|
|
3093
|
+
const slash = cursor.lastIndexOf("/");
|
|
3094
|
+
if (slash <= 0) break;
|
|
3095
|
+
cursor = cursor.slice(0, slash);
|
|
3096
|
+
}
|
|
3097
|
+
const target = imports[specifier] ? specifier : resolveImportTarget(specifier, imports);
|
|
3098
|
+
if (!target) {
|
|
3099
|
+
imports[specifier] = require_css.resolveNpmImport(specifier);
|
|
3100
|
+
return imports[specifier];
|
|
3101
|
+
}
|
|
3102
|
+
return imports[target];
|
|
3103
|
+
};
|
|
3104
|
+
const crawl = async (url) => {
|
|
3105
|
+
if (/\/\+esm(?:[?#]|$)/.test(url)) {
|
|
3106
|
+
await loadNative(url);
|
|
3107
|
+
return;
|
|
3108
|
+
}
|
|
3109
|
+
if (crawled.has(url)) return;
|
|
3110
|
+
crawled.add(url);
|
|
3111
|
+
const response = await fetch(url);
|
|
3112
|
+
if (!response.ok) throw new Error(`${response.status} ${url}`);
|
|
3113
|
+
const text = await response.text();
|
|
3114
|
+
await (0, es_module_lexer.init)();
|
|
3115
|
+
const [specifiers] = (0, es_module_lexer.parse)(text);
|
|
3116
|
+
let source = text;
|
|
3117
|
+
for (const item of [...specifiers].reverse()) if (item.type === "dynamic") source = source.slice(0, item.importStart) + "__import" + source.slice(item.importStart + 6);
|
|
3118
|
+
texts.set(url, source);
|
|
3119
|
+
await Promise.all(specifiers.map(async (item) => {
|
|
3120
|
+
if (item.type !== "static" && item.type !== "reexport-star") return;
|
|
3121
|
+
const next = dependencyUrl(url, item.specifier);
|
|
3122
|
+
if (next) await crawl(next);
|
|
3123
|
+
}));
|
|
3124
|
+
};
|
|
3125
|
+
const requireFrom = (from) => (id) => {
|
|
3126
|
+
if (HOST_VUE.has(id) && prefersLocalBuiltin(id, imports, cdnURL)) return toHostModule(builtins.vue);
|
|
3127
|
+
const builtinId = localBuiltinId(id);
|
|
3128
|
+
if (builtinId) return toHostModule(hostModules[builtinId]);
|
|
3129
|
+
if (require_css.isRelativeSpecifier(id) || /^https?:\/\//.test(id)) return evaluate(new URL(id, from).href);
|
|
3130
|
+
const target = imports[id] ? id : resolveImportTarget(id, imports);
|
|
3131
|
+
if (!target || !imports[target]) throw new Error(`[Playground] 未注册的模块 "${id}"`);
|
|
3132
|
+
const loaded = evaluate(imports[target]);
|
|
3133
|
+
if (target === id) return loaded;
|
|
3134
|
+
if (!resolveHostModule(id, { [target]: loaded }))
|
|
3135
|
+
/* istanbul ignore next -- 父包没有对应导出时才拒绝 */
|
|
3136
|
+
throw new Error(`[Playground] 未注册的模块 "${id}"`);
|
|
3137
|
+
return loaded;
|
|
3138
|
+
};
|
|
3139
|
+
const evaluate = (url) => {
|
|
3140
|
+
if (evaluated.has(url)) return evaluated.get(url);
|
|
3141
|
+
const text = texts.get(url);
|
|
3142
|
+
if (text == null) throw new Error(`[Playground] 远程模块尚未下载: ${url}`);
|
|
3143
|
+
const cjs = (0, sucrase.transform)(require_css.rewriteImportMeta(text, url), {
|
|
3144
|
+
transforms: ["imports"],
|
|
3145
|
+
disableESTransforms: true,
|
|
3146
|
+
production: true,
|
|
3147
|
+
filePath: url
|
|
3148
|
+
}).code;
|
|
3149
|
+
const module = { exports: {} };
|
|
3150
|
+
evaluated.set(url, module.exports);
|
|
3151
|
+
new Function("require", "module", "exports", "__import", cjs)(requireFrom(url), module, module.exports, async (id) => {
|
|
3152
|
+
const next = dependencyUrl(url, id);
|
|
3153
|
+
if (next) await load(next);
|
|
3154
|
+
else {
|
|
3155
|
+
const builtinId = localBuiltinId(id);
|
|
3156
|
+
if (builtinId && !(builtinId in hostModules)) hostModules[builtinId] = await ensureLocalBuiltin(builtinId);
|
|
3157
|
+
}
|
|
3158
|
+
return requireFrom(url)(id);
|
|
3159
|
+
});
|
|
3160
|
+
evaluated.set(url, module.exports);
|
|
3161
|
+
return module.exports;
|
|
3162
|
+
};
|
|
3163
|
+
const loading = /* @__PURE__ */ new Map();
|
|
3164
|
+
const load = (url) => {
|
|
3165
|
+
const pending = loading.get(url);
|
|
3166
|
+
if (pending) return pending;
|
|
3167
|
+
const task = (async () => {
|
|
3168
|
+
await crawl(url);
|
|
3169
|
+
await Promise.all([...pendingBuiltins].map(async (id) => {
|
|
3170
|
+
if (id === "vue" || id === "vue-router") return;
|
|
3171
|
+
hostModules[id] = await ensureLocalBuiltin(id);
|
|
3172
|
+
}));
|
|
3173
|
+
return evaluate(url);
|
|
3174
|
+
})();
|
|
3175
|
+
loading.set(url, task);
|
|
3176
|
+
return task;
|
|
3177
|
+
};
|
|
3178
|
+
return { load };
|
|
3179
|
+
};
|
|
3180
|
+
//#endregion
|
|
3181
|
+
//#region packages/playground/src/core/runtime/local/local-sandbox.vue?vue&type=script&setup=true&lang.ts
|
|
3182
|
+
var _hoisted_1$2 = ["srcdoc"];
|
|
3183
|
+
var local_sandbox_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ (0, vue.defineComponent)({
|
|
3184
|
+
__name: "local-sandbox",
|
|
3185
|
+
props: {
|
|
3186
|
+
files: {},
|
|
3187
|
+
entry: {},
|
|
3188
|
+
options: {},
|
|
3189
|
+
previewScroller: {
|
|
3190
|
+
type: Boolean,
|
|
3191
|
+
default: false
|
|
3192
|
+
},
|
|
3193
|
+
clearConsole: {
|
|
3194
|
+
type: Boolean,
|
|
3195
|
+
default: false
|
|
3196
|
+
},
|
|
3197
|
+
autoHeight: {
|
|
3198
|
+
type: Boolean,
|
|
3199
|
+
default: false
|
|
3200
|
+
}
|
|
3201
|
+
},
|
|
3202
|
+
emits: ["error"],
|
|
3203
|
+
setup(__props, { expose: __expose, emit: __emit }) {
|
|
3204
|
+
const props = __props;
|
|
3205
|
+
const emit = __emit;
|
|
3206
|
+
const bridgeSrcdoc = LOCAL_BRIDGE_SRCDOC;
|
|
3207
|
+
const containerEl = (0, vue.ref)(null);
|
|
3208
|
+
const bridgeEl = (0, vue.ref)(null);
|
|
3209
|
+
const mountEl = (0, vue.ref)(null);
|
|
3210
|
+
const compileError = (0, vue.ref)("");
|
|
3211
|
+
const runtimeError = (0, vue.ref)("");
|
|
3212
|
+
const messageSource = (0, vue.shallowRef)(null);
|
|
3213
|
+
let port = null;
|
|
3214
|
+
let previewApp = null;
|
|
3215
|
+
let version = 0;
|
|
3216
|
+
let pendingMount = null;
|
|
3217
|
+
const styleId = `docs-local-${Math.random().toString(36).slice(2, 10)}`;
|
|
3218
|
+
const publishError = () => {
|
|
3219
|
+
emit("error", {
|
|
3220
|
+
compile: compileError.value,
|
|
3221
|
+
runtime: runtimeError.value
|
|
3222
|
+
});
|
|
3223
|
+
};
|
|
3224
|
+
(0, vue.watch)([compileError, runtimeError], publishError);
|
|
3225
|
+
const createDocsLink = (preview) => (0, vue.defineComponent)({
|
|
3226
|
+
name: "DocsLink",
|
|
3227
|
+
props: { to: {
|
|
3228
|
+
type: String,
|
|
3229
|
+
default: ""
|
|
3230
|
+
} },
|
|
3231
|
+
setup(linkProps, { slots }) {
|
|
3232
|
+
return () => (0, vue.h)("a", {
|
|
3233
|
+
href: linkProps.to,
|
|
3234
|
+
style: {
|
|
3235
|
+
color: "inherit",
|
|
3236
|
+
textDecoration: "none"
|
|
3237
|
+
},
|
|
3238
|
+
onClick(event) {
|
|
3239
|
+
event.preventDefault();
|
|
3240
|
+
preview.parent.postMessage({
|
|
3241
|
+
action: "docs:navigate",
|
|
3242
|
+
to: linkProps.to
|
|
3243
|
+
});
|
|
3244
|
+
}
|
|
3245
|
+
}, slots.default?.());
|
|
3246
|
+
}
|
|
3247
|
+
});
|
|
3248
|
+
const destroyPreview = () => {
|
|
3249
|
+
previewApp?.unmount();
|
|
3250
|
+
previewApp = null;
|
|
3251
|
+
require_css.removeStyle(styleId);
|
|
3252
|
+
};
|
|
3253
|
+
const mountPreview = (component, preview, css) => {
|
|
3254
|
+
if (!mountEl.value) return;
|
|
3255
|
+
destroyPreview();
|
|
3256
|
+
require_css.injectStyle(styleId, css);
|
|
3257
|
+
if (props.clearConsole) console.clear();
|
|
3258
|
+
const useScroller = props.previewScroller === true;
|
|
3259
|
+
const app = vue.createApp({
|
|
3260
|
+
name: "LocalSandboxRoot",
|
|
3261
|
+
setup() {
|
|
3262
|
+
const service = createLocalPlayground(vue);
|
|
3263
|
+
(0, vue.provide)("docs:playground", service);
|
|
3264
|
+
(0, vue.onErrorCaptured)((error) => {
|
|
3265
|
+
const message = formatPlaygroundRuntimeError(error);
|
|
3266
|
+
if (message) runtimeError.value = message;
|
|
3267
|
+
return false;
|
|
3268
|
+
});
|
|
3269
|
+
(0, vue.onBeforeUnmount)(() => service.dispose());
|
|
3270
|
+
return () => {
|
|
3271
|
+
const content = (0, vue.h)(component);
|
|
3272
|
+
if (!useScroller) return content;
|
|
3273
|
+
return (0, vue.h)(_deot_vc.Scroller, {
|
|
3274
|
+
height: "100%",
|
|
3275
|
+
native: false,
|
|
3276
|
+
autoResize: true,
|
|
3277
|
+
showBar: true,
|
|
3278
|
+
contentClass: PREVIEW_SCROLL_CONTENT_CLASS
|
|
3279
|
+
}, { default: () => content });
|
|
3280
|
+
};
|
|
3281
|
+
}
|
|
3282
|
+
});
|
|
3283
|
+
app.component("DocsLink", createDocsLink(preview));
|
|
3284
|
+
app.config.errorHandler = (error) => {
|
|
3285
|
+
const message = formatPlaygroundRuntimeError(error);
|
|
3286
|
+
if (message) runtimeError.value = message;
|
|
3287
|
+
};
|
|
3288
|
+
app.mount(mountEl.value);
|
|
3289
|
+
previewApp = app;
|
|
3290
|
+
};
|
|
3291
|
+
const ensurePort = () => {
|
|
3292
|
+
const iframe = bridgeEl.value;
|
|
3293
|
+
if (!iframe?.contentWindow) return null;
|
|
3294
|
+
try {
|
|
3295
|
+
if (!installLocalBridge(iframe)) return null;
|
|
3296
|
+
} catch {
|
|
3297
|
+
return null;
|
|
3298
|
+
}
|
|
3299
|
+
port ??= new LocalPreviewPort(iframe);
|
|
3300
|
+
messageSource.value = iframe.contentWindow;
|
|
3301
|
+
return port;
|
|
3302
|
+
};
|
|
3303
|
+
const tryMount = async () => {
|
|
3304
|
+
const job = pendingMount;
|
|
3305
|
+
/* istanbul ignore if -- 桥接 iframe 尚未就绪或编译已被取代 */
|
|
3306
|
+
if (!job || job.version !== version) return;
|
|
3307
|
+
const preview = ensurePort();
|
|
3308
|
+
/* istanbul ignore if -- 挂载点在编译完成时已经存在 */
|
|
3309
|
+
if (!preview || !mountEl.value) return;
|
|
3310
|
+
await (0, vue.nextTick)();
|
|
3311
|
+
/* istanbul ignore if -- 桥接 iframe 尚未就绪或编译已被取代 */
|
|
3312
|
+
if (pendingMount !== job || !mountEl.value) return;
|
|
3313
|
+
pendingMount = null;
|
|
3314
|
+
mountPreview(job.component, preview, job.css);
|
|
3315
|
+
};
|
|
3316
|
+
const run = async () => {
|
|
3317
|
+
const current = ++version;
|
|
3318
|
+
pendingMount = null;
|
|
3319
|
+
compileError.value = "";
|
|
3320
|
+
runtimeError.value = "";
|
|
3321
|
+
publishError();
|
|
3322
|
+
destroyPreview();
|
|
3323
|
+
try {
|
|
3324
|
+
const { compilePlayground } = await Promise.resolve().then(() => require("./compile-29EUKPOy.cjs"));
|
|
3325
|
+
/* istanbul ignore if -- 并发编译时只保留最后一次 */
|
|
3326
|
+
if (current !== version) return;
|
|
3327
|
+
const compiled = await compilePlayground(props.files, { entry: props.entry });
|
|
3328
|
+
/* istanbul ignore if -- 并发编译时只保留最后一次 */
|
|
3329
|
+
if (current !== version) return;
|
|
3330
|
+
if (compiled.errors.length || !compiled.entry) {
|
|
3331
|
+
compileError.value = compiled.errors.join("\n") || "[Playground] 未能确定入口";
|
|
3332
|
+
publishError();
|
|
3333
|
+
return;
|
|
3334
|
+
}
|
|
3335
|
+
const imports = createRuntimeImports(props.options.cdnURL, props.options.builtinImportMap);
|
|
3336
|
+
const specifiers = require_css.collectBareSpecifiers(props.files, require_css.collectReachableFilenames(props.files, compiled.entry));
|
|
3337
|
+
const remote = createRemoteLoader(imports, {
|
|
3338
|
+
vue,
|
|
3339
|
+
vueRouter: vue_router
|
|
3340
|
+
}, props.options.cdnURL);
|
|
3341
|
+
const loaded = await loadLocalModules(specifiers, imports, {
|
|
3342
|
+
vue,
|
|
3343
|
+
vueRouter: vue_router
|
|
3344
|
+
}, (url) => remote.load(url), props.options.cdnURL);
|
|
3345
|
+
/* istanbul ignore if -- 并发编译时只保留最后一次 */
|
|
3346
|
+
if (current !== version) return;
|
|
3347
|
+
if (loaded.errors.length) {
|
|
3348
|
+
compileError.value = loaded.errors.join("\n");
|
|
3349
|
+
publishError();
|
|
3350
|
+
return;
|
|
3351
|
+
}
|
|
3352
|
+
const linked = linkPlayground(compiled, props.files, { modules: loaded.modules });
|
|
3353
|
+
/* istanbul ignore if -- 并发编译时只保留最后一次 */
|
|
3354
|
+
if (current !== version) return;
|
|
3355
|
+
if (linked.errors.length || !linked.component) {
|
|
3356
|
+
compileError.value = (linked.errors.length ? linked.errors : ["[Playground] 未能解析入口组件"]).join("\n");
|
|
3357
|
+
publishError();
|
|
3358
|
+
return;
|
|
3359
|
+
}
|
|
3360
|
+
pendingMount = {
|
|
3361
|
+
component: linked.component,
|
|
3362
|
+
css: linked.css,
|
|
3363
|
+
version: current
|
|
3364
|
+
};
|
|
3365
|
+
await tryMount();
|
|
3366
|
+
} catch (error) {
|
|
3367
|
+
/* istanbul ignore next -- 编译器自身异常才进入,普通错误走结果里的 errors */
|
|
3368
|
+
if (current !== version) return;
|
|
3369
|
+
/* istanbul ignore next -- 同上,只兜底编译器抛错 */
|
|
3370
|
+
compileError.value = error instanceof Error ? error.message : String(error);
|
|
3371
|
+
/* istanbul ignore next -- 同上,只兜底编译器抛错 */
|
|
3372
|
+
publishError();
|
|
3373
|
+
}
|
|
3374
|
+
};
|
|
3375
|
+
const handleBridgeLoad = () => {
|
|
3376
|
+
tryMount();
|
|
3377
|
+
};
|
|
3378
|
+
(0, vue.onMounted)(() => {
|
|
3379
|
+
run();
|
|
3380
|
+
});
|
|
3381
|
+
(0, vue.watch)(() => [
|
|
3382
|
+
props.files,
|
|
3383
|
+
props.entry,
|
|
3384
|
+
props.options,
|
|
3385
|
+
props.previewScroller
|
|
3386
|
+
], () => {
|
|
3387
|
+
if (!containerEl.value) return;
|
|
3388
|
+
run();
|
|
3389
|
+
}, { deep: true });
|
|
3390
|
+
(0, vue.onBeforeUnmount)(() => {
|
|
3391
|
+
version += 1;
|
|
3392
|
+
pendingMount = null;
|
|
3393
|
+
destroyPreview();
|
|
3394
|
+
});
|
|
3395
|
+
__expose({
|
|
3396
|
+
container: containerEl,
|
|
3397
|
+
messageSource,
|
|
3398
|
+
local: true,
|
|
3399
|
+
refresh: () => {
|
|
3400
|
+
run();
|
|
3401
|
+
}
|
|
3402
|
+
});
|
|
3403
|
+
return (_ctx, _cache) => {
|
|
3404
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
3405
|
+
ref_key: "containerEl",
|
|
3406
|
+
ref: containerEl,
|
|
3407
|
+
class: "docs-playground-local"
|
|
3408
|
+
}, [(0, vue.createElementVNode)("iframe", {
|
|
3409
|
+
ref_key: "bridgeEl",
|
|
3410
|
+
ref: bridgeEl,
|
|
3411
|
+
class: "docs-playground-local__bridge",
|
|
3412
|
+
tabindex: "-1",
|
|
3413
|
+
"aria-hidden": "true",
|
|
3414
|
+
title: "",
|
|
3415
|
+
srcdoc: (0, vue.unref)(bridgeSrcdoc),
|
|
3416
|
+
onLoad: handleBridgeLoad
|
|
3417
|
+
}, null, 40, _hoisted_1$2), (0, vue.createElementVNode)("div", {
|
|
3418
|
+
ref_key: "mountEl",
|
|
3419
|
+
ref: mountEl,
|
|
3420
|
+
class: (0, vue.normalizeClass)(["docs-playground-local__mount", { "docs-playground-local__mount--auto": __props.autoHeight }])
|
|
3421
|
+
}, null, 2)], 512);
|
|
3422
|
+
};
|
|
3423
|
+
}
|
|
3424
|
+
});
|
|
3425
|
+
//#endregion
|
|
3426
|
+
//#region packages/playground/src/core/runtime/local/local-sandbox.vue
|
|
3427
|
+
var local_sandbox_exports = /* @__PURE__ */ require_css.__exportAll({ default: () => local_sandbox_default });
|
|
3428
|
+
var local_sandbox_default = local_sandbox_vue_vue_type_script_setup_true_lang_default;
|
|
3429
|
+
//#endregion
|
|
1609
3430
|
//#region packages/playground/src/core/runtime/runtime.vue?vue&type=script&setup=true&lang.ts
|
|
1610
|
-
var _hoisted_1$1 = {
|
|
1611
|
-
var _hoisted_2$1 = {
|
|
3431
|
+
var _hoisted_1$1 = {
|
|
1612
3432
|
key: 0,
|
|
1613
3433
|
class: "docs-playground__runtime-error",
|
|
1614
3434
|
role: "alert"
|
|
1615
3435
|
};
|
|
1616
|
-
var
|
|
3436
|
+
var _hoisted_2$1 = {
|
|
1617
3437
|
key: 0,
|
|
1618
3438
|
class: "docs-playground__header"
|
|
1619
3439
|
};
|
|
1620
|
-
var
|
|
1621
|
-
var
|
|
1622
|
-
var
|
|
1623
|
-
var
|
|
3440
|
+
var _hoisted_3$1 = ["id", "title"];
|
|
3441
|
+
var _hoisted_4$1 = ["href"];
|
|
3442
|
+
var _hoisted_5$1 = { class: "docs-playground__title-text" };
|
|
3443
|
+
var _hoisted_6 = {
|
|
1624
3444
|
key: 1,
|
|
1625
3445
|
class: "docs-playground__runtime-error",
|
|
1626
3446
|
role: "alert"
|
|
1627
3447
|
};
|
|
1628
|
-
var
|
|
1629
|
-
var
|
|
3448
|
+
var _hoisted_7 = { class: "docs-playground-runtime__viewport-stage" };
|
|
3449
|
+
var _hoisted_8 = [
|
|
1630
3450
|
"aria-expanded",
|
|
1631
3451
|
"title",
|
|
1632
3452
|
"aria-label"
|
|
@@ -1672,7 +3492,6 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1672
3492
|
"navigate"
|
|
1673
3493
|
],
|
|
1674
3494
|
setup(__props, { expose: __expose, emit: __emit }) {
|
|
1675
|
-
const LocalSandbox = (0, vue.defineAsyncComponent)(() => Promise.resolve().then(() => require("./local-sandbox-DnkKrBhf.cjs")).then((n) => n.local_sandbox_exports));
|
|
1676
3495
|
const props = __props;
|
|
1677
3496
|
const { locale, t } = (0, _deot_docs_locale.useLocale)();
|
|
1678
3497
|
const displayTitle = (0, vue.computed)(() => props.title.trim());
|
|
@@ -1685,7 +3504,7 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1685
3504
|
const emit = __emit;
|
|
1686
3505
|
const joinCode = (...values) => values.filter(Boolean).join("\n");
|
|
1687
3506
|
const mergePreviewOptions = (extraHeadHTML) => {
|
|
1688
|
-
const runtimePreviewOptions =
|
|
3507
|
+
const runtimePreviewOptions = createRuntimePreviewOptions(props.options.cdnURL, { previewScroller: props.previewScroller });
|
|
1689
3508
|
return {
|
|
1690
3509
|
...runtimePreviewOptions,
|
|
1691
3510
|
...props.previewOptions,
|
|
@@ -1695,8 +3514,8 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1695
3514
|
extraHeadHTML
|
|
1696
3515
|
].filter(Boolean).join("\n"),
|
|
1697
3516
|
customCode: {
|
|
1698
|
-
importCode: joinCode(runtimePreviewOptions.customCode?.importCode, props.previewOptions?.customCode?.importCode, props.previewScroller ?
|
|
1699
|
-
useCode: joinCode(runtimePreviewOptions.customCode?.useCode, props.previewOptions?.customCode?.useCode, props.previewScroller ?
|
|
3517
|
+
importCode: joinCode(runtimePreviewOptions.customCode?.importCode, props.previewOptions?.customCode?.importCode, props.previewScroller ? PREVIEW_SCROLL_RESET_CODE : void 0, props.previewScroller ? PREVIEW_SCROLLER_IMPORT_CODE : void 0),
|
|
3518
|
+
useCode: joinCode(runtimePreviewOptions.customCode?.useCode, props.previewOptions?.customCode?.useCode, props.previewScroller ? PREVIEW_SCROLLER_USE_CODE : void 0)
|
|
1700
3519
|
}
|
|
1701
3520
|
};
|
|
1702
3521
|
};
|
|
@@ -1710,7 +3529,8 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1710
3529
|
"SSR": false
|
|
1711
3530
|
}.MODE !== "development";
|
|
1712
3531
|
const copyValue = (0, vue.computed)(() => props.files[props.entry] || "");
|
|
1713
|
-
const store = props.local ? null :
|
|
3532
|
+
const store = props.local ? null : createRuntimeStore(props.files, props.entry, props.options);
|
|
3533
|
+
const storeReady = (0, vue.computed)(() => store && !store.loading && Object.values(store.files).every((file) => require_css.isIgnoredFilename(file.filename) || !/\.(?:vue|[jt]sx?|json|s[ac]ss)$/.test(file.filename) || !file.code.trim() || !!file.compiled.js));
|
|
1714
3534
|
const sandboxRef = (0, vue.ref)(null);
|
|
1715
3535
|
const localError = (0, vue.ref)({
|
|
1716
3536
|
compile: "",
|
|
@@ -1721,21 +3541,21 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1721
3541
|
};
|
|
1722
3542
|
const temporaryHeight = usePreviewHeightBridge(sandboxRef);
|
|
1723
3543
|
const sandboxKey = (0, vue.ref)(0);
|
|
1724
|
-
const runtimeHeight =
|
|
1725
|
-
const runtimeError =
|
|
3544
|
+
const runtimeHeight = useSandboxAutoHeight(sandboxRef);
|
|
3545
|
+
const runtimeError = useSandboxRuntimeErrorGuard(sandboxRef);
|
|
1726
3546
|
useSandboxTheme(sandboxRef);
|
|
1727
3547
|
const compileErrorText = (0, vue.computed)(() => {
|
|
1728
3548
|
if (props.local) return localError.value.compile;
|
|
1729
|
-
return (store?.errors || []).map(
|
|
3549
|
+
return (store?.errors || []).map(toErrorText).filter(Boolean).join("\n");
|
|
1730
3550
|
});
|
|
1731
3551
|
const errorText = (0, vue.computed)(() => {
|
|
1732
3552
|
let runtime = "";
|
|
1733
3553
|
if (props.local) runtime = localError.value.runtime;
|
|
1734
|
-
else if (runtimeError.value) runtime =
|
|
3554
|
+
else if (runtimeError.value) runtime = formatSandboxRuntimeError(runtimeError.value, t("playground.runtime.importMapTip"));
|
|
1735
3555
|
return [compileErrorText.value, runtime].filter(Boolean).join("\n\n");
|
|
1736
3556
|
});
|
|
1737
3557
|
const handleBridgeMessage = (event) => {
|
|
1738
|
-
if (!
|
|
3558
|
+
if (!isSandboxMessage(sandboxRef.value, event)) return;
|
|
1739
3559
|
const data = event.data;
|
|
1740
3560
|
if (!data || data.action !== "docs:navigate" || typeof data.to !== "string") return;
|
|
1741
3561
|
emit("navigate", data.to);
|
|
@@ -1816,7 +3636,7 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1816
3636
|
return {
|
|
1817
3637
|
height: `${resolvePreviewBoxHeight(desiredViewportHeight.value, vertical)}px`,
|
|
1818
3638
|
padding: vertical === horizontal ? `${vertical}px` : `${vertical}px ${horizontal}px`,
|
|
1819
|
-
background:
|
|
3639
|
+
background: PLAYGROUND_RUNTIME_CANVAS_BACKGROUND
|
|
1820
3640
|
};
|
|
1821
3641
|
});
|
|
1822
3642
|
const stylelessStyle = (0, vue.computed)(() => errorText.value ? void 0 : { height: `${desiredViewportHeight.value}px` });
|
|
@@ -1836,27 +3656,27 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1836
3656
|
const apply = () => {
|
|
1837
3657
|
if (store) switch (action.type) {
|
|
1838
3658
|
case "update": {
|
|
1839
|
-
const file = store.files[
|
|
3659
|
+
const file = store.files[toReplFilename(action.filename)];
|
|
1840
3660
|
if (file) file.code = files[action.filename];
|
|
1841
3661
|
break;
|
|
1842
3662
|
}
|
|
1843
3663
|
case "create":
|
|
1844
|
-
store.addFile(
|
|
3664
|
+
store.addFile(createReplFile(action.filename, files[action.filename]));
|
|
1845
3665
|
break;
|
|
1846
3666
|
case "rename":
|
|
1847
|
-
store.renameFile(
|
|
3667
|
+
store.renameFile(toReplFilename(action.previousFilename), toReplFilename(action.filename));
|
|
1848
3668
|
break;
|
|
1849
3669
|
case "delete":
|
|
1850
|
-
store.setActive(
|
|
1851
|
-
delete store.files[
|
|
3670
|
+
store.setActive(toReplFilename(entry));
|
|
3671
|
+
delete store.files[toReplFilename(action.filename)];
|
|
1852
3672
|
break;
|
|
1853
3673
|
case "entry":
|
|
1854
|
-
store.mainFile =
|
|
1855
|
-
store.setActive(
|
|
3674
|
+
store.mainFile = toReplFilename(entry);
|
|
3675
|
+
store.setActive(toReplFilename(entry));
|
|
1856
3676
|
}
|
|
1857
3677
|
emit("files-change", files, entry, action);
|
|
1858
3678
|
};
|
|
1859
|
-
if (store)
|
|
3679
|
+
if (store) require_css.whenSassReady(files, apply);
|
|
1860
3680
|
else apply();
|
|
1861
3681
|
};
|
|
1862
3682
|
const handleEditor = () => {
|
|
@@ -1869,7 +3689,7 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1869
3689
|
return localError.value.compile ? [localError.value.compile] : [];
|
|
1870
3690
|
},
|
|
1871
3691
|
onFilesChange: handleFilesChange,
|
|
1872
|
-
onActiveChange: (filename) => store?.setActive(
|
|
3692
|
+
onActiveChange: (filename) => store?.setActive(toReplFilename(filename))
|
|
1873
3693
|
});
|
|
1874
3694
|
};
|
|
1875
3695
|
const handleInlineRefresh = () => {
|
|
@@ -1920,8 +3740,8 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1920
3740
|
if (!entry || entry === syncedEntry) return;
|
|
1921
3741
|
syncedEntry = entry;
|
|
1922
3742
|
if (!store) return;
|
|
1923
|
-
store.mainFile =
|
|
1924
|
-
store.setActive(
|
|
3743
|
+
store.mainFile = toReplFilename(entry);
|
|
3744
|
+
store.setActive(toReplFilename(entry));
|
|
1925
3745
|
});
|
|
1926
3746
|
(0, vue.watch)(() => props.activeView, (view) => {
|
|
1927
3747
|
if (view !== "runtime") handleClosePopup();
|
|
@@ -1937,16 +3757,16 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1937
3757
|
openPopup: handleOpenPopup
|
|
1938
3758
|
});
|
|
1939
3759
|
return (_ctx, _cache) => {
|
|
1940
|
-
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div",
|
|
3760
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", { class: (0, vue.normalizeClass)(["docs-playground-runtime-host", { "docs-playground-runtime-host--direct": __props.local && __props.styleless }]) }, [__props.styleless ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
1941
3761
|
key: 0,
|
|
1942
3762
|
ref_key: "runtimeRoot",
|
|
1943
3763
|
ref: runtimeRoot,
|
|
1944
3764
|
class: "docs-playground-runtime--styleless",
|
|
1945
3765
|
style: (0, vue.normalizeStyle)(stylelessStyle.value)
|
|
1946
|
-
}, [errorText.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("pre",
|
|
3766
|
+
}, [errorText.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("pre", _hoisted_1$1, (0, vue.toDisplayString)(errorText.value), 1)) : (0, vue.createCommentVNode)("v-if", true), (0, vue.createElementVNode)("div", {
|
|
1947
3767
|
class: "docs-playground-runtime__viewport",
|
|
1948
3768
|
style: (0, vue.normalizeStyle)(viewportStyle.value)
|
|
1949
|
-
}, [__props.local ? ((0, vue.openBlock)(), (0, vue.createBlock)(
|
|
3769
|
+
}, [__props.local ? ((0, vue.openBlock)(), (0, vue.createBlock)(local_sandbox_default, {
|
|
1950
3770
|
key: 0,
|
|
1951
3771
|
ref_key: "sandboxRef",
|
|
1952
3772
|
ref: sandboxRef,
|
|
@@ -1955,13 +3775,15 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1955
3775
|
options: __props.options,
|
|
1956
3776
|
"preview-scroller": __props.previewScroller,
|
|
1957
3777
|
"clear-console": clearConsole,
|
|
3778
|
+
"auto-height": !(0, vue.unref)(getViewportHeight)(__props.viewport),
|
|
1958
3779
|
onError: handleLocalError
|
|
1959
3780
|
}, null, 8, [
|
|
1960
3781
|
"files",
|
|
1961
3782
|
"entry",
|
|
1962
3783
|
"options",
|
|
1963
|
-
"preview-scroller"
|
|
1964
|
-
|
|
3784
|
+
"preview-scroller",
|
|
3785
|
+
"auto-height"
|
|
3786
|
+
])) : (0, vue.unref)(store) && storeReady.value ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_vue_repl.Sandbox), {
|
|
1965
3787
|
key: 1,
|
|
1966
3788
|
ref_key: "sandboxRef",
|
|
1967
3789
|
ref: sandboxRef,
|
|
@@ -1974,7 +3796,7 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1974
3796
|
ref: runtimeRoot,
|
|
1975
3797
|
class: "docs-playground-runtime"
|
|
1976
3798
|
}, [
|
|
1977
|
-
!__props.hideChrome ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div",
|
|
3799
|
+
!__props.hideChrome ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$1, [displayTitle.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
1978
3800
|
key: 0,
|
|
1979
3801
|
ref_key: "titleEl",
|
|
1980
3802
|
ref: titleEl,
|
|
@@ -1985,7 +3807,7 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1985
3807
|
}, [(0, vue.createElementVNode)("a", {
|
|
1986
3808
|
class: "docs-playground__title-anchor",
|
|
1987
3809
|
href: `#${titleId.value}`
|
|
1988
|
-
}, "#", 8,
|
|
3810
|
+
}, "#", 8, _hoisted_4$1), (0, vue.createElementVNode)("span", _hoisted_5$1, (0, vue.toDisplayString)(displayTitle.value), 1)], 8, _hoisted_3$1)) : (0, vue.createCommentVNode)("v-if", true), (0, vue.createVNode)(toolbar_default, {
|
|
1989
3811
|
"copy-value": copyValue.value,
|
|
1990
3812
|
viewport: __props.viewport,
|
|
1991
3813
|
"viewport-options": __props.viewportOptions,
|
|
@@ -1999,14 +3821,14 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
1999
3821
|
"viewport",
|
|
2000
3822
|
"viewport-options"
|
|
2001
3823
|
])])) : (0, vue.createCommentVNode)("v-if", true),
|
|
2002
|
-
errorText.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("pre",
|
|
3824
|
+
errorText.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("pre", _hoisted_6, (0, vue.toDisplayString)(errorText.value), 1)) : (0, vue.createCommentVNode)("v-if", true),
|
|
2003
3825
|
(0, vue.createElementVNode)("section", {
|
|
2004
3826
|
class: (0, vue.normalizeClass)(["docs-playground__preview", { "is-expanded": previewExpanded.value }]),
|
|
2005
3827
|
style: (0, vue.normalizeStyle)(previewStyle.value)
|
|
2006
|
-
}, [(0, vue.createElementVNode)("div",
|
|
3828
|
+
}, [(0, vue.createElementVNode)("div", _hoisted_7, [(0, vue.createElementVNode)("div", {
|
|
2007
3829
|
class: "docs-playground-runtime__viewport",
|
|
2008
3830
|
style: (0, vue.normalizeStyle)(viewportStyle.value)
|
|
2009
|
-
}, [__props.local ? ((0, vue.openBlock)(), (0, vue.createBlock)(
|
|
3831
|
+
}, [__props.local ? ((0, vue.openBlock)(), (0, vue.createBlock)(local_sandbox_default, {
|
|
2010
3832
|
key: sandboxKey.value,
|
|
2011
3833
|
ref_key: "sandboxRef",
|
|
2012
3834
|
ref: sandboxRef,
|
|
@@ -2015,13 +3837,15 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
2015
3837
|
options: __props.options,
|
|
2016
3838
|
"preview-scroller": __props.previewScroller,
|
|
2017
3839
|
"clear-console": clearConsole,
|
|
3840
|
+
"auto-height": !(0, vue.unref)(getViewportHeight)(__props.viewport),
|
|
2018
3841
|
onError: handleLocalError
|
|
2019
3842
|
}, null, 8, [
|
|
2020
3843
|
"files",
|
|
2021
3844
|
"entry",
|
|
2022
3845
|
"options",
|
|
2023
|
-
"preview-scroller"
|
|
2024
|
-
|
|
3846
|
+
"preview-scroller",
|
|
3847
|
+
"auto-height"
|
|
3848
|
+
])) : (0, vue.unref)(store) && storeReady.value ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_vue_repl.Sandbox), {
|
|
2025
3849
|
key: sandboxKey.value,
|
|
2026
3850
|
ref_key: "sandboxRef",
|
|
2027
3851
|
ref: sandboxRef,
|
|
@@ -2038,8 +3862,8 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
2038
3862
|
title: expandLabel.value,
|
|
2039
3863
|
"aria-label": expandLabel.value,
|
|
2040
3864
|
onClick: handleTogglePreviewExpand
|
|
2041
|
-
}, [(0, vue.createVNode)((0, vue.unref)(icon_default), { name: "expand" })], 10,
|
|
2042
|
-
], 512))]);
|
|
3865
|
+
}, [(0, vue.createVNode)((0, vue.unref)(icon_default), { name: "expand" })], 10, _hoisted_8)) : (0, vue.createCommentVNode)("v-if", true)], 6)
|
|
3866
|
+
], 512))], 2);
|
|
2043
3867
|
};
|
|
2044
3868
|
}
|
|
2045
3869
|
});
|
|
@@ -2102,7 +3926,7 @@ var playground_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
2102
3926
|
const locale = (0, vue.computed)(() => props.locale || inheritedLocale.locale.value);
|
|
2103
3927
|
(0, _deot_docs_locale.provideLocale)(locale);
|
|
2104
3928
|
const { t } = (0, _deot_docs_locale.useLocale)(locale);
|
|
2105
|
-
const initialFiles = Object.keys(props.files).length ? { ...props.files } : { [
|
|
3929
|
+
const initialFiles = Object.keys(props.files).length ? { ...props.files } : { [require_css.DEFAULT_ENTRY]: props.modelValue || require_css.NEW_SFC_CODE };
|
|
2106
3930
|
const initialEntry = props.entry && initialFiles[props.entry] !== void 0 ? props.entry : Object.keys(initialFiles)[0];
|
|
2107
3931
|
const sourceFiles = (0, vue.ref)(initialFiles);
|
|
2108
3932
|
const currentEntry = (0, vue.ref)(initialEntry);
|
|
@@ -2362,35 +4186,35 @@ var playground_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
2362
4186
|
});
|
|
2363
4187
|
//#endregion
|
|
2364
4188
|
exports.CodePreview = code_preview_default;
|
|
2365
|
-
exports.DEFAULT_CDN_URL =
|
|
4189
|
+
exports.DEFAULT_CDN_URL = require_css.DEFAULT_CDN_URL;
|
|
2366
4190
|
exports.Editor = Editor;
|
|
2367
|
-
exports.PREVIEW_SCROLLER_USE_CODE =
|
|
2368
|
-
exports.PREVIEW_SCROLL_CONTENT_CLASS =
|
|
2369
|
-
exports.PREVIEW_SCROLL_HTML_CLASS =
|
|
4191
|
+
exports.PREVIEW_SCROLLER_USE_CODE = PREVIEW_SCROLLER_USE_CODE;
|
|
4192
|
+
exports.PREVIEW_SCROLL_CONTENT_CLASS = PREVIEW_SCROLL_CONTENT_CLASS;
|
|
4193
|
+
exports.PREVIEW_SCROLL_HTML_CLASS = PREVIEW_SCROLL_HTML_CLASS;
|
|
2370
4194
|
exports.Playground = playground_default;
|
|
2371
|
-
exports.PlaygroundService =
|
|
2372
|
-
exports.applyPlaygroundImportMapOverride =
|
|
2373
|
-
exports.applyPlaygroundStyleOverride =
|
|
2374
|
-
exports.clearPlaygroundMaps =
|
|
2375
|
-
exports.createBuiltinImports =
|
|
2376
|
-
exports.createBuiltinStyles =
|
|
2377
|
-
exports.createRuntimePreviewOptions =
|
|
2378
|
-
exports.getPlaygroundImportMapOverrides =
|
|
2379
|
-
exports.getPlaygroundSiteModules =
|
|
2380
|
-
exports.getPlaygroundSiteStyles =
|
|
2381
|
-
exports.getPlaygroundStyleOverrides =
|
|
4195
|
+
exports.PlaygroundService = PlaygroundService;
|
|
4196
|
+
exports.applyPlaygroundImportMapOverride = applyPlaygroundImportMapOverride;
|
|
4197
|
+
exports.applyPlaygroundStyleOverride = applyPlaygroundStyleOverride;
|
|
4198
|
+
exports.clearPlaygroundMaps = clearPlaygroundMaps;
|
|
4199
|
+
exports.createBuiltinImports = require_css.createBuiltinImports;
|
|
4200
|
+
exports.createBuiltinStyles = require_css.createBuiltinStyles;
|
|
4201
|
+
exports.createRuntimePreviewOptions = createRuntimePreviewOptions;
|
|
4202
|
+
exports.getPlaygroundImportMapOverrides = getPlaygroundImportMapOverrides;
|
|
4203
|
+
exports.getPlaygroundSiteModules = getPlaygroundSiteModules;
|
|
4204
|
+
exports.getPlaygroundSiteStyles = getPlaygroundSiteStyles;
|
|
4205
|
+
exports.getPlaygroundStyleOverrides = getPlaygroundStyleOverrides;
|
|
2382
4206
|
exports.highlightCode = highlightCode;
|
|
2383
4207
|
exports.highlightCodeByLanguage = highlightCodeByLanguage;
|
|
2384
|
-
exports.isSafePlaygroundHref =
|
|
2385
|
-
exports.normalizeCdnURL =
|
|
4208
|
+
exports.isSafePlaygroundHref = isSafePlaygroundHref;
|
|
4209
|
+
exports.normalizeCdnURL = require_css.normalizeCdnURL;
|
|
2386
4210
|
exports.registerVueHighlight = registerVueHighlight;
|
|
2387
|
-
exports.removePlaygroundImportMapOverride =
|
|
2388
|
-
exports.removePlaygroundStyleOverride =
|
|
4211
|
+
exports.removePlaygroundImportMapOverride = removePlaygroundImportMapOverride;
|
|
4212
|
+
exports.removePlaygroundStyleOverride = removePlaygroundStyleOverride;
|
|
2389
4213
|
exports.resolveHighlightLanguage = resolveHighlightLanguage;
|
|
2390
4214
|
exports.resolvePlaygroundTitleId = resolvePlaygroundTitleId;
|
|
2391
|
-
exports.setPlaygroundImportMapOverrides =
|
|
2392
|
-
exports.setPlaygroundSiteModules =
|
|
2393
|
-
exports.setPlaygroundSiteStyles =
|
|
2394
|
-
exports.setPlaygroundStyleOverrides =
|
|
4215
|
+
exports.setPlaygroundImportMapOverrides = setPlaygroundImportMapOverrides;
|
|
4216
|
+
exports.setPlaygroundSiteModules = setPlaygroundSiteModules;
|
|
4217
|
+
exports.setPlaygroundSiteStyles = setPlaygroundSiteStyles;
|
|
4218
|
+
exports.setPlaygroundStyleOverrides = setPlaygroundStyleOverrides;
|
|
2395
4219
|
exports.slugifyPlaygroundTitle = slugifyPlaygroundTitle;
|
|
2396
4220
|
exports.vueHighlight = vueHighlight;
|