'use client';
import { Button } from '@workspace/ui/components/button';
import { cn } from '@workspace/ui/lib/utils';
import 'katex/dist/katex.min.css';
import { Check, Copy } from 'lucide-react';
import { useCallback, useState } from 'react';
import ReactMarkdown, { Components } from 'react-markdown';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
import rehypeKatex from 'rehype-katex';
import rehypeRaw from 'rehype-raw';
import remarkGfm from 'remark-gfm';
import remarkMath from 'remark-math';
import remarkToc from 'remark-toc';
interface CodeBlockProps {
className?: string;
children?: React.ReactNode;
[key: string]: unknown;
}
function CodeBlock({ className, children, ...props }: CodeBlockProps) {
const [copied, setCopied] = useState(false);
const match = className?.startsWith('language-') ? /language-(\w+)/.exec(className) : null;
const handleCopy = useCallback((text: string) => {
navigator.clipboard
.writeText(text)
.then(() => {
setCopied(true);
setTimeout(() => setCopied(false), 3000);
})
.catch(() => {
alert('Failed to copy text. Please try again.');
});
}, []);
if (match) {
return (
{match[1]}
{String(children).replace(/\n$/, '')}
);
}
return (
{children}
);
}
interface MarkdownProps {
children: string;
components?: Components;
}
export function Markdown({ children, components }: MarkdownProps) {
return (
(
),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
h2: ({ node, className, ...props }) => (
),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
h3: ({ node, className, ...props }) => (
),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
h4: ({ node, className, ...props }) => (
),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
h5: ({ node, className, ...props }) => (
),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
h6: ({ node, className, ...props }) => (
),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
p: ({ node, className, ...props }) => (
),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
a: ({ node, className, ...props }) => (
),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
blockquote: ({ node, className, ...props }) => (
),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
ul: ({ node, className, ...props }) => (
li]:mt-2', className)} {...props} />
),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
ol: ({ node, className, ...props }) => (
li]:mt-2', className)} {...props} />
),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
hr: ({ node, className, ...props }) => (
),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
table: ({ node, className, ...props }) => (
),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
th: ({ node, className, ...props }) => (
|
),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
td: ({ node, className, ...props }) => (
|
),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
tr: ({ node, className, ...props }) => (
td:first-child]:rounded-bl-lg [&:last-child>td:last-child]:rounded-br-lg',
className,
)}
{...props}
/>
),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
sup: ({ node, className, ...props }) => (
a]:text-xs [&>a]:no-underline', className)} {...props} />
),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
pre: ({ node, className, ...props }) => (
),
code(props) {
return ;
},
...components,
}}
>
{children}
);
}