news 2026/10/9 5:13:31

Sapling 文档站点中的 with-output 插件:让 MDX 示例代码自动补全真实输出

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Sapling 文档站点中的 with-output 插件:让 MDX 示例代码自动补全真实输出
  • 开发工具
  • CLI
  • 后端

【免费下载链接】sapling

A Scalable, User-Friendly Source Control System.

项目地址:https://gitcode.com/gh_mirrors/sa/sapling
点击查看免费下载

导读

sapling-output-plugin是 Sapling 网站(基于 Docusaurus + MDX)内置的一个 remark/MDX 插件,它让文档作者可以写出只含命令、不含输出的示例代码块(with-output代码块),并由真实运行的 Sapling CLI 在构建期自动补全输出结果。本文将以 website/src/plugins/sapling-output/README.md 为骨架,结合插件源码、debugruntest命令实现和站点配置,讲清它的使用语法、内部执行链路、运行依赖以及本地调试方法,读完即可在自己的文档项目中复刻这套“命令输出自动生成”的写作模式。

一、插件定位:在文档构建期“跑出”示例输出

在传统技术文档写作中,命令示例的输出往往是作者手工复制粘贴的,容易随版本迭代而失真。sapling-output-plugin解决了这个问题:它在文档静态构建阶段,把 Markdown(MDX)里标记为with-output的代码块转换成 Sapling 自身的.t测试文件,交给真实 CLI 执行,再把执行后补全的输出回填到代码块中渲染出来。

从站点配置可以看出它的接入位置——website/docusaurus.config.js 中,它作为 Docusaurus docs 的remarkPlugins之一注册:

remarkPlugins: [ [require('remark-github').default, {repository: 'facebook/sapling'}], require('sapling-output-plugin'), ],

插件本质是一个把 MDX AST 中所有lang === 'with-output'的code节点收集起来、异步改写其value的 remark 转换器(见 website/src/plugins/sapling-output/src/index.ts)。它借助unist-util-visit遍历语法树,并用Promise.all并行处理所有待补全的代码块。

二、使用语法:with-output代码块与隐藏区

1. 最简单的用法

在任意 MDX 文档中,把语言标记写成with-output:

```with-output $ echo a ```

构建渲染后,插件会运行这条命令并把真实输出补在下方,页面最终显示为:

$ echo a a

2. 语法来源:.t测试的简化版

with-output的语法与 Sapling 集成测试使用的.t测试文件高度一致(语法解析器见 eden/scm/sapling/testing/init.py),区别在于:在.t文件中每条命令前需要两个空格前缀,而with-output代码块不需要。插件会在内部把每一行自动加上" "前缀,转成标准的.t输入(对应源码processInput中的逻辑:website/src/plugins/sapling-output/src/index.ts)。

3. 用# hide begin/# hide end隐藏准备命令

文档作者经常需要在示例前做初始化,又不希望这些准备命令出现在读者面前。插件支持用# hide begin和# hide end圈定隐藏区域,例如:

```with-output # hide begin $ sl init repo $ cd repo $ touch a b # hide end $ sl add a $ sl st ```

渲染结果为(准备命令被隐去,只剩读者关心的命令和输出):

$ sl add a $ sl st A a ? b

注意:# hide begin/# hide end之间的命令仍会真实执行,只是其命令行不回显、其输出也不参与渲染。

三、内部原理:从 MDX 到.t再到回填输出

插件的核心实现在 website/src/plugins/sapling-output/src/index.ts,整个流程可分为四步。

1. 注入示例运行环境头(EXAMPLE_HEADER)

插件会在每个示例最前面插入一段被# hide begin/# hide end包裹的环境准备脚本(源码第 18-35 行),包括:

  • 向$HGRCPATH追加[ui]、[init]、[templatealias]配置:例如设置prefer-git=false,以及sl_difflink、github_pull_request_number、github_pr_state、github_pull_request_status_check_rollup等模板别名,使示例中的 PR 相关模板输出与真实环境一致;
  • 导出TEST_PROD_CONFIGS=1,以加载生产环境模板;
  • 导出HGCOLORS=16、SL_COLORS=16,强制 16 色输出,保证渲染出的彩色终端文本稳定可预期。

2. 生成临时.t文件并调用debugruntest --fix

renderExample(源码第 116-146 行)会在系统临时目录下创建前缀为mdx-sapling-output的临时目录,把处理后的示例写入example.t,然后调用:

sl debugruntest -q --fix example.t

其中--fix(等价于-i)表示“按实际输出更新测试文件”。执行结束后插件重新读回被补全的example.t,这就是渲染输出。调用失败时,退出码1表示“至少有一处输出不匹配”,这是预期结果,会被吞掉;其他错误码才会抛出。

3. 清理输出(processOutput)

读回的.t输出需要还原为文档友好的形式(源码第 72-93 行):

  • 删除每行开头的两个空格前缀(.t的输出行标记);
  • 移除# hide相关行以及# hide begin到# hide end之间的整段内容;
  • 去掉文件开头的空行。

4. 颜色支持

终端颜色 ANSI 序列会被映射为 HTML 颜色。源码中内置了 Windows Console 的 Campbell 调色板(COLORS常量,第 95-113 行),把\x1b[38;5;Nm之类的颜色码转换为对应的十六进制色值,从而在页面上还原命令输出的彩色效果(如A、?等状态标记的颜色区分)。

5. CLI 选择:SL环境变量

默认情况下插件调用sl命令;若希望指向特定路径的 Sapling 可执行文件,可设置环境变量SL(源码第 183-185 行):

SL=/path/to/sl yarn build

四、运行依赖:debugruntest命令详解

插件正常运行的前提是系统中存在可用的 Sapling CLI(sl)。它依赖的debugruntest(别名debugrt、.t)是 Sapling 内置的.t测试执行命令,定义于 eden/scm/sapling/commands/debug.py:

sl debugruntest [OPTION]... [TEST]... -i, --fix 更新测试以匹配实际输出 -j, --jobs 并行运行的 job 数 -x, --ext 要导入的扩展模块 -d, --direct 不使用隔离直接运行 --record 记录测试状态

其中norepo=True意味着该命令可在任意目录执行,无需处于仓库内——这正是插件能在文档构建期自由生成临时.t文件并运行的前提。

关于.t格式与debugruntest的更多细节(与run-tests.py的差异、扩展语法、Python>>>doctest 块等),可参考 eden/scm/sapling/testing/init.py。例如debugruntest支持 Python doctest 风格的>>>块——站点中 zstdelta 文档 就大量使用了这一特性,直接在with-output代码块里写交互式 Python 代码并让插件补全运行结果。

五、开发与调试指南

1. 插件工程结构

插件是一个独立的 TypeScript 工程,目录结构如下(详见 website/src/plugins/sapling-output/package.json):

  • src/index.ts:插件全部实现(CommonJS 导出 remark 插件);
  • package.json:依赖tmp-promise、unist-util-visit、typescript,产物输出到dist/;
  • yarn.lock:锁定依赖版本。

2. 在 Docusaurus 项目中应用修改

插件的构建产物为dist/index.js(main字段指定),Docusaurus 通过require('sapling-output-plugin')加载的正是这个产物。因此,修改插件源码后需要重新编译,再在 Docusaurus 项目内执行yarn install以生效。

3. TypeScript 编译

开发插件本体时,在 website/src/plugins/sapling-output 目录下:

yarn install yarn build

构建站点静态版本前务必执行上述两步。若正在活跃开发插件,则改用监听模式:

yarn install yarn watch

TypeScript 监听器会在后台增量更新dist/目录。注意:Docusaurus 不会热加载插件产物,修改后需要重启 Docusaurus 才能看到变化。

4. 调试临时文件

插件运行时会在系统临时目录创建前缀为mdx-sapling-output的临时目录,默认执行结束后自动删除。如需保留现场用于排查,设置环境变量:

MDX_SAPLING_OUTPUT_DEBUG=1 yarn build

设置后临时目录将不会被自动清理,可以检查生成的example.t(包含注入的环境头与补全后的输出)来定位问题。

六、仓库内的真实使用示例

with-output语法已在站点文档中实际投入使用。例如 website/docs/dev/internals/zstdelta.md 中讲解 ZstDelta 的diff/apply用法时,就直接书写了只含输入、不含输出的 Python 交互块,由插件在构建期补全len(a)、len(diff)、布尔判断等运行结果:

```with-output >>> import bindings, hashlib >>> a = b"".join(hashlib.sha256(str(i).encode()).digest() for i in range(1000)) >>> len(a) >>> b = a[:10000] + b'x' * 10000 + a[11000:] >>> diff = bindings.zstd.diff(a, b) >>> len(diff) >>> bindings.zstd.apply(a, diff) == b ```

这种“示例即测试、输出即真相”的写作方式,保证了文档中的命令输出永远与当前版本的 Sapling 实际行为保持一致,也是本插件的核心价值所在。

小结

sapling-output-plugin通过把 MDX 中的with-output代码块转为.t测试并借助sl debugruntest --fix真实执行,实现了文档示例输出的自动化与准确性。它覆盖了从语法设计(# hide begin/# hide end)、环境注入、输出回填到颜色渲染的完整链路,并提供了MDX_SAPLING_OUTPUT_DEBUG、SL等实用的调试与定制手段。若你的文档项目同样基于 Docusaurus,并希望命令示例永不过期,可直接复用这一插件的实现思路:接入方式、源码与命令定义分别见 website/src/plugins/sapling-output/README.md、website/src/plugins/sapling-output/src/index.ts 与 eden/scm/sapling/commands/debug.py。

  • 开发工具
  • CLI
  • 后端

【免费下载链接】sapling

A Scalable, User-Friendly Source Control System.

项目地址:https://gitcode.com/gh_mirrors/sa/sapling
点击查看免费下载

相关推荐

上一篇:如何免费解锁WeMod Pro高级功能:Wand-Enhancer完整使用指南
下一篇:如何免费解锁Wand专业版:一键移除2小时限制的完整教程

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/9 5:11:47

2026年AP组网设备清单:从选型到部署的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/9 5:10:46

linux中find查找

linux常用命令 find查找 find 查找范围 匹配条件(范围要尽量小,这样查找起来才快) #匹配条件: -name: 按照文件的名称-type: 文件类型(l,d,f)-size: 文件大小 &#xff…

作者头像 李华
网站建设 2026/10/9 5:08:58

GRE备考作业化:从目标拆解到每日清单的高效执行方案

1. 把GRE备考当成“作业”来经营:从目标到任务的翻译过程第一次翻开GRE官方指南的人,十有八九会和我当初一样,在目录面前坐半小时不动笔。整本书的章节、题型、评分规则铺在眼前,那种感觉不是“难”,而是“不知道自己该…

作者头像 李华