'use client';
import { memo } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { CodeBlock } from './CodeBlock';
import { cn } from '@/lib/utils';
interface MarkdownRendererProps {
content: string;
className?: string;
}
// 将 components 配置提取到组件外部,避免每次渲染时创建新对象
const markdownComponents = {
// 代码块
code({ className, children, ...props }: { className?: string; children?: React.ReactNode }) {
const match = /language-(\w+)/.exec(className || '');
const isInline = !match && !className;
if (isInline) {
// 行内代码 - 无特殊样式,仅等宽字体
return (
{children}
);
}
// 代码块
return (
);
},
// 段落
p({ children }: { children?: React.ReactNode }) {
return (
{children}
);
},
// 标题 - 使用相对单位保持与全局字体的比例
h1({ children }: { children?: React.ReactNode }) {
return (
{children}
);
},
h2({ children }: { children?: React.ReactNode }) {
return (
{children}
);
},
h3({ children }: { children?: React.ReactNode }) {
return (
{children}
);
},
h4({ children }: { children?: React.ReactNode }) {
return (
{children}
);
},
// 列表
ul({ children }: { children?: React.ReactNode }) {
return (
);
},
ol({ children }: { children?: React.ReactNode }) {
return (
{children}
);
},
li({ children }: { children?: React.ReactNode }) {
return (
{children}
);
},
// 链接
a({ href, children }: { href?: string; children?: React.ReactNode }) {
return (
{children}
);
},
// 粗体
strong({ children }: { children?: React.ReactNode }) {
return (
{children}
);
},
// 斜体
em({ children }: { children?: React.ReactNode }) {
return (
{children}
);
},
// 引用
blockquote({ children }: { children?: React.ReactNode }) {
return (
{children}
);
},
// 分割线
hr() {
return (
);
},
// 表格
table({ children }: { children?: React.ReactNode }) {
return (
);
},
thead({ children }: { children?: React.ReactNode }) {
return (
{children}
);
},
tbody({ children }: { children?: React.ReactNode }) {
return (
{children}
);
},
tr({ children }: { children?: React.ReactNode }) {
return (
{children}
);
},
th({ children }: { children?: React.ReactNode }) {
return (
{children}
|
);
},
td({ children }: { children?: React.ReactNode }) {
return (
{children}
|
);
},
// 图片
img(props: React.ImgHTMLAttributes) {
return (
);
},
};
// 使用 memo 包裹组件,避免不必要的重渲染
export const MarkdownRenderer = memo(function MarkdownRenderer({ content, className }: MarkdownRendererProps) {
return (
{content}
);
});