diff --git a/apps/v4/mdx-components.tsx b/apps/v4/mdx-components.tsx index 1e81720c9f..623cfd925e 100644 --- a/apps/v4/mdx-components.tsx +++ b/apps/v4/mdx-components.tsx @@ -55,69 +55,156 @@ function ComponentsListWrapper() { ) } +function getNodeText(node: React.ReactNode): string { + if (typeof node === "string" || typeof node === "number") { + return String(node) + } + + if (Array.isArray(node)) { + return node.map((child) => getNodeText(child)).join("") + } + + if (React.isValidElement<{ children?: React.ReactNode }>(node)) { + return getNodeText(node.props.children) + } + + return "" +} + +function getHeadingId(children: React.ReactNode) { + const id = getNodeText(children) + .trim() + .replace(/\s+/g, "-") + .replace(/'/g, "") + .replace(/\?/g, "") + .toLowerCase() + + return id || undefined +} + +function HeadingAnchor({ + id, + children, +}: { + id?: string + children: React.ReactNode +}) { + if (!id) { + return children + } + + return ( + + + {children} + + + + ) +} + export const mdxComponents = { - h1: ({ className, ...props }: React.ComponentProps<"h1">) => ( -
- ), - h2: ({ className, ...props }: React.ComponentProps<"h2">) => { + h1: ({ className, children, id, ...props }: React.ComponentProps<"h1">) => { + const headingId = id ?? getHeadingId(children) + + return ( +