function escapeHtml(text) { return text .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } export function parseMarkdown(text) { if (!text) return ''; // Escape HTML first to prevent XSS let html = escapeHtml(text); // Code blocks (``` ... ```) html = html.replace(/```(\w*)\n([\s\S]*?)```/g, (match, lang, code) => { const cls = lang ? ` class="language-${lang}"` : ''; return `
${code.trim()}`;
});
// Inline code
html = html.replace(/`([^`\n]+)`/g, '$1');
// Bold
html = html.replace(/\*\*([^*]+)\*\*/g, '$1');
// Italic (avoid matching bold remnants)
html = html.replace(/(?$1');
html = html.replace(/(?$1');
// Blockquotes (lines starting with >)
html = html.replace(/^>\s?(.+)$/gm, '$1'); // @mentions html = html.replace(/@(\w+)/g, '@$1'); // URLs — match http/https links html = html.replace( /(?$1' ); // Line breaks html = html.replace(/\n/g, '
/g, '
'); return html; }