File size: 2,214 Bytes
052672d
 
0fd8446
 
 
 
 
 
052672d
 
f80b091
 
 
 
052672d
0fd8446
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import { FC, memo } from 'react';
import ReactMarkdown, { Options } from 'react-markdown';
import Img from '../ui/Img';

import remarkGfm from 'remark-gfm';
import remarkMath from 'remark-math';
import rehypeRaw from 'rehype-raw';
import { CodeBlock } from '../ui/CodeBlock';

export const MemoizedReactMarkdown: FC<Options> = memo(
  ReactMarkdown,
  (prevProps, nextProps) =>
    prevProps.children === nextProps.children &&
    prevProps.className === nextProps.className,
);

export const Markdown: React.FC<{
  content: string;
}> = ({ content }) => {
  return (
    <>
      <MemoizedReactMarkdown
        className="break-words overflow-auto"
        remarkPlugins={[remarkGfm, remarkMath]}
        rehypePlugins={[rehypeRaw] as any}
        components={{
          p({ children, ...props }) {
            if (
              props.node.children.some(
                child => child.type === 'element' && child.tagName === 'img',
              )
            ) {
              return (
                <p className="flex flex-wrap gap-2 items-start">{children}</p>
              );
            }
            return <p className="mb-2 whitespace-pre-line">{children}</p>;
          },
          img(props) {
            if (props.src?.endsWith('.mp4')) {
              return (
                <video src={props.src} controls width={500} height={500} />
              );
            }
            return (
              <Img
                src={props.src ?? '/landing.png'}
                alt={props.alt ?? 'answer-image'}
                quality={100}
                sizes="(min-width: 66em) 15vw,
                        (min-width: 44em) 20vw,
                        100vw"
              />
            );
          },
          code({ node, inline, className, children, ...props }) {
            const match = /language-(\w+)/.exec(className || '');

            return (
              <CodeBlock
                key={Math.random()}
                language={(match && match[1]) || ''}
                value={String(children).replace(/\n$/, '')}
                {...props}
              />
            );
          },
        }}
      >
        {content}
      </MemoizedReactMarkdown>
    </>
  );
};