作者:Titus Wormer
快速开始
本文解释了如何将 MDX 集成到你的项目中。 它展示了如何使用你选择的打包器和 JSX 运行时。 要了解 MDX 格式的工作原理, 我们建议你先阅读§ 什么是 MDX。 如果你已经配置好并准备使用 MDX,请参见§ 使用 MDX。
目录
前置条件
MDX 依赖 JSX, 因此你的项目也需要支持 JSX。 任何 JSX 运行时(React、Preact、Vue 等)都可以。 请注意,我们会为你将 JSX 编译为 JavaScript,所以你不需要自行配置。
所有 @mdx-js/* 包都是用现代 JavaScript 编写的。 需要 Node.js 16 或更高版本才能使用。 我们的包也是仅支持 ESM 的。
注意:使用 Rust 而非 Node.js? 试试 mdxjs-rs!
快速入门
打包器
MDX 是一种编译为 JavaScript 的语言。 (我们也编译普通 Markdown 为 JavaScript。) 最简单的入门方式是使用你的打包器的集成(如果你有的话):
- 如果你使用 esbuild(或 Bun), 安装并配置
@mdx-js/esbuild - 如果你使用 Rollup(或 Vite), 安装并配置
@mdx-js/rollup - 如果你使用 webpack(或 Next.js), 安装并配置
@mdx-js/loader
你也可以在不用打包器的情况下使用 MDX:
- 你可以在 Node.js 中使用
@mdx-js/node-loader导入 MDX 文件 - 你可以使用我们的核心编译器
@mdx-js/mdx来编译 MDX 文件 - 你可以使用我们的核心编译器
@mdx-js/mdx来 执行(编译并运行)MDX 文件
有关这些工具的更多信息, 请参见它们的专门章节: ¶ Next.js、 ¶ Node.js、 ¶ Rollup、 ¶ Vite、 ¶ esbuild 和 ¶ webpack。
JSX
现在你已经设置了集成或 @mdx-js/mdx 本身, 是时候配置你的 JSX 运行时了。
- 如果你使用 React, 这是默认的; 可选安装和配置
@mdx-js/react - 如果你使用 Preact, 将
ProcessorOptions中的jsxImportSource设置为'preact'; 可选安装和配置@mdx-js/preact - 如果你使用 Svelte, 安装
svelte-jsx, 并将ProcessorOptions中的jsxImportSource设置为'svelte-jsx' - 如果你使用 Vue, 将
ProcessorOptions中的jsxImportSource设置为'vue'; 可选安装和配置@mdx-js/vue - 如果你使用 Solid, 将
ProcessorOptions中的jsxImportSource设置为'solid-js/h' - 如果你使用 Emotion, 将
ProcessorOptions中的jsxImportSource设置为'@emotion/react' - 如果你使用 Theme UI, 安装和配置
@mdx-js/react, 然后用<ThemeProvider />包裹你的 MDX 内容
其他 JSX 运行时通过设置 ProcessorOptions 中的 jsxImportSource 来支持。
有关这些工具的更多信息, 请参见它们的专门章节: ¶ Emotion、 ¶ Preact、 ¶ React、 ¶ Solid、 ¶ Svelte、 ¶ Theme UI 和 ¶ Vue。
编辑器
你可以通过在编辑器中添加 MDX 支持来提升使用体验:
- 如果你使用 VS Code, 试试
mdx-js/mdx-analyzer - 如果你使用 Vim, 试试
jxnblk/vim-mdx-js - 如果你使用 Sublime Text, 试试
jonsuh/mdx-sublime - 如果你使用 JetBrains IntelliJ/WebStorm, 试试
JetBrains/mdx-intellij-plugin
为我们的 VS Code 扩展提供语法高亮、并在 GitHub 上用于高亮代码块的语法高亮 维护于 wooorm/markdown-tm-language。
类型
展开类型化导入的示例
首先安装包:
npm install @types/mdx
…TypeScript 应该会自动识别:
import Post from './post.mdx' // `Post` 现在有类型了。
(alias) function Post(props: MDXProps): Element
import PostAn function component which renders the MDX content using JSX.
- @param props This value is be available as the named variable
propsinside the MDX component. - @returns A JSX element. The meaning of this may depend on the project configuration. I.e. it could be a React, Preact, or Vuex element.
我们的包使用 TypeScript 进行类型标注。 要让类型工作, JSX 命名空间必须被类型化。 这通过安装和使用你框架的类型来完成, 例如 @types/react, 然后增强 mdx/types.js 模块。
import * as React from 'react'
declare module 'mdx/types.js' {
export import JSX = React.JSX
}
(alias) namespace React
import React(alias) namespace JSX
import JSX = JSX(alias) namespace React
import Reactnamespace JSX要为导入的 .mdx、.md 等启用类型, 安装并使用 @types/mdx。 这个包还导出了几个有用的类型, 例如 MDXComponents,它代表 components 属性。 你可以这样导入它们:
import type {MDXComponents} from 'mdx/types.js'
(alias) type MDXComponents = NestedMDXComponents & {
[x: string]: Component<JSX.IntrinsicElements> | undefined;
} & {
wrapper?: Component<any>;
}
import MDXComponentsMDX components may be passed as the components.
The key is the name of the element to override. The value is the component to render instead.
安全
MDX 是一种编程语言。 如果你信任你的作者, 那没问题。 如果你不信任, 那就不安全。
不要让互联网上的随机人员编写 MDX。 如果你这样做, 你可能需要考虑使用带 sandbox 的 <iframe>, 但安全很难, 而且这似乎不是 100% 安全的。 对于 Node.js, vm2 听起来不错。 但你可能还需要使用 Docker 或类似工具对整个操作系统进行沙箱化, 执行速率限制, 并确保进程在耗时过长时可以被终止。
集成
打包器
esbuild
展开示例
import mdx from '@mdx-js/esbuild'
import esbuild from 'esbuild'
await esbuild.build({
entryPoints: ['index.mdx'],
format: 'esm',
outfile: 'output.js',
plugins: [mdx({/* jsxImportSource: …, otherOptions… */})]
})
(alias) function mdx(options?: Readonly<Options> | null | undefined): esbuild.Plugin
import mdxCreate an esbuild plugin to compile MDX to JS.
esbuild takes care of turning modern JavaScript features into syntax that works wherever you want it to. With other integrations you might need to use Babel for this, but with esbuild that’s not needed. See esbuild’s docs for more info.
- @param options Configuration (optional).
- @return Plugin.
import esbuildimport esbuildfunction build<{
entryPoints: string[];
format: "esm";
outfile: string;
plugins: esbuild.Plugin[];
}>(options: esbuild.SameShape<esbuild.BuildOptions, {
entryPoints: string[];
format: "esm";
outfile: string;
plugins: esbuild.Plugin[];
}>): Promise<esbuild.BuildResult<{
entryPoints: string[];
format: "esm";
outfile: string;
plugins: esbuild.Plugin[];
}>>This function invokes the "esbuild" command-line tool for you. It returns a promise that either resolves with a "BuildResult" object or rejects with a "BuildFailure" object.
- Works in node: yes
- Works in browser: yes
Documentation: https://esbuild.github.io/api/#build
(property) entryPoints: string[](property) format: "esm"(property) outfile: string(property) plugins: esbuild.Plugin[](alias) mdx(options?: Readonly<Options> | null | undefined): esbuild.Plugin
import mdxCreate an esbuild plugin to compile MDX to JS.
esbuild takes care of turning modern JavaScript features into syntax that works wherever you want it to. With other integrations you might need to use Babel for this, but with esbuild that’s not needed. See esbuild’s docs for more info.
- @param options Configuration (optional).
- @return Plugin.
我们支持 esbuild。 安装并配置 esbuild 插件 @mdx-js/esbuild。 根据你使用的运行时(React、Preact、Vue 等)配置你的 JSX 运行时。
要使用比你用户支持的更现代的 JavaScript 特性, 配置 esbuild 的 target。
另见 ¶ Bun, 你可能正在使用它, 获取更多信息。
Rollup
展开示例
/**
* @import {RollupOptions} from 'rollup'
*/
import mdx from '@mdx-js/rollup'
import {babel} from '@rollup/plugin-babel'
/** @type {RollupOptions} */
const config = {
// …
plugins: [
// …
mdx({/* jsxImportSource: …, otherOptions… */}),
// Babel 是可选的:
babel({
// Also run on what used to be `.mdx` (but is now JS):
extensions: ['.js', '.jsx', '.cjs', '.mjs', '.md', '.mdx'],
// Other options…
})
]
}
export default config
(alias) function mdx(options?: Readonly<Options> | null | undefined): Plugin
import mdxPlugin to compile MDX w/ rollup.
- @param options Configuration (optional).
- @return Rollup plugin.
(alias) function babel(options?: RollupBabelInputPluginOptions): Plugin
import babelA Rollup plugin for seamless integration between Rollup and Babel.
- @param options - Plugin options.
- @returns Plugin instance.
const config: RollupOptions- @type {RollupOptions}
(property) InputOptions.plugins?: InputPluginOption(alias) mdx(options?: Readonly<Options> | null | undefined): Plugin
import mdxPlugin to compile MDX w/ rollup.
- @param options Configuration (optional).
- @return Rollup plugin.
(alias) babel(options?: RollupBabelInputPluginOptions): Plugin
import babelA Rollup plugin for seamless integration between Rollup and Babel.
- @param options - Plugin options.
- @returns Plugin instance.
(property) RollupBabelInputPluginOptions.extensions?: string[]An array of file extensions that Babel should transpile. If you want to transpile TypeScript files with this plugin it's essential to include .ts and .tsx in this option.
- @default ['.js', '.jsx', '.es6', '.es', '.mjs']
const config: RollupOptions- @type {RollupOptions}
我们支持 Rollup。 安装并配置 Rollup 插件 @mdx-js/rollup。 根据你使用的运行时(React、Preact、Vue 等)配置你的 JSX 运行时。
要使用比你用户支持的更现代的 JavaScript 特性, 安装并配置 @rollup/plugin-babel。
另见 ¶ Vite, 如果你通过它使用 Rollup, 获取更多信息。
Webpack
展开示例
/**
* @import {Options} from '@mdx-js/loader'
* @import {Configuration} from 'webpack'
*/
/** @type {Configuration} */
const webpackConfig = {
module: {
// …
rules: [
// …
{
test: /\.mdx?$/,
use: [
// Babel 是可选的:
{loader: 'babel-loader', options: {}},
{
loader: '@mdx-js/loader',
/** @type {Options} */
options: {/* jsxImportSource: …, otherOptions… */}
}
]
}
]
}
}
export default webpackConfig
const webpackConfig: Configuration- @type {Configuration}
(property) Configuration.module?: ModuleOptionsOptions affecting the normal modules (NormalModuleFactory).
(property) ModuleOptions.rules?: (false | "" | 0 | RuleSetRule | "..." | null | undefined)[]An array of rules applied for modules.
(property) RuleSetRule.test?: string | RegExp | ((value: string) => boolean) | RuleSetLogicalConditionsAbsolute | RuleSetConditionAbsolute[]Shortcut for resource.test.
(property) RuleSetRule.use?: string | RuleSetUseFunction | (string | false | 0 | RuleSetUseFunction | {
ident?: string;
loader?: string;
options?: string | {
[index: string]: any;
};
} | null | undefined)[] | {
ident?: string;
loader?: string;
options?: string | {
[index: string]: any;
};
}Modifiers applied to the module when rule is matched.
(property) loader?: stringLoader name.
(property) options?: string | {
[index: string]: any;
}Loader options.
(property) loader?: stringLoader name.
(property) options?: string | {
[index: string]: any;
}Loader options.
const webpackConfig: Configuration- @type {Configuration}
我们支持 webpack。 安装并配置 webpack loader @mdx-js/loader。 根据你使用的运行时(React、Preact、Vue 等)配置你的 JSX 运行时。
要使用比你用户支持的更现代的 JavaScript 特性, 安装并配置 babel-loader。
另见 ¶ Next.js, 如果你通过它使用 webpack, 获取更多信息。
构建系统
Vite
展开示例
import mdx from '@mdx-js/rollup'
import {defineConfig} from 'vite'
const viteConfig = defineConfig({
plugins: [
mdx(/* jsxImportSource: …, otherOptions… */)
]
})
export default viteConfig
(alias) function mdx(options?: Readonly<Options> | null | undefined): Plugin
import mdxPlugin to compile MDX w/ rollup.
- @param options Configuration (optional).
- @return Rollup plugin.
(alias) function defineConfig(config: UserConfig): UserConfig (+5 overloads)
import defineConfigType helper to make it easier to use vite.config.ts accepts a direct {@link UserConfig } object, or a function that returns it. The function receives a {@link ConfigEnv } object.
const viteConfig: UserConfig(alias) defineConfig(config: UserConfig): UserConfig (+5 overloads)
import defineConfigType helper to make it easier to use vite.config.ts accepts a direct {@link UserConfig } object, or a function that returns it. The function receives a {@link ConfigEnv } object.
(property) UserConfig.plugins?: PluginOption[]Array of vite plugins to use.
(alias) mdx(options?: Readonly<Options> | null | undefined): Plugin
import mdxPlugin to compile MDX w/ rollup.
- @param options Configuration (optional).
- @return Rollup plugin.
const viteConfig: UserConfig我们支持 Vite。 安装并配置 Rollup 插件 @mdx-js/rollup。 根据你使用的运行时(React、Preact、Vue 等)配置你的 JSX 运行时。
要使用比你用户支持的更现代的 JavaScript 特性, 配置 Vite 的 build.target。
注意:如果你同时使用 @vitejs/plugin-react, 你必须强制 @mdx-js/rollup 在它之前的 pre 阶段运行:
// …
const viteConfig = defineConfig({
plugins: [
{enforce: 'pre', ...mdx({/* jsxImportSource: …, otherOptions… */})},
react({include: /\.(jsx|js|mdx|md|tsx|ts)$/})
]
})
// …
const viteConfig: UserConfig(alias) defineConfig(config: UserConfig): UserConfig (+5 overloads)
import defineConfigType helper to make it easier to use vite.config.ts accepts a direct {@link UserConfig } object, or a function that returns it. The function receives a {@link ConfigEnv } object.
(property) UserConfig.plugins?: PluginOption[]Array of vite plugins to use.
(property) Plugin<any>.enforce?: "pre" | "post"Enforce plugin invocation tier similar to webpack loaders. Hooks ordering is still subject to the order property in the hook object.
Plugin invocation order:
- alias resolution
enforce: 'pre'plugins- vite core plugins
- normal plugins
- vite build plugins
enforce: 'post'plugins- vite build post plugins
(alias) mdx(options?: Readonly<Options> | null | undefined): Plugin
import mdxPlugin to compile MDX w/ rollup.
- @param options Configuration (optional).
- @return Rollup plugin.
(alias) react(opts?: Options): Plugin[]
import react(property) Options.include?: string | RegExp | (string | RegExp)[]另见 Vite 中使用的 ¶ Rollup,如果你使用 Vue 请参见 ¶ Vue, 获取更多信息。
代码检查工具
ESLint
你可以使用 ESLint 和 eslint-mdx 来检查你的 MDX 代码。
mdxlint
你可以使用 remark-lint 和其他 [remark 插件][]通过 mdxlint 来检查你的 MDX 代码。
编译器
Babel
展开插件和示例用法
此插件:
/**
* @import {ParseResult, ParserOptions} from '@babel/parser'
* @import {File} from '@babel/types'
* @import {Program} from 'estree'
* @import {Plugin} from 'unified'
*/
import parser from '@babel/parser'
import {compileSync} from '@mdx-js/mdx'
import estreeToBabel from 'estree-to-babel'
/**
* Plugin that tells Babel to use a different parser.
*/
export function babelPluginSyntaxMdx() {
return {parserOverride: babelParserWithMdx}
}
/**
* Parser that handles MDX with `@mdx-js/mdx` and passes other things through
* to the normal Babel parser.
*
* @param {string} value
* @param {ParserOptions} options
* @returns {ParseResult<File>}
*/
function babelParserWithMdx(value, options) {
/** @type {string | undefined} */
// @ts-expect-error: babel changed the casing at some point and the types are out of date.
const filename = options.sourceFilename || options.sourceFileName
if (filename && /\.mdx?$/.test(filename)) {
// Babel does not support async parsers, unfortunately.
const file = compileSync(
{value, path: options.sourceFilename},
{recmaPlugins: [recmaBabel] /* jsxImportSource: …, otherOptions… */}
)
return /** @type {ParseResult<File>} */ (file.result)
}
return parser.parse(value, options)
}
/**
* A "recma" plugin is a unified plugin that runs on the estree (used by
* `@mdx-js/mdx` and much of the JS ecosystem but not Babel).
* This plugin defines `'estree-to-babel'` as the compiler,
* which means that the resulting Babel tree is given back by `compileSync`.
*
* @type {Plugin<[], Program, unknown>}
*/
function recmaBabel() {
// @ts-expect-error: `Program` is similar enough to a unist node.
this.compiler = compiler
/**
* @param {Program} tree
* @returns {unknown}
*/
function compiler(tree) {
// @ts-expect-error: TS2349: This expression *is* callable, `estreeToBabel` types are wrong.
return estreeToBabel(tree)
}
}
import parser(alias) function compileSync(vfileCompatible: Readonly<Compatible>, compileOptions?: Readonly<CompileOptions> | null | undefined): VFile
import compileSyncSynchronously compile MDX to JS.
When possible please use the async compile.
- @param vfileCompatible MDX document to parse.
- @param compileOptions Compile configuration (optional).
- @return Compiled file.
import estreeToBabelfunction babelPluginSyntaxMdx(): {
parserOverride: (value: string, options: parser.ParserOptions) => parser.ParseResult<File>;
}Plugin that tells Babel to use a different parser.
(property) parserOverride: (value: string, options: parser.ParserOptions) => parser.ParseResult<File>function babelParserWithMdx(value: string, options: parser.ParserOptions): parser.ParseResult<File>Parser that handles MDX with @mdx-js/mdx and passes other things through to the normal Babel parser.
- @param value
- @param options
- @returns
function babelParserWithMdx(value: string, options: parser.ParserOptions): parser.ParseResult<File>Parser that handles MDX with @mdx-js/mdx and passes other things through to the normal Babel parser.
- @param value
- @param options
- @returns
(parameter) value: string- @param value
(parameter) options: Partial<Options>- @param options
const filename: string | undefined- @type {string | undefined}
(parameter) options: Partial<Options>- @param options
(property) sourceFilename?: string | undefinedCorrelate output AST nodes with their source filename. Useful when generating code and source maps from the ASTs of multiple input files.
(parameter) options: Partial<Options>- @param options
anyconst filename: string | undefined- @type {string | undefined}
(method) RegExp.test(string: string): booleanReturns a Boolean value that indicates whether or not a pattern exists in a searched string.
- @param string String on which to perform the search.
const filename: string- @type {string | undefined}
const file: VFile(alias) compileSync(vfileCompatible: Readonly<Compatible>, compileOptions?: Readonly<CompileOptions> | null | undefined): VFile
import compileSyncSynchronously compile MDX to JS.
When possible please use the async compile.
- @param vfileCompatible MDX document to parse.
- @param compileOptions Compile configuration (optional).
- @return Compiled file.
(property) value: string(property) path: string | undefined(parameter) options: Partial<Options>- @param options
(property) sourceFilename?: string | undefinedCorrelate output AST nodes with their source filename. Useful when generating code and source maps from the ASTs of multiple input files.
(property) recmaPlugins?: PluggableList | null | undefinedList of recma plugins (optional).
class recmaBabel
function recmaBabel(this: Processor): void | Transformer<Program, Node> | undefinedA "recma" plugin is a unified plugin that runs on the estree (used by @mdx-js/mdx and much of the JS ecosystem but not Babel). This plugin defines 'estree-to-babel' as the compiler, which means that the resulting Babel tree is given back by compileSync.
- @type {Plugin<[], Program, unknown>}
const file: VFile(property) VFile.result: unknownCustom, non-string, compiled, representation.
This is used by unified to store non-string results. One example is when turning markdown into React nodes.
- @type {unknown}
import parser(alias) parse(input: string, options?: parser.ParserOptions): parser.ParseResult<File>
export parseParse the provided code as an entire ECMAScript program.
(parameter) value: string- @param value
(parameter) options: Partial<Options>- @param options
function recmaBabel(this: Processor): void | Transformer<Program, Node> | undefinedA "recma" plugin is a unified plugin that runs on the estree (used by @mdx-js/mdx and much of the JS ecosystem but not Babel). This plugin defines 'estree-to-babel' as the compiler, which means that the resulting Babel tree is given back by compileSync.
- @type {Plugin<[], Program, unknown>}
(property) recmaBabel.compiler: (tree: Program) => unknown(local function) compiler(tree: Program): unknown- @param tree
- @returns
(local function) compiler(tree: Program): unknown- @param tree
- @returns
(parameter) tree: Program- @param tree
import estreeToBabel(parameter) tree: Program- @param tree
…可以像这样与 Babel API 一起使用:
import babel from '@babel/core'
import {babelPluginSyntaxMdx} from './plugin.js'
const document = '# Hello, world!'
// Note that a filename must be set for our plugin to know it's MDX instead of JS.
const result = await babel.transformAsync(document, {
filename: 'example.mdx',
plugins: [babelPluginSyntaxMdx]
})
console.log(result)
import babel(alias) function babelPluginSyntaxMdx(): {
parserOverride: (value: string, options: babel.ParserOptions) => ParseResult<babel.types.File>;
}
import babelPluginSyntaxMdxPlugin that tells Babel to use a different parser.
const document: "# Hello, world!"const result: babel.BabelFileResult | nullimport babelfunction transformAsync(code: string, opts?: babel.TransformOptions): Promise<babel.BabelFileResult | null>Transforms the passed in code. Calling a callback with an object with the generated code, source map, and AST.
const document: "# Hello, world!"(property) TransformOptions.filename?: string | null | undefinedFilename for use in errors etc
Default: "unknown"
(property) TransformOptions.plugins?: babel.PluginItem[] | null | undefinedList of plugins to load and use
Default: []
(alias) function babelPluginSyntaxMdx(): {
parserOverride: (value: string, options: babel.ParserOptions) => ParseResult<babel.types.File>;
}
import babelPluginSyntaxMdxPlugin that tells Babel to use a different parser.
namespace console
var console: ConsoleThe console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.
The module exports two specific components:
- A
Consoleclass with methods such asconsole.log(),console.error()andconsole.warn()that can be used to write to any Node.js stream. - A global
consoleinstance configured to write toprocess.stdoutandprocess.stderr. The globalconsolecan be used without importing thenode:consolemodule.
Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.
Example using the global console:
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
Example using the Console class:
const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
- @see source
(method) Console.log(message?: any, ...optionalParams: any[]): voidPrints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).
const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout
See util.format() for more information.
- @since v0.1.100
const result: babel.BabelFileResult | null你可能应该直接使用 Rollup 或 webpack 而不是直接使用 Babel, 因为它们提供了更好的接口。 可以在 Babel 中使用 @mdx-js/mdx,而且会快一些, 因为它跳过了 @mdx-js/mdx 序列化和 Babel 解析(如果已经使用了 Babel 的话)。
Babel 不支持其解析器的语法扩展(它有"语法"插件, 但那些只是打开或关闭内部标志)。 它确实支持设置不同的解析器。 这反过来让我们选择是使用 @mdx-js/mdx 还是 @babel/parser。
站点生成器
Astro
Astro 有自己的 MDX 集成。 你可以通过 Astro CLI 添加集成:npx astro add mdx。
这个基础设置让你可以将 Markdown、Astro 组件和 MDX 文件作为 组件导入。 参见 Astro 的框架组件指南了解 如何在 MDX 文件中使用框架的组件。
有关如何结合 Astro 和 MDX 的更多信息, 请参见 Astro 的 MDX 集成文档。
Docusaurus
Docusaurus 默认支持 MDX。 参见 Docusaurus 的 MDX 和 React 指南了解 如何在 Docusaurus 中使用 MDX。
Gatsby
Gatsby 有自己的插件来支持 MDX。 参见 gatsby-plugin-mdx 了解如何在 Gatsby 中使用 MDX。
Next.js
展开示例
import nextMdx from '@next/mdx'
const withMdx = nextMdx({
// By default only the `.mdx` extension is supported.
extension: /\.mdx?$/,
options: {/* otherOptions… */}
})
const nextConfig = withMdx({
// Support MDX files as pages:
pageExtensions: ['md', 'mdx', 'tsx', 'ts', 'jsx', 'js'],
})
export default nextConfig
(alias) function nextMdx(options?: nextMdx.NextMDXOptions): WithMDX
(alias) namespace nextMdx
import nextMdxconst withMdx: WithMDX(property) nextMDX.NextMDXOptions.extension?: RuleSetConditionAbsoluteA webpack rule test to match files to treat as MDX.
- @default /.mdx$/
- @example // Support both .md and .mdx files. /.mdx?$/
(property) nextMDX.NextMDXOptions.options?: Options & {
remarkPlugins?: (string | [name: string, options: any] | NonNullable<Options["remarkPlugins"]>[number])[] | Options["remarkPlugins"];
rehypePlugins?: (string | [name: string, options: any] | NonNullable<Options["rehypePlugins"]>[number])[] | Options["rehypePlugins"];
}The options to pass to MDX.
const nextConfig: NextConfigconst withMdx: (config: NextConfig) => NextConfig(property) pageExtensions: string[]const nextConfig: NextConfigNext.js 有自己的 MDX 集成。 安装并配置 @next/mdx。
不要使用 providerImportSource 和 @mdx-js/react 来注入组件。 而是添加一个 mdx-components.tsx(在 src/ 或 / 中)文件。 参见 nextjs.org 上的配置 MDX 获取更多信息。
Parcel
Parcel 有自己的插件来支持 MDX。 参见 @parcel/transformer-mdx 了解如何在 Parcel 中使用 MDX。
注意:官方 Parcel 插件目前未维护。 对于有维护的替代方案, 试试 parcel-transformer-mdx。
JSX 运行时
Emotion
展开示例
import {compile} from '@mdx-js/mdx'
const js = String(await compile('# hi', {jsxImportSource: '@emotion/react', /* otherOptions… */}))
(alias) function compile(vfileCompatible: Readonly<Compatible>, compileOptions?: Readonly<CompileOptions> | null | undefined): Promise<VFile>
import compileCompile MDX to JS.
- @param vfileCompatible MDX document to parse.
- @param compileOptions Compile configuration (optional).
- @return Promise to compiled file.
const js: stringvar String: StringConstructor
(value?: any) => stringAllows manipulation and formatting of text strings and determination and location of substrings within strings.
(alias) compile(vfileCompatible: Readonly<Compatible>, compileOptions?: Readonly<CompileOptions> | null | undefined): Promise<VFile>
import compileCompile MDX to JS.
- @param vfileCompatible MDX document to parse.
- @param compileOptions Compile configuration (optional).
- @return Promise to compiled file.
(property) jsxImportSource?: string | null | undefinedPlace to import automatic JSX runtimes from (default: 'react'); when in the automatic runtime, this is used to define an import for Fragment, jsx, jsxDEV, and jsxs.
当 ProcessorOptions 中的 jsxImportSource 设置为 '@emotion/react' 时支持 Emotion。 你可以可选地安装和配置 @mdx-js/react 来 支持基于上下文的组件传递。
另见 Emotion 中使用的 ¶ React, 以及你可能使用的 ¶ Rollup 和 ¶ webpack, 获取更多信息。
Ink
展开示例
# Hi!
import React from 'react'
import {Text, render} from 'ink'
import Content from './example.mdx' // Assumes an integration is used to compile MDX -> JS.
render(
React.createElement(Content, {
components: {
h1(properties) {
return React.createElement(Text, {bold: true, ...properties})
},
p: Text
}
})
)
(alias) namespace React
import React(alias) function Text({ color, backgroundColor, dimColor, bold, italic, underline, strikethrough, inverse, wrap, children, "aria-label": ariaLabel, "aria-hidden": ariaHidden, }: Props): React.JSX.Element | null
import TextThis component can display text and change its style to make it bold, underlined, italic, or strikethrough.
(alias) const render: (node: React.ReactNode, options?: NodeJS.WriteStream | RenderOptions) => Instance
import renderMount a component and render the output.
(alias) function Content(props: MDXProps): Element
import ContentAn function component which renders the MDX content using JSX.
- @param props This value is be available as the named variable
propsinside the MDX component. - @returns A JSX element. The meaning of this may depend on the project configuration. I.e. it could be a React, Preact, or Vuex element.
(alias) render(node: React.ReactNode, options?: NodeJS.WriteStream | RenderOptions): Instance
import renderMount a component and render the output.
(alias) namespace React
import Reactfunction createElement<MDXProps>(type: React.FunctionComponent<MDXProps>, props?: (React.Attributes & MDXProps) | null | undefined, ...children: React.ReactNode[]): React.FunctionComponentElement<MDXProps> (+6 overloads)(alias) function Content(props: MDXProps): Element
import ContentAn function component which renders the MDX content using JSX.
- @param props This value is be available as the named variable
propsinside the MDX component. - @returns A JSX element. The meaning of this may depend on the project configuration. I.e. it could be a React, Preact, or Vuex element.
(property) MDXProps.components?: MDXComponentsThis prop may be used to customize how certain components are rendered.
(method) h1(properties: JSX.IntrinsicElements): React.FunctionComponentElement<Props>(parameter) properties: JSX.IntrinsicElements(alias) namespace React
import Reactfunction createElement<Props>(type: React.FunctionComponent<Props>, props?: (React.Attributes & Props) | null | undefined, ...children: React.ReactNode[]): React.FunctionComponentElement<Props> (+6 overloads)(alias) function Text({ color, backgroundColor, dimColor, bold, italic, underline, strikethrough, inverse, wrap, children, "aria-label": ariaLabel, "aria-hidden": ariaHidden, }: Props): React.JSX.Element | null
import TextThis component can display text and change its style to make it bold, underlined, italic, or strikethrough.
(property) bold?: booleanMake the text bold.
(parameter) properties: JSX.IntrinsicElements(property) p: ({ color, backgroundColor, dimColor, bold, italic, underline, strikethrough, inverse, wrap, children, "aria-label": ariaLabel, "aria-hidden": ariaHidden, }: Props) => React.JSX.Element | null(alias) function Text({ color, backgroundColor, dimColor, bold, italic, underline, strikethrough, inverse, wrap, children, "aria-label": ariaLabel, "aria-hidden": ariaHidden, }: Props): React.JSX.Element | null
import TextThis component can display text and change its style to make it bold, underlined, italic, or strikethrough.
可以这样使用:
node --loader=@mdx-js/node-loader example.js
Ink 使用 React JSX 运行时, 所以请先设置好它。 你需要将 HTML 元素替换为 Ink 的组件。 参见 § 组件表 了解它们是什么,以及 Ink 的 文档了解可以用什么替换。
另见 ¶ Node.js 和 ¶ React 获取更多 信息。
Preact
展开示例
import {compile} from '@mdx-js/mdx'
const js = String(await compile('# hi', {jsxImportSource: 'preact', /* otherOptions… */}))
(alias) function compile(vfileCompatible: Readonly<Compatible>, compileOptions?: Readonly<CompileOptions> | null | undefined): Promise<VFile>
import compileCompile MDX to JS.
- @param vfileCompatible MDX document to parse.
- @param compileOptions Compile configuration (optional).
- @return Promise to compiled file.
const js: stringvar String: StringConstructor
(value?: any) => stringAllows manipulation and formatting of text strings and determination and location of substrings within strings.
(alias) compile(vfileCompatible: Readonly<Compatible>, compileOptions?: Readonly<CompileOptions> | null | undefined): Promise<VFile>
import compileCompile MDX to JS.
- @param vfileCompatible MDX document to parse.
- @param compileOptions Compile configuration (optional).
- @return Promise to compiled file.
(property) jsxImportSource?: string | null | undefinedPlace to import automatic JSX runtimes from (default: 'react'); when in the automatic runtime, this is used to define an import for Fragment, jsx, jsxDEV, and jsxs.
当 ProcessorOptions 中的 jsxImportSource 设置为 'preact' 时支持 Preact。 你可以可选地安装和配置 @mdx-js/preact 来 支持基于上下文的组件传递。
另见你可能使用的 ¶ Rollup、¶ esbuild 和 ¶ webpack, 获取更多信息。
React
默认支持 React。 你可以可选地安装和配置 @mdx-js/react 来 支持基于上下文的组件传递。
另见你可能使用的 ¶ Rollup、¶ esbuild 和 ¶ webpack, 获取更多信息。
Theme UI
Theme UI 有自己的插件来支持 MDX。 参见 @theme-ui/mdx 了解如何在 Theme UI 中使用 MDX。
Svelte
展开示例
import {compile} from '@mdx-js/mdx'
const js = String(await compile('# hi', {jsxImportSource: 'svelte-jsx', /* otherOptions… */}))
(alias) function compile(vfileCompatible: Readonly<Compatible>, compileOptions?: Readonly<CompileOptions> | null | undefined): Promise<VFile>
import compileCompile MDX to JS.
- @param vfileCompatible MDX document to parse.
- @param compileOptions Compile configuration (optional).
- @return Promise to compiled file.
const js: stringvar String: StringConstructor
(value?: any) => stringAllows manipulation and formatting of text strings and determination and location of substrings within strings.
(alias) compile(vfileCompatible: Readonly<Compatible>, compileOptions?: Readonly<CompileOptions> | null | undefined): Promise<VFile>
import compileCompile MDX to JS.
- @param vfileCompatible MDX document to parse.
- @param compileOptions Compile configuration (optional).
- @return Promise to compiled file.
(property) jsxImportSource?: string | null | undefinedPlace to import automatic JSX runtimes from (default: 'react'); when in the automatic runtime, this is used to define an import for Fragment, jsx, jsxDEV, and jsxs.
当 ProcessorOptions 中的 jsxImportSource 设置为 'svelte-jsx' 时支持 Svelte。
另见你可能使用的 ¶ Rollup、¶ esbuild 和 ¶ webpack, 获取更多信息。
Vue
展开示例
import {compile} from '@mdx-js/mdx'
const js = String(await compile('# hi', {jsxImportSource: 'vue', /* otherOptions… */}))
(alias) function compile(vfileCompatible: Readonly<Compatible>, compileOptions?: Readonly<CompileOptions> | null | undefined): Promise<VFile>
import compileCompile MDX to JS.
- @param vfileCompatible MDX document to parse.
- @param compileOptions Compile configuration (optional).
- @return Promise to compiled file.
const js: stringvar String: StringConstructor
(value?: any) => stringAllows manipulation and formatting of text strings and determination and location of substrings within strings.
(alias) compile(vfileCompatible: Readonly<Compatible>, compileOptions?: Readonly<CompileOptions> | null | undefined): Promise<VFile>
import compileCompile MDX to JS.
- @param vfileCompatible MDX document to parse.
- @param compileOptions Compile configuration (optional).
- @return Promise to compiled file.
(property) jsxImportSource?: string | null | undefinedPlace to import automatic JSX runtimes from (default: 'react'); when in the automatic runtime, this is used to define an import for Fragment, jsx, jsxDEV, and jsxs.
当 ProcessorOptions 中的 jsxImportSource 设置为 'vue' 时支持 Vue。 你可以可选地安装和配置 @mdx-js/vue 来 支持基于上下文的组件传递。
另见你可能使用的 ¶ Vite, 获取更多信息。
Solid
展开示例
import {compile} from '@mdx-js/mdx'
const js = String(await compile('# hi', {jsxImportSource: 'solid-js/h', /* otherOptions… */}))
(alias) function compile(vfileCompatible: Readonly<Compatible>, compileOptions?: Readonly<CompileOptions> | null | undefined): Promise<VFile>
import compileCompile MDX to JS.
- @param vfileCompatible MDX document to parse.
- @param compileOptions Compile configuration (optional).
- @return Promise to compiled file.
const js: stringvar String: StringConstructor
(value?: any) => stringAllows manipulation and formatting of text strings and determination and location of substrings within strings.
(alias) compile(vfileCompatible: Readonly<Compatible>, compileOptions?: Readonly<CompileOptions> | null | undefined): Promise<VFile>
import compileCompile MDX to JS.
- @param vfileCompatible MDX document to parse.
- @param compileOptions Compile configuration (optional).
- @return Promise to compiled file.
(property) jsxImportSource?: string | null | undefinedPlace to import automatic JSX runtimes from (default: 'react'); when in the automatic runtime, this is used to define an import for Fragment, jsx, jsxDEV, and jsxs.
当 ProcessorOptions 中的 jsxImportSource 设置为 'solid-js/h' 时支持 Solid。
另见你可能使用的 ¶ Rollup 和 ¶ Vite, 获取更多信息。
JavaScript 引擎
Node.js
可以通过 @mdx-js/node-loader 在 Node 中导入 MDX 文件。 参见其 readme 了解如何配置。
Bun
可以通过 Create an esbuild plugin to compile MDX to JS. esbuild takes care of turning modern JavaScript features into syntax that works wherever you want it to. With other integrations you might need to use Babel for this, but with esbuild that’s not needed. See esbuild’s docs for more info. A Bun plugin. Used for extending Bun's behavior at runtime, or with {@link Bun.build } Create an esbuild plugin to compile MDX to JS. esbuild takes care of turning modern JavaScript features into syntax that works wherever you want it to. With other integrations you might need to use Babel for this, but with esbuild that’s not needed. See esbuild’s docs for more info. A Bun plugin. Used for extending Bun's behavior at runtime, or with {@link Bun.build }@mdx-js/esbuild 在 Bun 中导入 MDX 文件。展开示例
preload = ["./bun-mdx.ts"]
import mdx from '@mdx-js/esbuild'
import {type BunPlugin, plugin} from 'bun'
await plugin(mdx() as unknown as BunPlugin)
(alias) function mdx(options?: Readonly<Options> | null | undefined): Plugin
import mdx(alias) interface BunPlugin
import BunPlugin(alias) const plugin: Bun.BunRegisterPlugin
import plugin(alias) plugin<BunPlugin>(options: BunPlugin): void | Promise<void>
import plugin(alias) mdx(options?: Readonly<Options> | null | undefined): Plugin
import mdx(alias) interface BunPlugin
import BunPlugin
延伸阅读
- 如果你想在项目中使用 MDX 内容, 请参见§ 使用 MDX
- 如果你在集成 MDX 时遇到错误, 请参见§ MDX 故障排除 或 § 支持