Files
chat/frontend/src/components/Markdown.tsx
T

46 lines
1.5 KiB
TypeScript

import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import { CopyButton } from "./ui.tsx";
function CodeBlock({ code, lang }: { code: string; lang: string }) {
return (
<div className="relative">
{lang && (
<span className="absolute left-4 top-2.5 text-[11px] font-medium uppercase tracking-wide text-stone-400">{lang}</span>
)}
<div className="absolute right-2.5 top-2">
<CopyButton text={code} />
</div>
<pre className={lang ? "pt-9" : ""}>
<code>{code}</code>
</pre>
</div>
);
}
export function Markdown({ text }: { text: string }) {
return (
<div className="md space-y-3 text-[15px] leading-relaxed">
<ReactMarkdown
remarkPlugins={[remarkGfm]}
components={{
pre({ children }) {
// react-markdown nests <code> inside <pre>; render our block instead.
const child = Array.isArray(children) ? children[0] : children;
const props = (child as { props?: { className?: string; children?: unknown } })?.props;
const className = props?.className || "";
const lang = className.replace("language-", "");
const code = String(props?.children ?? "").replace(/\n$/, "");
return <CodeBlock code={code} lang={lang} />;
},
code({ children }) {
return <code>{children}</code>;
},
}}
>
{text}
</ReactMarkdown>
</div>
);
}