|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- import ReactMarkdown from 'react-markdown'
- import 'katex/dist/katex.min.css'
- import RemarkMath from 'remark-math'
- import RemarkBreaks from 'remark-breaks'
- import RehypeKatex from 'rehype-katex'
- import RemarkGfm from 'remark-gfm'
- import RehypeRaw from 'rehype-raw'
- import { flow } from 'lodash-es'
- import cn from '@/utils/classnames'
- import { customUrlTransform, preprocessLaTeX, preprocessThinkTag } from './markdown-utils'
- import {
- AudioBlock,
- CodeBlock,
- Img,
- Link,
- MarkdownButton,
- MarkdownForm,
- Paragraph,
- ScriptBlock,
- ThinkBlock,
- VideoBlock,
- } from '@/app/components/base/markdown-blocks'
-
- /**
- * @fileoverview Main Markdown rendering component.
- * This file was refactored to extract individual block renderers and utility functions
- * into separate modules for better organization and maintainability as of [Date of refactor].
- * Further refactoring candidates (custom block components not fitting general categories)
- * are noted in their respective files if applicable.
- */
- export type MarkdownProps = {
- content: string
- className?: string
- customDisallowedElements?: string[]
- customComponents?: Record<string, React.ComponentType<any>>
- }
-
- export const Markdown = (props: MarkdownProps) => {
- const { customComponents = {} } = props
- const latexContent = flow([
- preprocessThinkTag,
- preprocessLaTeX,
- ])(props.content)
-
- return (
- <div className={cn('markdown-body', '!text-text-primary', props.className)}>
- <ReactMarkdown
- remarkPlugins={[
- RemarkGfm,
- [RemarkMath, { singleDollarTextMath: false }],
- RemarkBreaks,
- ]}
- rehypePlugins={[
- RehypeKatex,
- RehypeRaw as any,
- // The Rehype plug-in is used to remove the ref attribute of an element
- () => {
- return (tree: any) => {
- const iterate = (node: any) => {
- if (node.type === 'element' && node.properties?.ref)
- delete node.properties.ref
-
- if (node.type === 'element' && !/^[a-z][a-z0-9]*$/i.test(node.tagName)) {
- node.type = 'text'
- node.value = `<${node.tagName}`
- }
-
- if (node.children)
- node.children.forEach(iterate)
- }
- tree.children.forEach(iterate)
- }
- },
- ]}
- urlTransform={customUrlTransform}
- disallowedElements={['iframe', 'head', 'html', 'meta', 'link', 'style', 'body', ...(props.customDisallowedElements || [])]}
- components={{
- code: CodeBlock,
- img: Img,
- video: VideoBlock,
- audio: AudioBlock,
- a: Link,
- p: Paragraph,
- button: MarkdownButton,
- form: MarkdownForm,
- script: ScriptBlock as any,
- details: ThinkBlock,
- ...customComponents,
- }}
- >
- {/* Markdown detect has problem. */}
- {latexContent}
- </ReactMarkdown>
- </div>
- )
- }
|