diff --git a/frontend/src/pages/front/ChatPage.tsx b/frontend/src/pages/front/ChatPage.tsx index edc3b06..bacbd3b 100644 --- a/frontend/src/pages/front/ChatPage.tsx +++ b/frontend/src/pages/front/ChatPage.tsx @@ -6,9 +6,7 @@ import type { Conversation, Message } from '@/types'; import './ChatPage.css'; // ===== 增强渲染依赖 ===== -import hljs from 'highlight.js'; import 'highlight.js/styles/github.css'; -import katex from 'katex'; import 'katex/dist/katex.min.css'; import mermaid from 'mermaid'; @@ -16,7 +14,7 @@ mermaid.initialize({ startOnLoad: false, theme: 'default' }); // ===== Enhanced Markdown Renderer ===== // 媒体(图片/视频)以受限缩略图呈现,并提供下载(格式+尺寸)选项 -interface MediaInfo { type: 'img' | 'video'; src: string; alt?: string; } +import { renderMarkdownToHtml, MediaInfo } from '@/utils/markdown'; // 全屏灯箱预览 const ChatLightbox: React.FC<{ src: string; type: 'img' | 'video'; onClose: () => void }> = ({ src, type, onClose }) => { @@ -154,182 +152,17 @@ const ChatMedia: React.FC<{ info: MediaInfo }> = ({ info }) => { }; const MarkdownContent: React.FC<{ content: string }> = ({ content }) => { + // 渲染管线(代码块/加粗/表格/换行/媒体占位符等)已抽到 src/utils/markdown.ts, + // 组件只负责把返回的 html 切分为「文本片段 + 媒体组件」。 + const { html, media } = useMemo(() => renderMarkdownToHtml(content), [content]); + const nodes = useMemo(() => { - let text = content; - - // 1. Extract code blocks first (protect from other replacements) - const codeBlocks: string[] = []; - const mermaidBlocks: string[] = []; - text = text.replace(/```(\w*)\n?([\s\S]*?)```/g, (_m: string, _lang: string, code: string) => { - if (_lang === 'mermaid') { - const idx = mermaidBlocks.length; - mermaidBlocks.push('
'); - return '\x00MERMAID' + idx + '\x00'; - } - const idx = codeBlocks.length; - codeBlocks.push('
' + escapeHtml(code.trim()) + '
'); - return '\x00CODEBLOCK' + idx + '\x00'; - }); - - // 2. Extract inline code - const inlineCodes: string[] = []; - text = text.replace(/`([^`]+)`/g, (_m: string, code: string) => { - const idx = inlineCodes.length; - inlineCodes.push('' + escapeHtml(code) + ''); - return '\x00INLINE' + idx + '\x00'; - }); - - // 2.5 Extract media blocks (/