Spaces:
Running
Running
File size: 2,855 Bytes
6e29063 |
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 92 93 94 95 96 97 98 99 100 101 102 |
import { CodeHighlight } from "@mantine/code-highlight";
import { Box, Button, Code } from "@mantine/core";
import React, { lazy } from "react";
import rehypeExternalLinks from "rehype-external-links";
import remarkGfm from "remark-gfm";
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 (
<Button
component="a"
href={href}
target="_blank"
rel="nofollow noopener noreferrer"
variant="light"
color="gray"
size="compact-xs"
radius="xl"
style={{
textDecoration: "none",
transform: "translateY(-2px)",
}}
>
{children}
</Button>
);
},
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>;
},
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>
);
}
|