import { FC, memo } 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, (prevProps, nextProps) => prevProps.children === nextProps.children && prevProps.components === nextProps.components, ); type MarkdownProps = { content: string; components?: Components; }; export const Markdown = ({ content, components }: MarkdownProps) => { return (
    {content}
    ); };