export function renderRichText(container, text) { container.innerHTML = ""; const lines = String(text).replaceAll("\r\n", "\n").split("\n"); let list = null; let codeLines = null; let paragraph = []; const flushParagraph = () => { if (paragraph.length === 0) { return; } const element = document.createElement("p"); element.innerHTML = formatInline(paragraph.join(" ")); container.appendChild(element); paragraph = []; }; const flushList = () => { if (list) { container.appendChild(list); list = null; } }; const flushCode = () => { if (!codeLines) { return; } const pre = document.createElement("pre"); pre.textContent = codeLines.join("\n"); container.appendChild(pre); codeLines = null; }; for (const line of lines) { if (line.startsWith("```")) { flushParagraph(); flushList(); if (codeLines) { flushCode(); } else { codeLines = []; } continue; } if (codeLines) { codeLines.push(line); continue; } const listMatch = line.match(/^\s*[-*]\s+(.+)$/); if (listMatch) { flushParagraph(); if (!list) { list = document.createElement("ul"); } const item = document.createElement("li"); item.innerHTML = formatInline(listMatch[1]); list.appendChild(item); continue; } if (!line.trim()) { flushParagraph(); flushList(); continue; } flushList(); paragraph.push(line.trim()); } flushParagraph(); flushList(); flushCode(); } export function escapeHtml(value) { return String(value) .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">"); } function formatInline(value) { return escapeHtml(value) .replace(/\*\*(.+?)\*\*/g, "$1") .replace(/\*(.+?)\*/g, "$1") .replace(/`(.+?)`/g, "$1"); }