/// async function runCode(code, consoleCode) { consoleCode.textContent += `\nRunning code....\n`; try { const module = await import(`data:text/javascript;charset=utf-8,${encodeURIComponent(code)}`); module.default?.(); } catch (error) { consoleCode.textContent += `${error}\n`; } } class Debounce { timer = null lastCall = 0; constructor(timeout) { this.timeout = timeout; } run(fn) { const now = Date.now(); if (this.timer === null && now - this.lastCall > this.timeout) { fn(); this.lastCall = now; return; } if (this.timer !== null) { clearTimeout(this.timer); this.timer = null; } this.timer = setTimeout(() => { fn(); this.lastCall = Date.now(); this.timer = null; }, this.timeout) } } const editor = ace.edit("editor"); editor.setTheme("ace/theme/gruvbox"); editor.session.setMode("ace/mode/javascript"); editor.setValue(sessionStorage.getItem("code") ?? editor.getValue(), -1); const runButton = document.querySelector("#run-button"); const saveButton = document.querySelector("#save-button"); const consoleCode = document.querySelector("#console-code"); const sessionSaveDebounce = new Debounce(1000); editor.addEventListener("change", (ev) => { sessionSaveDebounce.run(() => { sessionStorage.setItem("code", editor.getValue()) }) }) runButton.onclick = (ev) => { const code = editor.getValue(); runCode(code, consoleCode); runButton.textContent = "⚙️ Running..."; }; saveButton.onclick = (ev) => { const code = editor.getValue(); const element = document.createElement("a"); element.setAttribute("href", `data:text/javascript;charset=utf-8,${encodeURIComponent(code)}`); const filename = prompt("Filename?") element.setAttribute("download", filename.endsWith(".js") ? filename : `${filename}.js`); element.style.display = "none"; document.body.appendChild(element); element.click(); document.body.removeChild(element); };