返回 DeepSeek-Reasonix
MarkdownRenderer.tsx
根目录 / desktop / frontend / src / components / MarkdownRenderer.tsx
1 import { memo, useMemo, useRef } from "react";
2 import ReactMarkdown from "react-markdown";
3 import "katex/dist/katex.min.css";
4 import { normalizeMath } from "./mathNormalize";
5 import { createComponents } from "./markdownComponents";
6 import { reasonixRehypePlugins, reasonixRemarkPlugins } from "./markdownRemarkPlugins";
7 import { markdownImageUrlTransform, markdownUrlTransform } from "../lib/markdownPipeline";
8
9 // Markdown rendering via react-markdown + remark-gfm (tables, task lists,
10 // strike, autolinks) and remark-math + rehype-katex for $/$$ KaTeX math.
11 // This is the STREAMING path (incremental commits of a live answer); history
12 // rows render worker-parsed HAST blocks through MarkdownHistory instead, with
13 // the same plugins, components map, and urlTransform.
14 //
15 // The math pre-pass repairs LLM-native delimiters and display structure.
16 // remarkMathPolicy then classifies parsed inline-math AST nodes using their
17 // surrounding prose, avoiding false positives on currency and env vars.
18 //
19 // file:/// hrefs come from local-path linkification (remarkLocalPathLinks)
20 // and must survive URL sanitisation; markdownUrlTransform (shared with the
21 // worker parse pipeline) keeps them while blanking javascript: and friends.
22
23 const MarkdownRenderer = memo(function MarkdownRenderer({
24 text,
25 plainStatusBlocks = false,
26 bare = false,
27 }: {
28 text: string;
29 plainStatusBlocks?: boolean;
30 bare?: boolean;
31 }) {
32 const containerRef = useRef<HTMLDivElement>(null);
33 const mathContent = useMemo(() => normalizeMath(text), [text]);
34 const components = useMemo(() => createComponents(plainStatusBlocks), [plainStatusBlocks]);
35 const content = (
36 <ReactMarkdown
37 remarkPlugins={reasonixRemarkPlugins}
38 rehypePlugins={reasonixRehypePlugins}
39 components={components}
40 // file:/// anchors (local path linkification) are safe to keep; the
41 // default transform would blank them along with javascript: etc.
42 urlTransform={(value, key, node) => node.tagName === "img" && key === "src"
43 ? markdownImageUrlTransform(value)
44 : markdownUrlTransform(value)}
45 >
46 {mathContent}
47 </ReactMarkdown>
48 );
49 return bare ? content : <div className="md" ref={containerRef}>{content}</div>;
50 });
51
52 export default MarkdownRenderer;
53
53 lines Plain Text