Files
deerflow-code/web-code/components/qa/components/MarkdownContent.tsx
T
2026-05-27 19:43:15 +08:00

69 lines
1.9 KiB
TypeScript

import React from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import './MarkdownContent.css';
type Props = {
content?: string;
referenceMap?: Record<string, string>;
className?: string;
};
function rehypeHighlightRefs(referenceMap?: Record<string, string>) {
return function (tree: any) {
function walk(node: any) {
if (!node.children) return;
const next = [];
for (const child of node.children) {
if (child.type === 'text') {
const parts = child.value.split(/(\[\d+\])/g);
if (parts.length > 1) {
for (const part of parts) {
if (!part) continue;
const m = part.match(/^\[(\d+)\]$/);
if (m) {
const num = m[1];
const itemId = referenceMap?.[num];
next.push({
type: 'element',
tagName: 'span',
properties: {
className: 'ref-cite',
'data-tooltip': itemId ? `ID: ${itemId}` : `引用 ${num}`,
},
children: [{ type: 'text', value: part }],
});
} else {
next.push({ type: 'text', value: part });
}
}
} else {
next.push(child);
}
} else {
walk(child);
next.push(child);
}
}
node.children = next;
}
walk(tree);
};
}
export default function MarkdownContent({ content, referenceMap, className = '' }: Props): JSX.Element | null {
if (!content) return null;
const rehypePlugins = [() => rehypeHighlightRefs(referenceMap)];
return (
<div className={`markdown-body ${className}`}>
<ReactMarkdown
remarkPlugins={[remarkGfm]}
rehypePlugins={rehypePlugins}
>
{content}
</ReactMarkdown>
</div>
);
}