*]:border [&>*]:border-border [&>*]:p-4",
// NOTE: remove extra margin from prose grid cells of first and last element
"[&>*>*:first-child]:!mt-0 [&>*>*:last-child]:!mb-0",
colsClass[cols],
topBorderClass[cols],
leftBorderClass[cols],
className,
)}
>
{children}
);
}
function CustomLink(props: React.ComponentProps<"a">) {
const href = props.href ?? "";
if (href.startsWith("/")) {
return (
{props.children}
);
}
if (href.startsWith("#")) {
return ;
}
return ;
}
function ButtonLink(
props: React.ComponentProps & { href: string },
) {
return (
);
}
function Code({ children, className, ...props }: React.ComponentProps<"code">) {
// Only apply syntax highlighting if a language is specified (className contains "language-")
const hasLanguage = className?.includes("language-");
if (hasLanguage) {
const codeHTML = highlight(children?.toString() ?? "");
return (
dangerouslySetInnerHTML={{ __html: codeHTML }}
className={className}
{...props}
/>
);
}
// Plain code block without language - render as-is
return (
{children}
);
}
function extractTextFromReactNode(node: React.ReactNode): string {
if (typeof node === "string") {
return node;
}
if (typeof node === "number") {
return String(node);
}
if (Array.isArray(node)) {
return node.map(extractTextFromReactNode).join("");
}
if (React.isValidElement(node)) {
const props = node.props as { children?: React.ReactNode };
if (props.children) {
return extractTextFromReactNode(props.children);
}
}
return "";
}
function Pre({ children, ...props }: React.ComponentProps<"pre">) {
const textContent = extractTextFromReactNode(children);
return (
{children}
);
}
export function slugify(str: string) {
return str
.toString()
.toLowerCase()
.trim() // Remove whitespace from both ends of a string
.replace(/\s+/g, "-") // Replace spaces with -
.replace(/&/g, "-and-") // Replace & with 'and'
.replace(/[^\w-]+/g, "") // Remove all non-word characters except for -
.replace(/--+/g, "-"); // Replace multiple - with single -
}
function createHeading(level: number) {
const Heading = ({ children }: { children: React.ReactNode }) => {
const slug = slugify(children?.toString() ?? "");
return React.createElement(
`h${level}`,
{ id: slug },
[
React.createElement("a", {
href: `#${slug}`,
key: `link-${slug}`,
className: "anchor",
}),
],
children,
);
};
Heading.displayName = `Heading${level}`;
return Heading;
}
function Details({
children,
summary,
open = false,
}: {
children: React.ReactNode;
summary: string;
open?: boolean;
}) {
return (
{summary}
{React.isValidElement(children)
? // biome-ignore lint/suspicious/noExplicitAny:
React.cloneElement(children, { hidden: "until-found" } as any)
: children}
);
}
function CustomImage({
className,
...props
}: React.ComponentProps) {
const { src, alt, width, height, ...rest } = props;
if (!src || typeof src !== "string") {
return (
{alt}
);
}
// Get actual image dimensions from filesystem
const dimensions = getImageDimensions(src);
const imageWidth = width || dimensions?.width || 1200;
const imageHeight = height || dimensions?.height || 630;
// Generate dark mode image path by adding .dark before extension
const getDarkImagePath = (path: string) => {
const match = path.match(/^(.+)(\.[^.]+)$/);
if (match) {
return `${match[1]}.dark${match[2]}`;
}
return path;
};
// Check if dark image exists, fallback to light version if not
const checkDarkImageExists = (darkPath: string) => {
// If path starts with /, it's in the public directory
if (darkPath.startsWith("/")) {
const publicPath = join(process.cwd(), "public", darkPath);
return existsSync(publicPath);
}
// For relative paths, check relative to public
const publicPath = join(process.cwd(), "public", darkPath);
return existsSync(publicPath);
};
const darkSrc = getDarkImagePath(src);
const useDarkImage = checkDarkImageExists(darkSrc);
return (
{alt && {alt}}
);
}
export const components = {
h1: createHeading(1),
h2: createHeading(2),
h3: createHeading(3),
h4: createHeading(4),
h5: createHeading(5),
h6: createHeading(6),
Image: CustomImage,
a: CustomLink,
ButtonLink: ButtonLink,
code: Code,
pre: Pre,
Table,
Grid,
Details, // Capital D for JSX usage with props
details: Details, // lowercase for HTML tag replacement
SimpleChart: LatencyChartTable,
Tweet: (props: TweetProps) => {
return (