Skip to content

Commit 1e4df0f

Browse files
committed
migrate to next/mdx
1 parent ecc6fea commit 1e4df0f

File tree

10 files changed

+301
-196
lines changed

10 files changed

+301
-196
lines changed
Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { MDXComponents } from "mdx/types";
12
import Blockquote from "@/components/blockquote";
23
import ButtonLinks from "@/components/button-links";
34
import Callout, {
@@ -9,7 +10,6 @@ import Callout, {
910
} from "@/components/callout";
1011
import CardLinks from "@/components/card-links";
1112
import CodeBlock from "@/components/codeblock";
12-
import s from "@/components/custom-mdx/CustomMDX.module.css";
1313
import DonateCard from "@/components/donate-card";
1414
import GitHub from "@/components/github";
1515
import { processGitHubLinks } from "@/components/github/mdx";
@@ -19,7 +19,13 @@ import SponsorCard from "@/components/sponsor-card";
1919
import { BodyParagraph, LI } from "@/components/text";
2020
import VTSequence from "@/components/vt-sequence";
2121
import Video from "@/components/video";
22-
import { isValidElement, type ReactElement } from "react";
22+
import s from "@/lib/docs/docs-mdx.module.css";
23+
import {
24+
isValidElement,
25+
type ComponentPropsWithoutRef,
26+
type ImgHTMLAttributes,
27+
type ReactElement,
28+
} from "react";
2329

2430
type MermaidCodeElement = {
2531
className?: string;
@@ -33,35 +39,35 @@ function isReactElement(
3339
return isValidElement(children);
3440
}
3541

36-
// mdxComponents defines the React component map used by docs MDX compilation.
37-
export const mdxComponents = {
38-
h1: (props: React.ComponentPropsWithoutRef<"h1">) => (
42+
// mdxComponents defines the React component map used while rendering docs MDX.
43+
const mdxComponents: MDXComponents = {
44+
h1: (props: ComponentPropsWithoutRef<"h1">) => (
3945
<JumplinkHeader {...props} as="h1" />
4046
),
41-
h2: (props: React.ComponentPropsWithoutRef<"h2">) => (
47+
h2: (props: ComponentPropsWithoutRef<"h2">) => (
4248
<JumplinkHeader {...props} as="h2" />
4349
),
44-
h3: (props: React.ComponentPropsWithoutRef<"h3">) => (
50+
h3: (props: ComponentPropsWithoutRef<"h3">) => (
4551
<JumplinkHeader {...props} as="h3" />
4652
),
47-
h4: (props: React.ComponentPropsWithoutRef<"h4">) => (
53+
h4: (props: ComponentPropsWithoutRef<"h4">) => (
4854
<JumplinkHeader {...props} as="h4" />
4955
),
50-
h5: (props: React.ComponentPropsWithoutRef<"h5">) => (
56+
h5: (props: ComponentPropsWithoutRef<"h5">) => (
5157
<JumplinkHeader {...props} as="h5" />
5258
),
53-
h6: (props: React.ComponentPropsWithoutRef<"h6">) => (
59+
h6: (props: ComponentPropsWithoutRef<"h6">) => (
5460
<JumplinkHeader {...props} as="h6" />
5561
),
56-
li: (props: React.ComponentPropsWithoutRef<"li">) => {
62+
li: (props: ComponentPropsWithoutRef<"li">) => {
5763
const processedChildren = processGitHubLinks(props.children);
5864
return <LI {...props}>{processedChildren}</LI>;
5965
},
60-
p: (props: React.ComponentPropsWithoutRef<"p">) => {
66+
p: (props: ComponentPropsWithoutRef<"p">) => {
6167
const processedChildren = processGitHubLinks(props.children);
6268
return <BodyParagraph {...props}>{processedChildren}</BodyParagraph>;
6369
},
64-
code: (props: React.ComponentPropsWithoutRef<"code">) => {
70+
code: (props: ComponentPropsWithoutRef<"code">) => {
6571
if (!props.className) {
6672
return <code {...props} />;
6773
}
@@ -75,7 +81,7 @@ export const mdxComponents = {
7581

7682
return <code {...props} />;
7783
},
78-
pre: (props: React.ComponentPropsWithoutRef<"pre">) => {
84+
pre: (props: ComponentPropsWithoutRef<"pre">) => {
7985
const { children } = props;
8086
if (isReactElement(children)) {
8187
const className = children.props?.className;
@@ -93,7 +99,7 @@ export const mdxComponents = {
9399
return <CodeBlock {...props} />;
94100
},
95101
blockquote: Blockquote,
96-
img: (props: React.ImgHTMLAttributes<HTMLImageElement>) => (
102+
img: (props: ImgHTMLAttributes<HTMLImageElement>) => (
97103
// biome-ignore lint/performance/noImgElement: Docs content deliberately uses plain img tags.
98104
<img className={s.image} src={props.src} alt={props.alt} />
99105
),
@@ -115,3 +121,11 @@ export const mdxComponents = {
115121
<Mermaid {...props} />
116122
),
117123
};
124+
125+
// useMDXComponents returns the component map that Next.js uses while rendering MDX files.
126+
export function useMDXComponents(components: MDXComponents): MDXComponents {
127+
return {
128+
...mdxComponents,
129+
...components,
130+
};
131+
}

next.config.mjs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,42 @@
1+
import createMDX from "@next/mdx";
2+
import { createRequire } from "node:module";
3+
4+
// require resolves plugin module paths for the MDX loader in ESM config files.
5+
const require = createRequire(import.meta.url);
6+
7+
// gfmAlertsAsCalloutsPlugin points at the local remark plugin that maps GFM alerts to Callout nodes.
8+
const gfmAlertsAsCalloutsPlugin = require.resolve(
9+
"./src/lib/docs/remark-gfm-alerts-as-callouts.mjs",
10+
);
11+
12+
// headingIdsPlugin points at the local remark plugin that applies stable heading IDs.
13+
const headingIdsPlugin = require.resolve(
14+
"./src/lib/docs/remark-heading-ids.mjs",
15+
);
16+
17+
// syntaxHighlightingPlugin points at the local rehype plugin that enables code highlighting.
18+
const syntaxHighlightingPlugin = require.resolve(
19+
"./src/lib/docs/rehype-highlight-all.mjs",
20+
);
21+
22+
// withMDX configures the Next.js MDX pipeline for docs rendering.
23+
const withMDX = createMDX({
24+
extension: /\.mdx?$/,
25+
options: {
26+
remarkPlugins: [
27+
"remark-frontmatter",
28+
"remark-gfm",
29+
gfmAlertsAsCalloutsPlugin,
30+
headingIdsPlugin,
31+
],
32+
rehypePlugins: [syntaxHighlightingPlugin],
33+
},
34+
});
35+
36+
// nextConfig contains shared website framework and header behavior.
137
/** @type {import('next').NextConfig} */
238
const nextConfig = {
39+
pageExtensions: ["ts", "tsx", "js", "jsx", "md", "mdx"],
340
reactStrictMode: true,
441
experimental: {
542
// The homepage animation and docs reference pages intentionally ship
@@ -28,4 +65,4 @@ const nextConfig = {
2865
},
2966
};
3067

31-
export default nextConfig;
68+
export default withMDX(nextConfig);

0 commit comments

Comments
 (0)