【mdBook】7.1 预处理器

预处理器是在书籍加载后、渲染前立即运行的一段代码,允许您更新和修改书籍。可能的用例包括:

  • 创建自定义助手,如 {``{#include /path/to/file.md}}
  • 将 LaTeX 风格的表达式($$ \frac{1}{3} $$)替换为它们的 MathJax 等效形式

有关使用预处理器的更多信息,请参阅"配置预处理器"章节。

集成到 MDBook

MDBook 使用相当简单的机制来发现第三方插件。在 book.toml 中添加一个新表(例如,对于 foo 预处理器使用 [preprocessor.foo]),然后 mdbook 将尝试调用 mdbook-foo 程序作为构建过程的一部分。

执行流程

一旦定义了预处理器并且构建过程开始,mdBook 会执行 preprocessor.foo.command 键中定义的命令两次:

第一次调用:检查渲染器支持

bash 复制代码
mdbook-foo supports [渲染器名称]
  • 预处理器应以状态码 0 退出(如果支持给定的渲染器)
  • 或以非零退出代码返回(如果不支持)

第二次调用:实际处理

bash 复制代码
mdbook-foo
  • mdbook 将 JSON 数据传入 stdin
  • JSON 格式为 [context, book] 数组
    • context 是序列化的 PreprocessorContext 对象
    • book 是包含书籍内容的 Book 对象
  • 预处理器应将修改后的 Book 对象的 JSON 格式返回到 stdout

实现预处理器

Rust 实现方式

最简单的方法是创建自己的 Preprocessor trait 实现,然后创建一个 shell 二进制文件来将输入转换为正确的 Preprocessor 方法。

便利工具:

  • examples/ 目录中有一个无操作预处理器示例
  • 可轻松适配用于其他预处理器

实现提示

通过将 mdbook 作为库引入,预处理器可以访问处理书籍的现有基础设施。

基本流程:

  1. 使用 CmdPreprocessor::parse_input() 反序列化写入 stdin 的 JSON
  2. 通过 Book::for_each_mut() 原地修改每个章节
  3. 使用 serde_json crate 将结果写入 stdout

章节访问方式:

  • 直接访问(通过递归迭代章节)
  • 使用便利方法 Book::for_each_mut()

Markdown 处理

chapter.content 只是一个恰好是 Markdown 的字符串。虽然完全可以使用正则表达式或手动查找替换,但您可能希望将输入处理为更计算机友好的格式。

推荐工具:

  • pulldown-cmark:生产级的事件驱动 Markdown 解析器
  • pulldown-cmark-to-cmark:将事件转换回 Markdown 文本

示例代码:从 Markdown 中移除所有强调,同时避免意外破坏文档

rust 复制代码
fn remove_emphasis(num_removed_items: &mut usize, chapter: &mut Chapter) -> Result<String, Error> {
    let mut buf = String::with_capacity(chapter.content.len());

    let events = Parser::new(&chapter.content).filter(|e| match e {
        Event::Start(Tag::Emphasis) | Event::Start(Tag::Strong) => {
            *num_removed_items += 1;
            false
        }
        Event::End(TagEnd::Emphasis) | Event::End(TagEnd::Strong) => false,
        _ => true,
    });

    Ok(pulldown_cmark_to_cmark::cmark(events, &mut buf).map(|_| buf)?)
}

使用其他语言实现预处理器

mdBook 使用 stdin 和 stdout 与预处理器通信的事实使得用 Rust 以外的语言实现它们变得容易。

Python 示例:修改第一章内容的简单预处理器

python 复制代码
import json
import sys

if __name__ == '__main__':
    if len(sys.argv) > 1:  # 检查是否收到任何参数
        if sys.argv[1] == "supports": 
            # 返回退出状态码 0,因为另一个参数只是渲染器的名称
            sys.exit(0)

    # 从 stdin 加载上下文和书籍表示
    context, book = json.load(sys.stdin)
    # 现在,我们可以修改第一章的内容
    book['sections'][0]['Chapter']['content'] = '# Hello'
    # 完成书籍修改后,只需将其打印到 stdout
    print(json.dumps(book))

配置对应:

toml 复制代码
[preprocessor.foo]
command = "python preprocessor.py"
相关推荐
jearry4 天前
一个编辑器两个内核:Markdown 实时视图与源码视图并存时的竞态、光标锚点与 PDF 导出
windows·markdown
FungLeo5 天前
成为全栈·Flutter App 篇·Flutter Markdown 阅读器:支持范围与渲染边界
flutter·markdown·dart·代码高亮·成为全栈·移动阅读
飞塔老梅子6 天前
21. PDF文件转换成Markdown格式 ❀ 老梅子学AI
pdf·markdown·转换·mineru·docling
天府云创8 天前
GEO内容优化之读懂llms.txt 、robots.txt和sitemap.xml
markdown·schema·geo·结构化数据·sitemap.xml·llms.txt·llms-full.txt
weixin_416660078 天前
AI 生成的流程图和公式,怎样一起导出到 Word?附可复用测试样例
word·流程图·markdown·豆包·deepseek
古少侠10 天前
AI 生成的 Markdown 怎么变成可交付的 Word?DS随心转 工程化收口清单
markdown·工程化·办公效率·word交付
用户2986985301410 天前
React 中实现 Word 与 Markdown 双向转换的实践记录
javascript·react.js·markdown
周永恒13 天前
AI制作配图
ai·markdown·绘图·工作流·博客园
洛小豆13 天前
我是 AI 牛马,老板说:做个简单的原生跨平台 Markdown 编辑器
人工智能·ai编程·markdown
Access开发易登软件16 天前
Access 导入 Markdown 表格:把文档里的数据写进表
前端·html·vba·markdown·access开发