@deot/docs-playground 1.1.1 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,8 +1,11 @@
1
- import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, openBlock, ref, renderList, toDisplayString, unref, vModelText, vShow, watch, withCtx, withDirectives, withKeys, withModifiers } from "vue";
1
+ import { a as DEFAULT_CDN_URL, i as normalizeCdnURL, n as createBuiltinImports, o as DEFAULT_ENTRY, r as createBuiltinStyles, s as NEW_SFC_CODE } from "./cdn-DEvdGJu2.js";
2
+ import { A as PREVIEW_SCROLLER_USE_CODE, C as toErrorText, D as resolveSandboxMessageSource, E as resolveSandboxContainer, M as PREVIEW_SCROLL_HTML_CLASS, N as PREVIEW_SCROLL_RESET_CODE, O as useSandboxAutoHeight, S as formatSandboxRuntimeError, T as isSandboxMessage, _ as removePlaygroundStyleOverride, a as createRuntimeStore, b as setPlaygroundSiteStyles, c as applyPlaygroundImportMapOverride, d as getPlaygroundImportMapOverrides, f as getPlaygroundSiteModules, g as removePlaygroundImportMapOverride, h as isSafePlaygroundHref, i as createRuntimePreviewOptions, j as PREVIEW_SCROLL_CONTENT_CLASS, k as PREVIEW_SCROLLER_IMPORT_CODE, l as applyPlaygroundStyleOverride, m as getPlaygroundStyleOverrides, n as createReplFile, o as toReplFilename, p as getPlaygroundSiteStyles, s as PlaygroundService, t as PLAYGROUND_RUNTIME_CANVAS_BACKGROUND, u as clearPlaygroundMaps, v as setPlaygroundImportMapOverrides, w as useSandboxRuntimeErrorGuard, x as setPlaygroundStyleOverrides, y as setPlaygroundSiteModules } from "./store-D8vwi-HV.js";
3
+ import { r as whenSassReady } from "./scss-Co2it4vB.js";
4
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineAsyncComponent, defineComponent, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, openBlock, ref, renderList, toDisplayString, unref, vModelText, vShow, watch, withCtx, withDirectives, withKeys, withModifiers } from "vue";
2
5
  import { Clipboard, Dropdown, DropdownItem, DropdownMenu, Message, Popconfirm, Portal, Scroller, TransitionFade } from "@deot/vc";
3
6
  import { provideLocale, useLocale } from "@deot/docs-locale";
4
7
  import hljs from "highlight.js";
5
- import { File, Sandbox, useStore } from "@vue/repl";
8
+ import { Sandbox } from "@vue/repl";
6
9
  import { EditorView, basicSetup } from "codemirror";
7
10
  import { css } from "@codemirror/lang-css";
8
11
  import { javascript } from "@codemirror/lang-javascript";
@@ -310,12 +313,6 @@ var files_preview_default = /* @__PURE__ */ defineComponent({
310
313
  }
311
314
  });
312
315
  //#endregion
313
- //#region packages/playground/src/constants.ts
314
- var DEFAULT_ENTRY = "App.vue";
315
- /** 预览样式和默认 import map 共用的 npm CDN 前缀。 */
316
- var DEFAULT_CDN_URL = "https://cdn.jsdelivr.net/npm";
317
- var NEW_SFC_CODE = `<script setup lang="ts"><\/script>\n\n<template>\n <div>\n <slot />\n <\/div>\n<\/template>\n`;
318
- //#endregion
319
316
  //#region packages/playground/src/editor/drag.ts
320
317
  var events = typeof document !== "undefined" && "ontouchstart" in document ? {
321
318
  start: "touchstart",
@@ -833,220 +830,6 @@ var resolvePlaygroundTitleId = (title, explicitId = "", isOccupied) => {
833
830
  while (isOccupied(`${base}-${index}`)) index += 1;
834
831
  return `${base}-${index}`;
835
832
  };
836
- //#endregion
837
- //#region packages/playground/src/core/preview-scroll.ts
838
- /** iframe 包装成功后挂在 `html` 上,供样式与 auto-height 识别。 */
839
- var PREVIEW_SCROLL_HTML_CLASS = "docs-playground-preview-scroll";
840
- /** Scroller 内容节点 class,auto-height 优先测量该节点。 */
841
- var PREVIEW_SCROLL_CONTENT_CLASS = "docs-playground-preview-scroll__content";
842
- /** 重评时先清掉 html class,避免 `await import` 期间仍套用 `height:100%`。 */
843
- var PREVIEW_SCROLL_RESET_CODE = `document.documentElement.classList.remove("${PREVIEW_SCROLL_HTML_CLASS}");`;
844
- /** 动态探测 `@deot/vc`;失败时为空对象,不阻断 DocsLink / 预览挂载。 */
845
- var PREVIEW_SCROLLER_IMPORT_CODE = "const __docsVc=await import(\"@deot/vc\").catch(()=>({}))";
846
- /**
847
- * Vue 的 `mount` 闭包的是 `createApp(root)` 时的根组件,改 `app._component` 不会生效。
848
- * 因此劫持 `app.mount`:等全部 useCode 注册完后,再 `createApp` 包一层 Scroller。
849
- * 前导分号避免接在 `app.component(...)` 后被 ASI 解析成调用返回值。
850
- */
851
- var PREVIEW_SCROLLER_USE_CODE = [
852
- ";(()=>{",
853
- PREVIEW_SCROLL_RESET_CODE,
854
- "const __DocsScroller=__docsVc&&__docsVc.Scroller;",
855
- "if(!__DocsScroller)return;",
856
- "const UserApp=app._component;",
857
- "app.mount=(container,...rest)=>{",
858
- "const next=_createApp({",
859
- "name:\"DocsPreviewRoot\",",
860
- "setup(){return()=>__docsH(__DocsScroller,{",
861
- "height:\"100%\",",
862
- "native:false,",
863
- "autoResize:true,",
864
- "showBar:true,",
865
- `contentClass:"${PREVIEW_SCROLL_CONTENT_CLASS}"`,
866
- "},{default:()=>__docsH(UserApp)})}",
867
- "});",
868
- "next.config.errorHandler=app.config.errorHandler;",
869
- "if(app._context&&next._context){",
870
- "if(app._context.components)Object.assign(next._context.components,app._context.components);",
871
- "if(app._context.directives)Object.assign(next._context.directives,app._context.directives);",
872
- "}",
873
- "window.__app__=next;",
874
- `document.documentElement.classList.add("${PREVIEW_SCROLL_HTML_CLASS}");`,
875
- "return next.mount(container,...rest)",
876
- "}",
877
- "})()"
878
- ].join("");
879
- var PREVIEW_SCROLLER_STYLE = [
880
- `html.${PREVIEW_SCROLL_HTML_CLASS},`,
881
- `html.${PREVIEW_SCROLL_HTML_CLASS} body,`,
882
- `html.${PREVIEW_SCROLL_HTML_CLASS} #app{`,
883
- "height:100%;min-height:100%;margin:0;overflow:hidden",
884
- "}",
885
- `html.${PREVIEW_SCROLL_HTML_CLASS} #app>.vc-scroller,`,
886
- `html.${PREVIEW_SCROLL_HTML_CLASS} #app>.vc-scroller>.vc-scroller__wrapper{`,
887
- "height:100%;max-height:100%;box-sizing:border-box",
888
- "}"
889
- ].join("");
890
- var resolveSandboxContainer = (sandbox) => sandbox?.container ? unref(sandbox.container) : null;
891
- var resolveScrollContent = (iframeDocument) => {
892
- if (!iframeDocument.documentElement.classList.contains("docs-playground-preview-scroll")) return null;
893
- return iframeDocument.querySelector(`.${PREVIEW_SCROLL_CONTENT_CLASS}`);
894
- };
895
- var useSandboxAutoHeight = (sandboxRef) => {
896
- const height = ref(24);
897
- let container = null;
898
- let iframe = null;
899
- let containerObserver = null;
900
- let contentObserver = null;
901
- let scrollMountObserver = null;
902
- let observedScrollNode = null;
903
- let frameId = 0;
904
- const cancelMeasure = () => {
905
- if (!frameId) return;
906
- cancelAnimationFrame(frameId);
907
- frameId = 0;
908
- };
909
- const measureDocumentContent = (iframeWindow, iframeDocument) => {
910
- const { body, documentElement } = iframeDocument;
911
- const bodyStyle = iframeWindow.getComputedStyle(body);
912
- const bodyMargins = (Number.parseFloat(bodyStyle.marginTop) || 0) + (Number.parseFloat(bodyStyle.marginBottom) || 0);
913
- const rootTop = documentElement.getBoundingClientRect().top;
914
- const bodyRect = body.getBoundingClientRect();
915
- const collapsedTop = Math.max(0, bodyRect.top - rootTop);
916
- let childrenBottom = 0;
917
- for (const child of body.children) {
918
- const rect = child.getBoundingClientRect();
919
- const marginBottom = Number.parseFloat(iframeWindow.getComputedStyle(child).marginBottom) || 0;
920
- childrenBottom = Math.max(childrenBottom, rect.bottom + marginBottom - rootTop);
921
- }
922
- const scrollHeight = Math.max(body.scrollHeight, documentElement.scrollHeight);
923
- const overflowingHeight = scrollHeight > (iframe?.clientHeight || 0) + 1 ? scrollHeight : 0;
924
- return Math.ceil(Math.max(body.offsetHeight + bodyMargins + collapsedTop, bodyRect.height + bodyMargins + collapsedTop, childrenBottom, overflowingHeight));
925
- };
926
- const measureScrollContent = (scrollContent) => {
927
- const contentStyle = scrollContent.ownerDocument.defaultView?.getComputedStyle(scrollContent);
928
- const margins = contentStyle ? (Number.parseFloat(contentStyle.marginTop) || 0) + (Number.parseFloat(contentStyle.marginBottom) || 0) : 0;
929
- let childrenBottom = 0;
930
- const rootTop = scrollContent.getBoundingClientRect().top;
931
- for (const child of scrollContent.children) {
932
- const rect = child.getBoundingClientRect();
933
- const marginBottom = Number.parseFloat(scrollContent.ownerDocument.defaultView?.getComputedStyle(child).marginBottom || "0") || 0;
934
- childrenBottom = Math.max(childrenBottom, rect.bottom + marginBottom - rootTop);
935
- }
936
- return Math.ceil(Math.max(scrollContent.scrollHeight + margins, scrollContent.offsetHeight + margins, childrenBottom + margins));
937
- };
938
- const isEmptyPreviewApp = (iframeDocument) => {
939
- const app = iframeDocument.getElementById("app");
940
- return !!app && app.childElementCount === 0;
941
- };
942
- const measure = () => {
943
- frameId = 0;
944
- if (!iframe) return;
945
- try {
946
- const iframeWindow = iframe.contentWindow;
947
- const iframeDocument = iframe.contentDocument;
948
- if (!iframeWindow || !iframeDocument?.body) return;
949
- const scrollContent = resolveScrollContent(iframeDocument);
950
- if (!scrollContent && isEmptyPreviewApp(iframeDocument)) return;
951
- const contentHeight = scrollContent ? measureScrollContent(scrollContent) : measureDocumentContent(iframeWindow, iframeDocument);
952
- const nextHeight = Math.max(contentHeight, 24);
953
- if (height.value !== nextHeight) height.value = nextHeight;
954
- } catch {
955
- if (height.value !== 24) height.value = 24;
956
- }
957
- };
958
- const scheduleMeasure = () => {
959
- if (frameId) return;
960
- frameId = requestAnimationFrame(measure);
961
- };
962
- const disconnectContent = () => {
963
- contentObserver?.disconnect();
964
- contentObserver = null;
965
- scrollMountObserver?.disconnect();
966
- scrollMountObserver = null;
967
- observedScrollNode = null;
968
- cancelMeasure();
969
- };
970
- const observeContent = () => {
971
- disconnectContent();
972
- if (!iframe) return;
973
- try {
974
- const iframeWindow = iframe.contentWindow;
975
- const iframeDocument = iframe.contentDocument;
976
- const Observer = iframeWindow?.ResizeObserver;
977
- if (!iframeWindow || !iframeDocument?.body || !Observer) {
978
- scheduleMeasure();
979
- return;
980
- }
981
- const observer = new Observer(scheduleMeasure);
982
- observer.observe(iframeDocument.documentElement);
983
- observer.observe(iframeDocument.body);
984
- contentObserver = observer;
985
- const attachScrollContent = (node) => {
986
- if (!node || !contentObserver) return false;
987
- if (observedScrollNode === node) return true;
988
- if (observedScrollNode) contentObserver.unobserve(observedScrollNode);
989
- observedScrollNode = node;
990
- contentObserver.observe(node);
991
- return true;
992
- };
993
- const syncScrollContent = () => {
994
- attachScrollContent(resolveScrollContent(iframeDocument));
995
- scheduleMeasure();
996
- };
997
- scrollMountObserver = new MutationObserver(syncScrollContent);
998
- scrollMountObserver.observe(iframeDocument.documentElement, {
999
- attributes: true,
1000
- attributeFilter: ["class"]
1001
- });
1002
- scrollMountObserver.observe(iframeDocument.body, {
1003
- childList: true,
1004
- subtree: true
1005
- });
1006
- syncScrollContent();
1007
- } catch {
1008
- if (height.value !== 24) height.value = 24;
1009
- }
1010
- };
1011
- const handleIframeLoad = () => observeContent();
1012
- const setIframe = (nextIframe) => {
1013
- if (iframe === nextIframe) return;
1014
- iframe?.removeEventListener("load", handleIframeLoad);
1015
- disconnectContent();
1016
- iframe = nextIframe;
1017
- if (!iframe) {
1018
- height.value = 24;
1019
- return;
1020
- }
1021
- iframe.addEventListener("load", handleIframeLoad);
1022
- iframe.style.height = "100%";
1023
- observeContent();
1024
- };
1025
- const syncIframe = () => setIframe(container?.querySelector("iframe") || null);
1026
- const setContainer = (nextContainer) => {
1027
- if (container === nextContainer) return;
1028
- containerObserver?.disconnect();
1029
- containerObserver = null;
1030
- container = nextContainer;
1031
- setIframe(null);
1032
- if (!container) return;
1033
- containerObserver = new MutationObserver(syncIframe);
1034
- containerObserver.observe(container, {
1035
- childList: true,
1036
- subtree: true
1037
- });
1038
- syncIframe();
1039
- };
1040
- watch(() => resolveSandboxContainer(sandboxRef.value), setContainer, {
1041
- flush: "post",
1042
- immediate: true
1043
- });
1044
- onBeforeUnmount(() => {
1045
- setContainer(null);
1046
- cancelMeasure();
1047
- });
1048
- return height;
1049
- };
1050
833
  var resolvePreviewBoxHeight = (contentHeight, verticalInset = 0, borderWidth = 1) => {
1051
834
  const content = Number.isFinite(contentHeight) ? Math.max(0, contentHeight) : 0;
1052
835
  const inset = Number.isFinite(verticalInset) ? Math.max(0, verticalInset) : 0;
@@ -1125,68 +908,6 @@ var scrollPlaygroundToViewportStart = (el) => {
1125
908
  });
1126
909
  };
1127
910
  //#endregion
1128
- //#region packages/playground/src/core/runtime/error-guard.ts
1129
- var UNKNOWN_RUNTIME_ERROR = "运行时发生未知错误";
1130
- var MODULE_SPECIFIER_RE = /Failed to resolve module specifier|Error resolving module specifier/u;
1131
- var forwardSandboxRuntimeError = (event) => {
1132
- if (!(event instanceof ErrorEvent) || event.error != null || !event.message) return;
1133
- event.stopImmediatePropagation();
1134
- if (event.message === "ResizeObserver loop limit exceeded" || event.message === "ResizeObserver loop completed with undelivered notifications.") return;
1135
- window.parent.postMessage({
1136
- action: "error",
1137
- value: event.message
1138
- }, "*");
1139
- };
1140
- var SANDBOX_RUNTIME_ERROR_CAPTURE_HTML = [
1141
- "<script>",
1142
- `window.addEventListener('error', ${forwardSandboxRuntimeError.toString()}, true);`,
1143
- "<\/script>"
1144
- ].join("\n");
1145
- var toRuntimeErrorMessage = (value, message) => {
1146
- if (typeof value === "string" && value) return value;
1147
- if (value instanceof Error && value.message) return value.message;
1148
- if (value && typeof value === "object" && "message" in value) {
1149
- const valueMessage = value.message;
1150
- if (typeof valueMessage === "string" && valueMessage) return valueMessage;
1151
- }
1152
- if (typeof message === "string" && message) return message;
1153
- if (value !== null && value !== void 0) try {
1154
- return String(value);
1155
- } catch {
1156
- return UNKNOWN_RUNTIME_ERROR;
1157
- }
1158
- return UNKNOWN_RUNTIME_ERROR;
1159
- };
1160
- var normalizeRuntimeErrorMessage = (data) => {
1161
- if (!data || typeof data !== "object") return false;
1162
- const message = data;
1163
- if (message.action !== "error") return false;
1164
- message.value = toRuntimeErrorMessage(message.value, message.message);
1165
- return true;
1166
- };
1167
- var toErrorText = (value) => {
1168
- if (typeof value === "string" && value) return value;
1169
- if (value instanceof Error && value.message) return value.message;
1170
- return "";
1171
- };
1172
- var formatSandboxRuntimeError = (message, importMapTip) => {
1173
- if (!MODULE_SPECIFIER_RE.test(message)) return message;
1174
- return `${message.replace(/\. Relative references must.*$/u, "").replace(/\.$/u, "")}.\n${importMapTip}`;
1175
- };
1176
- var useSandboxRuntimeErrorGuard = (sandboxRef) => {
1177
- const error = ref("");
1178
- if (typeof window === "undefined") return error;
1179
- const handleMessage = (event) => {
1180
- const iframe = resolveSandboxContainer(sandboxRef.value)?.querySelector("iframe");
1181
- if (!iframe || event.source !== iframe.contentWindow) return;
1182
- if (!normalizeRuntimeErrorMessage(event.data)) return;
1183
- error.value = event.data.value;
1184
- };
1185
- window.addEventListener("message", handleMessage, true);
1186
- onBeforeUnmount(() => window.removeEventListener("message", handleMessage, true));
1187
- return error;
1188
- };
1189
- //#endregion
1190
911
  //#region packages/playground/src/core/runtime/viewport.ts
1191
912
  var DEFAULT_VIEWPORT_OPTIONS = ["auto", 375];
1192
913
  var isValidViewport = (viewport) => {
@@ -1369,6 +1090,73 @@ var useSandboxTheme = (sandboxRef) => {
1369
1090
  });
1370
1091
  };
1371
1092
  //#endregion
1093
+ //#region packages/playground/src/core/runtime/height-bridge.ts
1094
+ /**
1095
+ * 只接收本宿主当前 iframe 的高度请求,应用重评时切换会话。
1096
+ * @param sandbox 预览容器。
1097
+ * @param maxHeight 当前可用高度,普通预览默认不限制。
1098
+ * @returns 所有有效请求的最大高度。
1099
+ */
1100
+ function usePreviewHeightBridge(sandbox, maxHeight = () => Infinity) {
1101
+ const height = ref(0);
1102
+ const requests = /* @__PURE__ */ new Map();
1103
+ let source = null;
1104
+ let session = "";
1105
+ let disposed = false;
1106
+ const sync = () => {
1107
+ height.value = Math.max(0, ...requests.values());
1108
+ };
1109
+ const reset = () => {
1110
+ requests.clear();
1111
+ session = "";
1112
+ source = null;
1113
+ sync();
1114
+ };
1115
+ const handleMessage = async (event) => {
1116
+ const current = resolveSandboxMessageSource(sandbox.value);
1117
+ const data = event.data;
1118
+ if (!current || event.source !== current || data?.action !== "docs:height" || typeof data.session !== "string") return;
1119
+ if (data.operation === "start") {
1120
+ reset();
1121
+ source = current;
1122
+ session = data.session;
1123
+ return;
1124
+ }
1125
+ if (source !== current || session !== data.session) return;
1126
+ if (data.operation === "stop") {
1127
+ reset();
1128
+ return;
1129
+ }
1130
+ if (!Number.isSafeInteger(data.id) || data.id <= 0) return;
1131
+ if (data.operation === "release") {
1132
+ requests.delete(data.id);
1133
+ sync();
1134
+ return;
1135
+ }
1136
+ if (data.operation !== "enable" || !Number.isFinite(data.height) || data.height <= 0) return;
1137
+ const accepted = data.height <= maxHeight();
1138
+ if (accepted) requests.set(data.id, data.height);
1139
+ sync();
1140
+ const receiver = source;
1141
+ await nextTick();
1142
+ if (disposed || source !== receiver || session !== data.session) return;
1143
+ receiver?.postMessage({
1144
+ action: "docs:height:applied",
1145
+ session,
1146
+ id: data.id,
1147
+ accepted
1148
+ }, "*");
1149
+ };
1150
+ watch(() => resolveSandboxMessageSource(sandbox.value), reset, { flush: "sync" });
1151
+ if (typeof window !== "undefined") window.addEventListener("message", handleMessage);
1152
+ onBeforeUnmount(() => {
1153
+ disposed = true;
1154
+ if (typeof window !== "undefined") window.removeEventListener("message", handleMessage);
1155
+ reset();
1156
+ });
1157
+ return height;
1158
+ }
1159
+ //#endregion
1372
1160
  //#region packages/playground/src/core/runtime/toolbar.vue?vue&type=script&setup=true&lang.ts
1373
1161
  var _hoisted_1$3 = { class: "docs-playground__tools" };
1374
1162
  var _hoisted_2$3 = {
@@ -1585,426 +1373,6 @@ var toolbar_default = /* @__PURE__ */ defineComponent({
1585
1373
  }
1586
1374
  });
1587
1375
  //#endregion
1588
- //#region packages/playground/src/cdn.ts
1589
- var PREVIEW_STYLE_ASSETS = [
1590
- "@deot/style/dist/index.normalize-only.css",
1591
- "@deot/vc-components/dist/index.style.css",
1592
- "@deot/style/dist/index.css"
1593
- ];
1594
- var BUILTIN_IMPORT_ASSETS = {
1595
- "@deot/vc": "@deot/vc/dist/index.js",
1596
- "@deot/vc-shared": "@deot/vc-shared/dist/index.js",
1597
- "@deot/vc-hooks": "@deot/vc-hooks/dist/index.js",
1598
- "@deot/vc-components": "@deot/vc-components/dist/index.js",
1599
- "@deot/helper-resize": "@deot/helper-resize/dist/index.js",
1600
- "@deot/helper-utils": "@deot/helper-utils/dist/index.js",
1601
- "@deot/helper-cache": "@deot/helper-cache/dist/index.js",
1602
- "@deot/helper-fp": "@deot/helper-fp/dist/index.js",
1603
- "@deot/helper-dom": "@deot/helper-dom/dist/index.js",
1604
- "@deot/helper-wheel": "@deot/helper-wheel/dist/index.js",
1605
- "@deot/helper-validator": "@deot/helper-validator/dist/index.js",
1606
- "@deot/helper-load": "@deot/helper-load/dist/index.js",
1607
- "@deot/helper-scheduler": "@deot/helper-scheduler/dist/index.js",
1608
- "@deot/helper-emitter": "@deot/helper-emitter/dist/index.js",
1609
- "@deot/helper-is": "@deot/helper-is/dist/index.js",
1610
- "@deot/helper-device": "@deot/helper-device/dist/index.js",
1611
- "@deot/helper-route": "@deot/helper-route/dist/index.js",
1612
- "@deot/helper-unicode": "@deot/helper-unicode/dist/index.js",
1613
- "@deot/helper": "@deot/helper/dist/index.js",
1614
- "normalize-wheel": "normalize-wheel-es/dist/index.mjs",
1615
- "photoswipe": "photoswipe/dist/photoswipe.esm.js",
1616
- "photoswipe/lightbox": "photoswipe/dist/photoswipe-lightbox.esm.js"
1617
- };
1618
- var normalizeCdnURL = (cdnURL = DEFAULT_CDN_URL) => {
1619
- return cdnURL.trim().replace(/\/+$/u, "") || "https://cdn.jsdelivr.net/npm";
1620
- };
1621
- var cdnJoin = (origin, asset) => `${origin}/${asset.replace(/^\/+/u, "")}`;
1622
- var jsdelivrEsmURL = (asset) => cdnJoin(DEFAULT_CDN_URL, asset);
1623
- var SASS_CDN_URL = jsdelivrEsmURL("sass/+esm");
1624
- var cdnAsset = (cdnURL, asset) => cdnJoin(normalizeCdnURL(cdnURL), asset);
1625
- var createBuiltinImports = (cdnURL = DEFAULT_CDN_URL) => ({
1626
- ...Object.fromEntries(Object.entries(BUILTIN_IMPORT_ASSETS).map(([specifier, asset]) => [specifier, cdnAsset(cdnURL, asset)])),
1627
- "lodash-es": jsdelivrEsmURL("lodash-es/+esm"),
1628
- "vue": "https://play.vuejs.org/vue.runtime.esm-browser.js",
1629
- "vue/server-renderer": "https://play.vuejs.org/server-renderer.esm-browser.js"
1630
- });
1631
- var createBuiltinStyles = (cdnURL = DEFAULT_CDN_URL) => Object.fromEntries(PREVIEW_STYLE_ASSETS.map((asset) => [asset, cdnAsset(cdnURL, asset)]));
1632
- //#endregion
1633
- //#region packages/playground/src/import-map.ts
1634
- /**
1635
- * 站点级同步内存:`$docs.modules` / `$docs.styles` 与管理页 import、CSS 覆盖。
1636
- */
1637
- var normalize = (value) => value.trim();
1638
- var isSafePlaygroundHref = (href) => {
1639
- const next = href.trim();
1640
- if (!next) return false;
1641
- if (/^https?:\/\//iu.test(next)) return true;
1642
- return next.startsWith("/") && !next.startsWith("//");
1643
- };
1644
- var filterSafeHrefs = (value = {}) => Object.fromEntries(Object.entries(value).filter((entry) => typeof entry[1] === "string" && isSafePlaygroundHref(entry[1])));
1645
- var sanitizeMap = (value = {}) => filterSafeHrefs(Object.fromEntries(Object.entries(value).map(([alias, url]) => [normalize(alias), normalize(url)]).filter(([alias]) => Boolean(alias))));
1646
- var createMapStore = () => {
1647
- let data = {};
1648
- const snapshot = () => ({ ...data });
1649
- const drop = (alias) => {
1650
- if (data[alias] === void 0) return snapshot();
1651
- const next = { ...data };
1652
- delete next[alias];
1653
- data = next;
1654
- return snapshot();
1655
- };
1656
- return {
1657
- get: snapshot,
1658
- set: (value = {}) => {
1659
- data = sanitizeMap(value);
1660
- },
1661
- apply: (alias, url) => {
1662
- const nextAlias = normalize(alias);
1663
- const nextUrl = normalize(url);
1664
- if (!nextAlias) return snapshot();
1665
- if (!isSafePlaygroundHref(nextUrl)) return drop(nextAlias);
1666
- data = {
1667
- ...data,
1668
- [nextAlias]: nextUrl
1669
- };
1670
- return snapshot();
1671
- },
1672
- remove: (alias) => {
1673
- const nextAlias = normalize(alias);
1674
- return nextAlias ? drop(nextAlias) : snapshot();
1675
- }
1676
- };
1677
- };
1678
- var siteModules = createMapStore();
1679
- var siteStyles = createMapStore();
1680
- var importOverrides = createMapStore();
1681
- var styleOverrides = createMapStore();
1682
- /**
1683
- * 站点默认 import。合并时夹在内置 CDN 与实例 `builtinImportMap` 之间。
1684
- */
1685
- var getPlaygroundSiteModules = siteModules.get;
1686
- var setPlaygroundSiteModules = siteModules.set;
1687
- /**
1688
- * 站点默认预览 CSS。合并时夹在内置样式表与管理页覆盖之间。
1689
- */
1690
- var getPlaygroundSiteStyles = siteStyles.get;
1691
- var setPlaygroundSiteStyles = siteStyles.set;
1692
- var getPlaygroundImportMapOverrides = importOverrides.get;
1693
- var setPlaygroundImportMapOverrides = importOverrides.set;
1694
- var applyPlaygroundImportMapOverride = importOverrides.apply;
1695
- var removePlaygroundImportMapOverride = importOverrides.remove;
1696
- var getPlaygroundStyleOverrides = styleOverrides.get;
1697
- var setPlaygroundStyleOverrides = styleOverrides.set;
1698
- var applyPlaygroundStyleOverride = styleOverrides.apply;
1699
- var removePlaygroundStyleOverride = styleOverrides.remove;
1700
- var clearPlaygroundMaps = () => {
1701
- [
1702
- siteModules,
1703
- siteStyles,
1704
- importOverrides,
1705
- styleOverrides
1706
- ].forEach((store) => store.set());
1707
- };
1708
- //#endregion
1709
- //#region packages/playground/src/core/scss.ts
1710
- var SCHEME = "docs-playground";
1711
- var STYLE_EXTS = [".scss", ".sass"];
1712
- var VUE_SCSS_STYLE_RE = /<style\b[^>]*\blang\s*=\s*(['"]?)s[ac]ss\1/i;
1713
- var LANG_ATTR_RE = /\s*lang\s*=\s*(['"]?)s[ac]ss\1/i;
1714
- var SCSS_ERROR_MARK = "[playground-sass]";
1715
- var INJECT_START = "/* docs-playground-scss-start */";
1716
- var INJECT_END = "/* docs-playground-scss-end */";
1717
- var EMPTY_JS = "export default {}\n";
1718
- var boundStores = /* @__PURE__ */ new WeakSet();
1719
- var wrappedCompilers = /* @__PURE__ */ new WeakSet();
1720
- var testLoader;
1721
- var loadedSass;
1722
- var loadPromise;
1723
- var fileCode = (value) => typeof value === "string" ? value : value.code;
1724
- var playgroundPath = (url) => decodeURIComponent(url.pathname.replace(/^\/+/u, ""));
1725
- var toPlaygroundUrl = (filename) => new URL(`${SCHEME}:///${filename.replace(/^\/+/u, "")}`);
1726
- var basename = (path) => path.split("/").pop() || path;
1727
- var scssSyntax = (filename, lang) => lang === "sass" || /\.sass$/i.test(filename) ? "indented" : "scss";
1728
- var errorText = (item) => item instanceof Error ? item.message : String(item);
1729
- var isScssFile = (filename) => /\.s[ac]ss$/i.test(filename);
1730
- var vueSourceNeedsScss = (source) => VUE_SCSS_STYLE_RE.test(source);
1731
- var resolveSassModule = async (url) => {
1732
- const mod = await import(
1733
- /* @vite-ignore */
1734
- url
1735
- );
1736
- const sass = typeof mod.compileString === "function" ? mod : mod.default;
1737
- if (typeof sass?.compileString !== "function") throw new Error(`Sass module at ${url} does not export compileString`);
1738
- return sass;
1739
- };
1740
- var loadSass = () => {
1741
- loadPromise ??= (testLoader ?? (() => resolveSassModule(SASS_CDN_URL)))().then((sass) => {
1742
- loadedSass = sass;
1743
- return sass;
1744
- });
1745
- return loadPromise;
1746
- };
1747
- var isScssPartial = (filename) => isScssFile(filename) && basename(filename).startsWith("_");
1748
- var filesNeedScss = (files) => Object.entries(files).some(([filename, value]) => isScssFile(filename) || /\.vue$/i.test(filename) && vueSourceNeedsScss(fileCode(value)));
1749
- var whenSassReady = (files, run) => {
1750
- if (!filesNeedScss(files) || loadedSass) run();
1751
- else loadSass().then(run);
1752
- };
1753
- var toPlaygroundFileMap = (files) => Object.fromEntries(Object.entries(files).map(([filename, value]) => [filename, fileCode(value)]));
1754
- var formatScssError = (filename, message) => `${SCSS_ERROR_MARK} ${filename}: ${message}`;
1755
- var scssFail = (filename, error) => formatScssError(filename, errorText(error));
1756
- var withUnderscore = (path) => {
1757
- const base = basename(path);
1758
- if (base.startsWith("_")) return path;
1759
- return `${path.slice(0, -base.length)}_${base}`;
1760
- };
1761
- var matchFileKey = (files, path) => [
1762
- path,
1763
- path.startsWith("src/") ? path : `src/${path}`,
1764
- path.replace(/^src\//u, "")
1765
- ].find((key) => files[key] !== void 0);
1766
- var stylesheetCandidates = (requestPath) => {
1767
- if (isScssFile(requestPath)) return [requestPath, withUnderscore(requestPath)];
1768
- return STYLE_EXTS.flatMap((ext) => [
1769
- `${requestPath}${ext}`,
1770
- withUnderscore(`${requestPath}${ext}`),
1771
- `${requestPath}/index${ext}`,
1772
- withUnderscore(`${requestPath}/index${ext}`)
1773
- ]);
1774
- };
1775
- var resolvePlaygroundStylesheet = (files, requestPath) => {
1776
- const found = [...new Set(stylesheetCandidates(requestPath).map((path) => matchFileKey(files, path)).filter((key) => Boolean(key)))];
1777
- if (found.length > 1) throw new Error(`Ambiguous Sass import "${requestPath}": ${found.join(", ")}`);
1778
- return found[0] ?? null;
1779
- };
1780
- var createPlaygroundImporter = (getFiles) => ({
1781
- canonicalize(url, context) {
1782
- if (/^[a-zA-Z][\w+.-]*:/u.test(url) && !url.startsWith(`${SCHEME}:`)) return null;
1783
- try {
1784
- const resolved = resolvePlaygroundStylesheet(getFiles(), playgroundPath(new URL(url, context.containingUrl ?? toPlaygroundUrl(""))));
1785
- return resolved ? toPlaygroundUrl(resolved) : null;
1786
- } catch {
1787
- return null;
1788
- }
1789
- },
1790
- load(canonicalUrl) {
1791
- const files = getFiles();
1792
- const key = playgroundPath(canonicalUrl);
1793
- return files[key] === void 0 ? null : {
1794
- contents: files[key],
1795
- syntax: scssSyntax(key)
1796
- };
1797
- }
1798
- });
1799
- var compileScssSource = (source, filename, sass, files, lang) => {
1800
- const importer = createPlaygroundImporter(() => files);
1801
- return sass.compileString(source, {
1802
- syntax: scssSyntax(filename, lang),
1803
- url: toPlaygroundUrl(filename),
1804
- importer,
1805
- importers: [importer]
1806
- }).css;
1807
- };
1808
- var rewriteVueSfcStyles = (source, filename, parse, sass, files) => {
1809
- const scssStyles = parse(source, { filename }).descriptor.styles.filter((style) => style.lang === "scss" || style.lang === "sass");
1810
- if (!scssStyles.length) return {
1811
- code: source,
1812
- errors: []
1813
- };
1814
- const errors = [];
1815
- let code = source;
1816
- for (const style of [...scssStyles].sort((left, right) => right.loc.start.offset - left.loc.start.offset)) {
1817
- const before = code.slice(0, style.loc.start.offset);
1818
- const after = code.slice(style.loc.end.offset);
1819
- const openStart = before.lastIndexOf("<style");
1820
- if (openStart < 0) {
1821
- errors.push(formatScssError(filename, "unable to locate <style> opening tag"));
1822
- continue;
1823
- }
1824
- try {
1825
- const css = compileScssSource(style.content, filename, sass, files, style.lang);
1826
- code = `${before.slice(0, openStart)}${before.slice(openStart).replace(LANG_ATTR_RE, "")}${css}${after}`;
1827
- } catch (error) {
1828
- errors.push(scssFail(filename, error));
1829
- }
1830
- }
1831
- return {
1832
- code,
1833
- errors
1834
- };
1835
- };
1836
- var appendParseErrors = (result, errors) => errors.length ? {
1837
- ...result,
1838
- errors: [...result.errors, ...errors.map((item) => new Error(item))]
1839
- } : result;
1840
- var wrapCompiler = (compiler, getFiles) => {
1841
- if (wrappedCompilers.has(compiler)) return compiler;
1842
- const originalParse = compiler.parse.bind(compiler);
1843
- const wrapped = { ...compiler };
1844
- wrapped.parse = ((source, options) => {
1845
- const filename = options?.filename || "anonymous.vue";
1846
- if (!vueSourceNeedsScss(source)) return originalParse(source, options);
1847
- const rewritten = loadedSass ? rewriteVueSfcStyles(source, filename, originalParse, loadedSass, getFiles()) : {
1848
- code: source,
1849
- errors: [formatScssError(filename, "compiler is not loaded")]
1850
- };
1851
- return appendParseErrors(originalParse(rewritten.errors.length ? source : rewritten.code, options), rewritten.errors);
1852
- });
1853
- wrappedCompilers.add(wrapped);
1854
- return wrapped;
1855
- };
1856
- var withInjectedCss = (css, extra) => {
1857
- const start = css.indexOf(INJECT_START);
1858
- const end = start < 0 ? -1 : css.indexOf(INJECT_END, start);
1859
- const base = (start < 0 ? css : `${css.slice(0, start)}${end >= 0 ? css.slice(end + 30) : ""}`).trimEnd();
1860
- if (!extra.trim()) return base;
1861
- const block = `${INJECT_START}\n${extra.trim()}\n${INJECT_END}`;
1862
- return base ? `${base}\n${block}` : block;
1863
- };
1864
- var isStandaloneScssError = (item) => {
1865
- const text = errorText(item);
1866
- return text.startsWith(SCSS_ERROR_MARK) && /\.s[ac]ss:/i.test(text);
1867
- };
1868
- var syncScssErrors = (store, scssErrors) => {
1869
- const next = [...scssErrors, ...store.errors.filter((item) => !isStandaloneScssError(item))];
1870
- if (next.map(String).join("\0") === store.errors.map(String).join("\0")) return;
1871
- store.errors = next;
1872
- };
1873
- var applyStandaloneScss = (store, sass = loadedSass) => {
1874
- if (!sass) return [];
1875
- const fileMap = toPlaygroundFileMap(store.files);
1876
- const errors = [];
1877
- const injected = [];
1878
- for (const [filename, file] of Object.entries(store.files)) {
1879
- if (!isScssFile(filename) || !file.compiled) continue;
1880
- try {
1881
- const css = compileScssSource(file.code, filename, sass, fileMap);
1882
- file.compiled.css = css;
1883
- file.compiled.js = EMPTY_JS;
1884
- file.compiled.ssr = EMPTY_JS;
1885
- if (!isScssPartial(filename) && css.trim()) injected.push(css);
1886
- } catch (error) {
1887
- errors.push(scssFail(filename, error));
1888
- }
1889
- }
1890
- const main = store.files[store.mainFile];
1891
- if (main?.compiled) {
1892
- const next = withInjectedCss(main.compiled.css || "", injected.join("\n"));
1893
- if (next !== (main.compiled.css || "")) main.compiled.css = next;
1894
- }
1895
- syncScssErrors(store, errors);
1896
- return errors;
1897
- };
1898
- var bindPlaygroundScss = (store) => {
1899
- if (boundStores.has(store)) return;
1900
- boundStores.add(store);
1901
- const getFiles = () => toPlaygroundFileMap(store.files);
1902
- const installCompiler = () => {
1903
- if (typeof store.compiler?.parse === "function") store.compiler = wrapCompiler(store.compiler, getFiles);
1904
- };
1905
- installCompiler();
1906
- watch(() => store.compiler, installCompiler);
1907
- watch(() => [
1908
- store.mainFile,
1909
- store.files[store.mainFile]?.compiled?.css,
1910
- store.errors.map(String).join("\0"),
1911
- Object.entries(store.files).filter(([filename]) => isScssFile(filename)).map(([filename, file]) => `${filename}:${file.code}`).join("\n")
1912
- ].join("\0"), () => {
1913
- if (loadedSass) applyStandaloneScss(store);
1914
- });
1915
- const originalSetFiles = store.setFiles.bind(store);
1916
- store.setFiles = async (newFiles, mainFile) => {
1917
- if (filesNeedScss(newFiles) && !loadedSass) await loadSass();
1918
- return originalSetFiles(newFiles, mainFile);
1919
- };
1920
- };
1921
- //#endregion
1922
- //#region packages/playground/src/core/store.ts
1923
- var DOCS_LINK_IMPORT_CODE = "import { h as __docsH } from \"vue\"";
1924
- var DOCS_LINK_USE_CODE = [
1925
- PREVIEW_SCROLL_RESET_CODE,
1926
- "app.component(\"DocsLink\",{",
1927
- "props:{to:{type:String,default:\"\"}},",
1928
- "setup(props,{slots}){return()=>__docsH(\"a\",{",
1929
- "href:props.to,",
1930
- "style:{color:\"inherit\",textDecoration:\"none\"},",
1931
- "onClick(event){event.preventDefault();window.parent.postMessage({action:\"docs:navigate\",to:props.to},\"*\")}",
1932
- "},slots.default?.())}",
1933
- "})"
1934
- ].join("");
1935
- var escapeHtmlAttr = (value) => value.replace(/&/gu, "&amp;").replace(/"/gu, "&quot;").replace(/'/gu, "&#39;").replace(/</gu, "&lt;").replace(/>/gu, "&gt;");
1936
- /**
1937
- * runtime 画布色。`previewInset` 露出的 padding、iframe chrome 和 sandbox
1938
- * `html`/`body` 必须共用这一变量,暗色下 `--docs-background-color` 与
1939
- * `--vc-background-color-light` 不同,否则会出现色带割裂。
1940
- */
1941
- var PLAYGROUND_RUNTIME_CANVAS_BACKGROUND = "var(--vc-background-color-light, var(--docs-background-color, #fff))";
1942
- var createRuntimePreviewOptions = (cdnURL = DEFAULT_CDN_URL, options = {}) => {
1943
- const previewScroller = options.previewScroller === true;
1944
- const hrefs = Object.values({
1945
- ...createBuiltinStyles(cdnURL),
1946
- ...getPlaygroundSiteStyles(),
1947
- ...getPlaygroundStyleOverrides()
1948
- });
1949
- const styleBlocks = [
1950
- `html,body{height:auto;min-height:0;background:${PLAYGROUND_RUNTIME_CANVAS_BACKGROUND}}`,
1951
- "body{color:var(--vc-foreground-color,#080f20)}",
1952
- ...previewScroller ? [PREVIEW_SCROLLER_STYLE] : []
1953
- ];
1954
- return {
1955
- showRuntimeError: false,
1956
- showRuntimeWarning: false,
1957
- headHTML: [
1958
- SANDBOX_RUNTIME_ERROR_CAPTURE_HTML,
1959
- "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">",
1960
- ...hrefs.map((href) => `<link rel="stylesheet" href="${escapeHtmlAttr(href)}">`),
1961
- "<style>",
1962
- ...styleBlocks,
1963
- "</style>"
1964
- ].join("\n"),
1965
- customCode: {
1966
- importCode: DOCS_LINK_IMPORT_CODE,
1967
- useCode: DOCS_LINK_USE_CODE
1968
- }
1969
- };
1970
- };
1971
- var toReplFilename = (filename) => filename.startsWith("src/") ? filename : `src/${filename}`;
1972
- var createReplFile = (filename, code) => {
1973
- const replFilename = toReplFilename(filename);
1974
- return new File(replFilename, code);
1975
- };
1976
- var createRuntimeStore = (files, entry, options) => {
1977
- const { cdnURL, builtinImportMap, ...storeOptions } = options;
1978
- const replFiles = ref(Object.fromEntries(Object.entries(files).map(([filename, code]) => {
1979
- const file = createReplFile(filename, code);
1980
- return [file.filename, file];
1981
- })));
1982
- const mainFile = ref(toReplFilename(entry));
1983
- const activeFilename = ref(toReplFilename(entry));
1984
- const store = useStore({
1985
- ...storeOptions,
1986
- files: replFiles,
1987
- mainFile,
1988
- activeFilename,
1989
- builtinImportMap: ref({
1990
- ...builtinImportMap,
1991
- imports: {
1992
- ...createBuiltinImports(cdnURL),
1993
- ...getPlaygroundSiteModules(),
1994
- ...filterSafeHrefs(builtinImportMap?.imports),
1995
- ...getPlaygroundImportMapOverrides()
1996
- }
1997
- }),
1998
- template: ref({
1999
- welcomeSFC: files[entry],
2000
- newSFC: NEW_SFC_CODE
2001
- })
2002
- });
2003
- bindPlaygroundScss(store);
2004
- whenSassReady(files, () => store.init());
2005
- return store;
2006
- };
2007
- //#endregion
2008
1376
  //#region packages/playground/src/core/runtime/alone/wrapper.vue?vue&type=script&setup=true&lang.ts
2009
1377
  var _hoisted_1$2 = ["aria-label"];
2010
1378
  var _hoisted_2$2 = { class: "docs-playground-popup__frame" };
@@ -2031,6 +1399,17 @@ var Alone = new Portal(/* @__PURE__ */ defineComponent({
2031
1399
  clearConsole: {
2032
1400
  type: Boolean,
2033
1401
  default: true
1402
+ },
1403
+ local: {
1404
+ type: Boolean,
1405
+ default: true
1406
+ },
1407
+ files: { default: () => ({}) },
1408
+ entry: { default: "" },
1409
+ options: { default: () => ({}) },
1410
+ previewScroller: {
1411
+ type: Boolean,
1412
+ default: false
2034
1413
  }
2035
1414
  },
2036
1415
  emits: [
@@ -2040,23 +1419,42 @@ var Alone = new Portal(/* @__PURE__ */ defineComponent({
2040
1419
  "portal-fulfilled"
2041
1420
  ],
2042
1421
  setup(__props, { emit: __emit }) {
1422
+ const LocalSandbox = defineAsyncComponent(() => import("./local-sandbox-B8IJ5jWb.js").then((n) => n.t));
2043
1423
  const props = __props;
2044
1424
  const emit = __emit;
2045
1425
  const { t } = useLocale();
2046
1426
  const currentViewport = ref(props.viewport);
2047
1427
  const sandboxRef = ref(null);
1428
+ const localError = ref({
1429
+ compile: "",
1430
+ runtime: ""
1431
+ });
1432
+ const handleLocalError = (payload) => {
1433
+ localError.value = payload;
1434
+ };
1435
+ const availableHeight = () => Math.max(0, getWindowInnerSize().height - 40 - 44);
1436
+ const temporaryHeight = usePreviewHeightBridge(sandboxRef, availableHeight);
2048
1437
  const sandboxKey = ref(0);
2049
1438
  const layoutTick = ref(0);
2050
1439
  const runtimeError = useSandboxRuntimeErrorGuard(sandboxRef);
2051
1440
  useSandboxTheme(sandboxRef);
2052
- const storeErrors = computed(() => (props.store.errors || []).map(toErrorText).filter(Boolean).join("\n"));
1441
+ const storeErrors = computed(() => props.local ? localError.value.compile : (props.store?.errors || []).map(toErrorText).filter(Boolean).join("\n"));
2053
1442
  const errorText = computed(() => {
2054
- const runtime = runtimeError.value ? formatSandboxRuntimeError(runtimeError.value, t("playground.runtime.importMapTip")) : "";
1443
+ const runtime = props.local ? localError.value.runtime : runtimeError.value ? formatSandboxRuntimeError(runtimeError.value, t("playground.runtime.importMapTip")) : "";
2055
1444
  return [storeErrors.value, runtime].filter(Boolean).join("\n\n");
2056
1445
  });
2057
1446
  const layout = computed(() => {
2058
1447
  layoutTick.value;
2059
- return resolvePopupLayout(currentViewport.value);
1448
+ const base = resolvePopupLayout(currentViewport.value);
1449
+ if (!temporaryHeight.value) return base;
1450
+ const canvasHeight = Math.min(availableHeight(), Math.max(base.canvasHeight, temporaryHeight.value));
1451
+ const shellHeight = Math.max(base.shellHeight, canvasHeight + 44);
1452
+ return {
1453
+ ...base,
1454
+ canvasHeight,
1455
+ shellHeight,
1456
+ bodyHeight: shellHeight - 44
1457
+ };
2060
1458
  });
2061
1459
  const shellStyle = computed(() => ({
2062
1460
  width: `${layout.value.shellWidth}px`,
@@ -2069,6 +1467,10 @@ var Alone = new Portal(/* @__PURE__ */ defineComponent({
2069
1467
  }));
2070
1468
  const handleRefresh = () => {
2071
1469
  runtimeError.value = "";
1470
+ localError.value = {
1471
+ compile: "",
1472
+ runtime: ""
1473
+ };
2072
1474
  sandboxKey.value++;
2073
1475
  };
2074
1476
  const handleViewportChange = (viewport) => {
@@ -2093,8 +1495,7 @@ var Alone = new Portal(/* @__PURE__ */ defineComponent({
2093
1495
  layoutTick.value++;
2094
1496
  };
2095
1497
  const handleBridgeMessage = (event) => {
2096
- const iframe = resolveSandboxContainer(sandboxRef.value)?.querySelector("iframe");
2097
- if (!iframe || event.source !== iframe.contentWindow) return;
1498
+ if (!isSandboxMessage(sandboxRef.value, event)) return;
2098
1499
  const data = event.data;
2099
1500
  if (!data || data.action !== "docs:navigate" || typeof data.to !== "string") return;
2100
1501
  emit("navigate", data.to);
@@ -2156,7 +1557,23 @@ var Alone = new Portal(/* @__PURE__ */ defineComponent({
2156
1557
  default: withCtx(() => [createElementVNode("div", {
2157
1558
  class: "docs-playground-popup__canvas",
2158
1559
  style: normalizeStyle(canvasStyle.value)
2159
- }, [(openBlock(), createBlock(unref(Sandbox), {
1560
+ }, [__props.local ? (openBlock(), createBlock(unref(LocalSandbox), {
1561
+ key: sandboxKey.value,
1562
+ ref_key: "sandboxRef",
1563
+ ref: sandboxRef,
1564
+ files: __props.files,
1565
+ entry: __props.entry,
1566
+ options: __props.options,
1567
+ "preview-scroller": __props.previewScroller,
1568
+ "clear-console": __props.clearConsole,
1569
+ onError: handleLocalError
1570
+ }, null, 8, [
1571
+ "files",
1572
+ "entry",
1573
+ "options",
1574
+ "preview-scroller",
1575
+ "clear-console"
1576
+ ])) : __props.store ? (openBlock(), createBlock(unref(Sandbox), {
2160
1577
  key: sandboxKey.value,
2161
1578
  ref_key: "sandboxRef",
2162
1579
  ref: sandboxRef,
@@ -2168,7 +1585,7 @@ var Alone = new Portal(/* @__PURE__ */ defineComponent({
2168
1585
  "store",
2169
1586
  "clear-console",
2170
1587
  "preview-options"
2171
- ]))], 4)]),
1588
+ ])) : createCommentVNode("v-if", true)], 4)]),
2172
1589
  _: 1
2173
1590
  })])
2174
1591
  ])], 4)], 8, _hoisted_1$2);
@@ -2233,7 +1650,11 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2233
1650
  title: { default: "" },
2234
1651
  id: { default: "" },
2235
1652
  viewport: { default: "auto" },
2236
- viewportOptions: { default: () => ["auto", 375] }
1653
+ viewportOptions: { default: () => ["auto", 375] },
1654
+ local: {
1655
+ type: Boolean,
1656
+ default: true
1657
+ }
2237
1658
  },
2238
1659
  emits: [
2239
1660
  "files-change",
@@ -2242,6 +1663,7 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2242
1663
  "navigate"
2243
1664
  ],
2244
1665
  setup(__props, { expose: __expose, emit: __emit }) {
1666
+ const LocalSandbox = defineAsyncComponent(() => import("./local-sandbox-B8IJ5jWb.js").then((n) => n.t));
2245
1667
  const props = __props;
2246
1668
  const { locale, t } = useLocale();
2247
1669
  const displayTitle = computed(() => props.title.trim());
@@ -2264,7 +1686,7 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2264
1686
  extraHeadHTML
2265
1687
  ].filter(Boolean).join("\n"),
2266
1688
  customCode: {
2267
- importCode: joinCode(DOCS_LINK_IMPORT_CODE, props.previewOptions?.customCode?.importCode, props.previewScroller ? PREVIEW_SCROLL_RESET_CODE : void 0, props.previewScroller ? PREVIEW_SCROLLER_IMPORT_CODE : void 0),
1689
+ 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),
2268
1690
  useCode: joinCode(runtimePreviewOptions.customCode?.useCode, props.previewOptions?.customCode?.useCode, props.previewScroller ? PREVIEW_SCROLLER_USE_CODE : void 0)
2269
1691
  }
2270
1692
  };
@@ -2279,20 +1701,32 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2279
1701
  "SSR": false
2280
1702
  }.MODE !== "development";
2281
1703
  const copyValue = computed(() => props.files[props.entry] || "");
2282
- const store = createRuntimeStore(props.files, props.entry, props.options);
1704
+ const store = props.local ? null : createRuntimeStore(props.files, props.entry, props.options);
2283
1705
  const sandboxRef = ref(null);
1706
+ const localError = ref({
1707
+ compile: "",
1708
+ runtime: ""
1709
+ });
1710
+ const handleLocalError = (payload) => {
1711
+ localError.value = payload;
1712
+ };
1713
+ const temporaryHeight = usePreviewHeightBridge(sandboxRef);
2284
1714
  const sandboxKey = ref(0);
2285
1715
  const runtimeHeight = useSandboxAutoHeight(sandboxRef);
2286
1716
  const runtimeError = useSandboxRuntimeErrorGuard(sandboxRef);
2287
1717
  useSandboxTheme(sandboxRef);
2288
- const compileErrorText = computed(() => (store.errors || []).map(toErrorText).filter(Boolean).join("\n"));
1718
+ const compileErrorText = computed(() => {
1719
+ if (props.local) return localError.value.compile;
1720
+ return (store?.errors || []).map(toErrorText).filter(Boolean).join("\n");
1721
+ });
2289
1722
  const errorText = computed(() => {
2290
- const runtime = runtimeError.value ? formatSandboxRuntimeError(runtimeError.value, t("playground.runtime.importMapTip")) : "";
1723
+ let runtime = "";
1724
+ if (props.local) runtime = localError.value.runtime;
1725
+ else if (runtimeError.value) runtime = formatSandboxRuntimeError(runtimeError.value, t("playground.runtime.importMapTip"));
2291
1726
  return [compileErrorText.value, runtime].filter(Boolean).join("\n\n");
2292
1727
  });
2293
1728
  const handleBridgeMessage = (event) => {
2294
- const iframe = resolveSandboxContainer(sandboxRef.value)?.querySelector("iframe");
2295
- if (!iframe || event.source !== iframe.contentWindow) return;
1729
+ if (!isSandboxMessage(sandboxRef.value, event)) return;
2296
1730
  const data = event.data;
2297
1731
  if (!data || data.action !== "docs:navigate" || typeof data.to !== "string") return;
2298
1732
  emit("navigate", data.to);
@@ -2325,27 +1759,33 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2325
1759
  }) - vertical * 2 - 2);
2326
1760
  };
2327
1761
  const syncFrozenExpandedHeight = () => {
2328
- if (!previewExpanded.value || props.expandable !== true) return;
1762
+ if (props.local || !previewExpanded.value || props.expandable !== true) return;
2329
1763
  frozenExpandedHeight.value = measureExpandedPreviewHeight();
2330
1764
  };
2331
1765
  if (typeof window !== "undefined") {
2332
1766
  window.addEventListener("message", handleBridgeMessage);
2333
1767
  window.addEventListener("resize", syncFrozenExpandedHeight);
2334
1768
  }
2335
- const canExpandPreview = computed(() => !props.styleless && isPlaygroundExpandable(props.expandable));
1769
+ const canExpandPreview = computed(() => !props.local && !props.styleless && isPlaygroundExpandable(props.expandable));
2336
1770
  const expandLabel = computed(() => t(previewExpanded.value ? "playground.runtime.collapsePreview" : "playground.runtime.expandPreview"));
2337
- const desiredViewportHeight = computed(() => {
1771
+ const baseViewportHeight = computed(() => {
1772
+ if (props.local) {
1773
+ const fixedHeight = getViewportHeight(props.viewport);
1774
+ if (fixedHeight) return fixedHeight;
1775
+ return runtimeHeight.value;
1776
+ }
2338
1777
  if (previewExpanded.value && props.expandable === true) return frozenExpandedHeight.value;
2339
1778
  if (previewExpanded.value && isPlaygroundExpandable(props.expandable)) return resolveExpandedPreviewHeight(props.expandable, 0);
2340
1779
  const fixedHeight = getViewportHeight(props.viewport);
2341
1780
  if (fixedHeight) return fixedHeight;
2342
1781
  return runtimeHeight.value;
2343
1782
  });
1783
+ const desiredViewportHeight = computed(() => Math.max(baseViewportHeight.value, temporaryHeight.value));
2344
1784
  const scrollExpandedPreviewIntoView = () => {
2345
1785
  scrollPlaygroundToViewportStart(runtimeRoot.value);
2346
1786
  };
2347
1787
  const handleTogglePreviewExpand = () => {
2348
- if (!canExpandPreview.value) return;
1788
+ if (props.local || !canExpandPreview.value) return;
2349
1789
  if (!previewExpanded.value) {
2350
1790
  if (props.expandable === true) frozenExpandedHeight.value = measureExpandedPreviewHeight();
2351
1791
  else frozenExpandedHeight.value = 0;
@@ -2385,7 +1825,7 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2385
1825
  syncedFiles = { ...files };
2386
1826
  syncedEntry = entry;
2387
1827
  const apply = () => {
2388
- switch (action.type) {
1828
+ if (store) switch (action.type) {
2389
1829
  case "update": {
2390
1830
  const file = store.files[toReplFilename(action.filename)];
2391
1831
  if (file) file.code = files[action.filename];
@@ -2407,20 +1847,28 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2407
1847
  }
2408
1848
  emit("files-change", files, entry, action);
2409
1849
  };
2410
- whenSassReady(files, apply);
1850
+ if (store) whenSassReady(files, apply);
1851
+ else apply();
2411
1852
  };
2412
1853
  const handleEditor = () => {
2413
1854
  Editor.popup({
2414
1855
  files: { ...props.files },
2415
1856
  entry: props.entry,
2416
1857
  locale: locale.value,
2417
- getCodeErrors: () => store.errors,
1858
+ getCodeErrors: () => {
1859
+ if (!props.local) return store?.errors || [];
1860
+ return localError.value.compile ? [localError.value.compile] : [];
1861
+ },
2418
1862
  onFilesChange: handleFilesChange,
2419
- onActiveChange: (filename) => store.setActive(toReplFilename(filename))
1863
+ onActiveChange: (filename) => store?.setActive(toReplFilename(filename))
2420
1864
  });
2421
1865
  };
2422
1866
  const handleInlineRefresh = () => {
2423
1867
  runtimeError.value = "";
1868
+ localError.value = {
1869
+ compile: "",
1870
+ runtime: ""
1871
+ };
2424
1872
  sandboxKey.value++;
2425
1873
  };
2426
1874
  const handleClosePopup = () => {
@@ -2428,6 +1876,11 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2428
1876
  };
2429
1877
  const handleOpenPopup = () => {
2430
1878
  Alone.popup({
1879
+ local: props.local,
1880
+ files: props.files,
1881
+ entry: props.entry,
1882
+ options: props.options,
1883
+ previewScroller: props.previewScroller,
2431
1884
  store,
2432
1885
  copyValue: copyValue.value,
2433
1886
  title: props.title,
@@ -2448,11 +1901,16 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2448
1901
  syncedFiles = { ...files };
2449
1902
  syncedEntry = props.entry;
2450
1903
  runtimeError.value = "";
2451
- store.setFiles(files, props.entry);
1904
+ localError.value = {
1905
+ compile: "",
1906
+ runtime: ""
1907
+ };
1908
+ if (store) store.setFiles(files, props.entry);
2452
1909
  }, { deep: true });
2453
1910
  watch(() => props.entry, (entry) => {
2454
1911
  if (!entry || entry === syncedEntry) return;
2455
1912
  syncedEntry = entry;
1913
+ if (!store) return;
2456
1914
  store.mainFile = toReplFilename(entry);
2457
1915
  store.setActive(toReplFilename(entry));
2458
1916
  });
@@ -2479,13 +1937,29 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2479
1937
  }, [errorText.value ? (openBlock(), createElementBlock("pre", _hoisted_2$1, toDisplayString(errorText.value), 1)) : createCommentVNode("v-if", true), createElementVNode("div", {
2480
1938
  class: "docs-playground-runtime__viewport",
2481
1939
  style: normalizeStyle(viewportStyle.value)
2482
- }, [createVNode(unref(Sandbox), {
1940
+ }, [__props.local ? (openBlock(), createBlock(unref(LocalSandbox), {
1941
+ key: 0,
1942
+ ref_key: "sandboxRef",
1943
+ ref: sandboxRef,
1944
+ files: __props.files,
1945
+ entry: __props.entry,
1946
+ options: __props.options,
1947
+ "preview-scroller": __props.previewScroller,
1948
+ "clear-console": clearConsole,
1949
+ onError: handleLocalError
1950
+ }, null, 8, [
1951
+ "files",
1952
+ "entry",
1953
+ "options",
1954
+ "preview-scroller"
1955
+ ])) : unref(store) ? (openBlock(), createBlock(unref(Sandbox), {
1956
+ key: 1,
2483
1957
  ref_key: "sandboxRef",
2484
1958
  ref: sandboxRef,
2485
1959
  store: unref(store),
2486
1960
  "auto-store-init": false,
2487
1961
  "preview-options": mergedPreviewOptions.value
2488
- }, null, 8, ["store", "preview-options"])], 4)], 4)) : (openBlock(), createElementBlock("div", {
1962
+ }, null, 8, ["store", "preview-options"])) : createCommentVNode("v-if", true)], 4)], 4)) : (openBlock(), createElementBlock("div", {
2489
1963
  key: 1,
2490
1964
  ref_key: "runtimeRoot",
2491
1965
  ref: runtimeRoot,
@@ -2523,7 +1997,22 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2523
1997
  }, [createElementVNode("div", _hoisted_8, [createElementVNode("div", {
2524
1998
  class: "docs-playground-runtime__viewport",
2525
1999
  style: normalizeStyle(viewportStyle.value)
2526
- }, [(openBlock(), createBlock(unref(Sandbox), {
2000
+ }, [__props.local ? (openBlock(), createBlock(unref(LocalSandbox), {
2001
+ key: sandboxKey.value,
2002
+ ref_key: "sandboxRef",
2003
+ ref: sandboxRef,
2004
+ files: __props.files,
2005
+ entry: __props.entry,
2006
+ options: __props.options,
2007
+ "preview-scroller": __props.previewScroller,
2008
+ "clear-console": clearConsole,
2009
+ onError: handleLocalError
2010
+ }, null, 8, [
2011
+ "files",
2012
+ "entry",
2013
+ "options",
2014
+ "preview-scroller"
2015
+ ])) : unref(store) ? (openBlock(), createBlock(unref(Sandbox), {
2527
2016
  key: sandboxKey.value,
2528
2017
  ref_key: "sandboxRef",
2529
2018
  ref: sandboxRef,
@@ -2531,7 +2020,7 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2531
2020
  "auto-store-init": false,
2532
2021
  "clear-console": clearConsole,
2533
2022
  "preview-options": mergedPreviewOptions.value
2534
- }, null, 8, ["store", "preview-options"]))], 4)]), canExpandPreview.value ? (openBlock(), createElementBlock("button", {
2023
+ }, null, 8, ["store", "preview-options"])) : createCommentVNode("v-if", true)], 4)]), canExpandPreview.value ? (openBlock(), createElementBlock("button", {
2535
2024
  key: 0,
2536
2025
  type: "button",
2537
2026
  class: normalizeClass(["docs-playground__expand", { "is-expanded": previewExpanded.value }]),
@@ -2582,6 +2071,10 @@ var playground_default = /* @__PURE__ */ defineComponent({
2582
2071
  type: Boolean,
2583
2072
  default: false
2584
2073
  },
2074
+ local: {
2075
+ type: Boolean,
2076
+ default: true
2077
+ },
2585
2078
  previewOptions: {},
2586
2079
  locale: {}
2587
2080
  },
@@ -2740,7 +2233,8 @@ var playground_default = /* @__PURE__ */ defineComponent({
2740
2233
  "preview-options": __props.previewOptions,
2741
2234
  "preview-inset": __props.previewInset,
2742
2235
  "preview-scroller": __props.previewScroller,
2743
- expandable: __props.expandable,
2236
+ local: __props.local,
2237
+ expandable: __props.local ? false : __props.expandable,
2744
2238
  styleless: true,
2745
2239
  title: __props.title,
2746
2240
  id: __props.id,
@@ -2756,6 +2250,7 @@ var playground_default = /* @__PURE__ */ defineComponent({
2756
2250
  "preview-options",
2757
2251
  "preview-inset",
2758
2252
  "preview-scroller",
2253
+ "local",
2759
2254
  "expandable",
2760
2255
  "title",
2761
2256
  "id",
@@ -2809,7 +2304,8 @@ var playground_default = /* @__PURE__ */ defineComponent({
2809
2304
  "preview-options": __props.previewOptions,
2810
2305
  "preview-inset": __props.previewInset,
2811
2306
  "preview-scroller": __props.previewScroller,
2812
- expandable: __props.expandable,
2307
+ local: __props.local,
2308
+ expandable: __props.local ? false : __props.expandable,
2813
2309
  "hide-chrome": true,
2814
2310
  title: __props.title,
2815
2311
  id: __props.id,
@@ -2827,6 +2323,7 @@ var playground_default = /* @__PURE__ */ defineComponent({
2827
2323
  "preview-options",
2828
2324
  "preview-inset",
2829
2325
  "preview-scroller",
2326
+ "local",
2830
2327
  "expandable",
2831
2328
  "title",
2832
2329
  "id",
@@ -2855,4 +2352,4 @@ var playground_default = /* @__PURE__ */ defineComponent({
2855
2352
  }
2856
2353
  });
2857
2354
  //#endregion
2858
- export { code_preview_default as CodePreview, DEFAULT_CDN_URL, Editor, PREVIEW_SCROLLER_USE_CODE, PREVIEW_SCROLL_CONTENT_CLASS, PREVIEW_SCROLL_HTML_CLASS, playground_default as Playground, applyPlaygroundImportMapOverride, applyPlaygroundStyleOverride, clearPlaygroundMaps, createBuiltinImports, createBuiltinStyles, createRuntimePreviewOptions, getPlaygroundImportMapOverrides, getPlaygroundSiteModules, getPlaygroundSiteStyles, getPlaygroundStyleOverrides, highlightCode, highlightCodeByLanguage, isSafePlaygroundHref, normalizeCdnURL, registerVueHighlight, removePlaygroundImportMapOverride, removePlaygroundStyleOverride, resolveHighlightLanguage, resolvePlaygroundTitleId, setPlaygroundImportMapOverrides, setPlaygroundSiteModules, setPlaygroundSiteStyles, setPlaygroundStyleOverrides, slugifyPlaygroundTitle, vueHighlight };
2355
+ export { code_preview_default as CodePreview, DEFAULT_CDN_URL, Editor, PREVIEW_SCROLLER_USE_CODE, PREVIEW_SCROLL_CONTENT_CLASS, PREVIEW_SCROLL_HTML_CLASS, playground_default as Playground, PlaygroundService, applyPlaygroundImportMapOverride, applyPlaygroundStyleOverride, clearPlaygroundMaps, createBuiltinImports, createBuiltinStyles, createRuntimePreviewOptions, getPlaygroundImportMapOverrides, getPlaygroundSiteModules, getPlaygroundSiteStyles, getPlaygroundStyleOverrides, highlightCode, highlightCodeByLanguage, isSafePlaygroundHref, normalizeCdnURL, registerVueHighlight, removePlaygroundImportMapOverride, removePlaygroundStyleOverride, resolveHighlightLanguage, resolvePlaygroundTitleId, setPlaygroundImportMapOverrides, setPlaygroundSiteModules, setPlaygroundSiteStyles, setPlaygroundStyleOverrides, slugifyPlaygroundTitle, vueHighlight };