From b7f0a567dae73ded0cd60a5b260532fffaf5ad5f Mon Sep 17 00:00:00 2001 From: JaviLib Date: Sun, 22 Feb 2026 05:11:28 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20correcci=C3=B3n=20de=20saltos=20de=20l?= =?UTF-8?q?=C3=ADnea=20en=20mensajes=20de=20usuario=20(frontend=20+=20back?= =?UTF-8?q?end)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/channels/http.go | 14 ++++++++ pkg/channels/http_templates/index.html | 46 +++++++++++++++++++++----- 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/pkg/channels/http.go b/pkg/channels/http.go index 31313ff9d..e46201f23 100644 --- a/pkg/channels/http.go +++ b/pkg/channels/http.go @@ -282,6 +282,12 @@ func generateChatID(r *http.Request) string { // renderMarkdown converts Markdown to HTML using goldmark func renderMarkdown(input string) string { + // Debug: log first 100 chars of input + // logger.DebugF("http renderMarkdown input", map[string]any{"input": input[:min(100, len(input))]}) + + // Convert newlines to
before markdown processing + input = strings.ReplaceAll(input, "\n", " \n") + md := goldmark.New( goldmark.WithExtensions( extension.GFM, @@ -292,7 +298,15 @@ func renderMarkdown(input string) string { var buf strings.Builder if err := md.Convert([]byte(input), &buf); err != nil { + logger.ErrorCF("http", "renderMarkdown error", map[string]any{"error": err.Error()}) return input // fallback to plain text on error } return buf.String() +} + +func min(a, b int) int { + if a < b { + return a + } + return b } \ No newline at end of file diff --git a/pkg/channels/http_templates/index.html b/pkg/channels/http_templates/index.html index 62c425a67..bfff7ef70 100644 --- a/pkg/channels/http_templates/index.html +++ b/pkg/channels/http_templates/index.html @@ -116,7 +116,7 @@ display: flex; gap: 12px; } - .input-wrapper input { + .input-wrapper textarea { flex: 1; padding: 14px 20px; border: 2px solid #2d2d44; @@ -125,12 +125,18 @@ color: white; font-size: 1rem; outline: none; - transition: border-color 0.2s; + resize: none; + min-height: 56px; + max-height: 200px; + line-height: 1.5; + box-sizing: border-box; + font-family: inherit; + overflow-y: auto; } - .input-wrapper input:focus { + .input-wrapper textarea:focus { border-color: #ff6b35; } - .input-wrapper input::placeholder { + .input-wrapper textarea::placeholder { color: #64748b; } .input-wrapper button { @@ -196,7 +202,7 @@
- +
@@ -247,7 +253,12 @@ function addMessage(content, type) { const div = document.createElement('div'); div.className = `message ${type}`; - div.innerHTML = content; + // Convert newlines to
for proper rendering in HTML + // For user messages, we need to preserve line breaks from textarea + let processedContent = content.replace(/\n/g, '
'); + // Also handle double newlines as paragraphs (optional, for better readability) + processedContent = processedContent.replace(/\n\n/g, '

'); + div.innerHTML = processedContent; chatContainer.appendChild(div); chatContainer.scrollTop = chatContainer.scrollHeight; } @@ -267,7 +278,7 @@ } function sendMessage() { - const content = messageInput.value.trim(); + const content = messageInput.value; if (!content || !connected) return; addMessage(content, 'user'); @@ -287,9 +298,26 @@ } sendButton.addEventListener('click', sendMessage); - messageInput.addEventListener('keypress', (e) => { - if (e.key === 'Enter') sendMessage(); + messageInput.addEventListener('keydown', (e) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + sendMessage(); + } }); + + // Auto-resize textarea + function autoResizeTextarea() { + const textarea = document.getElementById('messageInput'); + textarea.style.height = 'auto'; + textarea.style.height = textarea.scrollHeight + 'px'; + } + + messageInput.addEventListener('input', autoResizeTextarea); + messageInput.addEventListener('keyup', autoResizeTextarea); + messageInput.addEventListener('click', autoResizeTextarea); + + // Initialize height + setTimeout(autoResizeTextarea, 100); // Heartbeat to keep connection alive setInterval(() => {