refactor(markdown): Optimize rendering with memoized components and dynamic imports #2889
- Memoize math engine selection - Create dynamic components callback for markdown rendering - Optimize import statements for KaTeX extensions
This commit is contained in:
parent
70eb0a9187
commit
1738a74e8c
@ -1,12 +1,13 @@
|
|||||||
import 'katex/dist/katex.min.css'
|
import 'katex/dist/katex.min.css'
|
||||||
import 'katex/dist/contrib/copy-tex'
|
import 'katex/dist/contrib/copy-tex'
|
||||||
|
import 'katex/dist/contrib/mhchem'
|
||||||
|
|
||||||
import MarkdownShadowDOMRenderer from '@renderer/components/MarkdownShadowDOMRenderer'
|
import MarkdownShadowDOMRenderer from '@renderer/components/MarkdownShadowDOMRenderer'
|
||||||
import { useSettings } from '@renderer/hooks/useSettings'
|
import { useSettings } from '@renderer/hooks/useSettings'
|
||||||
import type { Message } from '@renderer/types'
|
import type { Message } from '@renderer/types'
|
||||||
import { escapeBrackets, removeSvgEmptyLines, withGeminiGrounding } from '@renderer/utils/formats'
|
import { escapeBrackets, removeSvgEmptyLines, withGeminiGrounding } from '@renderer/utils/formats'
|
||||||
import { isEmpty } from 'lodash'
|
import { isEmpty } from 'lodash'
|
||||||
import { type FC, useMemo } from 'react'
|
import { type FC, useCallback, useMemo } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import ReactMarkdown, { type Components } from 'react-markdown'
|
import ReactMarkdown, { type Components } from 'react-markdown'
|
||||||
import rehypeKatex from 'rehype-katex'
|
import rehypeKatex from 'rehype-katex'
|
||||||
@ -16,8 +17,6 @@ import rehypeRaw from 'rehype-raw'
|
|||||||
import remarkGfm from 'remark-gfm'
|
import remarkGfm from 'remark-gfm'
|
||||||
import remarkMath from 'remark-math'
|
import remarkMath from 'remark-math'
|
||||||
|
|
||||||
import 'katex/dist/contrib/mhchem'
|
|
||||||
|
|
||||||
import CodeBlock from './CodeBlock'
|
import CodeBlock from './CodeBlock'
|
||||||
import ImagePreview from './ImagePreview'
|
import ImagePreview from './ImagePreview'
|
||||||
import Link from './Link'
|
import Link from './Link'
|
||||||
@ -33,7 +32,7 @@ const Markdown: FC<Props> = ({ message }) => {
|
|||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { renderInputMessageAsMarkdown, mathEngine } = useSettings()
|
const { renderInputMessageAsMarkdown, mathEngine } = useSettings()
|
||||||
|
|
||||||
const rehypeMath = mathEngine === 'KaTeX' ? rehypeKatex : rehypeMathjax
|
const rehypeMath = useMemo(() => (mathEngine === 'KaTeX' ? rehypeKatex : rehypeMathjax), [mathEngine])
|
||||||
|
|
||||||
const messageContent = useMemo(() => {
|
const messageContent = useMemo(() => {
|
||||||
const empty = isEmpty(message.content)
|
const empty = isEmpty(message.content)
|
||||||
@ -47,6 +46,20 @@ const Markdown: FC<Props> = ({ message }) => {
|
|||||||
return hasElements ? [rehypeRaw, rehypeMath] : [rehypeMath]
|
return hasElements ? [rehypeRaw, rehypeMath] : [rehypeMath]
|
||||||
}, [messageContent, rehypeMath])
|
}, [messageContent, rehypeMath])
|
||||||
|
|
||||||
|
const components = useCallback(() => {
|
||||||
|
const baseComponents = {
|
||||||
|
a: Link,
|
||||||
|
code: CodeBlock,
|
||||||
|
img: ImagePreview
|
||||||
|
} as Partial<Components>
|
||||||
|
|
||||||
|
if (messageContent.includes('<style>')) {
|
||||||
|
baseComponents.style = MarkdownShadowDOMRenderer as any
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseComponents
|
||||||
|
}, [messageContent])
|
||||||
|
|
||||||
if (message.role === 'user' && !renderInputMessageAsMarkdown) {
|
if (message.role === 'user' && !renderInputMessageAsMarkdown) {
|
||||||
return <p style={{ marginBottom: 5, whiteSpace: 'pre-wrap' }}>{messageContent}</p>
|
return <p style={{ marginBottom: 5, whiteSpace: 'pre-wrap' }}>{messageContent}</p>
|
||||||
}
|
}
|
||||||
@ -56,14 +69,7 @@ const Markdown: FC<Props> = ({ message }) => {
|
|||||||
rehypePlugins={rehypePlugins}
|
rehypePlugins={rehypePlugins}
|
||||||
remarkPlugins={[remarkMath, remarkGfm]}
|
remarkPlugins={[remarkMath, remarkGfm]}
|
||||||
className="markdown"
|
className="markdown"
|
||||||
components={
|
components={components()}
|
||||||
{
|
|
||||||
style: MarkdownShadowDOMRenderer,
|
|
||||||
a: Link,
|
|
||||||
code: CodeBlock,
|
|
||||||
img: ImagePreview
|
|
||||||
} as Partial<Components>
|
|
||||||
}
|
|
||||||
remarkRehypeOptions={{
|
remarkRehypeOptions={{
|
||||||
footnoteLabel: t('common.footnotes'),
|
footnoteLabel: t('common.footnotes'),
|
||||||
footnoteLabelTagName: 'h4',
|
footnoteLabelTagName: 'h4',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user