Add markdown rendering for chat messages

This commit is contained in:
2026-01-07 10:58:10 +01:00
parent b39f7c1e7f
commit 0f1b23772c
3 changed files with 97 additions and 7 deletions
+4 -2
View File
@@ -73,7 +73,7 @@
</div> </div>
<div id="messages"></div> <div id="messages"></div>
<div class="input-container"> <div class="input-container">
<input id="msgInput" placeholder="Type your message..."/> <textarea id="msgInput" placeholder="Type your message..."></textarea>
<button id="send"></button> <button id="send"></button>
</div> </div>
<div class="logout-container"> <div class="logout-container">
@@ -82,6 +82,8 @@
</div> </div>
</div> </div>
</div> </div>
<script src="script.js"></script> <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/dompurify@3.0.6/dist/purify.min.js" defer></script>
<script src="script.js" defer></script>
</body> </body>
</html> </html>
+22 -3
View File
@@ -67,6 +67,16 @@ function setAuthMessage(msg, state = "") {
authMsg.className = state ? `status ${state}` : 'status'; authMsg.className = state ? `status ${state}` : 'status';
} }
function setMessageContent(element, content) {
if (window.marked && window.DOMPurify) {
const rendered = marked.parse(content, { breaks: true });
element.innerHTML = DOMPurify.sanitize(rendered);
return;
}
element.textContent = content;
}
function addMessage(content, isUser = false, isLoading = false, saveToHistory = true) { function addMessage(content, isUser = false, isLoading = false, saveToHistory = true) {
const msgDiv = document.createElement('div'); const msgDiv = document.createElement('div');
msgDiv.className = `msg ${isUser ? 'user' : 'bot'}${isLoading ? ' loading' : ''}`; msgDiv.className = `msg ${isUser ? 'user' : 'bot'}${isLoading ? ' loading' : ''}`;
@@ -80,7 +90,16 @@ function addMessage(content, isUser = false, isLoading = false, saveToHistory =
</div> </div>
`; `;
} else { } else {
msgDiv.textContent = content; const header = document.createElement('div');
header.className = 'msg-header';
header.textContent = isUser ? 'You' : 'DeepFake';
const body = document.createElement('div');
body.className = 'msg-content';
setMessageContent(body, content);
msgDiv.appendChild(header);
msgDiv.appendChild(body);
if (saveToHistory) { if (saveToHistory) {
chatHistory.push({ chatHistory.push({
@@ -204,7 +223,7 @@ async function sendMessage() {
if (isProcessing) return; if (isProcessing) return;
const msg = msgInput.value.trim(); const msg = msgInput.value.trim();
if (!msg) return; if (!msg) return;
addMessage(`You: ${msg}`, true); addMessage(msg, true);
msgInput.value = ""; msgInput.value = "";
msgInput.style.height = 'auto'; msgInput.style.height = 'auto';
setLoadingState(true); setLoadingState(true);
@@ -216,7 +235,7 @@ async function sendMessage() {
messagesDiv.removeChild(loadingMsg); messagesDiv.removeChild(loadingMsg);
} }
if (res.reply) { if (res.reply) {
addMessage(`DeepFake: ${res.reply}`, false); addMessage(res.reply, false);
} else { } else {
addMessage(`[Error: ${res.error}]`, false); addMessage(`[Error: ${res.error}]`, false);
} }
+71 -2
View File
@@ -338,9 +338,12 @@ button:disabled {
overflow-wrap: break-word; overflow-wrap: break-word;
animation: fadeIn 0.3s ease; animation: fadeIn 0.3s ease;
position: relative; position: relative;
white-space: pre-wrap; white-space: normal;
margin: 0; margin: 0;
flex-shrink: 0; flex-shrink: 0;
display: flex;
flex-direction: column;
gap: 6px;
} }
@keyframes fadeIn { @keyframes fadeIn {
@@ -377,6 +380,73 @@ button:disabled {
justify-content: center; justify-content: center;
} }
.msg-header {
font-size: 0.7rem;
letter-spacing: 0.12em;
text-transform: uppercase;
font-weight: 700;
color: rgba(255, 255, 255, 0.7);
}
.msg-content {
display: grid;
gap: 10px;
}
.msg-content > * {
margin: 0;
}
.msg-content p {
margin: 0;
}
.msg-content ul,
.msg-content ol {
margin: 0;
padding-left: 20px;
}
.msg-content li {
margin: 4px 0;
}
.msg-content pre {
background: rgba(15, 15, 35, 0.9);
padding: 12px 14px;
border-radius: 12px;
overflow-x: auto;
border: 1px solid rgba(255, 255, 255, 0.08);
}
.msg-content code {
font-family: "JetBrains Mono", "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
background: rgba(255, 255, 255, 0.08);
padding: 2px 6px;
border-radius: 6px;
font-size: 0.9em;
}
.msg-content pre code {
background: transparent;
padding: 0;
}
.msg-content blockquote {
margin: 0;
padding-left: 14px;
border-left: 3px solid rgba(255, 255, 255, 0.2);
color: var(--text-secondary);
}
.msg-content a {
color: #93c5fd;
}
.msg-content a:hover {
color: #bfdbfe;
}
.typing-indicator { display: flex; align-items: center; gap: 6px; height: 16px; } .typing-indicator { display: flex; align-items: center; gap: 6px; height: 16px; }
.typing-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--text-secondary); animation: typingAnimation 1.2s infinite ease-in-out; } .typing-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--text-secondary); animation: typingAnimation 1.2s infinite ease-in-out; }
.typing-dot:nth-child(1) { animation-delay: -0.32s; } .typing-dot:nth-child(1) { animation-delay: -0.32s; }
@@ -490,4 +560,3 @@ html, body {
overflow-wrap: break-word; overflow-wrap: break-word;
word-break: break-word; word-break: break-word;
} }