diff --git a/lightrag_webui/src/components/retrieval/ChatMessage.tsx b/lightrag_webui/src/components/retrieval/ChatMessage.tsx index 1cb20792..9fbcd7b4 100644 --- a/lightrag_webui/src/components/retrieval/ChatMessage.tsx +++ b/lightrag_webui/src/components/retrieval/ChatMessage.tsx @@ -18,6 +18,16 @@ import { oneLight, oneDark } from 'react-syntax-highlighter/dist/cjs/styles/pris import { LoaderIcon, ChevronDownIcon } from 'lucide-react' import { useTranslation } from 'react-i18next' +// KaTeX configuration options interface +interface KaTeXOptions { + errorColor?: string; + throwOnError?: boolean; + displayMode?: boolean; + strict?: boolean; + trust?: boolean; + errorCallback?: (error: string, latex: string) => void; +} + export type MessageWithError = Message & { id: string // Unique identifier for stable React keys isError?: boolean @@ -38,7 +48,7 @@ export type MessageWithError = Message & { export const ChatMessage = ({ message }: { message: MessageWithError }) => { // Remove isComplete prop const { t } = useTranslation() const { theme } = useTheme() - const [katexPlugin, setKatexPlugin] = useState(null) + const [katexPlugin, setKatexPlugin] = useState<((options?: KaTeXOptions) => any) | null>(null) const [isThinkingExpanded, setIsThinkingExpanded] = useState(false) // Directly use props passed from the parent. @@ -64,26 +74,55 @@ export const ChatMessage = ({ message }: { message: MessageWithError }) => { // useEffect(() => { const loadKaTeX = async () => { try { - const [{ default: rehypeKatex }] = await Promise.all([ - import('rehype-katex'), - import('katex/dist/katex.min.css') - ]) - setKatexPlugin(() => rehypeKatex) + const { default: rehypeKatex } = await import('rehype-katex'); + setKatexPlugin(() => rehypeKatex); } catch (error) { - console.error('Failed to load KaTeX:', error) + console.error('Failed to load KaTeX plugin:', error); + // Set to null to ensure we don't try to use a failed plugin + setKatexPlugin(null); } - } - loadKaTeX() - }, []) + }; + + loadKaTeX(); + }, []); const mainMarkdownComponents = useMemo(() => ({ - code: (props: any) => ( - - ), + code: (props: any) => { + const { inline, className, children, ...restProps } = props; + const match = /language-(\w+)/.exec(className || ''); + const language = match ? match[1] : undefined; + + // Handle math blocks ($$...$$) - provide better container and styling + if (language === 'math' && !inline) { + return ( +
+
{children}
+
+ ); + } + + // Handle inline math ($...$) - ensure proper inline display + if (language === 'math' && inline) { + return ( + + {children} + + ); + } + + // Handle all other code (inline and block) + return ( + + {children} + + ); + }, p: ({ children }: { children?: ReactNode }) =>
{children}
, h1: ({ children }: { children?: ReactNode }) =>

{children}

, h2: ({ children }: { children?: ReactNode }) =>

{children}

, @@ -148,7 +187,14 @@ export const ChatMessage = ({ message }: { message: MessageWithError }) => { // throwOnError: false, displayMode: false, strict: false, - trust: true + trust: true, + // Add silent error handling to avoid console noise + errorCallback: (error: string, latex: string) => { + // Only show detailed errors in development environment + if (process.env.NODE_ENV === 'development') { + console.warn('KaTeX rendering error in thinking content:', error, 'for LaTeX:', latex); + } + } }] as any] : []), rehypeReact ]} @@ -182,7 +228,14 @@ export const ChatMessage = ({ message }: { message: MessageWithError }) => { // throwOnError: false, displayMode: false, strict: false, - trust: true + trust: true, + // Add silent error handling to avoid console noise + errorCallback: (error: string, latex: string) => { + // Only show detailed errors in development environment + if (process.env.NODE_ENV === 'development') { + console.warn('KaTeX rendering error in main content:', error, 'for LaTeX:', latex); + } + } } ] as any] : []), rehypeReact diff --git a/lightrag_webui/src/index.css b/lightrag_webui/src/index.css index d4413cec..aa3fa927 100644 --- a/lightrag_webui/src/index.css +++ b/lightrag_webui/src/index.css @@ -167,3 +167,62 @@ background-color: hsl(0 0% 0%); } } + +/* KaTeX Math Formula Styles */ +.katex-display-wrapper { + text-align: center; + position: relative; +} + +.katex-display-wrapper .katex-display { + margin: 0.5em 0; + text-align: center; +} + +.katex-inline-wrapper .katex { + font-size: inherit; + line-height: inherit; +} + +/* Ensure KaTeX formulas inherit color properly */ +.katex .base { + color: inherit; +} + +/* Improve KaTeX display for different themes */ +.katex .mord, +.katex .mop, +.katex .mbin, +.katex .mrel, +.katex .mpunct, +.katex .mopen, +.katex .mclose, +.katex .minner { + color: inherit; +} + +/* Fix KaTeX display overflow issues */ +.katex-display { + overflow-x: auto; + overflow-y: hidden; + max-width: 100%; +} + +.katex-display > .katex { + white-space: nowrap; +} + +/* Improve KaTeX error display */ +.katex .katex-error { + background-color: rgba(255, 0, 0, 0.1); + border: 1px solid rgba(255, 0, 0, 0.3); + border-radius: 4px; + padding: 2px 4px; + color: #dc2626; +} + +.dark .katex .katex-error { + background-color: rgba(255, 0, 0, 0.2); + border-color: rgba(255, 0, 0, 0.4); + color: #ef4444; +} diff --git a/lightrag_webui/src/main.tsx b/lightrag_webui/src/main.tsx index 081fef26..fb234a60 100644 --- a/lightrag_webui/src/main.tsx +++ b/lightrag_webui/src/main.tsx @@ -3,6 +3,7 @@ import { createRoot } from 'react-dom/client' import './index.css' import AppRouter from './AppRouter' import './i18n.ts'; +import 'katex/dist/katex.min.css';