cleanup markdown
This commit is contained in:
79
src/components/ClientMdx.tsx
Normal file
79
src/components/ClientMdx.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
"use client";
|
||||
|
||||
import { evaluate } from "@mdx-js/mdx";
|
||||
import { MDXProvider, useMDXComponents } from "@mdx-js/react";
|
||||
import type { MDXComponents } from "mdx/types";
|
||||
import { useEffect, useState, type ComponentType, type ReactNode } from "react";
|
||||
import * as runtime from "react/jsx-runtime";
|
||||
import rehypeHighlight from "rehype-highlight";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import { mdxComponents } from "~/components/mdx-components";
|
||||
|
||||
type MdxModule = {
|
||||
default: ComponentType<{ components?: MDXComponents }>;
|
||||
};
|
||||
|
||||
type ClientMdxProps = {
|
||||
source: string;
|
||||
components?: MDXComponents;
|
||||
format?: "md" | "mdx";
|
||||
fallback?: ReactNode;
|
||||
errorFallback?: (error: Error) => ReactNode;
|
||||
};
|
||||
|
||||
export function ClientMdx({
|
||||
source,
|
||||
components = mdxComponents,
|
||||
format = "md",
|
||||
fallback = null,
|
||||
errorFallback,
|
||||
}: ClientMdxProps) {
|
||||
const [Content, setContent] = useState<MdxModule["default"] | null>(null);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
const trimmed = source.trim();
|
||||
|
||||
if (!trimmed) {
|
||||
setContent(null);
|
||||
setError(null);
|
||||
return;
|
||||
}
|
||||
|
||||
void evaluate(trimmed, {
|
||||
...runtime,
|
||||
baseUrl: import.meta.url,
|
||||
format,
|
||||
useMDXComponents,
|
||||
rehypePlugins: [rehypeHighlight],
|
||||
remarkPlugins: [remarkGfm],
|
||||
})
|
||||
.then((mod) => {
|
||||
if (cancelled) return;
|
||||
setContent(() => (mod as MdxModule).default);
|
||||
setError(null);
|
||||
})
|
||||
.catch((nextError: unknown) => {
|
||||
if (cancelled) return;
|
||||
setContent(null);
|
||||
setError(nextError instanceof Error ? nextError : new Error("Failed to render MDX"));
|
||||
});
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [format, source]);
|
||||
|
||||
if (error) {
|
||||
return errorFallback ? errorFallback(error) : <p>{source}</p>;
|
||||
}
|
||||
|
||||
if (!Content) return <>{fallback}</>;
|
||||
|
||||
return (
|
||||
<MDXProvider components={components}>
|
||||
<Content components={components} />
|
||||
</MDXProvider>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user