import { cn } from "@/lib/utils"; import { marked } from "marked"; import { Suspense, isValidElement, memo, useMemo } from "react"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; const DEFAULT_PRE_BLOCK_CLASS = "my-4 overflow-x-auto w-fit rounded-xl bg-zinc-950 text-zinc-50 dark:bg-zinc-900 border border-border p-4"; const extractTextContent = node => { if (typeof node === "string") { return node; } if (Array.isArray(node)) { return node.map(extractTextContent).join(""); } if (isValidElement(node)) { return extractTextContent(node.props.children); } return ""; }; const HighlightedPre = memo(async ({ children, className, language, ...props }) => { const { codeToTokens, bundledLanguages } = await import("shiki"); const code = extractTextContent(children); if (!(language in bundledLanguages)) { return ( (
                {children}
            
) ); } const { tokens } = await codeToTokens(code, { lang: language, themes: { light: "github-dark", dark: "github-dark", }, }); return ( (
            
                {tokens.map((line, lineIndex) => (
                    
                        {line.map((token, tokenIndex) => {
                            const style =
                                typeof token.htmlStyle === "string"
                                    ? undefined
                                    : token.htmlStyle;

                            return (
                                (
                                    {token.content}
                                )
                            );
                        })}
                        {lineIndex !== tokens.length - 1 && "\n"}
                    
                ))}
            
        
) ); }); HighlightedPre.displayName = "HighlightedPre"; const CodeBlock = ({ children, language, className, ...props }) => { return ( ( {children} }> {children} ) ); }; CodeBlock.displayName = "CodeBlock"; const components = { h1: ({ children, ...props }) => (

{children}

), h2: ({ children, ...props }) => (

{children}

), h3: ({ children, ...props }) => (

{children}

), h4: ({ children, ...props }) => (

{children}

), h5: ({ children, ...props }) => (
{children}
), h6: ({ children, ...props }) => (
{children}
), p: ({ children, ...props }) => (

{children}

), strong: ({ children, ...props }) => ( {children} ), a: ({ children, ...props }) => ( {children} ), ol: ({ children, ...props }) => (
    {children}
), ul: ({ children, ...props }) => ( ), li: ({ children, ...props }) => (
  • {children}
  • ), blockquote: ({ children, ...props }) => (
    {children}
    ), hr: (props) => (
    ), table: ({ children, ...props }) => (
    {children}
    ), tr: ({ children, ...props }) => ( {children} ), th: ({ children, ...props }) => ( {children} ), td: ({ children, ...props }) => ( {children} ), img: ({ alt, ...props }) => ( // biome-ignore lint/a11y/useAltText: alt is not required ({alt}) ), code: ({ children, node, className, ...props }) => { const match = /language-(\w+)/.exec(className || ""); if (match) { return ( ( {children} ) ); } return ( ( {children} ) ); }, pre: ({ children }) => <>{children}, }; function parseMarkdownIntoBlocks(markdown) { if (!markdown) { return []; } const tokens = marked.lexer(markdown); return tokens.map((token) => token.raw); } const MemoizedMarkdownBlock = memo(({ content, className }) => { return ( ( {content} ) ); }, (prevProps, nextProps) => { if (prevProps.content !== nextProps.content) { return false; } return true; }); MemoizedMarkdownBlock.displayName = "MemoizedMarkdownBlock"; export const MarkdownContent = memo(({ content, id, className }) => { const blocks = useMemo(() => parseMarkdownIntoBlocks(content || ""), [content]); return blocks.map((block, index) => ( index }`} /> )); }); MarkdownContent.displayName = "MarkdownContent";