码桶
发现社区成员的开源项目
Markdown.tsx1.7 KB
import { useMemo } from 'react'
import { marked } from 'marked'
import DOMPurify from 'dompurify'
import { cn } from '@/lib/utils'
/**
* Markdown 渲染组件(支持富文本 + 代码块),输出经 DOMPurify 消毒防 XSS。
* 用于兑换弹窗公告等需要富文本展示的场景。
*/
export function Markdown({ content, className }: { content: string; className?: string }) {
const html = useMemo(() => {
try {
const raw = marked.parse(content || '', { async: false, breaks: true }) as string
return DOMPurify.sanitize(raw)
} catch {
return ''
}
}, [content])
if (!content) return null
return (
<div
className={cn(
'text-sm leading-relaxed break-words space-y-2',
// 代码块 / 行内代码
'[&_pre]:overflow-x-auto [&_pre]:rounded-md [&_pre]:bg-zinc-900 [&_pre]:p-3 [&_pre]:text-xs [&_pre]:text-zinc-100',
'[&_code]:font-mono [&_:not(pre)>code]:rounded [&_:not(pre)>code]:bg-muted [&_:not(pre)>code]:px-1 [&_:not(pre)>code]:py-0.5 [&_:not(pre)>code]:text-[13px]',
// 标题 / 列表 / 引用 / 链接 / 表格
'[&_h1]:text-base [&_h1]:font-bold [&_h2]:text-[15px] [&_h2]:font-bold [&_h3]:text-sm [&_h3]:font-semibold',
'[&_ul]:list-disc [&_ul]:pl-5 [&_ol]:list-decimal [&_ol]:pl-5',
'[&_blockquote]:border-l-2 [&_blockquote]:pl-3 [&_blockquote]:text-muted-foreground',
'[&_a]:text-primary [&_a]:underline',
'[&_table]:w-full [&_table]:text-xs [&_th]:border [&_th]:px-2 [&_th]:py-1 [&_td]:border [&_td]:px-2 [&_td]:py-1',
'[&_img]:max-w-full [&_hr]:my-2',
className,
)}
dangerouslySetInnerHTML={{ __html: html }}
/>
)
}