vitepress-plugin-sandpack
Version:
use sandpack-vue3 in vitepress as directive.
421 lines (420 loc) • 11.6 kB
JavaScript
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
};