【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"
相关推荐
程序员老刘13 小时前
一杯奶茶钱,PicGo + 阿里云 OSS 搭建永久稳定的个人图床
flutter·markdown
課代表5 天前
大语言模型能够理解的11种文件格式
人工智能·语言模型·自然语言处理·llm·markdown·token·模型
chenshiming8028 天前
AI 编程 Vibe coding 尝试,1 天完成多平台 Markdown 编辑/阅读软件开发
ai编程·markdown·vibecoding
信码由缰9 天前
停止编写Excel规格文档:企业级Java开发的Markdown先行方法
java·ai编程·markdown
海棠AI实验室10 天前
Markdown 写作工作流:把编辑器当作你的“交付系统”
编辑器·markdown
伟贤AI之路11 天前
原创分享:Markdown 表格导出 Excel/Json - 方便数据处理分析
json·excel·markdown
Code Talk11 天前
VS Code markdown preview 与 github markdown渲染数学公式中的“_”不一致的问题
github·markdown·math
wscats12 天前
Markdown 编辑器技术调研
前端·人工智能·markdown
belldeep13 天前
python:markdown + python-docx 将 Markdown 文件格式转为 Word 文档
python·word·markdown·docx
打小就很皮...13 天前
发送到飞书机器人的完整流程(拓展)
react·markdown·webhook·飞书机器人