import { FC, memo, useMemo } from "react"; import ReactMarkdown, { Options, Components } from "react-markdown"; import { CodeBlock } from "./CodeBlock"; import remarkGfm from "remark-gfm"; import remarkMath from "remark-math"; import rehypeRaw from "rehype-raw"; const defaultComponents: Components = { a({ children, ...props }) { return ( {children} ); }, // @ts-expect-error -- inline code({ children, className, inline, ...props }) { if (Array.isArray(children) && children.length) { if (children[0] == "▍") { return ( ); } children[0] = (children?.[0] as string).replace("`▍`", "▍"); } const match = /language-(\w+)/.exec(className || ""); // Detect inline code: if it has a language class or contains newlines, it's likely a code block // Otherwise, treat it as inline code const hasLanguage = match && match[1]; const content = String(children); const hasNewlines = content.includes("\n"); const isInline = !hasLanguage && !hasNewlines; if (isInline) { return ( {children} ); } return ( ); }, h1: ({ children, ...props }) => (

{children}

), h2: ({ children, ...props }) => (

{children}

), h3: ({ children, ...props }) => (

{children}

), h4: ({ children, ...props }) => (

{children}

), h5: ({ children, ...props }) => (
{children}
), h6: ({ children, ...props }) => (
{children}
), p: ({ children, ...props }) => (
{children}
), pre: ({ children, ...props }) => (
      {children}
    
), blockquote: ({ children, ...props }) => (
{children}
), ul: ({ children, ...props }) => ( ), li: ({ children, ...props }) => (
  • {children}
  • ), }; const MemoizedReactMarkdown: FC = memo(ReactMarkdown); type MarkdownProps = Omit & { content: string; }; export const Markdown = ({ content, components, remarkPlugins, rehypePlugins, ...rest }: MarkdownProps) => { const mergedComponents = useMemo( () => ({ ...defaultComponents, ...components }), [components], ); const mergedRemarkPlugins = useMemo( () => [ remarkGfm, [remarkMath, { singleDollarTextMath: false }], ...(remarkPlugins ?? []), ], [remarkPlugins], ); const mergedRehypePlugins = useMemo( () => [rehypeRaw, ...(rehypePlugins ?? [])], [rehypePlugins], ); return (
    {content}
    ); };