import { rustExecute } from "./rustRepl-CARlbZyO.js"; import { onMounted, ref } from "vue"; import { http } from "../utils/http.js"; import { sleep } from "../utils/sleep.js"; //#region src/client/composables/codeRepl.ts const ignoredNodes = [".diff.remove", ".vp-copy-ignore"]; const RE_LANGUAGE = /language-(\w+)/; const api = { go: "https://api.pengzhanbo.cn/repl/golang/run", kotlin: "https://api.pengzhanbo.cn/repl/kotlin/run" }; let pyodide = null; const langAlias = { kt: "kotlin", kotlin: "kotlin", go: "go", rust: "rust", rs: "rust", py: "python", python: "python" }; const supportLang = [ "kotlin", "go", "rust", "python" ]; function resolveLang(lang) { return lang ? langAlias[lang] || lang : ""; } function resolveCode(el) { const clone = el.cloneNode(true); clone.querySelectorAll(ignoredNodes.join(",")).forEach((node) => node.remove()); return clone.textContent || ""; } function resolveCodeInfo(el) { const wrapper = el.querySelector("div[class*=language-]"); const lang = wrapper?.className.match(RE_LANGUAGE)?.[1]; const codeEl = wrapper?.querySelector("pre"); let code = ""; if (codeEl) code = resolveCode(codeEl); return { lang: resolveLang(lang), code }; } function useCodeRepl(el) { const lang = ref(); const loaded = ref(true); const firstRun = ref(true); const finished = ref(true); const stdout = ref([]); const stderr = ref([]); const error = ref(""); const backendVersion = ref(""); onMounted(() => { if (el.value) lang.value = resolveCodeInfo(el.value).lang; }); const executeMap = { kotlin: executeKotlin, go: executeGolang, rust: executeRust, python: executePython }; function onCleanRun() { loaded.value = false; finished.value = false; stdout.value = []; stderr.value = []; error.value = ""; firstRun.value = true; backendVersion.value = ""; } async function onRunCode() { if (!el.value || !loaded.value) return; const info = resolveCodeInfo(el.value); lang.value = info.lang; if (!lang.value || !info.code || !supportLang.includes(lang.value)) return; if (firstRun.value) firstRun.value = false; loaded.value = false; finished.value = false; stdout.value = []; stderr.value = []; error.value = ""; await executeMap[lang.value]?.(info.code); } async function executeGolang(code) { const res = await http.post(api.go, { code }); backendVersion.value = `v${res.version}`; loaded.value = true; if (res.error) { error.value = res.error; finished.value = true; return; } const events = res.events || []; for (const event of events) if (event.kind === "stdout") { if (event.delay) await sleep(event.delay / 1e6); stdout.value.push(event.message); } else if (event.kind === "stderr") stderr.value.push(event.message); finished.value = true; } async function executeKotlin(code) { const filename = "File.kt"; const res = await http.post(api.kotlin, { args: "", files: [{ name: filename, publicId: "", text: code }] }); backendVersion.value = `v${res.version}`; loaded.value = true; if (res.errors) { const errors = Array.isArray(res.errors[filename]) ? res.errors[filename] : [res.errors[filename]]; if (errors.length) errors.forEach(({ message, severity }) => severity === "ERROR" && stderr.value.push(message)); } stdout.value.push(res.text); finished.value = true; } async function executeRust(code) { await rustExecute(code, { onBegin: () => { loaded.value = true; finished.value = false; stdout.value = []; stderr.value = []; error.value = ""; backendVersion.value = "release"; }, onError(message) { error.value = message; }, onStdout(message) { stdout.value.push(message); }, onStderr(message) { stderr.value.push(message); }, onEnd: () => { finished.value = true; } }); } async function executePython(code) { loaded.value = false; finished.value = false; if (pyodide === null) { const { loadPyodide, version } = await import( /* webpackChunkName: "pyodide" */ "pyodide" ); pyodide = await loadPyodide({ indexURL: `https://cdn.jsdelivr.net/pyodide/v${version}/full/` }); } pyodide.setStdout({ batched: (msg) => stdout.value.push(msg) }); try { stdout.value.push(pyodide.runPython(code)); } catch (e) { stderr.value.push(String(e)); } loaded.value = true; finished.value = true; } return { onRunCode, onCleanRun, lang, backendVersion, firstRun, stderr, stdout, loaded, finished, error }; } //#endregion export { resolveCode, resolveCodeInfo, useCodeRepl };