MarkdownText.tsx raw

   1  import { ExternalLink } from 'lucide-react'
   2  import { memo } from 'react'
   3  import Markdown from 'react-markdown'
   4  import remarkGfm from 'remark-gfm'
   5  import remarkBreaks from 'remark-breaks'
   6  
   7  const MarkdownText = memo(function MarkdownText({ text }: { text: string }) {
   8    return (
   9      <Markdown
  10        remarkPlugins={[remarkGfm, remarkBreaks]}
  11        components={{
  12          a: ({ href, children, ...props }) => (
  13            <a
  14              {...props}
  15              href={href}
  16              target="_blank"
  17              rel="noreferrer noopener"
  18              className="break-words inline-flex items-baseline gap-1 underline text-foreground"
  19            >
  20              {children} <ExternalLink className="size-3" />
  21            </a>
  22          ),
  23          p: ({ children, ...props }) => <span {...props} className="break-words">{children}</span>,
  24          code: ({ className, children, ...props }) => {
  25            const isBlock = className?.startsWith('language-')
  26            if (isBlock) {
  27              return (
  28                <code {...props} className={`${className ?? ''} break-words whitespace-pre-wrap`}>
  29                  {children}
  30                </code>
  31              )
  32            }
  33            return (
  34              <code {...props} className="bg-muted px-1 py-0.5 rounded text-sm break-words">
  35                {children}
  36              </code>
  37            )
  38          },
  39          pre: (props) => (
  40            <pre
  41              {...props}
  42              className="bg-muted rounded-md p-3 overflow-x-auto my-2 text-sm whitespace-pre-wrap"
  43            />
  44          ),
  45          img: (props) => (
  46            <img
  47              {...props}
  48              className="max-w-full max-h-[50vh] object-contain rounded-md my-2"
  49              loading="lazy"
  50            />
  51          )
  52        }}
  53      >
  54        {text}
  55      </Markdown>
  56    )
  57  })
  58  
  59  export default MarkdownText
  60