import { computed, getCurrentInstance, onMounted, ref, toValue, useId, watch } from "vue"; import { onClickOutside, useEventListener } from "@vueuse/core"; import { isPlainObject } from "vuepress/shared"; //#region src/client/composables/demo.ts function useExpand(defaultExpand = true) { const expanded = ref(defaultExpand); function toggle() { expanded.value = !expanded.value; } return [expanded, toggle]; } function useResources(el, config) { const resources = computed(() => { const conf = toValue(config); if (!conf) return []; return [{ name: "JavaScript", items: conf.jsLib?.map((url) => ({ name: normalizeName(url), url })) }, { name: "CSS", items: conf.cssLib?.map((url) => ({ name: normalizeName(url), url })) }].filter((i) => i.items?.length); }); function normalizeName(url) { return url.slice(url.lastIndexOf("/") + 1); } const showResources = ref(false); function toggleResources() { showResources.value = !showResources.value; } onClickOutside(el, () => { showResources.value = false; }); return { resources, showResources, toggleResources }; } function useFence(fence, config) { const data = ref({ js: "", css: "", html: "", jsType: "", cssType: "" }); onMounted(() => { if (!fence.value) return; const conf = toValue(config); data.value.html = conf?.html ?? ""; const els = Array.from(fence.value.querySelectorAll("div[class*=\"language-\"]")); for (const el of els) { const lang = el.className.match(/language-(\w+)/)?.[1] ?? ""; const content = el.querySelector("pre")?.textContent ?? ""; if (lang === "js" || lang === "javascript") { data.value.js = content; data.value.jsType = "js"; } if (lang === "ts" || lang === "typescript") { data.value.js = content; data.value.jsType = "ts"; } if (lang === "css" || lang === "scss" || lang === "less" || lang === "stylus" || lang === "styl") { data.value.css = content; data.value.cssType = lang === "styl" ? "stylus" : lang; } } }); return data; } function useNormalDemo(draw, title, config) { const current = getCurrentInstance(); const id = useId(); const isDark = computed(() => current?.appContext.config.globalProperties.$isDark.value); const height = ref("100px"); onMounted(() => { if (!draw.value) return; const iframeDoc = draw.value.contentDocument || draw.value.contentWindow?.document; if (!iframeDoc) return; const templateId = `VPDemoNormalDraw${id}`; useEventListener("message", (event) => { const data = parseData(event.data); if (data.type === templateId) height.value = `${data.height + 5}px`; }); watch([config, title], () => { iframeDoc.write(createHTMLTemplate(toValue(title) || "Demo", templateId, toValue(config))); }, { immediate: true }); watch(isDark, () => { iframeDoc.documentElement.dataset.theme = isDark.value ? "dark" : "light"; }, { immediate: true }); }); return { id, height }; } function createHTMLTemplate(title, id, config) { const { cssLib = [], jsLib = [], html, css, script } = config || {}; const stylesheet = cssLib.map((url) => ``).join(""); const scripts = jsLib.map((url) => `