import Link from "next/link"; import { Children, isValidElement, type ComponentPropsWithoutRef, type ReactNode, } from "react"; import { Badge } from "~/components/ui/badge"; import { Button } from "~/components/ui/button"; import { cn } from "~/lib/utils"; type CalloutVariant = "note" | "tip" | "warning"; const calloutStyles: Record = { note: "border-sky-500/40 bg-sky-500/10 text-sky-950 dark:text-sky-100", tip: "border-emerald-500/40 bg-emerald-500/10 text-emerald-950 dark:text-emerald-100", warning: "border-amber-500/40 bg-amber-500/10 text-amber-950 dark:text-amber-100", }; function Callout({ title, variant = "note", children, }: { title?: string; variant?: CalloutVariant; children: ReactNode; }) { return ( ); } function Lead({ children }: { children: ReactNode }) { return {children}; } function TagList({ tags }: { tags: string[] }) { return (
{tags.map((tag) => ( {tag} ))}
); } function ButtonLink({ href, children, variant = "default", }: { href: string; children: ReactNode; variant?: ComponentPropsWithoutRef["variant"]; }) { const isExternal = /^https?:\/\//.test(href); return ( ); } function Figure({ src, alt, caption, }: { src: string; alt: string; caption?: string; }) { return (
{alt} {caption &&
{caption}
}
); } // A bare markdown image (![alt](src)) fills the prose width. Pass a numeric // markdown title — ![alt](src "160") — to render it as a fixed-size, circular // avatar instead (used by the CV header). Untitled images keep the old look. function Img({ src, alt, title }: { src: string; alt?: string; title?: string }) { const size = title && /^\d+$/.test(title) ? Number(title) : undefined; if (size) { return ( {alt ); } return {alt; } function PullQuote({ children }: { children: ReactNode }) { return (
{children}
); } function ExternalLink(props: ComponentPropsWithoutRef<"a">) { const href = props.href ?? ""; const isExternal = /^https?:\/\//.test(href); if (!isExternal) return ; return ; } const blockComponents = new Set([Callout, Figure, PullQuote, TagList]); function Paragraph({ children }: { children: ReactNode }) { const containsBlockComponent = Children.toArray(children).some( (child) => isValidElement(child) && blockComponents.has(child.type), ); if (containsBlockComponent) return <>{children}; return

{children}

; } export const mdxComponents = { a: ExternalLink, p: Paragraph, Badge, ButtonLink, Callout, Figure, img: Img, Lead, PullQuote, TagList, };