@mdx-js/mdx
MDX 编译器。
¥MDX compiler.
内容
¥Contents
¥Use
这是什么?
¥What is this?
该包是一个将 MDX 转换为 JavaScript 的编译器。它还可以评估 MDX 代码。
¥This package is a compiler that turns MDX into JavaScript. It can also evaluate MDX code.
我什么时候应该使用这个?
¥When should I use this?
这是将 MDX 转换为 JavaScript 的核心编译器,为你提供最大的控制权。如果你使用的是打包器(Rollup、esbuild、webpack)、站点构建器(Next.js)或打包器附带的构建系统(Vite),那么最好使用集成:见 § 集成。
¥This is the core compiler for turning MDX into JavaScript which gives you the most control. If you’re using a bundler (Rollup, esbuild, webpack), a site builder (Next.js), or build system (Vite) which comes with a bundler, you’re better off using an integration: see § Integrations.
安装
¥Install
这个包是 仅限 ESM。在 Node.js(版本 16+)中,使用 npm 安装:
¥This package is ESM only. In Node.js (version 16+), install with npm:
npm install @mdx-js/mdx
在 Deno 中使用 esm.sh
:
¥In Deno with esm.sh
:
import {compile} from 'https://esm.sh/@mdx-js/mdx@3'
在带有 esm.sh
的浏览器中:
¥In browsers with esm.sh
:
<script type="module">
import {compile} from 'https://esm.sh/@mdx-js/mdx@3?bundle'
</script>
使用
¥Use
假设我们有一个 MDX 文档 example.mdx
:
¥Say we have an MDX document, example.mdx
:
export function Thing() {
return <>World!</>
}
# Hello, <Thing />
…以及 example.js
中的一些代码,用于将 example.mdx
编译为 JavaScript:
¥…and some code in example.js
to compile example.mdx
to JavaScript:
import fs from 'node:fs/promises'
import {compile} from '@mdx-js/mdx'
const compiled = await compile(await fs.readFile('example.mdx'))
console.log(String(compiled))
产量大致为:
¥Yields roughly:
import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from 'react/jsx-runtime'
export function Thing() {
return _jsx(_Fragment, {children: 'World!'})
}
function _createMdxContent(props) {
const _components = {h1: 'h1', ...props.components}
return _jsxs(_components.h1, {children: ['Hello, ', _jsx(Thing, {})]})
}
export default function MDXContent(props = {}) {
const {wrapper: MDXLayout} = props.components || {}
return MDXLayout
? _jsx(MDXLayout, {...props, children: _jsx(_createMdxContent, {...props})})
: _createMdxContent(props)
}
有关 MDX 如何工作以及如何使用结果的更多信息,请参阅 § 使用 MDX。
¥See § Using MDX for more on how MDX work and how to use the result.
API
该包导出以下标识符:compile
、compileSync
、createProcessor
、evaluate
、evaluateSync
、nodeTypes
、run
和 runSync
。没有默认导出。
¥This package exports the following identifiers: compile
, compileSync
, createProcessor
, evaluate
, evaluateSync
, nodeTypes
, run
, and runSync
. There is no default export.
compile(file, options?)
将 MDX 编译为 JS。
¥Compile MDX to JS.
参数
¥Parameters
file
(Compatible
从vfile
) — 要解析的 MDX 文档¥
file
(Compatible
fromvfile
) — MDX document to parseoptions
(CompileOptions
,可选) - 编译配置¥
options
(CompileOptions
, optional) — compile configuration
返回
¥Returns
对编译文件的 Promise(Promise<VFile>
)。
¥Promise to compiled file (Promise<VFile>
).
示例
¥Examples
file
的输入值可以是许多不同的值。你可以传递 UTF-8 格式的 string
、Uint8Array
、VFile
或任何可以提供给 new VFile
的内容。
¥The input value for file
can be many different things. You can pass a string
, Uint8Array
in UTF-8, VFile
, or anything that can be given to new VFile
.
import {compile} from '@mdx-js/mdx'
import {VFile} from 'vfile'
await compile(':)')
await compile(Buffer.from(':-)'))
await compile({path: 'path/to/file.mdx', value: '🥳'})
await compile(new VFile({path: 'path/to/file.mdx', value: '🤭'}))
输出 VFile
可用于访问生成的代码之外的其他内容:
¥The output VFile
can be used to access more than the generated code:
import {compile} from '@mdx-js/mdx'
import remarkPresetLintConsistent from 'remark-preset-lint-consistent' // Lint rules to check for consistent markdown.
import {reporter} from 'vfile-reporter'
const file = await compile('*like this* or _like this_?', {remarkPlugins: [remarkPresetLintConsistent]})
console.error(reporter(file))
产量:
¥Yields:
1:16-1:27 warning Emphasis should use `*` as a marker emphasis-marker remark-lint
⚠ 1 warning
compileSync(file, options?)
同步编译 MDX 为 JS。
¥Synchronously compile MDX to JS.
如果可能,请使用异步 compile
。
¥When possible please use the async compile
.
参数
¥Parameters
file
(Compatible
从vfile
) — 要解析的 MDX 文档¥
file
(Compatible
fromvfile
) — MDX document to parseoptions
(CompileOptions
,可选) - 编译配置¥
options
(CompileOptions
, optional) — compile configuration
返回
¥Returns
编译文件(VFile
)。
¥Compiled file (VFile
).
createProcessor(options?)
创建一个处理器来将 markdown 或 MDX 编译为 JavaScript。
¥Create a processor to compile markdown or MDX to JavaScript.
注意:
format: 'detect'
不允许出现在ProcessorOptions
中。¥Note:
format: 'detect'
is not allowed inProcessorOptions
.
参数
¥Parameters
options
(ProcessorOptions
,可选) - 流程配置¥
options
(ProcessorOptions
, optional) — process configuration
返回
¥Returns
处理器 (Processor
从 unified
)。
¥Processor (Processor
from unified
).
evaluate(file, options)
当你信任自己的内容时,evaluate
就能发挥作用。如果可能,请使用 compile
,写入文件,然后使用 Node 运行或使用 § 集成 之一。
¥When you trust your content, evaluate
can work. When possible, use compile
, write to a file, and then run with Node or use one of the § Integrations.
☢️ 危险:它被称为评估,因为它
eval
JavaScript。¥☢️ Danger: it’s called evaluate because it
eval
s JavaScript.
参数
¥Parameters
file
(Compatible
从vfile
) — 要解析的 MDX 文档¥
file
(Compatible
fromvfile
) — MDX document to parseoptions
(EvaluateOptions
,必填) - 配置¥
options
(EvaluateOptions
, required) — configuration
返回
¥Returns
对模块的 Promise (Promise<MDXModule>
从 mdx/types.js
)。
¥Promise to a module (Promise<MDXModule>
from mdx/types.js
).
结果是一个对象,其中 default
字段设置为组件;导出的任何其他内容也可用。例如,假设 § 使用 中 example.mdx
的内容在 file
中,则:
¥The result is an object with a default
field set to the component; anything else that was exported is available too. For example, assuming the contents of example.mdx
from § Use was in file
, then:
import {evaluate} from '@mdx-js/mdx'
import * as runtime from 'react/jsx-runtime'
console.log(await evaluate(file, runtime))
…产量:
¥…yields:
{Thing: [Function: Thing], default: [Function: MDXContent]}
注意
¥Notes
编译(和运行)MDX 需要时间。
¥Compiling (and running) MDX takes time.
如果你使用基于虚拟 DOM 的框架(例如 React)实时渲染经常更改的 MDX 字符串,则性能改进的一个方法是自行调用 MDXContent
组件。原因是 evaluate
每次都会创建一个新函数,无法区分:
¥If you are live-rendering a string of MDX that often changes using a virtual DOM based framework (such as React), one performance improvement is to call the MDXContent
component yourself. The reason is that the evaluate
creates a new function each time, which cannot be diffed:
const {default: MDXContent} = await evaluate('…')
-<MDXContent {...props} />
+MDXContent(props)
evaluateSync(file, options)
同步编译并运行 MDX。
¥Compile and run MDX, synchronously.
如果可能,请使用异步 evaluate
。
¥When possible please use the async evaluate
.
☢️ 危险:它被称为评估,因为它
eval
JavaScript。¥☢️ Danger: it’s called evaluate because it
eval
s JavaScript.
参数
¥Parameters
file
(Compatible
从vfile
) — 要解析的 MDX 文档¥
file
(Compatible
fromvfile
) — MDX document to parseoptions
(EvaluateOptions
,必填) - 配置¥
options
(EvaluateOptions
, required) — configuration
返回
¥Returns
¥Module (MDXModule
from mdx/types.js
).
nodeTypes
由 mdast-util-mdx
创建的节点类型列表,必须从 mdast 树到 hash 树(Array<string>
)不受影响地传递。
¥List of node types made by mdast-util-mdx
, which have to be passed through untouched from the mdast tree to the hast tree (Array<string>
).
run(code, options)
运行使用 outputFormat: 'function-body'
编译的代码。
¥Run code compiled with outputFormat: 'function-body'
.
☢️ 危险:这个
eval
JavaScript。¥☢️ Danger: this
eval
s JavaScript.
参数
¥Parameters
code
(VFile
或string
) — 要运行的 JavaScript 函数体¥
code
(VFile
orstring
) — JavaScript function body to runoptions
(RunOptions
,必填) - 配置¥
options
(RunOptions
, required) — configuration
返回
¥Returns
对模块的 Promise(Promise<MDXModule>
从 mdx/types.js
);结果是一个对象,其中 default
字段设置为组件;导出的任何其他内容也可用。
¥Promise to a module (Promise<MDXModule>
from mdx/types.js
); the result is an object with a default
field set to the component; anything else that was exported is available too.
示例
¥Example
在服务器上:
¥On the server:
import {compile} from '@mdx-js/mdx'
const code = String(await compile('# hi', {outputFormat: 'function-body'}))
// To do: send `code` to the client somehow.
在客户端:
¥On the client:
import {run} from '@mdx-js/mdx'
import * as runtime from 'react/jsx-runtime'
const code = '' // To do: get `code` from server somehow.
const {default: Content} = await run(code, {...runtime, baseUrl: import.meta.url})
console.log(Content)
…产量:
¥…yields:
[Function: MDXContent]
runSync(code, options)
同步运行代码。
¥Run code, synchronously.
如果可能,请使用异步 run
。
¥When possible please use the async run
.
☢️ 危险:这个
eval
JavaScript。¥☢️ Danger: this
eval
s JavaScript.
参数
¥Parameters
code
(VFile
或string
) — 要运行的 JavaScript 函数体¥
code
(VFile
orstring
) — JavaScript function body to runoptions
(RunOptions
,必填) - 配置¥
options
(RunOptions
, required) — configuration
返回
¥Returns
¥Module (MDXModule
from mdx/types.js
).
CompileOptions
compile
(TypeScript 类型)的配置。
¥Configuration for compile
(TypeScript type).
CompileOptions
与 ProcessorOptions
相同,但 format
选项支持 'detect'
值(默认值)。'detect'
格式意味着对扩展名为 mdExtensions
的文件使用 'md'
,否则使用 'mdx'
。
¥CompileOptions
is the same as ProcessorOptions
with the exception that the format
option supports a 'detect'
value, which is the default. The 'detect'
format means to use 'md'
for files with an extension in mdExtensions
and 'mdx'
otherwise.
类型
¥Type
/**
* Configuration for `compile`
*/
type CompileOptions = Omit<ProcessorOptions, 'format'> & {
/**
* Format of `file` (default: `'detect'`).
*/
format?: 'detect' | 'md' | 'mdx' | null | undefined
}
EvaluateOptions
evaluate
(TypeScript 类型)的配置。
¥Configuration for evaluate
(TypeScript type).
EvaluateOptions
与 CompileOptions
相同,只是不允许使用选项 baseUrl
、jsx
、jsxImportSource
、jsxRuntime
、outputFormat
、pragma
、pragmaFrag
、pragmaImportSource
和 providerImportSource
,并且还使用 RunOptions
。
¥EvaluateOptions
is the same as CompileOptions
, except that the options baseUrl
, jsx
, jsxImportSource
, jsxRuntime
, outputFormat
, pragma
, pragmaFrag
, pragmaImportSource
, and providerImportSource
are not allowed, and that RunOptions
are also used.
类型
¥Type
/**
* Configuration for `evaluate`.
*/
type EvaluateOptions = Omit<
CompileOptions,
| 'baseUrl' // Note that this is also in `RunOptions`.
| 'jsx'
| 'jsxImportSource'
| 'jsxRuntime'
| 'outputFormat'
| 'pragma'
| 'pragmaFrag'
| 'pragmaImportSource'
| 'providerImportSource'
> &
RunOptions
Fragment
代表子项,通常是一个符号(TypeScript 类型)。
¥Represent the children, typically a symbol (TypeScript type).
类型
¥Type
type Fragment = unknown
Jsx
创建一个生产元素(TypeScript 类型)。
¥Create a production element (TypeScript type).
参数
¥Parameters
type
(unknown
) — 元素类型:Fragment
符号、标签名称 (string
)、组件¥
type
(unknown
) — element type:Fragment
symbol, tag name (string
), componentproperties
(Properties
) — 元素属性和children
¥
properties
(Properties
) — element properties andchildren
key
(string
或undefined
)— 使用键¥
key
(string
orundefined
) — key to use
返回
¥Returns
框架中的元素 (JSX.Element
)。
¥Element from your framework (JSX.Element
).
JsxDev
创建一个开发元素(TypeScript 类型)。
¥Create a development element (TypeScript type).
参数
¥Parameters
type
(unknown
) — 元素类型:Fragment
符号、标签名称 (string
)、组件¥
type
(unknown
) — element type:Fragment
symbol, tag name (string
), componentproperties
(Properties
) — 元素属性和children
¥
properties
(Properties
) — element properties andchildren
key
(string
或undefined
)— 使用键¥
key
(string
orundefined
) — key to useisStaticChildren
(boolean
) — 是否传递两个或多个子级(在数组中),即是否使用jsxs
或jsx
¥
isStaticChildren
(boolean
) — whether two or more children are passed (in an array), which is whetherjsxs
orjsx
would be usedsource
(Source
) — 有关来源的信息¥
source
(Source
) — info about sourceself
(unknown
) — 上下文对象 (this
)¥
self
(unknown
) — context object (this
)
ProcessorOptions
createProcessor
(TypeScript 类型)的配置。
¥Configuration for createProcessor
(TypeScript type).
字段
¥Fields
SourceMapGenerator
(SourceMapGenerator
fromsource-map
, 可选) — 添加源映射(对象形式)作为结果文件上的map
字段¥
SourceMapGenerator
(SourceMapGenerator
fromsource-map
, optional) — add a source map (object form) as themap
field on the resulting file
Expand example
Assuming example.mdx
from § Use exists, then:
import fs from 'node:fs/promises'
import {compile} from '@mdx-js/mdx'
import {SourceMapGenerator} from 'source-map'
const file = await compile(
{path: 'example.mdx', value: await fs.readFile('example.mdx')},
{SourceMapGenerator}
)
console.log(file.map)
…yields:
{
file: 'example.mdx',
mappings: ';;aAAaA,QAAQ;YAAQ;;;;;;;;iBAE3B',
names: ['Thing'],
sources: ['example.mdx'],
version: 3
}
baseUrl
(URL
或string
,可选,示例:import.meta.url
)— 将此 URL 用作import.meta.url
并解析相对于它的import
和export … from
¥
baseUrl
(URL
orstring
, optional, example:import.meta.url
) — use this URL asimport.meta.url
and resolveimport
andexport … from
relative to it
Expand example
Say we have a module example.js
:
import {compile} from '@mdx-js/mdx'
const code = 'export {number} from "./data.js"\n\n# hi'
const baseUrl = 'https://a.full/url' // Typically `import.meta.url`
console.log(String(await compile(code, {baseUrl})))
…now running node example.js
yields:
import {jsx as _jsx} from 'react/jsx-runtime'
export {number} from 'https://a.full/data.js'
function _createMdxContent(props) { /* … */ }
export default function MDXContent(props = {}) { /* … */ }
development
(boolean
,默认值:false
) — 是否在生成的代码中向错误消息添加额外信息并使用开发自动 JSX 运行时(/jsx-dev-runtime
中的Fragment
和jsxDEV
);当通过 Vite 使用 webpack 加载器 (@mdx-js/loader
) 或 Rollup 集成 (@mdx-js/rollup
) 时,这是根据你如何配置这些工具自动推断出来的¥
development
(boolean
, default:false
) — whether to add extra info to error messages in generated code and use the development automatic JSX runtime (Fragment
andjsxDEV
from/jsx-dev-runtime
); when using the webpack loader (@mdx-js/loader
) or the Rollup integration (@mdx-js/rollup
) through Vite, this is automatically inferred from how you configure those tools
Expand example
Say we had some MDX that references a component that can be passed or provided at runtime:
**Note**<NoteIcon />: some stuff.
And a module to evaluate that:
import fs from 'node:fs/promises'
import {evaluate} from '@mdx-js/mdx'
import * as runtime from 'react/jsx-runtime'
const path = 'example.mdx'
const value = await fs.readFile(path)
const MDXContent = (await evaluate({path, value}, {...runtime, baseUrl: import.meta.url})).default
console.log(MDXContent({}))
…running that would normally (production) yield:
Error: Expected component `NoteIcon` to be defined: you likely forgot to import, pass, or provide it.
at _missingMdxReference (eval at run (…/@mdx-js/mdx/lib/run.js:18:10), <anonymous>:27:9)
at _createMdxContent (eval at run (…/@mdx-js/mdx/lib/run.js:18:10), <anonymous>:15:20)
at MDXContent (eval at run (…/@mdx-js/mdx/lib/run.js:18:10), <anonymous>:9:9)
at main (…/example.js:11:15)
…but if we add development: true
to our example:
@@ -7,6 +7,6 @@
import fs from 'node:fs/promises'
-import * as runtime from 'react/jsx-runtime'
+import * as runtime from 'react/jsx-dev-runtime'
import {evaluate} from '@mdx-js/mdx'
const path = 'example.mdx'
const value = await fs.readFile(path)
-const MDXContent = (await evaluate({path, value}, {...runtime, baseUrl: import.meta.url})).default
+const MDXContent = (await evaluate({path, value}, {development: true, ...runtime, baseUrl: import.meta.url})).default
console.log(MDXContent({}))
…and we’d run it again, we’d get:
Error: Expected component `NoteIcon` to be defined: you likely forgot to import, pass, or provide it.
It’s referenced in your code at `1:9-1:21` in `example.mdx`
provide it.
at _missingMdxReference (eval at run (…/@mdx-js/mdx/lib/run.js:18:10), <anonymous>:27:9)
at _createMdxContent (eval at run (…/@mdx-js/mdx/lib/run.js:18:10), <anonymous>:15:20)
at MDXContent (eval at run (…/@mdx-js/mdx/lib/run.js:18:10), <anonymous>:9:9)
at main (…/example.js:11:15)
elementAttributeNameCase
('html'
或'react
,默认值:'react'
)— 用于属性名称的大小写;HTML 大小写例如为class
、stroke-linecap
、xml:lang
;React 外壳例如为className
、strokeLinecap
、xmlLang
;对于用 MDX 编写的 JSX 组件,作者必须了解它们使用哪个框架并相应地编写代码;对于该项目生成的 AST 节点,此选项对其进行配置¥
elementAttributeNameCase
('html'
or'react
, default:'react'
) — casing to use for attribute names; HTML casing is for exampleclass
,stroke-linecap
,xml:lang
; React casing is for exampleclassName
,strokeLinecap
,xmlLang
; for JSX components written in MDX, the author has to be aware of which framework they use and write code accordingly; for AST nodes generated by this project, this option configures itformat
('md'
或'mdx'
,默认:'mdx'
) - 文件的格式;'md'
表示视为 markdown,'mdx'
表示视为 MDX¥
format
('md'
or'mdx'
, default:'mdx'
) — format of the file;'md'
means treat as markdown and'mdx'
means treat as MDX
Expand example
compile('…') // Seen as MDX.
compile('…', {format: 'mdx'}) // Seen as MDX.
compile('…', {format: 'md'}) // Seen as markdown.
jsx
(boolean
,默认:false
) - 是否保留 JSX;默认情况下编译 JSX,以便生成的文件可以立即运行。¥
jsx
(boolean
, default:false
) — whether to keep JSX; the default is to compile JSX away so that the resulting file is immediately runnable.
Expand example
If file
is the contents of example.mdx
from § Use, then:
compile(file, {jsx: true})
…yields this difference:
-import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from 'react/jsx-runtime'
+/*@jsxRuntime automatic*/
+/*@jsxImportSource react*/
export function Thing() {
- return _jsx(_Fragment, {children: 'World'})
+ return <>World!</>
}
function _createMdxContent(props) {
const _components = {
h1: 'h1',
...props.components
}
- return _jsxs(_components.h1, {children: ['Hello ', _jsx(Thing, {})]})
+ return <_components.h1>{"Hello "}<Thing /></_components.h1>
}
export default function MDXContent(props = {}) {
const {wrapper: MDXLayout} = props.components || {}
return MDXLayout
- ? _jsx(MDXLayout, {
- ...props,
- children: _jsx(_createMdxContent, props)
- })
+ ? <MDXLayout {...props}><_createMdxContent {...props} /></MDXLayout>
: _createMdxContent(props)
}
}
jsxImportSource
(string
,默认值:'react'
) — 导入自动 JSX 运行时的位置;当在automatic
运行时时,这用于定义Fragment
、jsx
、jsxDEV
和jsxs
的导入¥
jsxImportSource
(string
, default:'react'
) — place to import automatic JSX runtimes from; when in theautomatic
runtime, this is used to define an import forFragment
,jsx
,jsxDEV
, andjsxs
Expand example
If file
is the contents of example.mdx
from § Use, then:
compile(file, {jsxImportSource: 'preact'})
…yields this difference:
-import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from 'react/jsx-runtime'
+import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from 'preact/jsx-runtime'
jsxRuntime
('automatic'
或'classic'
,默认值:'automatic'
) - 要使用的 JSX 运行时;自动运行时编译为import _jsx from '$importSource/jsx-runtime'\n_jsx('p')
;经典运行时编译为诸如h('p')
之类的调用¥
jsxRuntime
('automatic'
or'classic'
, default:'automatic'
) — JSX runtime to use; the automatic runtime compiles toimport _jsx from '$importSource/jsx-runtime'\n_jsx('p')
; the classic runtime compiles to calls such ash('p')
👉 注意:对经典运行时的支持已被弃用,并且可能会在下一个主要版本中删除。
¥👉 Note: support for the classic runtime is deprecated and will likely be removed in the next major version.
Expand example
If file
is the contents of example.mdx
from § Use, then:
compile(file, {jsxRuntime: 'classic'})
…yields this difference:
-import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from 'react/jsx-runtime'
+import React from 'react'
export function Thing() {
- return _jsx(_Fragment, {children: 'World'})
+ return React.createElement(React.Fragment, null, 'World!')
}
…
outputFormat
('function-body'
或'program'
,默认:'program'
)— 要生成的输出格式;在大多数情况下应该使用'program'
,它会生成一个完整的程序;evaluate
内部使用'function-body'
编译为可以传递给run
的代码;在某些情况下,你可能希望evaluate
在单独的步骤中执行操作,例如在服务器上编译并在客户端上运行时。¥
outputFormat
('function-body'
or'program'
, default:'program'
) — output format to generate; in most cases'program'
should be used, it results in a whole program; internallyevaluate
uses'function-body'
to compile to code that can be passed torun
; in some cases, you might want whatevaluate
does in separate steps, such as when compiling on the server and running on the client.
Expand example
With a module example.js
:
import {compile} from '@mdx-js/mdx'
const code = 'export const no = 3.14\n\n# hi {no}'
console.log(String(await compile(code, {outputFormat: 'program'}))) // Default.
console.log(String(await compile(code, {outputFormat: 'function-body'})))
…yields:
import {jsx as _jsx, jsxs as _jsxs} from 'react/jsx-runtime'
export const no = 3.14
function _createMdxContent(props) { /* … */ }
export default function MDXContent(props = {}) { /* … */ }
'use strict'
const {Fragment: _Fragment, jsx: _jsx} = arguments[0]
const no = 3.14
function _createMdxContent(props) { /* … */ }
function MDXContent(props = {}) { /* … */ }
return {no, default: MDXContent}
The 'program'
format will use import statements to import the runtime (and optionally provider) and use an export statement to yield the MDXContent
component.
The 'function-body'
format will get the runtime (and optionally provider) from arguments[0]
, rewrite export statements, and use a return statement to yield what was exported.
mdExtensions
(Array<string>
, 默认值:['.md', '.markdown', '.mdown', '.mkdn', '.mkd', '.mdwn', '.mkdown', '.ron']
) — Markdown 扩展列表,带点影响 § 集成¥
mdExtensions
(Array<string>
, default:['.md', '.markdown', '.mdown', '.mkdn', '.mkd', '.mdwn', '.mkdown', '.ron']
) — list of markdown extensions, with dot affects § IntegrationsmdxExtensions
(Array<string>
,默认值:['.mdx']
) — MDX 扩展列表,带点;影响 § 集成¥
mdxExtensions
(Array<string>
, default:['.mdx']
) — list of MDX extensions, with dot; affects § Integrationspragma
(string
,默认值:'React.createElement'
) — JSX 的编译指示,在经典运行时中用作函数调用的标识符:<x />
至React.createElement('x')
;更改此设置时,你还应该定义pragmaFrag
和pragmaImportSource
¥
pragma
(string
, default:'React.createElement'
) — pragma for JSX, used in the classic runtime as an identifier for function calls:<x />
toReact.createElement('x')
; when changing this, you should also definepragmaFrag
andpragmaImportSource
too👉 注意:对经典运行时的支持已被弃用,并且可能会在下一个主要版本中删除。
¥👉 Note: support for the classic runtime is deprecated and will likely be removed in the next major version.
Expand example
If file
is the contents of example.mdx
from § Use, then:
compile(file, {
jsxRuntime: 'classic',
pragma: 'preact.createElement',
pragmaFrag: 'preact.Fragment',
pragmaImportSource: 'preact/compat'
})
…yields this difference:
-import React from 'react'
+import preact from 'preact/compat'
export function Thing() {
- return React.createElement(React.Fragment, null, 'World!')
+ return preact.createElement(preact.Fragment, null, 'World!')
}
…
pragmaFrag
(string
, 默认值:'React.Fragment'
) — 片段符号的编译指示,在经典运行时中用作未命名调用的标识符:<>
至React.createElement(React.Fragment)
;更改此设置时,你还应该定义pragma
和pragmaImportSource
¥
pragmaFrag
(string
, default:'React.Fragment'
) — pragma for fragment symbol, used in the classic runtime as an identifier for unnamed calls:<>
toReact.createElement(React.Fragment)
; when changing this, you should also definepragma
andpragmaImportSource
too👉 注意:对经典运行时的支持已被弃用,并且可能会在下一个主要版本中删除。
¥👉 Note: support for the classic runtime is deprecated and will likely be removed in the next major version.
pragmaImportSource
(string
, 默认:'react'
) — 从哪里导入pragma
的标识符,在经典运行时使用;举例来说,当pragma
为'a.b'
,pragmaImportSource
为'c'
时,将生成以下结果:import a from 'c'
和a.b('h1', {})
之类的东西;更改此设置时,你还应该定义pragma
和pragmaFrag
¥
pragmaImportSource
(string
, default:'react'
) — where to import the identifier ofpragma
from, used in the classic runtime; to illustrate, whenpragma
is'a.b'
andpragmaImportSource
is'c'
the following will be generated:import a from 'c'
and things such asa.b('h1', {})
; when changing this, you should also definepragma
andpragmaFrag
too👉 注意:对经典运行时的支持已被弃用,并且可能会在下一个主要版本中删除。
¥👉 Note: support for the classic runtime is deprecated and will likely be removed in the next major version.
providerImportSource
(string
,可选,示例:'@mdx-js/react'
) — 导入提供者的位置;通常它用于支持上下文(React、Preact)的运行时,但它可以用于将组件注入到编译后的代码中;该模块必须导出标识符useMDXComponents
,在不带参数的情况下调用该标识符以获取组件对象(请参阅UseMdxComponents
)¥
providerImportSource
(string
, optional, example:'@mdx-js/react'
) — place to import a provider from; normally it’s used for runtimes that support context (React, Preact), but it can be used to inject components into the compiled code; the module must export and identifieruseMDXComponents
which is called without arguments to get an object of components (seeUseMdxComponents
)
Expand example
If file
is the contents of example.mdx
from § Use, then:
compile(file, {providerImportSource: '@mdx-js/react'})
…yields this difference:
import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from 'react/jsx-runtime'
+import {useMDXComponents as _provideComponents} from '@mdx-js/react'
export function Thing() {
return _jsx(_Fragment, {children: 'World'})
}
function _createMdxContent(props) {
const _components = {
h1: 'h1',
+ ..._provideComponents(),
...props.components
}
return _jsxs(_components.h1, {children: ['Hello ', _jsx(Thing, {})]})
}
export default function MDXContent(props = {}) {
- const {wrapper: MDXLayout} = props.components || {}
+ const {wrapper: MDXLayout} = {
+ ..._provideComponents(),
+ ...props.components
+ }
return MDXLayout
? _jsx(MDXLayout, {...props, children: _jsx(_createMdxContent, {})})
: _createMdxContent()
recmaPlugins
(PluggableList
从unified
,可选) - recma 插件列表;这是一个新的生态系统,目前处于测试阶段,用于改造 esast 树 (JavaScript)¥
recmaPlugins
(PluggableList
fromunified
, optional) — list of recma plugins; this is a new ecosystem, currently in beta, to transform esast trees (JavaScript)
Expand example
import recmaMdxIsMdxComponent from 'recma-mdx-is-mdx-component'
await compile(file, {recmaPlugins: [recmaMdxIsMdxComponent]})
rehypePlugins
(PluggableList
从unified
,可选)- rehype 插件 列表¥
rehypePlugins
(PluggableList
fromunified
, optional) — list of rehype plugins
Expand example
import rehypeKatex from 'rehype-katex' // Render math with KaTeX.
import remarkMath from 'remark-math' // Support math like `$so$`.
await compile(file, {rehypePlugins: [rehypeKatex], remarkPlugins: [remarkMath]})
await compile(file, {
// A plugin with options:
rehypePlugins: [[rehypeKatex, {strict: true, throwOnError: true}]],
remarkPlugins: [remarkMath]
})
remarkPlugins
(PluggableList
从unified
,可选)- remark 插件 列表¥
remarkPlugins
(PluggableList
fromunified
, optional) — list of remark plugins
Expand example
import remarkFrontmatter from 'remark-frontmatter' // YAML and such.
import remarkGfm from 'remark-gfm' // Tables, footnotes, strikethrough, task lists, literal URLs.
await compile(file, {remarkPlugins: [remarkGfm]}) // One plugin.
await compile(file, {remarkPlugins: [[remarkFrontmatter, 'toml']]}) // A plugin with options.
await compile(file, {remarkPlugins: [remarkGfm, remarkFrontmatter]}) // Two plugins.
await compile(file, {remarkPlugins: [[remarkGfm, {singleTilde: false}], remarkFrontmatter]}) // Two plugins, first w/ options.
remarkRehypeOptions
(Options
从remark-rehype
,可选)- 传递到remark-rehype
的选项;选项allowDangerousHtml
将始终设置为true
,并且 MDX 节点(请参阅nodeTypes
)将被传递;特别是,如果你的内容不是英文,你可能需要传递脚注的配置¥
remarkRehypeOptions
(Options
fromremark-rehype
, optional) — options to pass through toremark-rehype
; the optionallowDangerousHtml
will always be set totrue
and the MDX nodes (seenodeTypes
) are passed through; In particular, you might want to pass configuration for footnotes if your content is not in English
Expand example
compile({value: '…'}, {remarkRehypeOptions: {clobberPrefix: 'comment-1'}})
stylePropertyNameCase
('css'
或'dom
,默认值:'dom'
)— 用于style
对象中属性名称的大小写;CSS 大小写例如为background-color
和-webkit-line-clamp
;DOM 大小写例如为backgroundColor
和WebkitLineClamp
;对于用 MDX 编写的 JSX 组件,作者必须了解它们使用哪个框架并相应地编写代码;对于该项目生成的 AST 节点,此选项对其进行配置¥
stylePropertyNameCase
('css'
or'dom
, default:'dom'
) — casing to use for property names instyle
objects; CSS casing is for examplebackground-color
and-webkit-line-clamp
; DOM casing is for examplebackgroundColor
andWebkitLineClamp
; for JSX components written in MDX, the author has to be aware of which framework they use and write code accordingly; for AST nodes generated by this project, this option configures ittableCellAlignToStyle
(boolean
, 默认:true
) — 将td
和th
上过时的align
属性转换为 CSSstyle
属性¥
tableCellAlignToStyle
(boolean
, default:true
) — turn obsoletealign
properties ontd
andth
into CSSstyle
properties
RunOptions
用于运行编译代码(TypeScript 类型)的配置。
¥Configuration to run compiled code (TypeScript type).
Fragment
、jsx
和 jsxs
在生产模式 (development: false
) 下编译代码时使用。Fragment
和 jsxDEV
在开发模式(development: true
)下编译时使用。当使用 providerImportSource: '#'
编译代码时使用 useMDXComponents
(此编译选项的确切值并不重要)。
¥Fragment
, jsx
, and jsxs
are used when the code is compiled in production mode (development: false
). Fragment
and jsxDEV
are used when compiled in development mode (development: true
). useMDXComponents
is used when the code is compiled with providerImportSource: '#'
(the exact value of this compile option doesn’t matter).
字段
¥Fields
Fragment
(Fragment
,必需)- 用于片段的符号¥
Fragment
(Fragment
, required) — symbol to use for fragmentsbaseUrl
(URL
或string
,可选,例如:import.meta.url
)— 将此 URL 用作import.meta.url
,并解析与之相关的import
和export … from
;该选项也可以在CompileOptions
中编译时给出;你应该传递这个(可能在运行时),因为否则在使用import.meta.url
/import
/export … from
时可能会出现运行时错误¥
baseUrl
(URL
orstring
, optional, example:import.meta.url
) — use this URL asimport.meta.url
and resolveimport
andexport … from
relative to it; this option can also be given at compile time inCompileOptions
; you should pass this (likely at runtime), as you might get runtime errors when usingimport.meta.url
/import
/export … from
otherwisejsx
(Jsx
, 可选) — 在生产模式下生成具有静态子元素的元素的函数¥
jsx
(Jsx
, optional) — function to generate an element with static children in production modejsxDEV
(JsxDev
, 可选) — 在开发模式下生成元素的函数¥
jsxDEV
(JsxDev
, optional) — function to generate an element in development modejsxs
(Jsx
,可选)- 在生产模式下生成具有动态子元素的元素的函数¥
jsxs
(Jsx
, optional) — function to generate an element with dynamic children in production modeuseMDXComponents
(UseMdxComponents
, 可选) — 获取要使用的组件的函数¥
useMDXComponents
(UseMdxComponents
, optional) — function to get components to use
示例
¥Examples
/jsx-runtime
模块将公开 Fragment
、jsx
和 jsxs
:
¥A /jsx-runtime
module will expose Fragment
, jsx
, and jsxs
:
import * as runtime from 'react/jsx-runtime'
const {default: Content} = await evaluate('# hi', {...runtime, baseUrl: import.meta.url, ...otherOptions})
/jsx-dev-runtime
模块将公开 Fragment
和 jsxDEV
:
¥A /jsx-dev-runtime
module will expose Fragment
and jsxDEV
:
import * as runtime from 'react/jsx-dev-runtime'
const {default: Content} = await evaluate('# hi', {development: true, baseUrl: import.meta.url, ...runtime, ...otherOptions})
我们的提供商将公开 useMDXComponents
:
¥Our providers will expose useMDXComponents
:
import * as provider from '@mdx-js/react'
import * as runtime from 'react/jsx-runtime'
const {default: Content} = await evaluate('# hi', {...provider, ...runtime, baseUrl: import.meta.url, ...otherOptions})
UseMdxComponents
获取组件(TypeScript 类型)。
¥Get components (TypeScript type).
参数
¥Parameters
没有参数。
¥There are no parameters.
返回
¥Returns
组件 (MDXComponents
从 mdx/types.js
)。
¥Components (MDXComponents
from mdx/types.js
).
类型
¥Types
该包完全采用 TypeScript 类型。它导出附加类型 CompileOptions
、EvaluateOptions
、Fragment
、Jsx
、JsxDev
、ProcessorOptions
、RunOptions
和 UseMdxComponents
。
¥This package is fully typed with TypeScript. It exports the additional types CompileOptions
, EvaluateOptions
, Fragment
, Jsx
, JsxDev
, ProcessorOptions
, RunOptions
, and UseMdxComponents
.
为了使评估的 MDX 类型正常工作,请确保键入 TypeScript JSX
命名空间。这是通过安装和使用框架类型来完成的,例如 @types/react
。请参阅我们网站上的 § 类型 了解信息。
¥For types of evaluated MDX to work, make sure the TypeScript JSX
namespace is typed. This is done by installing and using the types of your framework, such as @types/react
. See § Types on our website for information.
架构
¥Architecture
要了解这个项目的用途,首先了解 Unified 的用途非常重要:请通读 unifiedjs/unified
自述文件(需要阅读 API 部分之前的部分)。
¥To understand what this project does, it’s very important to first understand what unified does: please read through the unifiedjs/unified
readme (the part until you hit the API section is required reading).
@mdx-js/mdx
是一个统一的管道 - 经过封装,因此大多数人不需要了解统一。处理器执行以下步骤:
¥@mdx-js/mdx
is a unified pipeline — wrapped so that most folks don’t need to know about unified. The processor goes through these steps:
将 MDX(带有嵌入式 JSX、ESM 和表达式的序列化 Markdown)解析为 mdast(Markdown 语法树)
¥parse MDX (serialized markdown with embedded JSX, ESM, and expressions) to mdast (markdown syntax tree)
通过 remark 进行转换(Markdown 生态系统)
¥transform through remark (markdown ecosystem)
将 mdast 转换为 hast (HTML 语法树)
¥transform mdast to hast (HTML syntax tree)
通过 rehype 进行转换(HTML 生态系统)
¥transform through rehype (HTML ecosystem)
将 hast 转换为 esast(JS 语法树)
¥transform hast to esast (JS syntax tree)
完成获取组件所需的工作
¥do the work needed to get a component
通过 recma(JS 生态系统)进行转换
¥transform through recma (JS ecosystem)
将 esast 序列化为 JavaScript
¥serialize esast as JavaScript
输入是 MDX(带有嵌入式 JSX、ESM 和表达式的序列化 Markdown)。markdown 使用 micromark/micromark
和嵌入式 JS 及其扩展之一 micromark/micromark-extension-mdxjs
进行解析(后者又使用 acorn)。然后使用 syntax-tree/mdast-util-from-markdown
及其扩展 syntax-tree/mdast-util-mdx
将解析器的结果转换为语法树:mdast。
¥The input is MDX (serialized markdown with embedded JSX, ESM, and expressions). The markdown is parsed with micromark/micromark
and the embedded JS with one of its extensions micromark/micromark-extension-mdxjs
(which in turn uses acorn). Then syntax-tree/mdast-util-from-markdown
and its extension syntax-tree/mdast-util-mdx
are used to turn the results from the parser into a syntax tree: mdast.
Markdown 最接近源格式。这就是 remark 插件 发挥作用的地方。通常情况下,这里不应该发生太多事情。但也许你想支持 GFM(表格等)或 frontmatter?然后你可以在这里添加一个插件:分别为 remark-gfm
或 remark-frontmatter
。
¥Markdown is closest to the source format. This is where remark plugins come in. Typically, there shouldn’t be much going on here. But perhaps you want to support GFM (tables and such) or frontmatter? Then you can add a plugin here: remark-gfm
or remark-frontmatter
, respectively.
Markdown 之后,我们进入 hast(HTML)。这个转变是由 syntax-tree/mdast-util-to-hast
完成的。等等,为什么,HTML 需要什么?部分原因是我们关心 HTML 语义:我们想知道某个东西是 <a>
,而不是它是与资源的链接 ([text](url)
) 还是对已定义链接定义的引用 ([text][id]\n\n[id]: url
)。所以 HTML AST 更接近我们想要的目标。另一个原因是,当人们使用 MDX -> JS、markdown -> HTML,甚至只处理 HTML -> HTML 时,需要很多东西:MDX 以外的用例。通过在这些情况下使用单个 AST 并编写一个适用于该 AST 的插件,该插件可以支持所有这些用例(例如,用于语法高亮的 rehypejs/rehype-highlight
或用于数学的 rehypejs/rehype-katex
)。所以,这就是 rehype 插件 的用武之地:可能是大多数插件。
¥After markdown, we go to hast (HTML). This transformation is done by syntax-tree/mdast-util-to-hast
. Wait, why, what is HTML needed? Part of the reason is that we care about HTML semantics: we want to know that something is an <a>
, not whether it’s a link with a resource ([text](url)
) or a reference to a defined link definition ([text][id]\n\n[id]: url
). So an HTML AST is closer to where we want to go. Another reason is that there are many things folks need when they go MDX -> JS, markdown -> HTML, or even folks who only process their HTML -> HTML: use cases other than MDX. By having a single AST in these cases and writing a plugin that works on that AST, that plugin can supports all these use cases (for example, rehypejs/rehype-highlight
for syntax highlighting or rehypejs/rehype-katex
for math). So, this is where rehype plugins come in: most of the plugins, probably.
然后我们转到 JavaScript:esast(JS;与 estree 兼容的 AST,但看起来更像其他 unist AST)。这个转变是由 rehype-recma
完成的。这是一个新的生态系统,还没有实用程序或插件。但这正是 @mdx-js/mdx
发挥作用的地方:它在其中添加导入/导出,在其中将 JSX 编译为 _jsx()
调用,以及在其中执行它提供的其他很酷的事情。
¥Then we go to JavaScript: esast (JS; an AST which is compatible with estree but looks a bit more like other unist ASTs). This transformation is done by rehype-recma
. This is a new ecosystem that does not have utilities or plugins yet. But it’s where @mdx-js/mdx
does its thing: where it adds imports/exports, where it compiles JSX away into _jsx()
calls, and where it does the other cool things that it provides.
最后,输出是序列化的 JavaScript。最后一步是由 astring 完成的,它是一个小型且快速的 JS 生成器。
¥Finally, The output is serialized JavaScript. That final step is done by astring, a small and fast JS generator.
兼容性
¥Compatibility
由统一集体维护的项目与 Node.js 的维护版本兼容。
¥Projects maintained by the unified collective are compatible with maintained versions of Node.js.
当我们削减新的主要版本时,我们会放弃对未维护的 Node.js 版本的支持。这意味着我们尝试保持当前版本 @mdx-js/mdx@^3
与 Node.js 16 兼容。
¥When we cut a new major release, we drop support for unmaintained versions of Node. This means we try to keep the current release line, @mdx-js/mdx@^3
, compatible with Node.js 16.
安全
¥Security
请参阅我们网站上的 § 安全 了解信息。
¥See § Security on our website for information.
贡献
¥Contribute
请参阅我们网站上的 § 贡献 了解入门方法。请参阅 § 支持 了解获取帮助的方法。
¥See § Contribute on our website for ways to get started. See § Support for ways to get help.
该项目有 行为守则。通过与此存储库、组织或社区交互,你同意遵守其条款。
¥This project has a code of conduct. By interacting with this repository, organization, or community you agree to abide by its terms.
许可证
¥License