UNPKG

vitepress-plugin-sandpack

Version:
421 lines (420 loc) 11.6 kB
import { defineComponent as T, useCssVars as _, ref as N, computed as v, useSlots as $, watch as j, onBeforeMount as H, onMounted as A, nextTick as D, openBlock as P, createBlock as R, unref as y } from "vue"; import * as q from "@codesandbox/sandpack-themes"; import { renderToString as F } from "vue/server-renderer"; import { Sandpack as E } from "sandpack-vue3"; const B = (e) => e.trim().replace(/'/g, "").replace(/"/g, ""), M = (e) => { const t = {}; return e.split(",").forEach((r) => { let [s, o] = r.split(":"); s = B(s), o = B(o), t[s] = o; }), t; }, x = (e) => { let t = "/src/index.js"; switch (e) { case "vanilla-ts": t = "/src/index.ts"; break; case "angular": t = "/src/app/app.component.ts"; break; case "react": t = "/App.js"; break; case "react-ts": t = "/App.tsx"; break; case "vue": t = "/src/App.vue"; break; case "vue3": t = "/src/App.vue"; break; case "svelte": t = "/index.js"; break; case "solid": t = "/App.tsx"; break; } return t; }, W = (e, t) => { let n; const r = (e || "").split(" "), s = r.includes("[hidden]"), o = r.includes("[readonly]") || r.includes("[readOnly]"), l = r.includes("[active]"), c = r.find((i) => i.includes(".")); return c && (n = c, n = n === "App.vue" ? x(t) : n, n = n.startsWith("/") ? n : `/${n}`), { hidden: s, active: l, readOnly: o, path: n }; }, d = (e) => typeof e > "u" || String(e).trim() === "" ? !0 : ["false", "0"].includes(String(e).trim()) ? !1 : !!e, b = (e) => e ? typeof e == "string" ? M(e) : e : void 0, L = async (e, t) => { var l, c; const n = {}, r = t.default ? t.default() : []; let s = r.filter((i) => i.type === "div") || [], o = 0; if (Array.isArray(s)) { if (!s.length) { const i = r ? (l = r[0]) == null ? void 0 : l.ctx : {}; i && (i != null && i.slots) && (s = (c = i.slots) != null && c.default ? i.slots.default() : []); } for await (const i of s) { let h = "", m = document.createElement("div"); const u = i.children || [], { active: f, hidden: a, readOnly: p, path: g } = W(JSON.parse(decodeURIComponent(e.codeOptions))[o], e.template), S = g || x(e.template), w = u.find((C) => C.type === "pre"); i.children = w ? [w] : []; const k = await F(i); m.insertAdjacentHTML("beforeend", k), h = m.innerText, m = null, n[S] = { code: h, active: f, hidden: a, readOnly: p }, o++; } } return n; }, I = (e = {}) => { const { options: t } = e, n = t && typeof t == "object" ? { ...t } : {}, r = { autorun: d(e.autorun), editorWidthPercentage: isNaN(Number(e.editorWidthPercentage)) ? 50 : Number(e.editorWidthPercentage), showNavigator: d(e.showNavigator), showLineNumbers: d(e.showLineNumbers), showRefreshButton: d(e.showRefreshButton), showTabs: d(e.showTabs), showConsoleButton: d(e.showConsoleButton), showConsole: d(e.showConsole), closableTabs: d(e.closableTabs), wrapContent: d(e.wrapContent), resizablePanels: d(e.resizablePanels), readOnly: d(e.readOnly), showReadOnly: d(e.showReadOnly) }; for (const s in n) s in r && (["editorWidthPercentage"].includes(s) ? r.editorWidthPercentage = isNaN(Number(n[s])) ? 50 : Number(n[s]) : r[s] = d(n[s])); return r; }, z = (e) => { const { deps: t, devDeps: n, entry: r, customSetup: s } = e, o = s && typeof s == "object" ? s : void 0, l = { dependencies: void 0, devDependencies: void 0, entry: void 0, npmRegistries: void 0 }; return (t || n || r) && (l.dependencies = b(t), l.devDependencies = b(n), l.entry = r || void 0), o && (l.dependencies = b(o.deps), l.devDependencies = b(o.devDeps), l.entry = o.entry, l.npmRegistries = o.npmRegistries), l; }, U = { /** * light theme name * @default 'light' */ lightTheme: { type: String, required: !1, default: "light" }, /** * dark theme name * @default 'dark' */ darkTheme: { type: String, required: !1, default: "dark" }, /** * sandbox language * @default 'vue3' */ template: { type: String, required: !1, default: "vue3" }, /** * hide code editor * @default false */ hideEditor: { type: [Boolean, String], required: !1, default: !1 }, /** * right to left layout * @default false */ rtl: { type: [Boolean, String], required: !1, default: !1 }, // options /** * sandbox options * @default undefined */ options: { type: Object, required: !1, default: void 0 }, /** * auto run code * @default true */ autorun: { type: [String, Boolean], required: !1, default: !0 }, /** * preview area height, default undefined * @default undefined */ previewHeight: { type: Number, required: !1, default: void 0 }, /** * editor area height, default undefined * @default undefined */ coderHeight: { type: Number, required: !1, default: void 0 }, /** * show route navigator in preview area * @default false */ showNavigator: { type: [String, Boolean], required: !1, default: !1 }, /** * show line numbers in editor file * @default false */ showLineNumbers: { type: [String, Boolean], required: !1, default: !1 }, /** * show refresh button in preview area * @default true */ showRefreshButton: { type: [String, Boolean], required: !1, default: !0 }, /** * show tabs in editor area * @default true */ showTabs: { type: [String, Boolean], required: !1, default: !0 }, /** * show console button in preview area * @default true */ showConsoleButton: { type: [String, Boolean], required: !1, default: !0 }, /** * show console panel in preview area * @default false */ showConsole: { type: [String, Boolean], required: !1, default: !1 }, /** * enable close editor file * @default false */ closableTabs: { type: [String, Boolean], required: !1, default: !1 }, /** * enable wrap content of editor file * @default false */ wrapContent: { type: [String, Boolean], required: !1, default: !1 }, /** * enable resizable editor width * @default true */ resizablePanels: { type: [String, Boolean], required: !1, default: !0 }, /** * endable readonly of editor file * @default false */ readOnly: { type: [String, Boolean], required: !1, default: !1 }, /** * show readonly label in editor file * @default true */ showReadOnly: { type: [String, Boolean], required: !1, default: !0 }, // customSetup /** * sandbox custom setup, like `dependencies` or `devDependencies`... * @default undefined */ customSetup: { type: Object, required: !1, default: void 0 }, /** * Any template will include the needed dependencies, * but you can specify any additional dependencies. The key * should be the name of the package, while the value is the version, * in exactly the same format as it would be inside package.json. * * Examples: * ```js * { * "react": "latest", * "@material-ui/core": "4.12.3", * } * * // or * * '@material-ui/core: ^4.12.3, react: latest' * ``` */ deps: { type: [String, Object], required: !1, default: void 0 }, /** * Sandpack doesn't install devDependencies, because most tools in there * were build tools, which is not necessary to properly run a sandbox, * but maybe required for running locally or export to CodeSandbox. * * Examples: * ```js * { * "@types/react": "latest", * } * * // or * * '@types/react: latest' * ``` */ devDeps: { type: [String, Object], required: !1, default: void 0 }, /** * The entry file is the starting point of the bundle process. * * If you change the path of the entry file, make sure you control * all the files that go into the bundle process, as prexisting * settings in the template might not work anymore. */ entry: { type: String, required: !1, default: void 0 }, /** this is a build-in prop, do not edit it */ codeOptions: { type: String, required: !1, default: void 0 } }, Q = /* @__PURE__ */ T({ __name: "Sandbox", props: U, setup(e) { _((p) => ({ "8966ea8e": i.value, a364191e: s.value, "07fe9e36": l.value })); const t = e, n = N({}), r = (p) => { var g; return t[p] ?? ((g = t == null ? void 0 : t.options) == null ? void 0 : g[p]); }, s = v(() => d(r("hideEditor")) ? "none" : "flex"), o = v(() => isNaN(Number(r("previewHeight"))) ? void 0 : Number(r("previewHeight"))), l = v(() => o.value ? `${o.value}px` : "var(--sp-layout-height)"), c = v(() => isNaN(Number(r("coderHeight"))) ? void 0 : Number(r("coderHeight"))), i = v(() => c.value ? `${c.value}px` : "var(--sp-layout-height)"), h = $(), m = N(!1), u = v( () => m.value ? q[r("darkTheme")] || "dark" : q[r("lightTheme")] || "light" ), f = async () => { n.value = await L(t, h); }, a = () => { typeof document < "u" && document.documentElement && (m.value = document.documentElement.classList.contains("dark")); }; return j(t, f), H(f), A(() => { D(() => { typeof document < "u" && document.documentElement && new MutationObserver((g) => { g[0].target && a(); }).observe(document.documentElement, { attributes: !0, attributeFilter: ["class"] }), a(); }); }), (p, g) => (P(), R(y(E), { theme: u.value, template: p.template, rtl: y(d)(p.rtl), files: n.value, options: y(I)(t), "custom-setup": y(z)(t) }, null, 8, ["theme", "template", "rtl", "files", "options", "custom-setup"])); } }); const O = (e) => e.split("-").map((n) => n.substring(0, 1).toUpperCase() + n.substring(1)).join("-"), V = (e = "") => { const t = e.split(" "); let n = !1; for (const r of t) if (/([{1})([\s\S]*)([\.]{1}([\s\S]+))(]{1})/.test(r)) { n = !0; break; } return n; }, X = (e, t, n) => ((s, o, l) => { var c, i; if (s[o].nesting === 1) { const h = []; for (let u = o + 1; s[u] && !(s[u].nesting === -1 && s[u].type === "container_sandbox_close"); ++u) if (s[u].type === "fence" && s[u].tag === "code") { let f = "", a = ((c = s[u]) == null ? void 0 : c.info) || ""; V(a) && (a.includes("prefix=") ? a = a.replace("prefix=", "").replace("[", "").replace("]", "") : a = a.replace("[", " /").replace("]", ""), f = a.substring(a.lastIndexOf(".") + 1), a = `${f} ${a}`, a.includes("#active") && (a = `${a.replace("#active", "")} [active]`), a.includes("#readOnly") && (a = `${a.replace("#readOnly", "")} [readOnly]`), a.includes("#hidden") && (a = `${a.replace("#hidden", "")} [hidden]`)), h.push(a); } const m = ((i = s[o].attrs) == null ? void 0 : i.map(([u, f]) => f ? `${u}="${f}"` : u)) || []; return `<${O(l)} codeOptions="${encodeURIComponent(JSON.stringify(h))}" ${m.join(" ")}>`; } return `</${O(l)}>`; })(e, t, n); export { Q as Sandbox, z as getCustomSetupFromProps, x as getDefaultFileName, W as getFileAttributes, L as getSandpackFiles, I as getSandpackOptions, d as parsedBoolean, b as parsedDeps, X as renderSandbox, U as sandboxProps };