diff options
| author | YurenHao0426 <blackhao0426@gmail.com> | 2026-02-13 19:23:14 +0000 |
|---|---|---|
| committer | YurenHao0426 <blackhao0426@gmail.com> | 2026-02-13 19:23:14 +0000 |
| commit | 962e96b0f0f0b91341b65e53b9b52b7c5b10f6d6 (patch) | |
| tree | a986d07dd1209ff3993aa5eaa9492ca943feba08 /frontend/src/components/Sidebar.tsx | |
| parent | dbe25778281ded7db601520349e37a39a4b04ceb (diff) | |
Add LaTeX math rendering with KaTeX
Support both $...$ / $$...$$ (remark-math) and \(...\) / \[...\] (GPT-style)
delimiters via a preprocessor that normalizes to dollar-sign syntax before
passing to ReactMarkdown.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'frontend/src/components/Sidebar.tsx')
| -rw-r--r-- | frontend/src/components/Sidebar.tsx | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx index 13cf3e9..f114151 100644 --- a/frontend/src/components/Sidebar.tsx +++ b/frontend/src/components/Sidebar.tsx @@ -6,6 +6,17 @@ import type { NodeData, Trace, Message, MergedTrace, MergeStrategy } from '../st import type { Edge } from 'reactflow'; import ReactMarkdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; +import remarkMath from 'remark-math'; +import rehypeKatex from 'rehype-katex'; +import 'katex/dist/katex.min.css'; + +// Preprocess LaTeX delimiters: convert \(...\) → $...$ and \[...\] → $$...$$ +const preprocessLaTeX = (content: string): string => { + return content + .replace(/\\\[([\s\S]*?)\\\]/g, (_, math) => `$$${math}$$`) + .replace(/\\\(([\s\S]*?)\\\)/g, (_, math) => `$${math}$`); +}; + import { Play, Settings, Info, ChevronLeft, ChevronRight, Maximize2, Edit3, X, Check, FileText, MessageCircle, Send, GripVertical, GitMerge, Trash2, AlertCircle, Loader2, Navigation, Upload, Search, Link, Layers } from 'lucide-react'; interface SidebarProps { @@ -1904,7 +1915,7 @@ const Sidebar: React.FC<SidebarProps> = ({ isOpen, onToggle, onInteract }) => { ? 'bg-gray-900 border-gray-700 prose-invert text-gray-200' : 'bg-gray-50 border-gray-200 text-gray-900' }`}> - <ReactMarkdown remarkPlugins={[remarkGfm]}>{selectedNode.data.response || (streamingNodeId === selectedNode.id ? streamBuffer : '')}</ReactMarkdown> + <ReactMarkdown remarkPlugins={[remarkGfm, remarkMath]} rehypePlugins={[rehypeKatex]}>{preprocessLaTeX(selectedNode.data.response || (streamingNodeId === selectedNode.id ? streamBuffer : ''))}</ReactMarkdown> </div> )} </div> @@ -2203,7 +2214,7 @@ const Sidebar: React.FC<SidebarProps> = ({ isOpen, onToggle, onInteract }) => { /> ) : ( <div className="prose prose-sm max-w-none"> - <ReactMarkdown remarkPlugins={[remarkGfm]}>{selectedNode.data.response}</ReactMarkdown> + <ReactMarkdown remarkPlugins={[remarkGfm, remarkMath]} rehypePlugins={[rehypeKatex]}>{preprocessLaTeX(selectedNode.data.response || '')}</ReactMarkdown> </div> )} </div> @@ -2599,7 +2610,7 @@ const Sidebar: React.FC<SidebarProps> = ({ isOpen, onToggle, onInteract }) => { <p className="whitespace-pre-wrap">{msg.content}</p> ) : ( <div className={`prose prose-sm max-w-none ${isDark ? 'prose-invert' : ''}`}> - <ReactMarkdown remarkPlugins={[remarkGfm]}>{msg.content}</ReactMarkdown> + <ReactMarkdown remarkPlugins={[remarkGfm, remarkMath]} rehypePlugins={[rehypeKatex]}>{preprocessLaTeX(msg.content)}</ReactMarkdown> </div> )} </div> |
