utils/mdToHtml.ts (23 lines of code) (raw):

/** * Very small markdown -> HTML for headers (#), paragraphs, bold (**text**) and links [text](url). * Safe subset suitable for our content. Extend if needed. */ export const mdToHtml = (md: string) => { let result = md; // Headers: # h1, ## h2, etc. (process before escaping since we allow HTML) result = result.replace(/^### (.+)$/gm, '<h3>$1</h3>'); result = result.replace(/^## (.+)$/gm, '<h2>$1</h2>'); result = result.replace(/^# (.+)$/gm, '<h2>$1</h2>'); // Using h2 for h1 to keep semantic structure // Bold: **text** result = result.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>'); // Links: [text](url) result = result.replace( /\[([^\]]+?)\]\((https?:\/\/[^\s)]+)\)/g, '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>' ); // Paragraphs: split by double newline and wrap non-header lines in <p> result = result .split(/\n\n+/) .map(block => { const trimmed = block.trim(); if (!trimmed) return ''; // Don't wrap if it's already a heading or other HTML tag if (trimmed.startsWith('<h') || trimmed.startsWith('<p>')) { return trimmed; } return `<p>${trimmed}</p>`; }) .join('\n'); return result; };