74 lines
2.0 KiB
TypeScript
74 lines
2.0 KiB
TypeScript
import React from "react";
|
|
import Markdown from "react-markdown";
|
|
import remarkGfm from "remark-gfm";
|
|
import remarkBreaks from "remark-breaks";
|
|
import remarkMath from "remark-math";
|
|
import rehypeRaw from "rehype-raw";
|
|
import rehypeKatex from "rehype-katex";
|
|
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
|
import { gruvboxDark } from "react-syntax-highlighter/dist/esm/styles/prism";
|
|
import "katex/dist/katex.min.css";
|
|
|
|
type MarkdownRendererProps = {
|
|
children: string;
|
|
};
|
|
|
|
export default function MarkdownRenderer({
|
|
children: markdown,
|
|
}: MarkdownRendererProps) {
|
|
return (
|
|
<Markdown
|
|
remarkPlugins={[remarkGfm, remarkMath, remarkBreaks]}
|
|
rehypePlugins={[rehypeRaw, rehypeKatex]}
|
|
components={{
|
|
code({ node, inline, className, children, ...props }: any) {
|
|
const match = /language-(\w+)/.exec(className || "");
|
|
return !inline && match ? (
|
|
<SyntaxHighlighter
|
|
style={gruvboxDark}
|
|
PreTag="div"
|
|
language={match[1]}
|
|
{...props}
|
|
>
|
|
{String(children).replace(/\n$/, "")}
|
|
</SyntaxHighlighter>
|
|
) : (
|
|
<code className={className} {...props}>
|
|
{children}
|
|
</code>
|
|
);
|
|
},
|
|
ul({ children, ...props }) {
|
|
return (
|
|
<ul
|
|
style={{ listStyleType: "disc", listStylePosition: "inside" }}
|
|
{...props}
|
|
>
|
|
{children}
|
|
</ul>
|
|
);
|
|
},
|
|
ol({ children, ...props }) {
|
|
return (
|
|
<ol
|
|
style={{ listStyleType: "decimal", listStylePosition: "inside" }}
|
|
{...props}
|
|
>
|
|
{children}
|
|
</ol>
|
|
);
|
|
},
|
|
li({ children, ...props }) {
|
|
return (
|
|
<li style={{ marginBottom: "4px" }} {...props}>
|
|
{children}
|
|
</li>
|
|
);
|
|
},
|
|
}}
|
|
>
|
|
{markdown}
|
|
</Markdown>
|
|
);
|
|
}
|