Markdown.tsx 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. import { PropsWithChildren } from 'react'
  2. import ReactMarkdown, { type Options } from 'react-markdown'
  3. import remarkGfm from 'remark-gfm'
  4. import { cn } from 'ui'
  5. import { InlineLink } from '@/components/ui/InlineLink'
  6. interface MarkdownProps extends Omit<Options, 'children' | 'node'> {
  7. className?: string
  8. /** @deprecated Should remove this and just take `children` instead */
  9. content?: string
  10. extLinks?: boolean
  11. }
  12. const H3 = ({
  13. children,
  14. }: React.DetailedHTMLProps<React.HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>) => (
  15. <h3 className="mb-1">{children}</h3>
  16. )
  17. const Code = ({
  18. children,
  19. }: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>) => (
  20. <code className="text-code-inline">{children}</code>
  21. )
  22. const A = ({
  23. href,
  24. children,
  25. }: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>) => (
  26. <InlineLink href={href ?? '/'}>{children}</InlineLink>
  27. )
  28. export const Markdown = ({
  29. children,
  30. className,
  31. content = '',
  32. extLinks = false,
  33. ...props
  34. }: PropsWithChildren<MarkdownProps>) => {
  35. return (
  36. <div className={cn('text-sm', className)}>
  37. <ReactMarkdown
  38. remarkPlugins={[remarkGfm]}
  39. components={{
  40. h3: H3,
  41. code: Code,
  42. a: A,
  43. }}
  44. {...props}
  45. >
  46. {(children as string) ?? content}
  47. </ReactMarkdown>
  48. </div>
  49. )
  50. }