From f903dd49188af8dc7cd4c010ba267618e68767a1 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Thu, 9 Apr 2026 01:39:01 -0300 Subject: [PATCH] fix: render HTML directly in bot messages without escaping - Detect HTML tags in bot responses and use content directly - Fix for both addMessage and streaming (updateStreaming/finalizeStreaming) - Prevents HTML source being shown to users --- ui/suite/chat/chat.html | 29 ++++++++++++++++++++--------- ui/suite/partials/chat.html | 29 ++++++++++++++++++++--------- 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/ui/suite/chat/chat.html b/ui/suite/chat/chat.html index 56164de..d5c9406 100644 --- a/ui/suite/chat/chat.html +++ b/ui/suite/chat/chat.html @@ -294,10 +294,15 @@ processedContent + ""; } else { - var parsed = - typeof marked !== "undefined" && marked.parse + // Check if content has HTML (any tag, including comments) + var hasHtmlTags = /<\/?[a-z][^>]*>|/i.test(content); + console.log("Bot message - hasHtmlTags:", hasHtmlTags, "content length:", content.length); + + var parsed = hasHtmlTags + ? content // Use HTML directly (no escaping!) + : (typeof marked !== "undefined" && marked.parse ? marked.parse(content) - : escapeHtml(content); + : escapeHtml(content)); parsed = renderMentionInMessage(parsed); div.innerHTML = '
' + @@ -727,10 +732,13 @@ function updateStreaming(content) { var el = document.getElementById(streamingMessageId); if (el) { - var parsed = - typeof marked !== "undefined" && marked.parse + // Check if content has HTML tags + var hasHtmlTags = /<\/?[a-z][^>]*>|/i.test(content); + var parsed = hasHtmlTags + ? content // Use HTML directly + : (typeof marked !== "undefined" && marked.parse ? marked.parse(content) - : escapeHtml(content); + : escapeHtml(content)); parsed = renderMentionInMessage(parsed); el.querySelector(".message-content").innerHTML = parsed; } @@ -739,10 +747,13 @@ function finalizeStreaming() { var el = document.getElementById(streamingMessageId); if (el) { - var parsed = - typeof marked !== "undefined" && marked.parse + // Check if content has HTML tags + var hasHtmlTags = /<\/?[a-z][^>]*>|/i.test(currentStreamingContent); + var parsed = hasHtmlTags + ? currentStreamingContent // Use HTML directly + : (typeof marked !== "undefined" && marked.parse ? marked.parse(currentStreamingContent) - : escapeHtml(currentStreamingContent); + : escapeHtml(currentStreamingContent)); parsed = renderMentionInMessage(parsed); el.querySelector(".message-content").innerHTML = parsed; el.removeAttribute("id"); diff --git a/ui/suite/partials/chat.html b/ui/suite/partials/chat.html index 791d823..74c1d6d 100644 --- a/ui/suite/partials/chat.html +++ b/ui/suite/partials/chat.html @@ -504,10 +504,15 @@ processedContent + "
"; } else { - var parsed = - typeof marked !== "undefined" && marked.parse + // Check if content has HTML (any tag, including comments) + var hasHtmlTags = /<\/?[a-z][^>]*>|/i.test(content); + console.log("Bot message - hasHtmlTags:", hasHtmlTags, "content length:", content.length); + + var parsed = hasHtmlTags + ? content // Use HTML directly (no escaping!) + : (typeof marked !== "undefined" && marked.parse ? marked.parse(content) - : escapeHtml(content); + : escapeHtml(content)); parsed = renderMentionInMessage(parsed); div.innerHTML = '
' + @@ -937,10 +942,13 @@ function updateStreaming(content) { var el = document.getElementById(streamingMessageId); if (el) { - var parsed = - typeof marked !== "undefined" && marked.parse + // Check if content has HTML tags + var hasHtmlTags = /<\/?[a-z][^>]*>|/i.test(content); + var parsed = hasHtmlTags + ? content // Use HTML directly + : (typeof marked !== "undefined" && marked.parse ? marked.parse(content) - : escapeHtml(content); + : escapeHtml(content)); parsed = renderMentionInMessage(parsed); el.querySelector(".message-content").innerHTML = parsed; } @@ -949,10 +957,13 @@ function finalizeStreaming() { var el = document.getElementById(streamingMessageId); if (el) { - var parsed = - typeof marked !== "undefined" && marked.parse + // Check if content has HTML tags + var hasHtmlTags = /<\/?[a-z][^>]*>|/i.test(currentStreamingContent); + var parsed = hasHtmlTags + ? currentStreamingContent // Use HTML directly + : (typeof marked !== "undefined" && marked.parse ? marked.parse(currentStreamingContent) - : escapeHtml(currentStreamingContent); + : escapeHtml(currentStreamingContent)); parsed = renderMentionInMessage(parsed); el.querySelector(".message-content").innerHTML = parsed; el.removeAttribute("id");