From b839e58aa45da1945d0c46c8070b4e7016c59f94 Mon Sep 17 00:00:00 2001 From: Agando Date: Mon, 1 Jun 2026 18:00:38 +0200 Subject: auto: 2026-06-01_18:00 changes --- modules/core/terminal.js | 70 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 6 deletions(-) (limited to 'modules/core/terminal.js') diff --git a/modules/core/terminal.js b/modules/core/terminal.js index 5008842..607c51a 100644 --- a/modules/core/terminal.js +++ b/modules/core/terminal.js @@ -399,7 +399,7 @@ .replace(/>/g, '>') .replace(/"/g, '"') .replace(/`/g, '`'); - return `
`; + return `
📄 Rendered HTML
`; } _renderHTMLBlock(text) { const renderRegex = /:::render-html\r?\n([\s\S]*?)\r?\n:::/g; @@ -483,9 +483,42 @@ this._streamChunks = []; } } + printUserPrompt(rawInput) { + const wrapper = document.createElement('div'); + wrapper.className = 'output-line user-prompt-line'; + const safe = rawInput.replace(//g, '>'); + const hasHtml = /<[a-z][\s\S]*>/i.test(rawInput.trim()); + const previewBtn = hasHtml ? `` : ''; + wrapper.innerHTML = ` + webx11@module:~$ + ${safe} + + ${previewBtn} + + `; + this.outputContainer.appendChild(wrapper); + this._historyBuffer.push({ l: rawInput, t: 'command-prompt' }); + if (this._historyBuffer.length > this._historyMaxLines) this._historyBuffer.shift(); + this.scrollToBottom(); + this._trimOutput(); + } + editPrompt(text) { + this.inputField.value = text; + this.inputField.focus(); + this.inputField.setSelectionRange(text.length, text.length); + } copyToClipboard(btn) { - const contentDiv = btn.nextElementSibling; - const text = contentDiv.innerText; + let text; + if (btn.classList.contains('user-copy-btn')) { + // User prompt: text is in .prompt-text sibling + const pSpan = btn.parentElement.querySelector('.prompt-text'); + if (pSpan) text = pSpan.textContent; + } else { + // AI response: text is in next sibling .ai-content + const contentDiv = btn.nextElementSibling; + if (contentDiv) text = contentDiv.innerText; + } + if (!text) return; navigator.clipboard.writeText(text).then(() => { const originalText = btn.textContent; btn.textContent = 'Copied!'; @@ -675,6 +708,8 @@ this._dirty = false; }, 180000); window.addEventListener('beforeunload', () => { + // Flush session before tab closes — avoids losing up to 3min of output on crash/close + try { this._autoSaveSession(); } catch (e) {} if (this._autoSaveTimer) { clearInterval(this._autoSaveTimer); this._autoSaveTimer = null; @@ -1008,7 +1043,7 @@ } async reloadPersistedModules() { const registry = this.moduleManager.moduleRegistry; - const skipList = ['calc', 'voice', 'cron', 'theme', 'wpm', 'mindmap', 'webdav', 'skill-pack-core', 'editor', 'diff', 'alias', 'finder', 'filemgr', 'cryptogzip', 'shell']; + const skipList = ['calc', 'voice', 'cron', 'theme', 'wpm', 'mindmap', 'webdav', 'skill-pack-core', 'editor', 'diff', 'alias', 'finder', 'filemgr', 'cryptogzip', 'shell', 'tutorial', 'busybox']; for (const mod of registry) { if (mod.enabled && mod.url) { // Skip ext modules — they load via _loadExtModules @@ -1021,7 +1056,7 @@ async executeCommand(rawInput) { if (!rawInput.trim()) return; this.markDirty(); - this.print(`webx11@module:~$ ${rawInput}`, 'command-prompt'); + this.printUserPrompt(rawInput); const pipeParts = this.splitPipe(rawInput.trim()); if (pipeParts.length > 1) { await this.executePipeChain(pipeParts); @@ -1248,6 +1283,29 @@ iframe.src = 'about:blank'; this.inputField.focus(); } + openRenderPreview(btn) { + const content = btn.getAttribute('data-content'); + if (!content) return; + const iframe = document.getElementById('preview-iframe'); + // The srcdoc content is already HTML-escaped from _renderHTMLPreview + const decoded = content.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/`/g, '`'); + iframe.srcdoc = decoded; + document.getElementById('preview-title').textContent = '📄 AI Rendered Preview (Fullscreen)'; + document.getElementById('preview-modal').style.display = 'flex'; + } + previewHtmlFromPrompt(btn) { + const content = btn.getAttribute('data-content'); + if (!content) return; + const iframe = document.getElementById('preview-iframe'); + // Content is HTML-escaped, decode it back + const decoded = content.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/`/g, '`'); + // Wrap in a basic HTML template if it doesn't have html/head/body tags + const hasOwnDoc = /${decoded}`; + iframe.srcdoc = fullDoc; + document.getElementById('preview-title').textContent = '📄 User HTML Preview'; + document.getElementById('preview-modal').style.display = 'flex'; + } openSkillsManager() { const modal = document.getElementById('skills-manager'); // Ensure /skills/ directory exists @@ -1671,7 +1729,7 @@ 'module-fetcher.js','module-skills.js','module-chatstudio.js' ]; const extFiles = [ - 'calc.js','voice.js','cron.js','theme.js','wpm.js','mindmap.js','skill-pack-core.js' + 'calc.js','voice.js','cron.js','theme.js','wpm.js','mindmap.js','webdav.js','skill-pack-core.js','editor.js','diff.js','alias.js','finder.js','filemgr.js','cryptogzip.js','tutorial.js','shell.js','busybox.js' ]; const addSection = (title) => { -- cgit v1.2.3