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}
), strong: ({ children, ...props }) => ( {children} ), a: ({ children, ...props }) => ( {children} ), ol: ({ children, ...props }) => ({children}), hr: (props) => (
{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 (
(