html Runner

HTML
CSS
JS
Console
Console ready...
`; consoleLogs.innerHTML = '
Running...
'; const doc = iframe.contentWindow.document; doc.open(); doc.write(source); 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 SYSTEM --- function saveHistory() { if(isInternalChange) return; if (historyIndex < history.length - 1) history = history.slice(0, historyIndex + 1); history.push({ html: htmlInput.value, css: cssInput.value, js: jsInput.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(state) { isInternalChange = true; htmlInput.value = state.html; cssInput.value = state.css; jsInput.value = state.js; isInternalChange = false; runCode(); } // --- AUTO RUN --- let timeout; let saveTimeout; function handleInput() { if(autoRunCheckbox.checked) { clearTimeout(timeout); timeout = setTimeout(runCode, 800); } clearTimeout(saveTimeout); saveTimeout = setTimeout(saveHistory, 1000); } htmlInput.addEventListener('input', handleInput); cssInput.addEventListener('input', handleInput); jsInput.addEventListener('input', handleInput); // --- UTILITIES --- function clearAll() { if(confirm("Are you sure?")) { htmlInput.value = ""; cssInput.value = ""; jsInput.value = ""; runCode(); saveHistory(); } } // --- DOWNLOAD WITH CUSTOM NAME --- function downloadCode() { const html = htmlInput.value; const css = cssInput.value; const js = jsInput.value; // Get filename from input let name = fileNameInput.value.trim(); if(!name) name = "project"; // Default if empty if(!name.endsWith('.html')) name += ".html"; // Append extension const content = ` ${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; // Use user's name document.body.appendChild(a); a.click(); document.body.removeChild(a); } function saveState() { const data = { html: htmlInput.value, css: cssInput.value, js: jsInput.value }; localStorage.setItem('gkp_runner_data', JSON.stringify(data)); } function loadState() { const data = localStorage.getItem('gkp_runner_data'); if(data) { const parsed = JSON.parse(data); htmlInput.value = parsed.html; cssInput.value = parsed.css; jsInput.value = parsed.js; } saveHistory(); runCode(); } loadState(); // Tab Key Support document.querySelectorAll('textarea').forEach(textarea => { textarea.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; } }); });