Spaces:
Running
Running
File size: 2,578 Bytes
b6ec86d |
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 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
import { CodeHighlight } from "@mantine/code-highlight";
import { Box, Code, Divider } from "@mantine/core";
import React, { lazy } from "react";
import rehypeExternalLinks from "rehype-external-links";
import remarkGfm from "remark-gfm";
import ExpandableLink from "./ExpandableLink";
const Markdown = lazy(() => import("react-markdown"));
interface MarkdownRendererProps {
content: string;
enableCopy?: boolean;
className?: string;
}
export default function MarkdownRenderer({
content,
enableCopy = true,
className = "",
}: MarkdownRendererProps) {
if (!content) {
return null;
}
return (
<Box className={className}>
<Markdown
remarkPlugins={[remarkGfm]}
rehypePlugins={[
[
rehypeExternalLinks,
{ target: "_blank", rel: ["nofollow", "noopener", "noreferrer"] },
],
]}
components={{
a(props) {
const { href, children } = props;
return (
<ExpandableLink href={href || ""}>{children}</ExpandableLink>
);
},
li(props) {
const { children } = props;
const processedChildren = React.Children.map(children, (child) => {
if (React.isValidElement(child) && child.type === "p") {
return (child.props as { children: React.ReactNode }).children;
}
return child;
});
return <li>{processedChildren}</li>;
},
hr() {
return <Divider variant="dashed" my="md" />;
},
pre(props) {
return <>{props.children}</>;
},
code(props) {
const { children, className, node } = props;
const codeContent = children?.toString().replace(/\n$/, "") ?? "";
let language = "text";
if (className) {
const languageMatch = /language-(\w+)/.exec(className);
if (languageMatch) language = languageMatch[1];
}
if (
language === "text" &&
node?.position?.end.line === node?.position?.start.line
) {
return <Code>{codeContent}</Code>;
}
return (
<CodeHighlight
code={codeContent}
language={language}
radius="md"
withCopyButton={enableCopy}
mb="xs"
/>
);
},
}}
>
{content}
</Markdown>
</Box>
);
}
|