diff --git a/packages/next-mdx/index.js b/packages/next-mdx/index.js
index 4d894b9af41d4..fbaa7bc4402f8 100644
--- a/packages/next-mdx/index.js
+++ b/packages/next-mdx/index.js
@@ -2,6 +2,7 @@ module.exports =
(pluginOptions = {}) =>
(nextConfig = {}) => {
const extension = pluginOptions.extension || /\.mdx$/
+ const userProvidedMdxOptions = pluginOptions.options
const mdxRsOptions = nextConfig?.experimental?.mdxRs
const loader = mdxRsOptions
@@ -9,16 +10,16 @@ module.exports =
loader: require.resolve('./mdx-rs-loader'),
options: {
providerImportSource: 'next-mdx-import-source-file',
- ...pluginOptions.options,
+ ...userProvidedMdxOptions,
// mdxRsOptions is a union of boolean and object type of MdxTransformOptions
...(mdxRsOptions === true ? {} : mdxRsOptions),
},
}
: {
- loader: require.resolve('@mdx-js/loader'),
+ loader: require.resolve('./mdx-js-loader'),
options: {
providerImportSource: 'next-mdx-import-source-file',
- ...pluginOptions.options,
+ ...userProvidedMdxOptions,
},
}
diff --git a/packages/next-mdx/mdx-js-loader.js b/packages/next-mdx/mdx-js-loader.js
new file mode 100644
index 0000000000000..4a7ae238b37c3
--- /dev/null
+++ b/packages/next-mdx/mdx-js-loader.js
@@ -0,0 +1,66 @@
+const mdxLoader = require('@mdx-js/loader')
+
+function interopDefault(mod) {
+ return mod.default || mod
+}
+
+async function importPlugin(plugin, projectRoot) {
+ if (Array.isArray(plugin) && typeof plugin[0] === 'string') {
+ plugin[0] = interopDefault(
+ await import(require.resolve(plugin[0], { paths: [projectRoot] }))
+ )
+ }
+ return plugin
+}
+
+async function getOptions(options, projectRoot) {
+ const {
+ recmaPlugins = [],
+ rehypePlugins = [],
+ remarkPlugins = [],
+ ...rest
+ } = options
+
+ const [updatedRecma, updatedRehype, updatedRemark] = await Promise.all([
+ Promise.all(
+ recmaPlugins.map((plugin) => importPlugin(plugin, projectRoot))
+ ),
+ Promise.all(
+ rehypePlugins.map((plugin) => importPlugin(plugin, projectRoot))
+ ),
+ Promise.all(
+ remarkPlugins.map((plugin) => importPlugin(plugin, projectRoot))
+ ),
+ ])
+
+ return {
+ ...rest,
+ recmaPlugins: updatedRecma,
+ rehypePlugins: updatedRehype,
+ remarkPlugins: updatedRemark,
+ }
+}
+
+module.exports = function nextMdxLoader(...args) {
+ const options = this.getOptions()
+ const callback = this.async().bind(this)
+ const loaderContext = this
+
+ getOptions(options, this.context).then((userProvidedMdxOptions) => {
+ const proxy = new Proxy(loaderContext, {
+ get(target, prop, receiver) {
+ if (prop === 'getOptions') {
+ return () => userProvidedMdxOptions
+ }
+
+ if (prop === 'async') {
+ return () => callback
+ }
+
+ return Reflect.get(target, prop, receiver)
+ },
+ })
+
+ mdxLoader.call(proxy, ...args)
+ })
+}
diff --git a/test/e2e/app-dir/mdx/app/rehype-plugin/page.mdx b/test/e2e/app-dir/mdx/app/rehype-plugin/page.mdx
new file mode 100644
index 0000000000000..daac920da9700
--- /dev/null
+++ b/test/e2e/app-dir/mdx/app/rehype-plugin/page.mdx
@@ -0,0 +1,5 @@
+# Rehype plugin
+
+```math
+C_L
+```
diff --git a/test/e2e/app-dir/mdx/mdx.test.ts b/test/e2e/app-dir/mdx/mdx.test.ts
index 516969ad9f27f..3e1afbca60428 100644
--- a/test/e2e/app-dir/mdx/mdx.test.ts
+++ b/test/e2e/app-dir/mdx/mdx.test.ts
@@ -8,6 +8,7 @@ for (const type of ['with-mdx-rs', 'without-mdx-rs']) {
'@next/mdx': 'canary',
'@mdx-js/loader': '^2.2.1',
'@mdx-js/react': '^2.2.1',
+ 'rehype-katex': '7.0.1',
},
env: {
WITH_MDX_RS: type === 'with-mdx-rs' ? 'true' : 'false',
@@ -59,6 +60,14 @@ for (const type of ['with-mdx-rs', 'without-mdx-rs']) {
'/_next/image?url=%2Ftest.jpg&w=384&q=75'
)
})
+
+ if (type === 'without-mdx-rs') {
+ it('should run plugins', async () => {
+ const html = await next.render('/rehype-plugin')
+ expect(html.includes('C')).toBe(true)
+ expect(html.includes('L')).toBe(true)
+ })
+ }
})
describe('pages directory', () => {
diff --git a/test/e2e/app-dir/mdx/next.config.js b/test/e2e/app-dir/mdx/next.config.mjs
similarity index 51%
rename from test/e2e/app-dir/mdx/next.config.js
rename to test/e2e/app-dir/mdx/next.config.mjs
index 4485a253ee1f7..f56317a7cadf4 100644
--- a/test/e2e/app-dir/mdx/next.config.js
+++ b/test/e2e/app-dir/mdx/next.config.mjs
@@ -1,5 +1,10 @@
-const withMDX = require('@next/mdx')({
+import nextMDX from '@next/mdx'
+const withMDX = nextMDX({
extension: /\.mdx?$/,
+ options: {
+ remarkPlugins: [],
+ rehypePlugins: [['rehype-katex', { strict: true, throwOnError: true }]],
+ },
})
/**
@@ -12,4 +17,4 @@ const nextConfig = {
},
}
-module.exports = withMDX(nextConfig)
+export default withMDX(nextConfig)