diff --git a/public/scripts/components/TerminalPanelComponent.js b/public/scripts/components/TerminalPanelComponent.js index 30b0871..50403d1 100644 --- a/public/scripts/components/TerminalPanelComponent.js +++ b/public/scripts/components/TerminalPanelComponent.js @@ -129,8 +129,22 @@ this._appendLine('[open] WebSocket connection established'); }); ws.addEventListener('message', (evt) => { - const data = typeof evt.data === 'string' ? evt.data : '[binary]'; - this._appendLine(data); + let dataStr = typeof evt.data === 'string' ? evt.data : '[binary]'; + // Decode any HTML entities so JSON isn't shown as " etc. + dataStr = this._decodeHtmlEntities(dataStr); + // Try to pretty-print JSON if applicable + const trimmed = dataStr.trim(); + if ((trimmed.startsWith('{') && trimmed.endsWith('}')) || (trimmed.startsWith('[') && trimmed.endsWith(']'))) { + try { + const obj = JSON.parse(trimmed); + const pretty = JSON.stringify(obj, null, 2); + this._appendLine(pretty); + return; + } catch (_) { + // fall through if not valid JSON + } + } + this._appendLine(dataStr); }); ws.addEventListener('error', (evt) => { this._appendLine('[error] WebSocket error'); @@ -170,6 +184,16 @@ if (bodyEl) bodyEl.scrollTop = bodyEl.scrollHeight; } + _decodeHtmlEntities(text) { + try { + const div = document.createElement('div'); + div.innerHTML = text; + return div.textContent || div.innerText || ''; + } catch (_) { + return text; + } + } + _adjustRightOffset() { try { const drawer = document.querySelector('.details-drawer');