/** * MarkdownContent - Renders markdown content with DOMPurify sanitization. * Used for topic and reply content display. * @see specs/prd-web.md Section 4 (Topic Components) */ import { sanitize } from 'isomorphic-dompurify' import { marked } from 'marked' import { cn } from '@/lib/utils' interface MarkdownContentProps { content: string className?: string } // Configure marked for safe defaults marked.setOptions({ breaks: true, gfm: true, }) // Configure marked renderer for links const renderer = new marked.Renderer() renderer.link = ({ href, text }: { href: string; text: string }) => { return `${text}` } marked.use({ renderer }) /** * Renders markdown content, sanitized against XSS. * Supports: headings, bold, italic, links, code blocks, lists, blockquotes. */ export function MarkdownContent({ content, className }: MarkdownContentProps) { const rawHtml = marked.parse(content, { async: false }) as string const cleanHtml = sanitize(rawHtml, { ALLOWED_TAGS: [ 'p', 'br', 'strong', 'em', 'a', 'code', 'pre', 'blockquote', 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'img', 'table', 'thead', 'tbody', 'tr', 'th', 'td', 'del', 'sup', 'sub', 'span', ], ALLOWED_ATTR: ['href', 'src', 'alt', 'title', 'class', 'rel', 'target'], ALLOW_DATA_ATTR: false, }) return (
) }