Skip to navigation

@mdx-js/mdx

MDX 编译器。

内容

这是什么?

该包是一个将 MDX 转换为 JavaScript 的编译器。 它还可以评估 MDX 代码。

我什么时候应该使用这个?

这是将 MDX 转换为 JavaScript 的核心编译器,为你提供最大的控制权。 如果你使用的是打包器(Rollup、esbuild、webpack)、站点构建器(Next.js)或打包器附带的构建系统(Vite),那么最好使用集成: 见 § 集成

安装

这个包是 仅限 ESM。 在 Node.js(版本 16+)中,使用 npm 安装:

Shell
npm install @mdx-js/mdx

在 Deno 中使用 esm.sh

TypeScript
import {compile} from 'https://esm.sh/@mdx-js/mdx@2'

在带有 esm.sh 的浏览器中:

HTML
<script type="module">
  import {compile} from 'https://esm.sh/@mdx-js/mdx@2?bundle'
</script>

使用

假设我们有一个 MDX 文档 example.mdx

MDX
export function Thing() {
  return <>World!</>
}

# Hello, <Thing />

…以及 example.js 中将 example.mdx 编译为 JavaScript 的一些代码:

TypeScript
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))

产量大致为:

TypeScript
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

API

该包导出以下标识符: compilecompileSynccreateProcessorevaluateevaluateSyncnodeTypesrunrunSync。 没有默认导出。

compile(file, options?)

将 MDX 编译为 JS。

参数

返回

对编译文件的 Promise(Promise<VFile>)。

例子

file 的输入值可以是许多不同的值。 你可以传递 UTF-8 格式的 stringUint8ArrayVFile 或任何可以提供给 new VFile 的内容。

TypeScript
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 可用于访问生成的代码之外的其他内容:

TypeScript
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))

产量:

Plain text
  1:16-1:27  warning  Emphasis should use `*` as a marker  emphasis-marker  remark-lint

⚠ 1 warning

compileSync(file, options?)

同步编译 MDX 为 JS。

如果可能,请使用异步 compile

参数

返回

编译文件(VFile)。

createProcessor(options?)

创建一个处理器来将 markdown 或 MDX 编译为 JavaScript。

注意format: 'detect' 不允许出现在 ProcessorOptions 中。

参数

返回

处理器 (Processorunified)。

evaluate(file, options)

编译run MDX。

当你信任自己的内容时,evaluate 就能发挥作用。 如果可能,请使用 compile,写入文件,然后使用 Node 运行或使用 § 集成 之一。

☢️ 危险: 它被称为 evaluate,因为它是 eval JavaScript。

参数

返回

对模块的 Promise (Promise<MDXModule>mdx/types.js)。

结果是一个对象,其中 default 字段设置为组件; 导出的任何其他内容也可用。 例如,假设 § 使用example.mdx 的内容在 file 中,则:

TypeScript
import {evaluate} from '@mdx-js/mdx'
import * as runtime from 'react/jsx-runtime'

console.log(await evaluate(file, runtime))

…yields:

TypeScript
{Thing: [Function: Thing], default: [Function: MDXContent]}

注意

编译(和运行)MDX 需要时间。

如果你使用基于虚拟 DOM 的框架(例如 React)实时渲染经常更改的 MDX 字符串,则性能改进的一个方法是自行调用 MDXContent 组件。 原因是 evaluate 每次都会创建一个新函数,无法区分:

Diff
 const {default: MDXContent} = await evaluate('…')

-<MDXContent {...props} />
+MDXContent(props)

evaluateSync(file, options)

同步编译并运行 MDX。

如果可能,请使用异步 evaluate

☢️ 危险: 它被称为 evaluate,因为它是 eval JavaScript。

参数

返回

模块(MDXModulemdx/types.js)。

nodeTypes

mdast-util-mdx 创建的节点类型列表,必须从 mdast 树到 hash 树(Array<string>)不受影响地传递。

run(code, options)

运行使用 outputFormat: 'function-body' 编译的代码。

☢️ 危险: 这个 eval JavaScript。

参数
  • codeVFilestring) — 要运行的 JavaScript 函数体
  • optionsRunOptionsrequired) — configuration

返回

对模块的 Promise(Promise<MDXModule>mdx/types.js); 结果是一个对象,其中 default 字段设置为组件; 导出的任何其他内容也可用。

例子

在服务器上:

TypeScript
import {compile} from '@mdx-js/mdx'

const code = String(await compile('# hi', {outputFormat: 'function-body'}))
// To do: send `code` to the client somehow.

在客户端:

TypeScript
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:

TypeScript
[Function: MDXContent]

runSync(code, options)

同步运行代码。

如果可能,请使用异步 run

☢️ 危险: 这个 eval JavaScript。

参数
  • codeVFilestring) — 要运行的 JavaScript 函数体
  • optionsRunOptionsrequired) — configuration

返回

模块(MDXModulemdx/types.js)。

CompileOptions

compile(TypeScript 类型)的配置。

CompileOptionsProcessorOptions 相同,但 format 选项支持 'detect' 值(默认值)。 'detect' 格式意味着对扩展名为 mdExtensions 的文件使用 'md',否则使用 'mdx'

类型
TypeScript
/**
 * Configuration for `compile`
 */
type CompileOptions = Omit<ProcessorOptions, 'format'> & {
  /**
   * Format of `file` (default: `'detect'`).
   */
  format?: 'detect' | 'md' | 'mdx' | null | undefined
}

EvaluateOptions

evaluate(TypeScript 类型)的配置。

EvaluateOptionsCompileOptions 相同,只是不允许使用选项 baseUrljsxjsxImportSourcejsxRuntimeoutputFormatpragmapragmaFragpragmaImportSourceproviderImportSource,并且还使用 RunOptions

类型
TypeScript
/**
 * 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 类型)。

类型
TypeScript
type Fragment = unknown

Jsx

创建一个生产元素(TypeScript 类型)。

参数
  • type (unknown) — 元素类型: Fragment 符号、标签名称 (string)、组件
  • props (Props) — 元素属性和 children
  • keystringundefined) — 使用键

返回

框架中的元素 (JSX.Element)。

JsxDev

创建一个开发元素(TypeScript 类型)。

参数
  • type (unknown) — 元素类型: Fragment 符号、标签名称 (string)、组件
  • props (Props) — 元素属性和 children
  • keystringundefined) — 使用键
  • isStaticChildren (boolean) — 是否传递两个或多个子级(在数组中),即是否使用 jsxsjsx
  • source (Source) — 有关来源的信息
  • self (unknown) — 上下文对象 (this)

ProcessorOptions

createProcessor(TypeScript 类型)的配置。

字段
  • SourceMapGeneratorSourceMapGeneratorsource-map,可选) — 添加源映射(对象形式)作为结果文件上的 map 字段

    展开示例

    假设 § 使用 中的 example.mdx 存在,则:

    TypeScript
    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:

    TypeScript
    {
      file: 'example.mdx',
      mappings: ';;aAAaA,QAAQ;YAAQ;;;;;;;;iBAE3B',
      names: ['Thing'],
      sources: ['example.mdx'],
      version: 3
    }
    
  • baseUrlURLstring,可选,例如:import.meta.url) — 使用此 URL 作为 import.meta.url 并解析与其相关的 importexport … from

    展开示例

    假设我们有一个模块 example.js

    TypeScript
    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})))
    

    …现在运行 node example.js 产量:

    TypeScript
    import {jsx as _jsx} from 'react/jsx-runtime'
    export {number} from 'https://a.full/data.js'
    function _createMdxContent(props) { /* … */ }
    export default function MDXContent(props = {}) { /* … */ }
    
  • developmentboolean,默认:false) — 是否向生成代码中的错误消息添加额外信息并使用开发自动 JSX 运行时(/jsx-dev-runtime 中的 FragmentjsxDEV); 当通过 Vite 使用 webpack 加载器 (@mdx-js/loader) 或 Rollup 集成 (@mdx-js/rollup) 时,这是根据你如何配置这些工具自动推断出来的

    展开示例

    假设我们有一些 MDX 引用了可以在运行时传递或提供的组件:

    MDX
    **Note**<NoteIcon />: some stuff.
    

    以及一个评估模块:

    TypeScript
    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({}))
    

    …运行通常(生产)会产生:

    Plain text
    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)
    

    …但如果我们将 development: true 添加到我们的示例中:

    Diff
    @@ -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({}))
    

    …我们再次运行它,我们会得到:

    Plain text
    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 大小写例如为 classstroke-linecapxml:lang; React 外壳例如为 classNamestrokeLinecapxmlLang; 对于用 MDX 编写的 JSX 组件,作者必须了解它们使用哪个框架并相应地编写代码; 对于该项目生成的 AST 节点,此选项对其进行配置

  • format'md''mdx',默认:'mdx') — 文件的格式; 'md' 表示视为 markdown,'mdx' 表示视为 MDX

    展开示例
    TypeScript
    compile('') // Seen as MDX.
    compile('', {format: 'mdx'}) // Seen as MDX.
    compile('', {format: 'md'}) // Seen as markdown.
    
  • jsxboolean,默认:false) — 是否保留 JSX; 默认情况下编译 JSX,以便生成的文件可以立即运行。

    展开示例

    如果 file§ 使用example.mdx 的内容,则:

    TypeScript
    compile(file, {jsx: true})
    

    …产生这个差异:

    Diff
    -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)
    }
    }
    
  • jsxImportSourcestring,默认:'react') — 导入自动 JSX 运行时的位置; 当在 automatic 运行时时,这用于定义 FragmentjsxjsxDEVjsxs 的导入

    展开示例

    如果 file§ 使用example.mdx 的内容,则:

    TypeScript
    compile(file, {jsxImportSource: 'preact'})
    

    …产生这个差异:

    Diff
    -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') 之类的调用

    👉 注意: 对经典运行时的支持已被弃用,并且可能会在下一个主要版本中删除。

    展开示例

    如果 file§ 使用example.mdx 的内容,则:

    TypeScript
    compile(file, {jsxRuntime: 'classic'})
    

    …产生这个差异:

    Diff
    -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 在单独的步骤中执行操作,例如在服务器上编译并在客户端上运行时。

    展开示例

    使用模块 example.js

    TypeScript
    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:

    TypeScript
    import {jsx as _jsx, jsxs as _jsxs} from 'react/jsx-runtime'
    export const no = 3.14
    function _createMdxContent(props) { /* … */ }
    export default function MDXContent(props = {}) { /* … */ }
    
    TypeScript
    'use strict'
    const {Fragment: _Fragment, jsx: _jsx} = arguments[0]
    const no = 3.14
    function _createMdxContent(props) { /* … */ }
    function MDXContent(props = {}) { /* … */ }
    return {no, default: MDXContent}
    

    'program' 格式将使用 import 语句导入运行时(以及可选的提供程序),并使用导出语句生成 MDXContent 组件。

    'function-body' 格式将从 arguments[0] 获取运行时(以及可选的提供程序),重写导出语句,并使用 return 语句生成导出的内容。

  • mdExtensionsArray<string>,默认:['.md', '.markdown', '.mdown', '.mkdn', '.mkd', '.mdwn', '.mkdown', '.ron']) — Markdown 扩展列表,带点影响 § 集成

  • mdxExtensionsArray<string>,默认:['.mdx']) — MDX 扩展列表,带点; 影响 § 集成

  • pragmastring,默认:'React.createElement') — JSX 的 pragma,在经典运行时中用作函数调用的标识符: <x />React.createElement('x'); 更改此设置时,你还应该定义 pragmaFragpragmaImportSource

    👉 注意: 对经典运行时的支持已被弃用,并且可能会在下一个主要版本中删除。

    展开示例

    如果 file§ 使用example.mdx 的内容,则:

    TypeScript
    compile(file, {
      jsxRuntime: 'classic',
      pragma: 'preact.createElement',
      pragmaFrag: 'preact.Fragment',
      pragmaImportSource: 'preact/compat'
    })
    

    …产生这个差异:

    Diff
    -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!')
    }
    …
    
  • pragmaFragstring,默认:'React.Fragment') — 片段符号的 pragma,在经典运行时中用作未命名调用的标识符: <>React.createElement(React.Fragment); 更改此设置时,你还应该定义 pragmapragmaImportSource

    👉 注意: 对经典运行时的支持已被弃用,并且可能会在下一个主要版本中删除。

  • pragmaImportSourcestring,默认:'react') — 从哪里导入 pragma 的标识符,在经典运行时使用; 举例来说,当 pragma'a.b'pragmaImportSource'c' 时,将生成以下结果: import a from 'c'a.b('h1', {}) 之类的东西; 更改此设置时,你还应该定义 pragmapragmaFrag

    👉 注意: 对经典运行时的支持已被弃用,并且可能会在下一个主要版本中删除。

  • providerImportSourcestring,可选,示例:'@mdx-js/react') — 导入提供商的地点; 通常它用于支持上下文(React、Preact)的运行时,但它可以用于将组件注入到编译后的代码中; 该模块必须导出标识符 useMDXComponents,在不带参数的情况下调用该标识符以获取组件对象(请参阅 UseMdxComponents

    展开示例

    如果 file§ 使用example.mdx 的内容,则:

    TypeScript
    compile(file, {providerImportSource: '@mdx-js/react'})
    

    …产生这个差异:

    Diff
    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()
    
  • recmaPluginsPluggableListunified,可选) — recma 插件列表; 这是一个新的生态系统,目前处于测试阶段,用于改造 esast 树 (JavaScript)

    展开示例
    TypeScript
    import recmaMdxIsMdxComponent from 'recma-mdx-is-mdx-component'
    
    await compile(file, {recmaPlugins: [recmaMdxIsMdxComponent]})
    
  • rehypePluginsPluggableListunified,可选) — rehype 插件 名单

    展开示例
    TypeScript
    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]
    })
    
  • remarkPluginsPluggableListunified,可选) — remark 插件 名单

    展开示例
    TypeScript
    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.
    
  • remarkRehypeOptionsOptionsremark-rehype,可选) — 传递到 remark-rehype 的选项; 选项 allowDangerousHtml 将始终设置为 true,并且 MDX 节点(请参阅 nodeTypes)将被传递; 特别是,如果你的内容不是英文,你可能需要传递脚注的配置

    展开示例
    TypeScript
    compile({value: ''}, {remarkRehypeOptions: {clobberPrefix: 'comment-1'}})
    
  • stylePropertyNameCase'css''dom,默认:'dom') — 用于 style 对象中属性名称的大小写; CSS 大小写例如为 background-color-webkit-line-clamp; DOM 大小写例如为 backgroundColorWebkitLineClamp; 对于用 MDX 编写的 JSX 组件,作者必须了解它们使用哪个框架并相应地编写代码; 对于该项目生成的 AST 节点,此选项对其进行配置

  • tableCellAlignToStyleboolean,默认:true) — 将 tdth 上过时的 align 属性转换为 CSS style 属性

RunOptions

用于运行编译代码(TypeScript 类型)的配置。

Fragmentjsxjsxs 在生产模式 (development: false) 下编译代码时使用。 FragmentjsxDEV 在开发模式(development: true)下编译时使用。 当使用 providerImportSource: '#' 编译代码时使用 useMDXComponents(此编译选项的确切值并不重要)。

字段
  • FragmentFragmentrequired) — 用于片段的符号
  • baseUrlURLstring,可选,例如:import.meta.url) — 使用此 URL 作为 import.meta.url 并解析与其相关的 importexport … from; 该选项也可以在 CompileOptions 中编译时给出; 你应该传递这个(可能在运行时),因为否则在使用 import.meta.url / import / export … from 时可能会出现运行时错误
  • jsxJsx,可选) — 在生产模式下生成具有静态子元素的元素的函数
  • jsxDEVJsxDev,可选) — 在开发模式下生成元素的函数
  • jsxsJsx,可选) — 在生产模式下生成具有动态子元素的元素的函数
  • useMDXComponentsUseMdxComponents,可选) — 获取要使用的组件的函数

例子

/jsx-runtime 模块将公开 Fragmentjsxjsxs

TypeScript
import * as runtime from 'react/jsx-runtime'

const {default: Content} = await evaluate('# hi', {...runtime, baseUrl: import.meta.url, ...otherOptions})

/jsx-dev-runtime 模块将公开 FragmentjsxDEV

TypeScript
import * as runtime from 'react/jsx-dev-runtime'

const {default: Content} = await evaluate('# hi', {development: true, baseUrl: import.meta.url, ...runtime, ...otherOptions})

我们的提供商将公开 useMDXComponents

TypeScript
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 类型)。

参数

没有参数。

返回

组件 (MDXComponentsmdx/types.js)。

类型

该包完全采用 TypeScript 类型。 它导出附加类型 CompileOptionsEvaluateOptionsFragmentJsxJsxDevProcessorOptionsRunOptionsUseMdxComponents

为了使评估的 MDX 类型正常工作,请确保键入 TypeScript JSX 命名空间。 这是通过安装和使用框架类型来完成的,例如 @types/react。 请参阅我们网站上的 § 类型 了解信息。

架构

要了解这个项目的用途,首先了解 Unified 的用途非常重要: 请通读 unifiedjs/unified 自述文件(需要阅读 API 部分之前的部分)。

@mdx-js/mdx 是统一管道 — 封装起来,这样大多数人就不需要了解统一了: core.js#L65。 处理器执行以下步骤:

  1. 将 MDX(带有嵌入式 JSX、ESM 和表达式的序列化 Markdown)解析为 mdast(Markdown 语法树)
  2. 通过 remark 进行转换(Markdown 生态系统)
  3. 将 mdast 转换为 hast (HTML 语法树)
  4. 通过 rehype 进行转换(HTML 生态系统)
  5. 将 hast 转换为 esast(JS 语法树)
  6. 完成获取组件所需的工作
  7. 通过 recma(JS 生态系统)进行转换
  8. 将 esast 序列化为 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

Markdown 最接近源格式。 这就是 remark 插件 发挥作用的地方。 通常情况下,这里不应该发生太多事情。 但也许你想支持 GFM(表格等)或 frontmatter? 然后你可以在这里添加一个插件: 分别为 remark-gfmremark-frontmatter

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 插件 的用武之地: 可能是大多数插件。

然后我们转到 JavaScript: esast(JS;与 estree 兼容的 AST,但看起来更像其他 unist AST)。 这个转变是由 syntax-tree/hast-util-to-estree 完成的。 这是一个新的生态系统,还没有实用程序或插件。 但这正是 @mdx-js/mdx 发挥作用的地方: 它在其中添加导入/导出,在其中将 JSX 编译为 _jsx() 调用,以及在其中执行它提供的其他很酷的事情。

最后,输出是序列化的 JavaScript。 最后一步是由 astring 完成的,它是一个小型且快速的 JS 生成器。

兼容性

由统一集体维护的项目与 Node.js 的维护版本兼容。

当我们削减新的主要版本时,我们会放弃对未维护的 Node.js 版本的支持。 这意味着我们尝试保持当前版本 @mdx-js/mdx@^3 与 Node.js 16 兼容。

安全

请参阅我们网站上的 § 安全 了解信息。

贡献

请参阅我们网站上的 § 贡献 了解入门方法。 请参阅 § 支持 了解获取帮助的方法。

该项目有 行为守则。 通过与此存储库、组织或社区交互,你同意遵守其条款。

许可证

MIT © 合成器和 Vercel

MDX 中文网 - 粤ICP备13048890号