本文介绍了在使用MDX时可能会遇到的几个常见问题和错误。为了理解MDX格式的工作原理,我们建议您从§ 什么是MDX开始。如何使用我们的软件包在它们的自述文件中有文档。要迁移到最新的MDX,请参阅§ 从v1迁移到v2。

集成 MDX 时遇到的问题

ESM

如果您在将 MDX 与不同工具集成时遇到问题,那很可能是由于 ESM:ECMAScript 模块。ESM 自 2015 年以来一直在进行开发,我们从一开始就支持了它们,并且在 MDX 版本 2 中完全切换到了它们。许多工具已经支持 ESM。大多数其他工具正在努力支持它们。一些仍然需要额外的配置。

sindresorhus 的 Gist非常棒,详细解释了如何在许多不同的工具中使用 ESM。如果您在使用 MDX、其他工具和 ESM 时遇到问题,您可能会在那里找到您需要的内容。请仔细阅读。如果您仍然遇到问题,则集成 MDX 的工具的问题跟踪器可能会提供答案。

如果您在不支持 ESM 的工具上遇到问题,例如 Electron,则一种短期解决方案是使用捆绑器制作 CJS 版本。

展开一个制作 CJS 捆绑包的示例

使用 esbuild,将 ESM 包 @mdx-js/mdx 捆绑为 CJS,输出到 vendor/mdx.js

Shell

  1. npx esbuild @mdx-js/mdx --bundle --platform=node --outfile=vendor/mdx.js

使用 MDX 时遇到的问题

使用 MDX 时出现的问题通常与我们软件包的 API 以及如何使用它们有关。有关更多信息和示例,请参阅您正在使用的软件包、函数和选项的文档。

options.renderer 不再受支持

此错误由 @mdx-js/loader,我们的 webpack 加载器抛出。它在版本 2 中引入,用于帮助迁移。

renderer 选项允许在每个编译后的 MDX 文件之前注入任意文本。通常用于支持除 React 之外的框架,例如 Preact。现在我们有了诸如 jsxImportSource 等选项,可以通过 recmaPlugins 添加任意的 JavaScript。由于版本 2 使用基于 AST 的方法,因此不再支持 renderer,因此将其删除。

请参阅§ 开始使用中的 Preact,了解如何支持 Preact。请参阅§ 扩展 MDX 中的创建插件,了解如何创建插件。

format: 'detect' 格式不正确

format: 'detect' 格式不正确

MDX 2 中的完整错误消息如下:

  1. Incorrect `format: 'detect'`: `createProcessor` 只能支持 `md` `mdx`;它不支持检测格式

MDX 3 中的完整错误消息如下:

  1. Unexpected `format: 'detect'``createProcessor` 不支持该选项,期望 `'mdx'` `'md'`

此错误由 @mdx-js/mdx,我们的核心编译器抛出。在引入 format 选项时引入。

当配置为 'detect' 时,format 选项允许推断文件是 MDX 还是纯 markdown。基于这些信息,插件会以不同的方式进行配置,并使用不同的选项。这在 createProcessorunified 中是不可能的。

要检测传递文件的格式,请使用 @mdx-js/mdx 中的 compile 或其中一个集成。

在经典运行时缺少 pragmaImportSource 中的 pragma

此错误由 @mdx-js/mdx,我们的核心编译器抛出。在引入 jsxRuntimepragmapragmaImportSource 选项时引入。

jsxRuntime 配置为 'classic'(默认值为 'automatic'),定义了 pragmaImportSource(默认值为 'react'),但是 pragma 定义为假值(默认值为 React.createElement)时,会抛出此错误。

如果您正在使用经典运行时,则必须定义一个 pragma

jsxRuntime: 'classic'pragmapragmaFragpragmaImportSource 不受支持的意外废弃选项

这是一个警告。这不是一个错误。您可以继续使用这些选项,但预计它们将来会被删除。

目前所有主要框架都支持自动 JSX 运行时。从 MDX 的角度来看,经典运行时存在几个潜在问题。

因此,我们强烈建议使用自动 JSX 运行时,并考虑删除对经典 JSX 运行时的支持。

evaluate 中给定的不是 Fragment

evaluate 中给定的不是 jsx

evaluate 中给定的不是 jsxs

这些错误由 @mdx-js/mdx,我们的核心编译器抛出。在引入 evaluate(和 evaluateSync)时引入。

evaluate 支持 React 和其他框架。但是这些框架必须支持自动 JSX 运行时,该运行时公开了这三个导出值。如果您收到此错误,则表示要么 a) 框架不支持自动 JSX 运行时,要么 b) 您没有将它们正确地传递给 evaluate

请参阅 [@mdx-js/mdx](/packages/mdx/#evaluatefile-options

) 中的 evaluate,了解如何传递这些值的示例。

期望在 options.baseUrl 中提供一个对应的闭合括号的表达式

MDX 中的完整错误消息如下:

  1. Unexpected missing `options.baseUrl` needed to support `export … from`, `import`, or `import.meta.url` when generating `function-body`

当专门使用 evaluate 运行 MDX,或者使用 outputFormat: 'function-body' 选项以稍后执行时,并且使用了 import.meta.urlimportexport … from 时,会抛出此错误。这些 JavaScript 功能取决于一个特定的 URL 来运行,而在运行函数体时该 URL 不可用或不正确。要解决此问题,请传递一个 baseUrl 选项。可能设置为 import.meta.url(或 window.location.href)。

编写 MDX 时遇到的问题

在编写 MDX 时遇到的问题通常与如何组合 JS(X) 和 markdown 有关。这是两种语言的奇怪组合:markdown 是空格敏感宽容的(您键入的内容可能不完全正确,但不会崩溃),而 JavaScript 是空格不敏感严格的(有拼写错误会导致崩溃)。

错误通常分为以下三类:

  • 未转义 <{ — 如果您希望它们作为纯文本而不是 JS(X),请转义它们(\<\{)。
  • 不正确的交错 — 查看§ 什么是 MDX 中的交错中的规则。
  • 损坏的 JavaScript — 确保您编写的 JavaScript 是有效的。

acorn 解析 import/exports 时出错:$error

此错误由我们的 MDX 解析器抛出。它在版本 2 中引入。当在行首找到关键字 importexport,但后面没有有效的 JavaScript 时,就会出现此错误。一个示例是:

  1. import 1/1

出现此错误的原因是解析器期望一个 JavaScript 的导入或导出语句。如果您想要单词 import 或 export,请确保它不是段落的开头。如果您确实需要一个导入或导出语句,请确保它是有效的 JavaScript。

在仅限代码的 import/exports 中出现意外的 $type

此错误由我们的 MDX 解析器抛出。它在版本 2 中引入。当 importexport 语句之后发现更多 JavaScript 时,就会出现此错误。一个示例是:

  1. export const a = 1
  2. const b = 2

出现此错误的原因是我们只允许 importexport 定义数据。如果要定义变量或函数,请导出它。

在表达式中出现意外的文件末尾:期望与 { 的相应闭合括号

此错误由我们的 MDX 解析器抛出。它在版本 2 中引入。当出现未跟随闭合大括号的开放大括号时,就会出现此错误。一个示例是:

  1. a { b

出现此错误的原因是解析器期望另一个大括号。如果您只是想要一个括号而不是表达式,请将其转义:\{。如果您确实想要一个表达式,请确保使用闭合括号 } 进行闭合。如果某处有一个闭合括号,请确保括号各自位于自己的行上,括号之前没有文本,并且在关闭括号之后没有文本,或者在括号之间没有空行。

表达式容器中的意外延迟行

此错误由我们的 MDX 解析器抛出。它在版本 3 中引入。当具有延迟行的容器与表达式结合时会出现此错误。例如:

  1. * {1 +
  2. 2}
  3. > {1 +
  4. 2}

此错误的原因是解析器可能指向一个 bug。请明确指定您的列表项和块引用:

  1. * {1 +
  2. 2}
  3. > {1 +
  4. > 2}

使用 acorn 解析表达式时出错:$error

此错误由我们的 MDX 解析器抛出。它在版本 2 中引入。当存在匹配的大括号时,解析器解释其中内容为 JavaScript 时导致语法错误时会出现此错误。例如:

  1. a {const b = 'c'} d

另一个示例:

  1. a {!} d

此错误的原因是解析器期望一个 JavaScript 表达式。如果您只想要括号而不是表达式,请转义开头:\{。如果您确实想要一个表达式,请确保它是有效的 JavaScript,并且是一个表达式。这意味着语句(如 ifelsefor 循环)是不起作用的。如果您需要复杂的逻辑,可以将语句和整个程序包装到 IIFE 中,或将其移出到一个不同的文件中,从那里导出它,并在 MDX 中导入它。

使用 acorn 解析表达式时出错:表达式之后的意外内容

此错误由我们的 MDX 解析器抛出。它在版本 2 中引入。当匹配的大括号中包含有效的 JavaScript,但是 JavaScript 太多时会出现此错误。例如:

  1. a {'b' 'c'} d

此错误的原因是解析器期望一个产生单个值的单个 JavaScript 表达式。如果您只想要括号而不是表达式,请转义开头:\{。如果您确实想要一个表达式,请确保它产生单个值。

在展开中出现意外的额外内容:仅支持一个单独的展开

此错误由我们的 MDX 解析器抛出。它在版本 2 中引入。当将多个值展开到 JSX 标签中时会出现此错误。例如:

  1. <div {...a, ...b} />

此错误的原因是 JSX 只允许一次展开一个值:

  1. <div {...a} {...b} />

代码中的意外 $type:仅支持展开元素

意外的空表达式

这些错误由我们的 MDX 解析器抛出。它们在版本 2 中引入。当大括号中使用的不是展开操作时会出现这些错误。例如:

  1. <div {values} {/* comment */} {} />

此错误的原因是 JSX 只允许展开值:

  1. <div {...a} />

在 $expect 中意外的文件结尾:期望 $expect

在 $expect 中意外的字符 $at:期望 $expect

这些错误由我们的 MDX 解析器抛出。它们在 MDX 版本 2 中引入。当在 JSX 标签中发现意外内容时会出现这些错误。一些示例是:

  1. <
  2. <.>
  3. </
  4. </.>
  5. <a
  6. <a?>
  7. <a:
  8. <a:+>
  9. <a.
  10. <a./>
  11. <a b
  12. <a b!>
  13. <a b:
  14. <a b:1>
  15. <a b=
  16. <a b=>
  17. <a b="
  18. <a b='
  19. <a b={
  20. <a/
  21. <a/->

意外的标签中的自关闭斜杠:预期标签结束

此错误由我们的 MDX 解析器抛出。它在版本 2 中引入。当一个关闭标签也被标记为自关闭时会出现此错误。例如:

  1. <h1>Text</h1/>

此错误的原因是只有打开标签才可以被标记为自关闭。在标签名称之后和 > 之前删除斜杠。

意外的闭合标签</$tag>,预期与<$tag>的相应闭合标签(位于 $at 处)

此错误由我们的 MDX 解析器抛出。它在版本 2 中引入。当发现一个不匹配预期的闭合标签时会出现此错误。例如:

  1. <a>Text</b>

此错误的原因是 JSX 中的标签必须匹配。您可能忘记了正确地打开或关闭其中一个。

无法关闭$type(位于 $at 处):仍然有不同类型的标记打开

无法关闭文档,仍然有一个标记($type,$at)打开

此错误由我们的 MDX 解析器抛出。它在版本 2 中引入。当 Markdown 和 JSX 没有正确交错时通常会出现此错误。例如:

  1. > <div>

此错误的原因是 Markdown 结构结束,但标签仍然打开着。请查看 § 什么是 MDX? 中的交错规则。