chat-with-gpt/app/src/components/markdown.tsx

65 lines
2.6 KiB
TypeScript
Raw Normal View History

2023-03-08 21:30:11 +00:00
import ReactMarkdown from 'react-markdown';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
import remarkGfm from 'remark-gfm';
import remarkMath from 'remark-math'
import rehypeKatex from 'rehype-katex'
import { Button, CopyButton } from '@mantine/core';
2023-03-10 22:00:37 +00:00
import { useMemo } from 'react';
2023-03-14 11:00:40 +00:00
import { FormattedMessage, useIntl } from 'react-intl';
2023-03-08 21:30:11 +00:00
export interface MarkdownProps {
content: string;
className?: string;
}
export function Markdown(props: MarkdownProps) {
2023-03-14 11:00:40 +00:00
const intl = useIntl();
2023-03-10 22:00:37 +00:00
const classes = useMemo(() => {
const classes = ['prose', 'dark:prose-invert'];
2023-03-08 21:30:11 +00:00
2023-03-10 22:00:37 +00:00
if (props.className) {
classes.push(props.className);
}
return classes;
}, [props.className])
const elem = useMemo(() => (
2023-03-08 21:30:11 +00:00
<div className={classes.join(' ')}>
<ReactMarkdown remarkPlugins={[remarkGfm, remarkMath]}
rehypePlugins={[rehypeKatex]}
components={{
code({ node, inline, className, children, ...props }) {
const match = /language-(\w+)/.exec(className || '')
return !inline ? (
<div>
<CopyButton value={String(children)}>
{({ copy, copied }) => (
<Button variant="subtle" size="sm" compact onClick={copy}>
<i className="fa fa-clipboard" />
2023-03-14 11:00:40 +00:00
<span>{copied ? <FormattedMessage defaultMessage="Copied" /> : <FormattedMessage defaultMessage="Copy" />}</span>
2023-03-08 21:30:11 +00:00
</Button>
)}
</CopyButton>
<SyntaxHighlighter
children={String(children).replace(/\n$/, '')}
style={vscDarkPlus as any}
language={match?.[1] || 'text'}
PreTag="div"
{...props}
/>
</div>
) : (
<code className={className} {...props}>
{children}
</code>
)
}
}}>{props.content}</ReactMarkdown>
</div>
2023-03-14 11:00:40 +00:00
), [props.content, classes, intl]);
2023-03-10 22:00:37 +00:00
return elem;
2023-03-08 21:30:11 +00:00
}