@deot/docs-playground 1.1.2 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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,229 +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
- "Object.assign(next._context.provides,app._context.provides);",
873
- "next._context.mixins.push(...app._context.mixins);",
874
- "}",
875
- "window.__app__=next;",
876
- `document.documentElement.classList.add("${PREVIEW_SCROLL_HTML_CLASS}");`,
877
- "return next.mount(container,...rest)",
878
- "}",
879
- "})()"
880
- ].join("");
881
- var PREVIEW_SCROLLER_STYLE = [
882
- `html.${PREVIEW_SCROLL_HTML_CLASS},`,
883
- `html.${PREVIEW_SCROLL_HTML_CLASS} body,`,
884
- `html.${PREVIEW_SCROLL_HTML_CLASS} #app{`,
885
- "height:100%;min-height:100%;margin:0;overflow:hidden",
886
- "}",
887
- `html.${PREVIEW_SCROLL_HTML_CLASS} #app>.vc-scroller,`,
888
- `html.${PREVIEW_SCROLL_HTML_CLASS} #app>.vc-scroller>.vc-scroller__wrapper{`,
889
- "height:100%;max-height:100%;box-sizing:border-box",
890
- "}"
891
- ].join("");
892
- var resolveSandboxContainer = (sandbox) => sandbox?.container ? unref(sandbox.container) : null;
893
- var resolveScrollContent = (iframeDocument) => {
894
- if (!iframeDocument.documentElement.classList.contains("docs-playground-preview-scroll")) return null;
895
- return iframeDocument.querySelector(`.${PREVIEW_SCROLL_CONTENT_CLASS}`);
896
- };
897
- var useSandboxAutoHeight = (sandboxRef) => {
898
- const height = ref(24);
899
- let container = null;
900
- let iframe = null;
901
- let containerObserver = null;
902
- let contentObserver = null;
903
- let scrollMountObserver = null;
904
- let observedScrollNode = null;
905
- let frameId = 0;
906
- const cancelMeasure = () => {
907
- if (!frameId) return;
908
- cancelAnimationFrame(frameId);
909
- frameId = 0;
910
- };
911
- const measureDocumentContent = (iframeWindow, iframeDocument) => {
912
- const { body, documentElement } = iframeDocument;
913
- const bodyStyle = iframeWindow.getComputedStyle(body);
914
- const bodyMargins = (Number.parseFloat(bodyStyle.marginTop) || 0) + (Number.parseFloat(bodyStyle.marginBottom) || 0);
915
- const rootTop = documentElement.getBoundingClientRect().top;
916
- const bodyRect = body.getBoundingClientRect();
917
- const collapsedTop = Math.max(0, bodyRect.top - rootTop);
918
- let childrenBottom = 0;
919
- for (const child of body.children) {
920
- if (iframeWindow.getComputedStyle(child).position === "fixed") continue;
921
- const rect = child.getBoundingClientRect();
922
- const marginBottom = Number.parseFloat(iframeWindow.getComputedStyle(child).marginBottom) || 0;
923
- childrenBottom = Math.max(childrenBottom, rect.bottom + marginBottom - rootTop);
924
- }
925
- const scrollHeight = Math.max(body.scrollHeight, documentElement.scrollHeight);
926
- const overflowingHeight = scrollHeight > (iframe?.clientHeight || 0) + 1 ? scrollHeight : 0;
927
- return Math.ceil(Math.max(body.offsetHeight + bodyMargins + collapsedTop, bodyRect.height + bodyMargins + collapsedTop, childrenBottom, overflowingHeight));
928
- };
929
- const measureScrollContent = (scrollContent) => {
930
- const contentStyle = scrollContent.ownerDocument.defaultView?.getComputedStyle(scrollContent);
931
- const margins = contentStyle ? (Number.parseFloat(contentStyle.marginTop) || 0) + (Number.parseFloat(contentStyle.marginBottom) || 0) : 0;
932
- let childrenBottom = 0;
933
- const rootTop = scrollContent.getBoundingClientRect().top;
934
- for (const child of scrollContent.children) {
935
- const rect = child.getBoundingClientRect();
936
- const marginBottom = Number.parseFloat(scrollContent.ownerDocument.defaultView?.getComputedStyle(child).marginBottom || "0") || 0;
937
- childrenBottom = Math.max(childrenBottom, rect.bottom + marginBottom - rootTop);
938
- }
939
- return Math.ceil(Math.max(scrollContent.scrollHeight + margins, scrollContent.offsetHeight + margins, childrenBottom + margins));
940
- };
941
- const isPendingPreviewApp = (iframeDocument) => {
942
- const app = iframeDocument.getElementById("app");
943
- return app ? app.childElementCount === 0 : !!iframe?.srcdoc;
944
- };
945
- const releaseBootstrapHeight = (target) => {
946
- nextTick(() => {
947
- if (iframe === target) target.style.height = "100%";
948
- });
949
- };
950
- const measure = () => {
951
- frameId = 0;
952
- if (!iframe) return;
953
- try {
954
- const iframeWindow = iframe.contentWindow;
955
- const iframeDocument = iframe.contentDocument;
956
- if (!iframeWindow || !iframeDocument?.body) return;
957
- const scrollContent = resolveScrollContent(iframeDocument);
958
- if (!scrollContent && isPendingPreviewApp(iframeDocument)) return;
959
- const contentHeight = scrollContent ? measureScrollContent(scrollContent) : measureDocumentContent(iframeWindow, iframeDocument);
960
- const nextHeight = Math.max(contentHeight, 24);
961
- if (height.value !== nextHeight) height.value = nextHeight;
962
- releaseBootstrapHeight(iframe);
963
- } catch {
964
- if (height.value !== 24) height.value = 24;
965
- }
966
- };
967
- const scheduleMeasure = () => {
968
- if (frameId) return;
969
- frameId = requestAnimationFrame(measure);
970
- };
971
- const disconnectContent = () => {
972
- contentObserver?.disconnect();
973
- contentObserver = null;
974
- scrollMountObserver?.disconnect();
975
- scrollMountObserver = null;
976
- observedScrollNode = null;
977
- cancelMeasure();
978
- };
979
- const observeContent = () => {
980
- disconnectContent();
981
- if (!iframe) return;
982
- try {
983
- const iframeWindow = iframe.contentWindow;
984
- const iframeDocument = iframe.contentDocument;
985
- const Observer = iframeWindow?.ResizeObserver;
986
- if (!iframeWindow || !iframeDocument?.body || !Observer) {
987
- scheduleMeasure();
988
- return;
989
- }
990
- const observer = new Observer(scheduleMeasure);
991
- observer.observe(iframeDocument.documentElement);
992
- observer.observe(iframeDocument.body);
993
- contentObserver = observer;
994
- const attachScrollContent = (node) => {
995
- if (!node || !contentObserver) return false;
996
- if (observedScrollNode === node) return true;
997
- if (observedScrollNode) contentObserver.unobserve(observedScrollNode);
998
- observedScrollNode = node;
999
- contentObserver.observe(node);
1000
- return true;
1001
- };
1002
- const syncScrollContent = () => {
1003
- attachScrollContent(resolveScrollContent(iframeDocument));
1004
- scheduleMeasure();
1005
- };
1006
- scrollMountObserver = new MutationObserver(syncScrollContent);
1007
- scrollMountObserver.observe(iframeDocument.documentElement, {
1008
- attributes: true,
1009
- attributeFilter: ["class"]
1010
- });
1011
- scrollMountObserver.observe(iframeDocument.body, {
1012
- childList: true,
1013
- subtree: true
1014
- });
1015
- syncScrollContent();
1016
- } catch {
1017
- if (height.value !== 24) height.value = 24;
1018
- }
1019
- };
1020
- const handleIframeLoad = () => observeContent();
1021
- const setIframe = (nextIframe) => {
1022
- if (iframe === nextIframe) return;
1023
- iframe?.removeEventListener("load", handleIframeLoad);
1024
- disconnectContent();
1025
- iframe = nextIframe;
1026
- if (!iframe) {
1027
- height.value = 24;
1028
- return;
1029
- }
1030
- iframe.addEventListener("load", handleIframeLoad);
1031
- iframe.style.height = `${Math.max(window.innerHeight, 24)}px`;
1032
- observeContent();
1033
- };
1034
- const syncIframe = () => setIframe(container?.querySelector("iframe") || null);
1035
- const setContainer = (nextContainer) => {
1036
- if (container === nextContainer) return;
1037
- containerObserver?.disconnect();
1038
- containerObserver = null;
1039
- container = nextContainer;
1040
- setIframe(null);
1041
- if (!container) return;
1042
- containerObserver = new MutationObserver(syncIframe);
1043
- containerObserver.observe(container, {
1044
- childList: true,
1045
- subtree: true
1046
- });
1047
- syncIframe();
1048
- };
1049
- watch(() => resolveSandboxContainer(sandboxRef.value), setContainer, {
1050
- flush: "post",
1051
- immediate: true
1052
- });
1053
- onBeforeUnmount(() => {
1054
- setContainer(null);
1055
- cancelMeasure();
1056
- });
1057
- return height;
1058
- };
1059
833
  var resolvePreviewBoxHeight = (contentHeight, verticalInset = 0, borderWidth = 1) => {
1060
834
  const content = Number.isFinite(contentHeight) ? Math.max(0, contentHeight) : 0;
1061
835
  const inset = Number.isFinite(verticalInset) ? Math.max(0, verticalInset) : 0;
@@ -1134,68 +908,6 @@ var scrollPlaygroundToViewportStart = (el) => {
1134
908
  });
1135
909
  };
1136
910
  //#endregion
1137
- //#region packages/playground/src/core/runtime/error-guard.ts
1138
- var UNKNOWN_RUNTIME_ERROR = "运行时发生未知错误";
1139
- var MODULE_SPECIFIER_RE = /Failed to resolve module specifier|Error resolving module specifier/u;
1140
- var forwardSandboxRuntimeError = (event) => {
1141
- if (!(event instanceof ErrorEvent) || event.error != null || !event.message) return;
1142
- event.stopImmediatePropagation();
1143
- if (event.message === "ResizeObserver loop limit exceeded" || event.message === "ResizeObserver loop completed with undelivered notifications.") return;
1144
- window.parent.postMessage({
1145
- action: "error",
1146
- value: event.message
1147
- }, "*");
1148
- };
1149
- var SANDBOX_RUNTIME_ERROR_CAPTURE_HTML = [
1150
- "<script>",
1151
- `window.addEventListener('error', ${forwardSandboxRuntimeError.toString()}, true);`,
1152
- "<\/script>"
1153
- ].join("\n");
1154
- var toRuntimeErrorMessage = (value, message) => {
1155
- if (typeof value === "string" && value) return value;
1156
- if (value instanceof Error && value.message) return value.message;
1157
- if (value && typeof value === "object" && "message" in value) {
1158
- const valueMessage = value.message;
1159
- if (typeof valueMessage === "string" && valueMessage) return valueMessage;
1160
- }
1161
- if (typeof message === "string" && message) return message;
1162
- if (value !== null && value !== void 0) try {
1163
- return String(value);
1164
- } catch {
1165
- return UNKNOWN_RUNTIME_ERROR;
1166
- }
1167
- return UNKNOWN_RUNTIME_ERROR;
1168
- };
1169
- var normalizeRuntimeErrorMessage = (data) => {
1170
- if (!data || typeof data !== "object") return false;
1171
- const message = data;
1172
- if (message.action !== "error") return false;
1173
- message.value = toRuntimeErrorMessage(message.value, message.message);
1174
- return true;
1175
- };
1176
- var toErrorText = (value) => {
1177
- if (typeof value === "string" && value) return value;
1178
- if (value instanceof Error && value.message) return value.message;
1179
- return "";
1180
- };
1181
- var formatSandboxRuntimeError = (message, importMapTip) => {
1182
- if (!MODULE_SPECIFIER_RE.test(message)) return message;
1183
- return `${message.replace(/\. Relative references must.*$/u, "").replace(/\.$/u, "")}.\n${importMapTip}`;
1184
- };
1185
- var useSandboxRuntimeErrorGuard = (sandboxRef) => {
1186
- const error = ref("");
1187
- if (typeof window === "undefined") return error;
1188
- const handleMessage = (event) => {
1189
- const iframe = resolveSandboxContainer(sandboxRef.value)?.querySelector("iframe");
1190
- if (!iframe || event.source !== iframe.contentWindow) return;
1191
- if (!normalizeRuntimeErrorMessage(event.data)) return;
1192
- error.value = event.data.value;
1193
- };
1194
- window.addEventListener("message", handleMessage, true);
1195
- onBeforeUnmount(() => window.removeEventListener("message", handleMessage, true));
1196
- return error;
1197
- };
1198
- //#endregion
1199
911
  //#region packages/playground/src/core/runtime/viewport.ts
1200
912
  var DEFAULT_VIEWPORT_OPTIONS = ["auto", 375];
1201
913
  var isValidViewport = (viewport) => {
@@ -1401,16 +1113,16 @@ function usePreviewHeightBridge(sandbox, maxHeight = () => Infinity) {
1401
1113
  sync();
1402
1114
  };
1403
1115
  const handleMessage = async (event) => {
1404
- const iframe = resolveSandboxContainer(sandbox.value)?.querySelector("iframe");
1116
+ const current = resolveSandboxMessageSource(sandbox.value);
1405
1117
  const data = event.data;
1406
- if (!iframe?.contentWindow || event.source !== iframe.contentWindow || data?.action !== "docs:height" || typeof data.session !== "string") return;
1118
+ if (!current || event.source !== current || data?.action !== "docs:height" || typeof data.session !== "string") return;
1407
1119
  if (data.operation === "start") {
1408
1120
  reset();
1409
- source = iframe.contentWindow;
1121
+ source = current;
1410
1122
  session = data.session;
1411
1123
  return;
1412
1124
  }
1413
- if (source !== iframe.contentWindow || session !== data.session) return;
1125
+ if (source !== current || session !== data.session) return;
1414
1126
  if (data.operation === "stop") {
1415
1127
  reset();
1416
1128
  return;
@@ -1435,7 +1147,7 @@ function usePreviewHeightBridge(sandbox, maxHeight = () => Infinity) {
1435
1147
  accepted
1436
1148
  }, "*");
1437
1149
  };
1438
- watch(() => resolveSandboxContainer(sandbox.value), reset, { flush: "sync" });
1150
+ watch(() => resolveSandboxMessageSource(sandbox.value), reset, { flush: "sync" });
1439
1151
  if (typeof window !== "undefined") window.addEventListener("message", handleMessage);
1440
1152
  onBeforeUnmount(() => {
1441
1153
  disposed = true;
@@ -1661,647 +1373,6 @@ var toolbar_default = /* @__PURE__ */ defineComponent({
1661
1373
  }
1662
1374
  });
1663
1375
  //#endregion
1664
- //#region packages/playground/src/cdn.ts
1665
- var PREVIEW_STYLE_ASSETS = [
1666
- "@deot/style/dist/index.normalize-only.css",
1667
- "@deot/vc-components/dist/index.style.css",
1668
- "@deot/style/dist/index.css"
1669
- ];
1670
- var BUILTIN_IMPORT_ASSETS = {
1671
- "@deot/vc": "@deot/vc/dist/index.js",
1672
- "@deot/vc-shared": "@deot/vc-shared/dist/index.js",
1673
- "@deot/vc-hooks": "@deot/vc-hooks/dist/index.js",
1674
- "@deot/vc-components": "@deot/vc-components/dist/index.js",
1675
- "@deot/helper-resize": "@deot/helper-resize/dist/index.js",
1676
- "@deot/helper-utils": "@deot/helper-utils/dist/index.js",
1677
- "@deot/helper-cache": "@deot/helper-cache/dist/index.js",
1678
- "@deot/helper-fp": "@deot/helper-fp/dist/index.js",
1679
- "@deot/helper-dom": "@deot/helper-dom/dist/index.js",
1680
- "@deot/helper-wheel": "@deot/helper-wheel/dist/index.js",
1681
- "@deot/helper-validator": "@deot/helper-validator/dist/index.js",
1682
- "@deot/helper-load": "@deot/helper-load/dist/index.js",
1683
- "@deot/helper-scheduler": "@deot/helper-scheduler/dist/index.js",
1684
- "@deot/helper-emitter": "@deot/helper-emitter/dist/index.js",
1685
- "@deot/helper-is": "@deot/helper-is/dist/index.js",
1686
- "@deot/helper-device": "@deot/helper-device/dist/index.js",
1687
- "@deot/helper-route": "@deot/helper-route/dist/index.js",
1688
- "@deot/helper-unicode": "@deot/helper-unicode/dist/index.js",
1689
- "@deot/helper": "@deot/helper/dist/index.js",
1690
- "normalize-wheel": "normalize-wheel-es/dist/index.mjs",
1691
- "photoswipe": "photoswipe/dist/photoswipe.esm.js",
1692
- "photoswipe/lightbox": "photoswipe/dist/photoswipe-lightbox.esm.js",
1693
- "vue": "vue/dist/vue.runtime.esm-browser.js",
1694
- "vue/server-renderer": "vue/dist/server-renderer.esm-browser.js"
1695
- };
1696
- var normalizeCdnURL = (cdnURL = DEFAULT_CDN_URL) => {
1697
- return cdnURL.trim().replace(/\/+$/u, "") || "https://cdn.jsdelivr.net/npm";
1698
- };
1699
- var cdnJoin = (origin, asset) => `${origin}/${asset.replace(/^\/+/u, "")}`;
1700
- var jsdelivrEsmURL = (asset) => cdnJoin(DEFAULT_CDN_URL, asset);
1701
- var SASS_CDN_URL = jsdelivrEsmURL("sass/+esm");
1702
- var cdnAsset = (cdnURL, asset) => cdnJoin(normalizeCdnURL(cdnURL), asset);
1703
- var createBuiltinImports = (cdnURL = DEFAULT_CDN_URL) => ({
1704
- ...Object.fromEntries(Object.entries(BUILTIN_IMPORT_ASSETS).map(([specifier, asset]) => [specifier, cdnAsset(cdnURL, asset)])),
1705
- "lodash-es": jsdelivrEsmURL("lodash-es/+esm")
1706
- });
1707
- var createBuiltinStyles = (cdnURL = DEFAULT_CDN_URL) => Object.fromEntries(PREVIEW_STYLE_ASSETS.map((asset) => [asset, cdnAsset(cdnURL, asset)]));
1708
- //#endregion
1709
- //#region packages/playground/src/import-map.ts
1710
- /**
1711
- * 站点级同步内存:`$docs.modules` / `$docs.styles` 与管理页 import、CSS 覆盖。
1712
- */
1713
- var normalize = (value) => value.trim();
1714
- var isSafePlaygroundHref = (href) => {
1715
- const next = href.trim();
1716
- if (!next) return false;
1717
- if (/^https?:\/\//iu.test(next)) return true;
1718
- return next.startsWith("/") && !next.startsWith("//");
1719
- };
1720
- var filterSafeHrefs = (value = {}) => Object.fromEntries(Object.entries(value).filter((entry) => typeof entry[1] === "string" && isSafePlaygroundHref(entry[1])));
1721
- var sanitizeMap = (value = {}) => filterSafeHrefs(Object.fromEntries(Object.entries(value).map(([alias, url]) => [normalize(alias), normalize(url)]).filter(([alias]) => Boolean(alias))));
1722
- var createMapStore = () => {
1723
- let data = {};
1724
- const snapshot = () => ({ ...data });
1725
- const drop = (alias) => {
1726
- if (data[alias] === void 0) return snapshot();
1727
- const next = { ...data };
1728
- delete next[alias];
1729
- data = next;
1730
- return snapshot();
1731
- };
1732
- return {
1733
- get: snapshot,
1734
- set: (value = {}) => {
1735
- data = sanitizeMap(value);
1736
- },
1737
- apply: (alias, url) => {
1738
- const nextAlias = normalize(alias);
1739
- const nextUrl = normalize(url);
1740
- if (!nextAlias) return snapshot();
1741
- if (!isSafePlaygroundHref(nextUrl)) return drop(nextAlias);
1742
- data = {
1743
- ...data,
1744
- [nextAlias]: nextUrl
1745
- };
1746
- return snapshot();
1747
- },
1748
- remove: (alias) => {
1749
- const nextAlias = normalize(alias);
1750
- return nextAlias ? drop(nextAlias) : snapshot();
1751
- }
1752
- };
1753
- };
1754
- var siteModules = createMapStore();
1755
- var siteStyles = createMapStore();
1756
- var importOverrides = createMapStore();
1757
- var styleOverrides = createMapStore();
1758
- /**
1759
- * 站点默认 import。合并时夹在内置 CDN 与实例 `builtinImportMap` 之间。
1760
- */
1761
- var getPlaygroundSiteModules = siteModules.get;
1762
- var setPlaygroundSiteModules = siteModules.set;
1763
- /**
1764
- * 站点默认预览 CSS。合并时夹在内置样式表与管理页覆盖之间。
1765
- */
1766
- var getPlaygroundSiteStyles = siteStyles.get;
1767
- var setPlaygroundSiteStyles = siteStyles.set;
1768
- var getPlaygroundImportMapOverrides = importOverrides.get;
1769
- var setPlaygroundImportMapOverrides = importOverrides.set;
1770
- var applyPlaygroundImportMapOverride = importOverrides.apply;
1771
- var removePlaygroundImportMapOverride = importOverrides.remove;
1772
- var getPlaygroundStyleOverrides = styleOverrides.get;
1773
- var setPlaygroundStyleOverrides = styleOverrides.set;
1774
- var applyPlaygroundStyleOverride = styleOverrides.apply;
1775
- var removePlaygroundStyleOverride = styleOverrides.remove;
1776
- var clearPlaygroundMaps = () => {
1777
- [
1778
- siteModules,
1779
- siteStyles,
1780
- importOverrides,
1781
- styleOverrides
1782
- ].forEach((store) => store.set());
1783
- };
1784
- //#endregion
1785
- //#region packages/playground/src/preview-service.ts
1786
- /** Preview iframe 内的高度服务;class 会被序列化到 iframe 执行。 */
1787
- var PlaygroundService = class {
1788
- target;
1789
- vue;
1790
- session;
1791
- /* istanbul ignore next -- class 会被序列化到没有覆盖率运行时的 iframe。 */
1792
- sequence = 0;
1793
- /* istanbul ignore next -- class 会被序列化到没有覆盖率运行时的 iframe。 */
1794
- disposed = false;
1795
- manual;
1796
- /* istanbul ignore next -- class 会被序列化到没有覆盖率运行时的 iframe。 */
1797
- requests = /* @__PURE__ */ new Set();
1798
- /* istanbul ignore next -- class 会被序列化到没有覆盖率运行时的 iframe。 */
1799
- owners = /* @__PURE__ */ new Set();
1800
- /**
1801
- * @param target 当前预览窗口。
1802
- * @param vue 与预览应用共用的 Vue 实例。
1803
- */
1804
- /* istanbul ignore next -- class 会被序列化到没有覆盖率运行时的 iframe。 */
1805
- constructor(target, vue) {
1806
- this.target = target;
1807
- this.vue = vue;
1808
- this.session = `${Date.now()}-${Math.random()}`;
1809
- this.dispose = this.dispose.bind(this);
1810
- this.post("start");
1811
- this.target.addEventListener("pagehide", this.dispose);
1812
- }
1813
- /**
1814
- * 申请手动临时高度;新请求会替换上一个手动请求。
1815
- * @param height iframe 最小高度。
1816
- * @returns iframe 是否在超时前应用目标高度。
1817
- */
1818
- enable(height) {
1819
- this.validateHeight(height);
1820
- this.manual?.release();
1821
- this.manual = this.createRequest(height);
1822
- return this.manual.ready;
1823
- }
1824
- /** 释放手动临时高度,不影响 `run` 创建的请求。 */
1825
- disable() {
1826
- this.manual?.release();
1827
- this.manual = void 0;
1828
- }
1829
- /**
1830
- * 创建等待高度后执行的事件处理函数。
1831
- * @param height iframe 最小高度。
1832
- * @param optionsOrHandler 可见状态配置,或最后一个 handler。
1833
- * @param lastHandler 使用配置时的最后一个 handler。
1834
- * @returns 保留 handler 参数和结果的异步事件处理函数。
1835
- */
1836
- run(height, optionsOrHandler, lastHandler) {
1837
- this.validateHeight(height);
1838
- if (optionsOrHandler === void 0) return (visible) => {
1839
- if (visible) return this.enable(height);
1840
- this.disable();
1841
- return Promise.resolve(void 0);
1842
- };
1843
- const visible = (typeof optionsOrHandler === "function" ? {} : optionsOrHandler).visible;
1844
- if (visible !== void 0 && !this.vue.isRef(visible) && typeof visible !== "function") throw new TypeError("Playground visible must be a ref or getter");
1845
- const handler = typeof optionsOrHandler === "function" ? optionsOrHandler : lastHandler ?? (this.vue.isRef(visible) ? () => {
1846
- visible.value = true;
1847
- } : void 0);
1848
- if (typeof handler !== "function") throw new TypeError("Playground run requires a handler");
1849
- let ownerDisposed = false;
1850
- let current;
1851
- let pending;
1852
- const disposeOwner = () => {
1853
- ownerDisposed = true;
1854
- current?.release();
1855
- this.owners.delete(disposeOwner);
1856
- };
1857
- this.owners.add(disposeOwner);
1858
- if (this.vue.getCurrentScope()) this.vue.onScopeDispose(disposeOwner);
1859
- return (...args) => {
1860
- if (this.disposed || ownerDisposed) return Promise.resolve(void 0);
1861
- if (pending) return pending;
1862
- const request = current = this.createRequest(height);
1863
- let executionFinished = false;
1864
- const unlock = () => {
1865
- if (executionFinished && request.released && current === request) {
1866
- pending = void 0;
1867
- current = void 0;
1868
- }
1869
- };
1870
- request.closed.then(unlock);
1871
- const execution = (async () => {
1872
- try {
1873
- if (!await request.ready || ownerDisposed || this.disposed) return void 0;
1874
- if (visible) request.watch(visible);
1875
- const result = await handler(...args);
1876
- if (!visible || !this.vue.toValue(visible)) request.release();
1877
- return result;
1878
- } catch (error) {
1879
- request.release();
1880
- throw error;
1881
- } finally {
1882
- executionFinished = true;
1883
- unlock();
1884
- }
1885
- })();
1886
- pending = execution;
1887
- return execution;
1888
- };
1889
- }
1890
- /** 释放当前预览应用持有的全部高度和监听。 */
1891
- /* istanbul ignore next -- 注入测试会从序列化后的 iframe class 调用该方法。 */
1892
- dispose() {
1893
- if (this.disposed) return;
1894
- this.disposed = true;
1895
- for (const disposeOwner of this.owners) disposeOwner();
1896
- for (const request of this.requests) request.release();
1897
- this.post("stop");
1898
- this.target.removeEventListener("pagehide", this.dispose);
1899
- if (this.target.$docsPlayground === this) delete this.target.$docsPlayground;
1900
- }
1901
- /** @param height iframe 最小高度。 */
1902
- validateHeight(height) {
1903
- if (!Number.isFinite(height) || height <= 0) throw new TypeError("Playground height must be a positive finite number");
1904
- }
1905
- /**
1906
- * @param operation 请求操作。
1907
- * @param id 请求标识。
1908
- * @param height iframe 最小高度。
1909
- */
1910
- /* istanbul ignore next -- 构造和销毁时会从序列化后的 iframe class 调用该方法。 */
1911
- post(operation, id = 0, height = 0) {
1912
- this.target.parent.postMessage({
1913
- action: "docs:height",
1914
- session: this.session,
1915
- operation,
1916
- id,
1917
- height
1918
- }, "*");
1919
- }
1920
- /**
1921
- * @param height iframe 最小高度。
1922
- * @returns 内部等待与释放句柄。
1923
- */
1924
- createRequest(height) {
1925
- this.validateHeight(height);
1926
- const id = ++this.sequence;
1927
- let released = false;
1928
- let settled = false;
1929
- let frame = 0;
1930
- let timer = 0;
1931
- let stopWatch;
1932
- let resolveReady;
1933
- let resolveClosed;
1934
- const ready = new Promise((resolve) => {
1935
- resolveReady = resolve;
1936
- });
1937
- const closed = new Promise((resolve) => {
1938
- resolveClosed = resolve;
1939
- });
1940
- const stopWaiting = () => {
1941
- this.target.cancelAnimationFrame(frame);
1942
- if (timer) {
1943
- this.target.clearTimeout(timer);
1944
- timer = 0;
1945
- }
1946
- this.target.removeEventListener("message", onMessage);
1947
- };
1948
- const release = () => {
1949
- if (released) return;
1950
- released = true;
1951
- stopWaiting();
1952
- stopWatch?.();
1953
- resolveReady(false);
1954
- resolveClosed();
1955
- this.requests.delete(request);
1956
- this.post("release", id);
1957
- };
1958
- const check = () => {
1959
- if (released) return;
1960
- if (this.target.innerHeight >= height) {
1961
- settled = true;
1962
- stopWaiting();
1963
- resolveReady(true);
1964
- } else frame = this.target.requestAnimationFrame(check);
1965
- };
1966
- const onMessage = (event) => {
1967
- const data = event.data;
1968
- if (event.source !== this.target.parent || data?.action !== "docs:height:applied" || data.session !== this.session || data.id !== id || settled) return;
1969
- if (!data.accepted) release();
1970
- else check();
1971
- };
1972
- const request = {
1973
- ready,
1974
- closed,
1975
- get released() {
1976
- return released;
1977
- },
1978
- release,
1979
- watch: (visible) => {
1980
- stopWatch = this.vue.watch(() => this.vue.toValue(visible), (value) => {
1981
- if (!value) release();
1982
- }, { flush: "sync" });
1983
- }
1984
- };
1985
- this.requests.add(request);
1986
- if (this.disposed) release();
1987
- else {
1988
- this.target.addEventListener("message", onMessage);
1989
- timer = this.target.setTimeout(() => {
1990
- timer = 0;
1991
- release();
1992
- }, 2e3);
1993
- this.post("enable", id, height);
1994
- }
1995
- return request;
1996
- }
1997
- };
1998
- var PREVIEW_SERVICE_IMPORT_CODE = "import * as __docsPreviewVue from \"vue\"";
1999
- var PREVIEW_SERVICE_USE_CODE = [
2000
- `;const __docsPlayground=new (${PlaygroundService.toString()})(window,__docsPreviewVue);`,
2001
- "app.provide(\"docs:playground\",__docsPlayground);",
2002
- "window.$docsPlayground=__docsPlayground;",
2003
- "app.mixin({beforeUnmount(){if(this===this.$root)__docsPlayground.dispose()}});"
2004
- ].join("");
2005
- //#endregion
2006
- //#region packages/playground/src/core/scss.ts
2007
- var SCHEME = "docs-playground";
2008
- var STYLE_EXTS = [".scss", ".sass"];
2009
- var VUE_SCSS_STYLE_RE = /<style\b[^>]*\blang\s*=\s*(['"]?)s[ac]ss\1/i;
2010
- var LANG_ATTR_RE = /\s*lang\s*=\s*(['"]?)s[ac]ss\1/i;
2011
- var SCSS_ERROR_MARK = "[playground-sass]";
2012
- var INJECT_START = "/* docs-playground-scss-start */";
2013
- var INJECT_END = "/* docs-playground-scss-end */";
2014
- var EMPTY_JS = "export default {}\n";
2015
- var boundStores = /* @__PURE__ */ new WeakSet();
2016
- var wrappedCompilers = /* @__PURE__ */ new WeakSet();
2017
- var testLoader;
2018
- var loadedSass;
2019
- var loadPromise;
2020
- var fileCode = (value) => typeof value === "string" ? value : value.code;
2021
- var playgroundPath = (url) => decodeURIComponent(url.pathname.replace(/^\/+/u, ""));
2022
- var toPlaygroundUrl = (filename) => new URL(`${SCHEME}:///${filename.replace(/^\/+/u, "")}`);
2023
- var basename = (path) => path.split("/").pop() || path;
2024
- var scssSyntax = (filename, lang) => lang === "sass" || /\.sass$/i.test(filename) ? "indented" : "scss";
2025
- var errorText = (item) => item instanceof Error ? item.message : String(item);
2026
- var isScssFile = (filename) => /\.s[ac]ss$/i.test(filename);
2027
- var vueSourceNeedsScss = (source) => VUE_SCSS_STYLE_RE.test(source);
2028
- var resolveSassModule = async (url) => {
2029
- const mod = await import(
2030
- /* @vite-ignore */
2031
- url
2032
- );
2033
- const sass = typeof mod.compileString === "function" ? mod : mod.default;
2034
- if (typeof sass?.compileString !== "function") throw new Error(`Sass module at ${url} does not export compileString`);
2035
- return sass;
2036
- };
2037
- var loadSass = () => {
2038
- loadPromise ??= (testLoader ?? (() => resolveSassModule(SASS_CDN_URL)))().then((sass) => {
2039
- loadedSass = sass;
2040
- return sass;
2041
- });
2042
- return loadPromise;
2043
- };
2044
- var isScssPartial = (filename) => isScssFile(filename) && basename(filename).startsWith("_");
2045
- var filesNeedScss = (files) => Object.entries(files).some(([filename, value]) => isScssFile(filename) || /\.vue$/i.test(filename) && vueSourceNeedsScss(fileCode(value)));
2046
- var whenSassReady = (files, run) => {
2047
- if (!filesNeedScss(files) || loadedSass) run();
2048
- else loadSass().then(run);
2049
- };
2050
- var toPlaygroundFileMap = (files) => Object.fromEntries(Object.entries(files).map(([filename, value]) => [filename, fileCode(value)]));
2051
- var formatScssError = (filename, message) => `${SCSS_ERROR_MARK} ${filename}: ${message}`;
2052
- var scssFail = (filename, error) => formatScssError(filename, errorText(error));
2053
- var withUnderscore = (path) => {
2054
- const base = basename(path);
2055
- if (base.startsWith("_")) return path;
2056
- return `${path.slice(0, -base.length)}_${base}`;
2057
- };
2058
- var matchFileKey = (files, path) => [
2059
- path,
2060
- path.startsWith("src/") ? path : `src/${path}`,
2061
- path.replace(/^src\//u, "")
2062
- ].find((key) => files[key] !== void 0);
2063
- var stylesheetCandidates = (requestPath) => {
2064
- if (isScssFile(requestPath)) return [requestPath, withUnderscore(requestPath)];
2065
- return STYLE_EXTS.flatMap((ext) => [
2066
- `${requestPath}${ext}`,
2067
- withUnderscore(`${requestPath}${ext}`),
2068
- `${requestPath}/index${ext}`,
2069
- withUnderscore(`${requestPath}/index${ext}`)
2070
- ]);
2071
- };
2072
- var resolvePlaygroundStylesheet = (files, requestPath) => {
2073
- const found = [...new Set(stylesheetCandidates(requestPath).map((path) => matchFileKey(files, path)).filter((key) => Boolean(key)))];
2074
- if (found.length > 1) throw new Error(`Ambiguous Sass import "${requestPath}": ${found.join(", ")}`);
2075
- return found[0] ?? null;
2076
- };
2077
- var createPlaygroundImporter = (getFiles) => ({
2078
- canonicalize(url, context) {
2079
- if (/^[a-zA-Z][\w+.-]*:/u.test(url) && !url.startsWith(`${SCHEME}:`)) return null;
2080
- try {
2081
- const resolved = resolvePlaygroundStylesheet(getFiles(), playgroundPath(new URL(url, context.containingUrl ?? toPlaygroundUrl(""))));
2082
- return resolved ? toPlaygroundUrl(resolved) : null;
2083
- } catch {
2084
- return null;
2085
- }
2086
- },
2087
- load(canonicalUrl) {
2088
- const files = getFiles();
2089
- const key = playgroundPath(canonicalUrl);
2090
- return files[key] === void 0 ? null : {
2091
- contents: files[key],
2092
- syntax: scssSyntax(key)
2093
- };
2094
- }
2095
- });
2096
- var compileScssSource = (source, filename, sass, files, lang) => {
2097
- const importer = createPlaygroundImporter(() => files);
2098
- return sass.compileString(source, {
2099
- syntax: scssSyntax(filename, lang),
2100
- url: toPlaygroundUrl(filename),
2101
- importer,
2102
- importers: [importer]
2103
- }).css;
2104
- };
2105
- var rewriteVueSfcStyles = (source, filename, parse, sass, files) => {
2106
- const scssStyles = parse(source, { filename }).descriptor.styles.filter((style) => style.lang === "scss" || style.lang === "sass");
2107
- if (!scssStyles.length) return {
2108
- code: source,
2109
- errors: []
2110
- };
2111
- const errors = [];
2112
- let code = source;
2113
- for (const style of [...scssStyles].sort((left, right) => right.loc.start.offset - left.loc.start.offset)) {
2114
- const before = code.slice(0, style.loc.start.offset);
2115
- const after = code.slice(style.loc.end.offset);
2116
- const openStart = before.lastIndexOf("<style");
2117
- if (openStart < 0) {
2118
- errors.push(formatScssError(filename, "unable to locate <style> opening tag"));
2119
- continue;
2120
- }
2121
- try {
2122
- const css = compileScssSource(style.content, filename, sass, files, style.lang);
2123
- code = `${before.slice(0, openStart)}${before.slice(openStart).replace(LANG_ATTR_RE, "")}${css}${after}`;
2124
- } catch (error) {
2125
- errors.push(scssFail(filename, error));
2126
- }
2127
- }
2128
- return {
2129
- code,
2130
- errors
2131
- };
2132
- };
2133
- var appendParseErrors = (result, errors) => errors.length ? {
2134
- ...result,
2135
- errors: [...result.errors, ...errors.map((item) => new Error(item))]
2136
- } : result;
2137
- var wrapCompiler = (compiler, getFiles) => {
2138
- if (wrappedCompilers.has(compiler)) return compiler;
2139
- const originalParse = compiler.parse.bind(compiler);
2140
- const wrapped = { ...compiler };
2141
- wrapped.parse = ((source, options) => {
2142
- const filename = options?.filename || "anonymous.vue";
2143
- if (!vueSourceNeedsScss(source)) return originalParse(source, options);
2144
- const rewritten = loadedSass ? rewriteVueSfcStyles(source, filename, originalParse, loadedSass, getFiles()) : {
2145
- code: source,
2146
- errors: [formatScssError(filename, "compiler is not loaded")]
2147
- };
2148
- return appendParseErrors(originalParse(rewritten.errors.length ? source : rewritten.code, options), rewritten.errors);
2149
- });
2150
- wrappedCompilers.add(wrapped);
2151
- return wrapped;
2152
- };
2153
- var withInjectedCss = (css, extra) => {
2154
- const start = css.indexOf(INJECT_START);
2155
- const end = start < 0 ? -1 : css.indexOf(INJECT_END, start);
2156
- const base = (start < 0 ? css : `${css.slice(0, start)}${end >= 0 ? css.slice(end + 30) : ""}`).trimEnd();
2157
- if (!extra.trim()) return base;
2158
- const block = `${INJECT_START}\n${extra.trim()}\n${INJECT_END}`;
2159
- return base ? `${base}\n${block}` : block;
2160
- };
2161
- var isStandaloneScssError = (item) => {
2162
- const text = errorText(item);
2163
- return text.startsWith(SCSS_ERROR_MARK) && /\.s[ac]ss:/i.test(text);
2164
- };
2165
- var syncScssErrors = (store, scssErrors) => {
2166
- const next = [...scssErrors, ...store.errors.filter((item) => !isStandaloneScssError(item))];
2167
- if (next.map(String).join("\0") === store.errors.map(String).join("\0")) return;
2168
- store.errors = next;
2169
- };
2170
- var applyStandaloneScss = (store, sass = loadedSass) => {
2171
- if (!sass) return [];
2172
- const fileMap = toPlaygroundFileMap(store.files);
2173
- const errors = [];
2174
- const injected = [];
2175
- for (const [filename, file] of Object.entries(store.files)) {
2176
- if (!isScssFile(filename) || !file.compiled) continue;
2177
- try {
2178
- const css = compileScssSource(file.code, filename, sass, fileMap);
2179
- file.compiled.css = css;
2180
- file.compiled.js = EMPTY_JS;
2181
- file.compiled.ssr = EMPTY_JS;
2182
- if (!isScssPartial(filename) && css.trim()) injected.push(css);
2183
- } catch (error) {
2184
- errors.push(scssFail(filename, error));
2185
- }
2186
- }
2187
- const main = store.files[store.mainFile];
2188
- if (main?.compiled) {
2189
- const next = withInjectedCss(main.compiled.css || "", injected.join("\n"));
2190
- if (next !== (main.compiled.css || "")) main.compiled.css = next;
2191
- }
2192
- syncScssErrors(store, errors);
2193
- return errors;
2194
- };
2195
- var bindPlaygroundScss = (store) => {
2196
- if (boundStores.has(store)) return;
2197
- boundStores.add(store);
2198
- const getFiles = () => toPlaygroundFileMap(store.files);
2199
- const installCompiler = () => {
2200
- if (typeof store.compiler?.parse === "function") store.compiler = wrapCompiler(store.compiler, getFiles);
2201
- };
2202
- installCompiler();
2203
- watch(() => store.compiler, installCompiler);
2204
- watch(() => [
2205
- store.mainFile,
2206
- store.files[store.mainFile]?.compiled?.css,
2207
- store.errors.map(String).join("\0"),
2208
- Object.entries(store.files).filter(([filename]) => isScssFile(filename)).map(([filename, file]) => `${filename}:${file.code}`).join("\n")
2209
- ].join("\0"), () => {
2210
- if (loadedSass) applyStandaloneScss(store);
2211
- });
2212
- const originalSetFiles = store.setFiles.bind(store);
2213
- store.setFiles = async (newFiles, mainFile) => {
2214
- if (filesNeedScss(newFiles) && !loadedSass) await loadSass();
2215
- return originalSetFiles(newFiles, mainFile);
2216
- };
2217
- };
2218
- //#endregion
2219
- //#region packages/playground/src/core/store.ts
2220
- var DOCS_LINK_IMPORT_CODE = "import { h as __docsH } from \"vue\"";
2221
- var DOCS_LINK_USE_CODE = [
2222
- PREVIEW_SCROLL_RESET_CODE,
2223
- "app.component(\"DocsLink\",{",
2224
- "props:{to:{type:String,default:\"\"}},",
2225
- "setup(props,{slots}){return()=>__docsH(\"a\",{",
2226
- "href:props.to,",
2227
- "style:{color:\"inherit\",textDecoration:\"none\"},",
2228
- "onClick(event){event.preventDefault();window.parent.postMessage({action:\"docs:navigate\",to:props.to},\"*\")}",
2229
- "},slots.default?.())}",
2230
- "})"
2231
- ].join("");
2232
- var escapeHtmlAttr = (value) => value.replace(/&/gu, "&amp;").replace(/"/gu, "&quot;").replace(/'/gu, "&#39;").replace(/</gu, "&lt;").replace(/>/gu, "&gt;");
2233
- /**
2234
- * runtime 画布色。`previewInset` 露出的 padding、iframe chrome 和 sandbox
2235
- * `html`/`body` 必须共用这一变量,暗色下 `--docs-background-color` 与
2236
- * `--vc-background-color-light` 不同,否则会出现色带割裂。
2237
- */
2238
- var PLAYGROUND_RUNTIME_CANVAS_BACKGROUND = "var(--vc-background-color-light, var(--docs-background-color, #fff))";
2239
- var createRuntimePreviewOptions = (cdnURL = DEFAULT_CDN_URL, options = {}) => {
2240
- const previewScroller = options.previewScroller === true;
2241
- const hrefs = Object.values({
2242
- ...createBuiltinStyles(cdnURL),
2243
- ...getPlaygroundSiteStyles(),
2244
- ...getPlaygroundStyleOverrides()
2245
- });
2246
- const styleBlocks = [
2247
- `html,body{height:auto;min-height:0;background:${PLAYGROUND_RUNTIME_CANVAS_BACKGROUND}}`,
2248
- "body{color:var(--vc-foreground-color,#080f20)}",
2249
- ...previewScroller ? [PREVIEW_SCROLLER_STYLE] : []
2250
- ];
2251
- return {
2252
- showRuntimeError: false,
2253
- showRuntimeWarning: false,
2254
- headHTML: [
2255
- SANDBOX_RUNTIME_ERROR_CAPTURE_HTML,
2256
- "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">",
2257
- ...hrefs.map((href) => `<link rel="stylesheet" href="${escapeHtmlAttr(href)}">`),
2258
- "<style>",
2259
- ...styleBlocks,
2260
- "</style>"
2261
- ].join("\n"),
2262
- customCode: {
2263
- importCode: `${DOCS_LINK_IMPORT_CODE}\n${PREVIEW_SERVICE_IMPORT_CODE}`,
2264
- useCode: `${DOCS_LINK_USE_CODE}\n${PREVIEW_SERVICE_USE_CODE}`
2265
- }
2266
- };
2267
- };
2268
- var toReplFilename = (filename) => filename.startsWith("src/") ? filename : `src/${filename}`;
2269
- var createReplFile = (filename, code) => {
2270
- const replFilename = toReplFilename(filename);
2271
- return new File(replFilename, code);
2272
- };
2273
- var createRuntimeStore = (files, entry, options) => {
2274
- const { cdnURL, builtinImportMap, ...storeOptions } = options;
2275
- const replFiles = ref(Object.fromEntries(Object.entries(files).map(([filename, code]) => {
2276
- const file = createReplFile(filename, code);
2277
- return [file.filename, file];
2278
- })));
2279
- const mainFile = ref(toReplFilename(entry));
2280
- const activeFilename = ref(toReplFilename(entry));
2281
- const store = useStore({
2282
- ...storeOptions,
2283
- files: replFiles,
2284
- mainFile,
2285
- activeFilename,
2286
- builtinImportMap: ref({
2287
- ...builtinImportMap,
2288
- imports: {
2289
- ...createBuiltinImports(cdnURL),
2290
- ...getPlaygroundSiteModules(),
2291
- ...filterSafeHrefs(builtinImportMap?.imports),
2292
- ...getPlaygroundImportMapOverrides()
2293
- }
2294
- }),
2295
- template: ref({
2296
- welcomeSFC: files[entry],
2297
- newSFC: NEW_SFC_CODE
2298
- })
2299
- });
2300
- bindPlaygroundScss(store);
2301
- whenSassReady(files, () => store.init());
2302
- return store;
2303
- };
2304
- //#endregion
2305
1376
  //#region packages/playground/src/core/runtime/alone/wrapper.vue?vue&type=script&setup=true&lang.ts
2306
1377
  var _hoisted_1$2 = ["aria-label"];
2307
1378
  var _hoisted_2$2 = { class: "docs-playground-popup__frame" };
@@ -2328,6 +1399,17 @@ var Alone = new Portal(/* @__PURE__ */ defineComponent({
2328
1399
  clearConsole: {
2329
1400
  type: Boolean,
2330
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
2331
1413
  }
2332
1414
  },
2333
1415
  emits: [
@@ -2337,20 +1419,28 @@ var Alone = new Portal(/* @__PURE__ */ defineComponent({
2337
1419
  "portal-fulfilled"
2338
1420
  ],
2339
1421
  setup(__props, { emit: __emit }) {
1422
+ const LocalSandbox = defineAsyncComponent(() => import("./local-sandbox-B8IJ5jWb.js").then((n) => n.t));
2340
1423
  const props = __props;
2341
1424
  const emit = __emit;
2342
1425
  const { t } = useLocale();
2343
1426
  const currentViewport = ref(props.viewport);
2344
1427
  const sandboxRef = ref(null);
1428
+ const localError = ref({
1429
+ compile: "",
1430
+ runtime: ""
1431
+ });
1432
+ const handleLocalError = (payload) => {
1433
+ localError.value = payload;
1434
+ };
2345
1435
  const availableHeight = () => Math.max(0, getWindowInnerSize().height - 40 - 44);
2346
1436
  const temporaryHeight = usePreviewHeightBridge(sandboxRef, availableHeight);
2347
1437
  const sandboxKey = ref(0);
2348
1438
  const layoutTick = ref(0);
2349
1439
  const runtimeError = useSandboxRuntimeErrorGuard(sandboxRef);
2350
1440
  useSandboxTheme(sandboxRef);
2351
- 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"));
2352
1442
  const errorText = computed(() => {
2353
- 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")) : "";
2354
1444
  return [storeErrors.value, runtime].filter(Boolean).join("\n\n");
2355
1445
  });
2356
1446
  const layout = computed(() => {
@@ -2377,6 +1467,10 @@ var Alone = new Portal(/* @__PURE__ */ defineComponent({
2377
1467
  }));
2378
1468
  const handleRefresh = () => {
2379
1469
  runtimeError.value = "";
1470
+ localError.value = {
1471
+ compile: "",
1472
+ runtime: ""
1473
+ };
2380
1474
  sandboxKey.value++;
2381
1475
  };
2382
1476
  const handleViewportChange = (viewport) => {
@@ -2401,8 +1495,7 @@ var Alone = new Portal(/* @__PURE__ */ defineComponent({
2401
1495
  layoutTick.value++;
2402
1496
  };
2403
1497
  const handleBridgeMessage = (event) => {
2404
- const iframe = resolveSandboxContainer(sandboxRef.value)?.querySelector("iframe");
2405
- if (!iframe || event.source !== iframe.contentWindow) return;
1498
+ if (!isSandboxMessage(sandboxRef.value, event)) return;
2406
1499
  const data = event.data;
2407
1500
  if (!data || data.action !== "docs:navigate" || typeof data.to !== "string") return;
2408
1501
  emit("navigate", data.to);
@@ -2464,7 +1557,23 @@ var Alone = new Portal(/* @__PURE__ */ defineComponent({
2464
1557
  default: withCtx(() => [createElementVNode("div", {
2465
1558
  class: "docs-playground-popup__canvas",
2466
1559
  style: normalizeStyle(canvasStyle.value)
2467
- }, [(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), {
2468
1577
  key: sandboxKey.value,
2469
1578
  ref_key: "sandboxRef",
2470
1579
  ref: sandboxRef,
@@ -2476,7 +1585,7 @@ var Alone = new Portal(/* @__PURE__ */ defineComponent({
2476
1585
  "store",
2477
1586
  "clear-console",
2478
1587
  "preview-options"
2479
- ]))], 4)]),
1588
+ ])) : createCommentVNode("v-if", true)], 4)]),
2480
1589
  _: 1
2481
1590
  })])
2482
1591
  ])], 4)], 8, _hoisted_1$2);
@@ -2541,7 +1650,11 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2541
1650
  title: { default: "" },
2542
1651
  id: { default: "" },
2543
1652
  viewport: { default: "auto" },
2544
- viewportOptions: { default: () => ["auto", 375] }
1653
+ viewportOptions: { default: () => ["auto", 375] },
1654
+ local: {
1655
+ type: Boolean,
1656
+ default: true
1657
+ }
2545
1658
  },
2546
1659
  emits: [
2547
1660
  "files-change",
@@ -2550,6 +1663,7 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2550
1663
  "navigate"
2551
1664
  ],
2552
1665
  setup(__props, { expose: __expose, emit: __emit }) {
1666
+ const LocalSandbox = defineAsyncComponent(() => import("./local-sandbox-B8IJ5jWb.js").then((n) => n.t));
2553
1667
  const props = __props;
2554
1668
  const { locale, t } = useLocale();
2555
1669
  const displayTitle = computed(() => props.title.trim());
@@ -2587,21 +1701,32 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2587
1701
  "SSR": false
2588
1702
  }.MODE !== "development";
2589
1703
  const copyValue = computed(() => props.files[props.entry] || "");
2590
- const store = createRuntimeStore(props.files, props.entry, props.options);
1704
+ const store = props.local ? null : createRuntimeStore(props.files, props.entry, props.options);
2591
1705
  const sandboxRef = ref(null);
1706
+ const localError = ref({
1707
+ compile: "",
1708
+ runtime: ""
1709
+ });
1710
+ const handleLocalError = (payload) => {
1711
+ localError.value = payload;
1712
+ };
2592
1713
  const temporaryHeight = usePreviewHeightBridge(sandboxRef);
2593
1714
  const sandboxKey = ref(0);
2594
1715
  const runtimeHeight = useSandboxAutoHeight(sandboxRef);
2595
1716
  const runtimeError = useSandboxRuntimeErrorGuard(sandboxRef);
2596
1717
  useSandboxTheme(sandboxRef);
2597
- 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
+ });
2598
1722
  const errorText = computed(() => {
2599
- 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"));
2600
1726
  return [compileErrorText.value, runtime].filter(Boolean).join("\n\n");
2601
1727
  });
2602
1728
  const handleBridgeMessage = (event) => {
2603
- const iframe = resolveSandboxContainer(sandboxRef.value)?.querySelector("iframe");
2604
- if (!iframe || event.source !== iframe.contentWindow) return;
1729
+ if (!isSandboxMessage(sandboxRef.value, event)) return;
2605
1730
  const data = event.data;
2606
1731
  if (!data || data.action !== "docs:navigate" || typeof data.to !== "string") return;
2607
1732
  emit("navigate", data.to);
@@ -2634,16 +1759,21 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2634
1759
  }) - vertical * 2 - 2);
2635
1760
  };
2636
1761
  const syncFrozenExpandedHeight = () => {
2637
- if (!previewExpanded.value || props.expandable !== true) return;
1762
+ if (props.local || !previewExpanded.value || props.expandable !== true) return;
2638
1763
  frozenExpandedHeight.value = measureExpandedPreviewHeight();
2639
1764
  };
2640
1765
  if (typeof window !== "undefined") {
2641
1766
  window.addEventListener("message", handleBridgeMessage);
2642
1767
  window.addEventListener("resize", syncFrozenExpandedHeight);
2643
1768
  }
2644
- const canExpandPreview = computed(() => !props.styleless && isPlaygroundExpandable(props.expandable));
1769
+ const canExpandPreview = computed(() => !props.local && !props.styleless && isPlaygroundExpandable(props.expandable));
2645
1770
  const expandLabel = computed(() => t(previewExpanded.value ? "playground.runtime.collapsePreview" : "playground.runtime.expandPreview"));
2646
1771
  const baseViewportHeight = computed(() => {
1772
+ if (props.local) {
1773
+ const fixedHeight = getViewportHeight(props.viewport);
1774
+ if (fixedHeight) return fixedHeight;
1775
+ return runtimeHeight.value;
1776
+ }
2647
1777
  if (previewExpanded.value && props.expandable === true) return frozenExpandedHeight.value;
2648
1778
  if (previewExpanded.value && isPlaygroundExpandable(props.expandable)) return resolveExpandedPreviewHeight(props.expandable, 0);
2649
1779
  const fixedHeight = getViewportHeight(props.viewport);
@@ -2655,7 +1785,7 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2655
1785
  scrollPlaygroundToViewportStart(runtimeRoot.value);
2656
1786
  };
2657
1787
  const handleTogglePreviewExpand = () => {
2658
- if (!canExpandPreview.value) return;
1788
+ if (props.local || !canExpandPreview.value) return;
2659
1789
  if (!previewExpanded.value) {
2660
1790
  if (props.expandable === true) frozenExpandedHeight.value = measureExpandedPreviewHeight();
2661
1791
  else frozenExpandedHeight.value = 0;
@@ -2695,7 +1825,7 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2695
1825
  syncedFiles = { ...files };
2696
1826
  syncedEntry = entry;
2697
1827
  const apply = () => {
2698
- switch (action.type) {
1828
+ if (store) switch (action.type) {
2699
1829
  case "update": {
2700
1830
  const file = store.files[toReplFilename(action.filename)];
2701
1831
  if (file) file.code = files[action.filename];
@@ -2717,20 +1847,28 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2717
1847
  }
2718
1848
  emit("files-change", files, entry, action);
2719
1849
  };
2720
- whenSassReady(files, apply);
1850
+ if (store) whenSassReady(files, apply);
1851
+ else apply();
2721
1852
  };
2722
1853
  const handleEditor = () => {
2723
1854
  Editor.popup({
2724
1855
  files: { ...props.files },
2725
1856
  entry: props.entry,
2726
1857
  locale: locale.value,
2727
- getCodeErrors: () => store.errors,
1858
+ getCodeErrors: () => {
1859
+ if (!props.local) return store?.errors || [];
1860
+ return localError.value.compile ? [localError.value.compile] : [];
1861
+ },
2728
1862
  onFilesChange: handleFilesChange,
2729
- onActiveChange: (filename) => store.setActive(toReplFilename(filename))
1863
+ onActiveChange: (filename) => store?.setActive(toReplFilename(filename))
2730
1864
  });
2731
1865
  };
2732
1866
  const handleInlineRefresh = () => {
2733
1867
  runtimeError.value = "";
1868
+ localError.value = {
1869
+ compile: "",
1870
+ runtime: ""
1871
+ };
2734
1872
  sandboxKey.value++;
2735
1873
  };
2736
1874
  const handleClosePopup = () => {
@@ -2738,6 +1876,11 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2738
1876
  };
2739
1877
  const handleOpenPopup = () => {
2740
1878
  Alone.popup({
1879
+ local: props.local,
1880
+ files: props.files,
1881
+ entry: props.entry,
1882
+ options: props.options,
1883
+ previewScroller: props.previewScroller,
2741
1884
  store,
2742
1885
  copyValue: copyValue.value,
2743
1886
  title: props.title,
@@ -2758,11 +1901,16 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2758
1901
  syncedFiles = { ...files };
2759
1902
  syncedEntry = props.entry;
2760
1903
  runtimeError.value = "";
2761
- store.setFiles(files, props.entry);
1904
+ localError.value = {
1905
+ compile: "",
1906
+ runtime: ""
1907
+ };
1908
+ if (store) store.setFiles(files, props.entry);
2762
1909
  }, { deep: true });
2763
1910
  watch(() => props.entry, (entry) => {
2764
1911
  if (!entry || entry === syncedEntry) return;
2765
1912
  syncedEntry = entry;
1913
+ if (!store) return;
2766
1914
  store.mainFile = toReplFilename(entry);
2767
1915
  store.setActive(toReplFilename(entry));
2768
1916
  });
@@ -2789,13 +1937,29 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2789
1937
  }, [errorText.value ? (openBlock(), createElementBlock("pre", _hoisted_2$1, toDisplayString(errorText.value), 1)) : createCommentVNode("v-if", true), createElementVNode("div", {
2790
1938
  class: "docs-playground-runtime__viewport",
2791
1939
  style: normalizeStyle(viewportStyle.value)
2792
- }, [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,
2793
1957
  ref_key: "sandboxRef",
2794
1958
  ref: sandboxRef,
2795
1959
  store: unref(store),
2796
1960
  "auto-store-init": false,
2797
1961
  "preview-options": mergedPreviewOptions.value
2798
- }, 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", {
2799
1963
  key: 1,
2800
1964
  ref_key: "runtimeRoot",
2801
1965
  ref: runtimeRoot,
@@ -2833,7 +1997,22 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2833
1997
  }, [createElementVNode("div", _hoisted_8, [createElementVNode("div", {
2834
1998
  class: "docs-playground-runtime__viewport",
2835
1999
  style: normalizeStyle(viewportStyle.value)
2836
- }, [(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), {
2837
2016
  key: sandboxKey.value,
2838
2017
  ref_key: "sandboxRef",
2839
2018
  ref: sandboxRef,
@@ -2841,7 +2020,7 @@ var runtime_default = /* @__PURE__ */ defineComponent({
2841
2020
  "auto-store-init": false,
2842
2021
  "clear-console": clearConsole,
2843
2022
  "preview-options": mergedPreviewOptions.value
2844
- }, 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", {
2845
2024
  key: 0,
2846
2025
  type: "button",
2847
2026
  class: normalizeClass(["docs-playground__expand", { "is-expanded": previewExpanded.value }]),
@@ -2892,6 +2071,10 @@ var playground_default = /* @__PURE__ */ defineComponent({
2892
2071
  type: Boolean,
2893
2072
  default: false
2894
2073
  },
2074
+ local: {
2075
+ type: Boolean,
2076
+ default: true
2077
+ },
2895
2078
  previewOptions: {},
2896
2079
  locale: {}
2897
2080
  },
@@ -3050,7 +2233,8 @@ var playground_default = /* @__PURE__ */ defineComponent({
3050
2233
  "preview-options": __props.previewOptions,
3051
2234
  "preview-inset": __props.previewInset,
3052
2235
  "preview-scroller": __props.previewScroller,
3053
- expandable: __props.expandable,
2236
+ local: __props.local,
2237
+ expandable: __props.local ? false : __props.expandable,
3054
2238
  styleless: true,
3055
2239
  title: __props.title,
3056
2240
  id: __props.id,
@@ -3066,6 +2250,7 @@ var playground_default = /* @__PURE__ */ defineComponent({
3066
2250
  "preview-options",
3067
2251
  "preview-inset",
3068
2252
  "preview-scroller",
2253
+ "local",
3069
2254
  "expandable",
3070
2255
  "title",
3071
2256
  "id",
@@ -3119,7 +2304,8 @@ var playground_default = /* @__PURE__ */ defineComponent({
3119
2304
  "preview-options": __props.previewOptions,
3120
2305
  "preview-inset": __props.previewInset,
3121
2306
  "preview-scroller": __props.previewScroller,
3122
- expandable: __props.expandable,
2307
+ local: __props.local,
2308
+ expandable: __props.local ? false : __props.expandable,
3123
2309
  "hide-chrome": true,
3124
2310
  title: __props.title,
3125
2311
  id: __props.id,
@@ -3137,6 +2323,7 @@ var playground_default = /* @__PURE__ */ defineComponent({
3137
2323
  "preview-options",
3138
2324
  "preview-inset",
3139
2325
  "preview-scroller",
2326
+ "local",
3140
2327
  "expandable",
3141
2328
  "title",
3142
2329
  "id",