"use strict"; // First, let's add the Marked library for markdown parsing const markedScript = document.createElement("script"); markedScript.src = "https://cdnjs.cloudflare.com/ajax/libs/marked/4.2.12/marked.min.js"; document.head.appendChild(markedScript); // Initialize toggle button functionality immediately const chatToggleBtn = document.getElementById("chatToggleBtn"); const chatBox = document.querySelector(".chat-box"); const notificationBadge = document.querySelector(".notification-badge"); chatToggleBtn.addEventListener("click", function () { chatBox.classList.toggle("active"); if (notificationBadge) { notificationBadge.remove(); } }); // Wait for marked to load before initializing chat markedScript.onload = function () { initializeChat(); }; function initializeChat() { var chatInput = document.querySelector("#chat_input"); var typing = document.querySelector("#typing"); var send = document.querySelector("#send"); var chatMessages = document.querySelector("#chat_messages"); var chatBoxBody = document.querySelector("#chat_box_body"); var chatForm = document.querySelector("#chat-form"); // Profile configuration const profile = { my: { name: "You", pic: "https://imgproxy.attic.sh/unsafe/rs:fit:540:540:1:1/t:1:FF00FF:false:false/aHR0cHM6Ly9hdHRp/Yy5zaC9sYmxjODRn/OTcxeXV5bnQwcXMz/NjNmbGNrZTQ5.webp", }, other: { name: "Assistant", pic: "/static/favicon.PNG", }, }; // Configure marked options marked.setOptions({ breaks: true, gfm: true, smartLists: true, smartypants: true, xhtml: true, }); function sanitizeHTML(str) { const div = document.createElement("div"); div.textContent = str; return div.innerHTML; } function renderMarkdown(text) { try { const rawHtml = marked.parse(text); const tempDiv = document.createElement("div"); tempDiv.innerHTML = rawHtml; tempDiv.querySelectorAll("pre code").forEach((block) => { block.textContent = block.innerHTML; }); return tempDiv.innerHTML; } catch (e) { console.error("Markdown parsing error:", e); return sanitizeHTML(text); } } function renderProfile(p) { return `
`; } function renderMessage(p, m) { const messageContent = p === "other" ? renderMarkdown(m) : sanitizeHTML(m); return ``; } function appendMessage(p, message) { const messageHtml = renderProfile(p) + renderMessage(p, message); chatMessages.insertAdjacentHTML("beforeend", messageHtml); // Reveal new elements with animation const newElements = document.querySelectorAll( ".profile.hide, .message.hide" ); newElements.forEach((elm) => { if (elm.classList.contains("profile")) { elm.style.height = "auto"; } elm.classList.remove("hide"); }); // Scroll to bottom chatBoxBody.scrollTop = chatBoxBody.scrollHeight; // Initialize syntax highlighting if available if (window.hljs) { document.querySelectorAll("pre code").forEach((block) => { hljs.highlightBlock(block); }); } } // Auto-resize textarea chatInput.addEventListener("input", function () { this.style.height = "0"; this.style.height = this.scrollHeight + 1 + "px"; }); // Handle enter key chatInput.addEventListener("keydown", function (evt) { if (evt.keyCode == 13 && !evt.shiftKey) { handleSubmit(); evt.preventDefault(); } }); // Handle form submission if (chatForm) { chatForm.addEventListener("submit", function (evt) { evt.preventDefault(); handleSubmit(); }); } async function handleSubmit() { const message = chatInput.value.trim(); if (!message) return; // Show user message appendMessage("my", message); // Clear input chatInput.value = ""; chatInput.style.height = "40px"; // Show typing indicator typing.classList.add("active"); try { // Send message to backend const formData = new FormData(); formData.append("text", message); const response = await fetch("/get", { method: "POST", body: formData, }); const data = await response.text(); // Hide typing indicator typing.classList.remove("active"); // Show bot response appendMessage("other", data); } catch (error) { console.error("Error:", error); typing.classList.remove("active"); appendMessage( "other", "Sorry, I encountered an error. Please try again." ); } } // Initialize scroll position chatBoxBody.scrollTop = chatBoxBody.scrollHeight; }