if exists, else append if(code.includes('')) { code = code.replace('', consoleScript + ''); } else { code = code + consoleScript; } consoleLogs.innerHTML = '
'; const doc = iframe.contentWindow.document; doc.open(); doc.write(code); doc.close(); saveState(); } // --- CONSOLE LISTENER --- window.addEventListener('message', function(event) { if (event.data && event.data.source === 'iframe-console') { const type = event.data.type; const msg = event.data.message; const div = document.createElement('div'); div.className = `log-line log-${type}`; div.innerText = `> ${msg}`; consoleLogs.appendChild(div); consoleLogs.scrollTop = consoleLogs.scrollHeight; } }); function toggleConsole() { const pane = document.getElementById('consolePane'); const icon = document.getElementById('consoleIcon'); pane.classList.toggle('collapsed'); icon.className = pane.classList.contains('collapsed') ? 'fas fa-chevron-up' : 'fas fa-chevron-down'; } // --- UNDO / REDO --- function saveHistory() { if(isInternalChange) return; if (historyIndex < history.length - 1) history = history.slice(0, historyIndex + 1); history.push(sourceInput.value); if(history.length > 50) history.shift(); historyIndex = history.length - 1; } function undo() { if (historyIndex > 0) { historyIndex--; restoreState(history[historyIndex]); } } function redo() { if (historyIndex < history.length - 1) { historyIndex++; restoreState(history[historyIndex]); } } function restoreState(content) { isInternalChange = true; sourceInput.value = content; isInternalChange = false; runCode(); } // --- AUTO RUN & HISTORY DEBOUNCE --- let timeout; let saveTimeout; function handleInput() { if(autoRunCheckbox.checked) { clearTimeout(timeout); timeout = setTimeout(runCode, 800); } clearTimeout(saveTimeout); saveTimeout = setTimeout(saveHistory, 1000); } sourceInput.addEventListener('input', handleInput); // --- UTILS --- function clearAll() { if(confirm("Clear current code?")) { sourceInput.value = ""; runCode(); saveHistory(); } } function downloadCode() { const content = sourceInput.value; let name = fileNameInput.value.trim(); if(!name) name = "index"; if(!name.endsWith('.html')) name += ".html"; const blob = new Blob([content], { type: "text/html" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = name; document.body.appendChild(a); a.click(); document.body.removeChild(a); } function saveState() { localStorage.setItem('gkp_runner2_code', sourceInput.value); } function loadState() { const saved = localStorage.getItem('gkp_runner2_code'); if(saved) sourceInput.value = saved; saveHistory(); runCode(); } // Tab Key Support sourceInput.addEventListener('keydown', function(e) { if (e.key == 'Tab') { e.preventDefault(); var start = this.selectionStart; var end = this.selectionEnd; this.value = this.value.substring(0, start) + " " + this.value.substring(end); this.selectionStart = this.selectionEnd = start + 2; } }); // Shortcuts document.addEventListener('keydown', function(e) { if ((e.ctrlKey || e.metaKey) && e.key === 'z') { e.preventDefault(); undo(); } if ((e.ctrlKey || e.metaKey) && e.key === 'y') { e.preventDefault(); redo(); } if ((e.ctrlKey || e.metaKey) && e.key === 's') { e.preventDefault(); downloadCode(); } }); // Init loadState();