资讯详情

资讯详情

remark-mdx 插件完全指南:为 Markdown 解析管线启用 MDX 语法(JSX / ESM / 表达式)

前端文档模板引擎【免费下载链接】mdxMarkdown for the component era项目地址https://gitcode.com/gh_mirrors/md/mdx点击查看免费下载导读remark-mdx是 MDX 官方仓库中维护的 remark 插件它的职责是在 unified/remark 的解析与序列化管线中启用 MDX 对 Markdown 的三类语法扩展JSXVideo id{123} /、ESM 导出与导入export {x} from y以及行内/块级表达式{1 1}。阅读本文后你将掌握remark-mdx的安装方式、unified().use(remarkMdx[, options])的完整配置项含默认值与取值说明、它与mdx-js/mdx编译器及 bundler 集成之间的层次关系并通过源码与测试用例理解它是如何同时打通 micromark解析与 mdast语法树/序列化两条扩展通道的。什么是 remark-mdxremark-mdx是一个 unified / remark 插件用于启用 MDX 在 Markdown 基础上新增的语法能力JSXx/、Video id{123} /这类内嵌组件标签export / importexport x from y这类 ESM 语句表达式{1 1}这类行内表达式与流式表达式。你可以用这个插件为 Markdown 增加**解析parse与序列化stringify**这两方面的支持既能读取包含 MDX 语法的文档并产出 mdast 语法树也能把包含 MDX 节点的 mdast 语法树重新序列化为 MDX 文本。需要特别注意的是remark-mdx并不负责把 MDX 编译成 JavaScript也不负责求值或渲染成 HTML——这一步由仓库中的 mdx-js/mdx 核心编译包 完成。remark-mdx专注的是语法层认识并正确表达 MDX 语法。什么时候应该使用它如果你正在与 remark、rehype 以及 unified 生态打交道并且需要处理 MDX 语法本身remark-mdx就非常有用。典型场景包括语法 lint对 MDX 源码做静态检查例如校验 JSX 标签是否闭合、表达式是否合法编译成非 JavaScript 目标把 MDX 语法树转换成其他形式的输出而不是编译成 JS语法树访问不借助完整编译器直接操作包含 MDX 节点的 mdast 语法树。如果你不使用插件体系、只想要语法树可以改用mdast-util-from-markdown搭配mdast-util-mdx这正是本插件底层使用的两个依赖详见下文源码剖析。在 MDX 工具链中通常还可以往上层选择mdx-js/mdx核心编译器负责把 MDX 编译成 JavaScript提供最底层的控制力集成层如果你在使用 Rollup、esbuild、webpack 等打包器或 Next.js、Vite 等自带打包器的站点构建体系直接使用对应集成如仓库中的 esbuild、rollup、loader 等更合适。安装remark-mdx是纯 ESM 包type: module见 packages/remark-mdx/package.json需要 Node.js 16 环境。npm 安装npm install remark-mdxDeno通过 esm.shimport remarkMdx from https://esm.sh/remark-mdx3浏览器通过 esm.sh 的 bundle 形式script typemodule import remarkMdx from https://esm.sh/remark-mdx3?bundle /script仓库中该包当前版本为3.1.1运行时依赖仅有两个mdast-util-mdx^3.0.0与micromark-extension-mdxjs^3.0.0见 packages/remark-mdx/package.json依赖面非常收敛。快速上手以下示例演示如何在 remark 流程中启用 MDX 语法并对一段混合内容做一次解析→序列化往返import {remark} from remark import remarkMdx from remark-mdx const file await remark() .use(remarkMdx) .process(import a from b\n\na b / c {1 1} d) console.log(String(file))输出结果import a from b a b/ c {1 1} d可以看到import语句、自闭合 JSX 标签b/和表达式{1 1}都能被正确识别并原样序列化回来普通文本a、c、d也保持不变。API 详解remark-mdx不导出任何具名标识符默认导出即插件函数remarkMdx。入口文件 packages/remark-mdx/index.js 只做两件事通过/// reference typesmdast-util-mdx /增强 mdast 节点类型以及export {default} from ./lib/index.js转发默认导出。unified().use(remarkMdx[, options])为当前 processor 添加 MDX 支持JSXVideo id{123} /export/importexport {x} from y表达式{1 1}。参数optionsOptions可选——配置对象。返回值无undefined。插件内部通过给 processor 的data注册三类扩展来生效详见下文源码剖析这与普通 remark 插件通过返回 transform 函数的模式不同——它不直接操作语法树而是注入解析与序列化扩展。OptionsOptions是配置对象的 TypeScript 类型由MicromarkOptionsmicromark 扩展配置与ToMarkdownOptionsmdast-util-mdx 序列化配置合并而成见 packages/remark-mdx/lib/index.js。字段如下字段类型默认值说明acornOptionsAcornOptions{ecmaVersion: 2024, locations: true, sourceType: module}acorn 的配置用于解析表达式与 ESM 语句生成 ESTree除locations外的字段均可覆盖printWidthnumberInfinity序列化时的折行宽度设为有限值如80后当某个标签在一行放不下时格式化器会把属性打印在独立行上默认行为是属性之间用空格分隔而非换行quote或属性值周围使用的首选引号quoteSmartbooleanfalse当使用另一种引号能减少字节数时自动改用另一种引号tightSelfClosingbooleanfalse自闭合元素闭合前不输出额外空格输出img/而非img /原文档注释明确说明acorn、addResult、allowEmpty、spread这几个选项有意不做公开文档化属于内部或半内部能力普通使用者无需配置。printWidth与quote、quoteSmart、tightSelfClosing都属于序列化端mdxToMarkdown的格式控制项在把 mdast 中的 MDX 节点写回文本时生效acornOptions则影响解析端对表达式与 ESM 的 ESTree 生成。源码剖析插件如何同时打通解析与序列化remark-mdx的完整实现只有 44 行packages/remark-mdx/lib/index.js核心逻辑是向 unified processor 的data注册三类扩展import {mdxFromMarkdown, mdxToMarkdown} from mdast-util-mdx import {mdxjs} from micromark-extension-mdxjs export default function remarkMdx(options) { const self this const settings options || emptyOptions const data self.data() const micromarkExtensions data.micromarkExtensions || (data.micromarkExtensions []) const fromMarkdownExtensions data.fromMarkdownExtensions || (data.fromMarkdownExtensions []) const toMarkdownExtensions data.toMarkdownExtensions || (data.toMarkdownExtensions []) micromarkExtensions.push(mdxjs(settings)) fromMarkdownExtensions.push(mdxFromMarkdown()) toMarkdownExtensions.push(mdxToMarkdown(settings)) }这三条通道各司其职micromarkExtensions→mdxjs(settings)注入来自micromark-extension-mdxjs的 micromark 扩展让底层分词器认识 JSX、ESM 和表达式语法acornOptions在这里消费用于把表达式与 ESM 解析成 ESTreefromMarkdownExtensions→mdxFromMarkdown()注入来自mdast-util-mdx的从 Markdown 到 mdast转换扩展把 micromark 产生的 token 组装成 MDX 类型的 mdast 节点toMarkdownExtensions→mdxToMarkdown(settings)注入从 mdast 到 Markdown的序列化扩展负责把 MDX 节点写回文本printWidth、quote、quoteSmart、tightSelfClosing在这里消费。settings对象被同时传给解析端mdxjs与序列化端mdxToMarkdown这也是Options类型定义为两者配置合并的原因。注意插件读取self.data()上的扩展数组时采用取已有或新建并push的方式因此可以与其他 remark 插件如remark-parse、remark-stringify和平共存、按注册顺序叠加。在核心编译器中的位置mdx-js/mdx的处理器构建逻辑packages/mdx/lib/core.js展示了remark-mdx的典型调用位置const pipeline unified().use(remarkParse) if (settings.format ! md) { pipeline.use(remarkMdx) }即先remarkParse解析 Markdown随后在format不是纯md时挂载remarkMdx之后才是remarkMarkAndUnravel、用户自定义 remark 插件、remarkRehype并passThrough全部 MDX 节点类型见 packages/mdx/lib/core.js以及 recma 系列的 JS 生成插件。这说明remark-mdx处于Markdown 语法树层的关键枢纽位置——它向上承接remarkParse向下为 rehype/recma 提供结构化的 MDX 节点。MDX 语法树节点类型通过mdxFromMarkdown组装出的 MDX 节点会以mdx*前缀出现在 mdast 中。从 packages/remark-mdx/test/index.js 的断言可以看到实际节点形态mdxJsxTextElement/mdxJsxFlowElementJSX 元素节点含name片段时name为null、attributes、children字段行内形式出现在 paragraph 内块级形式出现在 root 下mdxTextExpression/mdxFlowExpression表达式节点value保存原始表达式源码如1 1data.estree保存 acorn 解析出的 ESTreemdxjsEsmESM 语句节点mdxJsxAttribute/mdxJsxExpressionAttribute/mdxJsxAttributeValueExpressionJSX 属性相关节点分别表示普通属性、{...spread}展开属性、以及id{123}形式的表达式属性值。例如解析Alpha b/ charlie.得到的段落结构是text(Alpha )→mdxJsxTextElement(name: b, attributes: [], children: [])→text( charlie.)见 packages/remark-mdx/test/index.js。测试还验证了片段标签/的name为null、标签内部可以继续解析 Markdown如b*bravo*/b中bravo是emphasis节点、表达式节点保留value为原始字符串等行为。序列化端的行为特征packages/remark-mdx/test/index.js 同时验证了mdxToMarkdown的序列化行为这些细节对编写 remark 插件很有参考价值具名标签序列化为b /含空格自闭合片段序列化为/布尔属性输出为b bravo /带值属性输出为b bravobravo /带命名空间前缀的属性如br:avo也能保留{...properties}展开属性、b{1 1}表达式属性均能正确往返标签内部的纯文本若包含或{会被转义为\、\{避免与 JSX/表达式语法冲突见 packages/remark-mdx/test/index.js空表达式{}与非空表达式{1 1}都能序列化回原文。HTML 与 hastMDX 没有 HTML 表示MDX 语法在 HTML 中没有直接表示——它是比 HTML 更高层的语法。不过当你在处理 MDX 时通常仍会途经 hastHTML 抽象语法树。如果希望在转换为 hast 时保留 MDX 节点而不是报错或丢弃可以给remark-rehype配置passThrough把五个 MDX 节点类型放行remark().use(remarkMdx).use(remarkRehype, { passThrough: [ mdxjsEsm, mdxFlowExpression, mdxJsxFlowElement, mdxJsxTextElement, mdxTextExpression ] })这正是mdx-js/mdx核心编译器内部的做法在 packages/mdx/lib/core.js 中remarkRehype被配置为allowDangerousHtml: true并把nodeTypes即全部 MDX 节点类型合并进passThrough让 MDX 节点原样穿过 hast 层供后续 recma 阶段处理成 JavaScript。TypeScript 类型支持remark-mdx完全使用 TypeScript 类型标注源码基于 JSDocimport类型导入见 packages/remark-mdx/lib/index.js额外导出一个类型Options。如果你在编写自定义 remark 插件并希望unist-util-visit等遍历工具能识别 MDX 节点类型可以通过三斜线引用注册类型// Register MDX nodes in mdast: /// reference typesremark-mdx / /** * import {Root} from mdast */ import {visit} from unist-util-visit function myRemarkPlugin() { /** * param {Root} tree * Tree. * returns {undefined} * Nothing. */ return function (tree) { visit(tree, function (node) { console.log(node) // node can now be one of the MDX nodes. }) } }注册后visit回调中的node类型会扩展为包含全部mdx*节点类型的联合类型。包入口 packages/remark-mdx/index.js 本身也通过/// reference typesmdast-util-mdx /完成了节点类型增强。兼容性unified 社区维护的项目与受维护的 Node.js 版本保持兼容每当发布新的大版本时会放弃对已停止维护的 Node 版本的支持。当前发布线remark-mdx^3保持与Node.js 16兼容。安全性remark-mdx只负责解析与序列化语法本身不执行任何 MDX 中的 JavaScript。安全性问题主要出现在求值与渲染环节——即使用mdx-js/mdx的evaluate或运行时执行时需自行评估所处理内容的可信度避免执行不可信的代码。官方文档的 Security 章节提供了更详细的安全指引。延伸阅读MDX 核心编译器 mdx-js/mdx负责把 MDX 编译为 JavaScript内部正是通过pipeline.use(remarkMdx)接入本插件remark-mdx 插件实现44 行核心实现三条扩展通道一窥全貌remark-mdx 测试用例覆盖解析与序列化全部行为的权威参考包配置与依赖声明ESM-only、零 devDependencies、双运行时依赖MDX 集成包总览了解mdx-js/mdx、remark-mdx与各 bundler/框架集成的完整图谱。赞分享前端文档模板引擎【免费下载链接】mdxMarkdown for the component era项目地址https://gitcode.com/gh_mirrors/md/mdx点击查看免费下载相关推荐remark-mdx 完全指南在 unified/remark 生态中启用 JSX、import/export 与表达式语法remark mdx 完全指南在 unified/remark 生态中启用 JSX、import/export 与表达式语法 remark mdx 是 MDX前端文档模板引擎Astro MDX 实战用 with-mdx 示例掌握 .mdx 页面、JSX 表达式与交互组件Astro MDX 实战用 with mdx 示例掌握 .mdx 页面、JSX 表达式与交互组件 本文基于 Astro 仓库中的 with mdx 官方示例前端Web框架SSR前端构建MDX技术解析Markdown与JSX的完美融合MDX技术解析Markdown与JSX的完美融合 什么是MDX MDX是一种创新的文档格式它将Markdown的简洁语法与JSX的强大功能完美结合。这种格前端文档模板引擎上一篇勒索软件检测终极指南基于Hunting-Queries-Detection-Rules的攻击链分析与防御策略下一篇microlight.js完全指南从入门到精通的代码高亮解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →