diff --git a/nanochat/ui.html b/nanochat/ui.html index b2b4605..e742a31 100644 --- a/nanochat/ui.html +++ b/nanochat/ui.html @@ -5,6 +5,8 @@ NanoChat + + @@ -282,6 +355,39 @@ let currentTemperature = 0.8; let currentTopK = 50; + // Configure marked.js for better rendering + if (typeof marked !== 'undefined') { + marked.setOptions({ + breaks: true, // Convert line breaks to
+ gfm: true, // GitHub Flavored Markdown + sanitize: false, // We'll use DOMPurify instead + smartypants: false // Disable smart quotes for simplicity + }); + } + + // Markdown rendering function + function renderMarkdown(content) { + try { + if (typeof marked !== 'undefined' && typeof DOMPurify !== 'undefined') { + const rawHtml = marked.parse(content); + return DOMPurify.sanitize(rawHtml); + } else { + console.warn('Markdown libraries not loaded, falling back to plain text'); + return escapeHtml(content); + } + } catch (error) { + console.error('Markdown rendering failed:', error); + return escapeHtml(content); + } + } + + // HTML escape fallback function + function escapeHtml(text) { + const div = document.createElement('div'); + div.textContent = text; + return div.innerHTML; + } + chatInput.addEventListener('input', function() { this.style.height = 'auto'; this.style.height = Math.min(this.scrollHeight, 200) + 'px'; @@ -321,7 +427,13 @@ const contentDiv = document.createElement('div'); contentDiv.className = 'message-content'; - contentDiv.textContent = content; + + // Render markdown for assistant messages, plain text for others + if (role === 'assistant' && content) { + contentDiv.innerHTML = renderMarkdown(content); + } else { + contentDiv.textContent = content; + } // Add click handler for user messages to enable editing if (role === 'user' && messageIndex !== null) { @@ -395,7 +507,7 @@ messages: messages, temperature: currentTemperature, top_k: currentTopK, - max_tokens: 512 + max_tokens: 64 }), }); @@ -421,7 +533,8 @@ const data = JSON.parse(line.slice(6)); if (data.token) { fullResponse += data.token; - assistantContent.textContent = fullResponse; + // Render markdown in real-time as tokens arrive + assistantContent.innerHTML = renderMarkdown(fullResponse); chatContainer.scrollTop = chatContainer.scrollHeight; } } catch (e) {