"use client"; import "@/style/mdx.css"; import { cn } from "@/lib/utils"; import "katex/dist/katex.min.css"; import remarkGfm from "remark-gfm"; import remarkMath from "remark-math"; import rehypeKatex from "rehype-katex"; // import rehypeSlug from "rehype-slug"; import rehypePretty from "rehype-pretty-code"; import { Skeleton } from "@/components/ui/skeleton"; import { serialize } from "next-mdx-remote/serialize"; import { useCallback, useEffect, useState } from "react"; import { CircleAlert, TriangleAlert } from "lucide-react"; import { useMonacoTheme } from "@/hooks/use-monaco-theme"; // import rehypeAutolinkHeadings from "rehype-autolink-headings"; import { MdxComponents } from "@/components/content/mdx-components"; import { MDXRemote, MDXRemoteSerializeResult } from "next-mdx-remote"; interface MdxPreviewProps { source: string; className?: string; } export default function MdxPreview({ source, className, }: MdxPreviewProps) { const { currentTheme } = useMonacoTheme(); const [error, setError] = useState(null); const [isLoading, setIsLoading] = useState(true); const [mdxSource, setMdxSource] = useState(null); const getMdxSource = useCallback(async () => { setIsLoading(true); setError(null); try { const mdxSource = await serialize(source, { mdxOptions: { rehypePlugins: [ // rehypeSlug, // [ // rehypeAutolinkHeadings, // { // behavior: "wrap", // properties: { // className: ["subheading-anchor"], // ariaLabel: "Link to section", // }, // }, // ], [ rehypePretty, { theme: currentTheme, keepBackground: false, }, ], rehypeKatex, ], remarkPlugins: [remarkGfm, remarkMath], }, }); setMdxSource(mdxSource); } catch (error) { console.error("Failed to serialize Mdx:", error); setError("Failed to load mdx content."); } finally { setIsLoading(false); } }, [source, currentTheme]); // Delay the serialize process to the next event loop to avoid flickering // when copying code to the editor and the MDX preview shrinks. useEffect(() => { const timeoutId = setTimeout(() => { getMdxSource(); // Execute serializeMdx in the next event loop }, 0); return () => clearTimeout(timeoutId); // Cleanup timeout on component unmount }, [getMdxSource]); if (isLoading) { return (
); } if (error) { return (

); } if (!source) { return (

); } return (
); }