// The hub's file editor (hub spec ยง6.9): CodeMirror 6 mounted over a // textarea, which stays the form field, so the page works without script. import { EditorView, basicSetup } from "codemirror"; import { EditorState } from "@codemirror/state"; import { keymap } from "@codemirror/view"; import { indentWithTab } from "@codemirror/commands"; import { javascript } from "@codemirror/lang-javascript"; import { rust } from "@codemirror/lang-rust"; import { cpp } from "@codemirror/lang-cpp"; import { python } from "@codemirror/lang-python"; import { markdown } from "@codemirror/lang-markdown"; import { html } from "@codemirror/lang-html"; import { css } from "@codemirror/lang-css"; import { json } from "@codemirror/lang-json"; import { yaml } from "@codemirror/lang-yaml"; import { oneDark } from "@codemirror/theme-one-dark"; function language(path) { const ext = (path.split(".").pop() || "").toLowerCase(); switch (ext) { case "js": case "mjs": case "cjs": return javascript(); case "ts": case "mts": return javascript({ typescript: true }); case "jsx": return javascript({ jsx: true }); case "tsx": return javascript({ jsx: true, typescript: true }); case "rs": return rust(); case "c": case "h": case "cc": case "cpp": case "hpp": case "cxx": return cpp(); case "py": return python(); case "md": case "markdown": return markdown(); case "html": case "htm": return html(); case "css": return css(); case "json": return json(); case "yml": case "yaml": return yaml(); default: return []; } } function dark() { const t = document.documentElement.dataset.theme; if (t === "light") return false; if (t === "dark") return true; return !window.matchMedia || !window.matchMedia("(prefers-color-scheme: light)").matches; } function mount(textarea) { const view = new EditorView({ state: EditorState.create({ doc: textarea.value, extensions: [basicSetup, keymap.of([indentWithTab]), language(textarea.dataset.path || ""), dark() ? oneDark : [], EditorView.lineWrapping], }), }); textarea.style.display = "none"; textarea.parentNode.insertBefore(view.dom, textarea); view.dom.classList.add("cm-host"); const form = textarea.form; if (form) { form.addEventListener("submit", () => { textarea.value = view.state.doc.toString(); }); } return view; } document.querySelectorAll("textarea.code").forEach(mount); window.OxyEditor = { mount };