import React, { useState } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import rehypeRaw from 'rehype-raw';
interface MarkdownRendererProps {
content: string;
className?: string;
onCitationClick?: (index: number) => void;
}
const extractTextFromNode = (node: React.ReactNode): string => {
if (typeof node === 'string' || typeof node === 'number') return String(node);
if (Array.isArray(node)) return node.map(extractTextFromNode).join('');
if (React.isValidElement<{ children?: React.ReactNode }>(node)) return extractTextFromNode(node.props.children);
return '';
};
const CodeBlock: React.FC<{ children: React.ReactNode; className?: string }> = ({ children, className = '' }) => {
const [copied, setCopied] = useState(false);
const codeText = extractTextFromNode(children).replace(/\n$/, '');
const language = className?.match(/language-(\w+)/)?.[1];
const handleCopy = async () => {
try {
await navigator.clipboard.writeText(codeText);
setCopied(true);
window.setTimeout(() => setCopied(false), 1500);
} catch (error) {
console.error('复制代码失败:', error);
}
};
return (
{language || 'code'}
{children}
);
};
const MarkdownRenderer: React.FC = ({ content, className = '', onCitationClick }) => {
const contentWithCitationBadge = content.replace(
/\[\[(\d+)\]\]/g,
'',
);
return (
{
if (!onCitationClick) return;
const target = event.target as HTMLElement;
const button = target.closest('[data-citation-index]') as HTMLElement | null;
if (!button) return;
const index = Number(button.dataset.citationIndex || '0');
if (Number.isNaN(index) || index <= 0) return;
onCitationClick(index);
}}
>
,
h2: ({ node, ...props }) => ,
h3: ({ node, ...props }) => ,
h4: ({ node, ...props }) => ,
h5: ({ node, ...props }) => ,
h6: ({ node, ...props }) => ,
p: ({ node, ...props }) => ,
ul: ({ node, ...props }) => ,
ol: ({ node, ...props }) =>
,
li: ({ node, ...props }) => ,
// code: ({ node, inline, className, children, ...props }: any) => {
// if (inline) {
// return (
//
// {children}
//
// );
// }
// return {children};
// },
// pre: ({ node, children }) => <>{children}>,
blockquote: ({ node, ...props }) => (
),
a: ({ node, ...props }) => (
),
table: ({ node, ...props }) => (
),
thead: ({ node, ...props }) => ,
tbody: ({ node, ...props }) => ,
tr: ({ node, ...props }) =>
,
th: ({ node, ...props }) => | ,
td: ({ node, ...props }) => | ,
hr: ({ node, ...props }) =>
,
strong: ({ node, ...props }) => ,
em: ({ node, ...props }) => ,
}}
>
{contentWithCitationBadge}
);
};
export default MarkdownRenderer;