【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"
相关推荐
伟贤AI之路14 小时前
原创分享:Markdown转思维导图,一键导出SVG、PNG、JPG、PDF
markdown
yuhaiqun19894 天前
Typora 技能进阶:从会写 Markdown 到玩转配置 + 插件高效学习笔记
经验分享·笔记·python·学习·学习方法·ai编程·markdown
臼犀4 天前
孩子,那不是说明书,那是祈祷文
人工智能·程序员·markdown
用户298698530145 天前
如何在 C# .NET 中将 Markdown 转换为 PDF 和 Excel:完整指南
后端·c#·markdown
星夜落月5 天前
从零开始:在服务器上部署Material for MkDocs完全指南
运维·markdown·建站
草帽lufei6 天前
VSCode+PicGo实现Markdown图床自动同步
markdown·visual studio code
十五年专注C++开发6 天前
Typora:优雅的 Markdown 编辑器
编辑器·markdown
李新_8 天前
基于Markwon封装Markdown组件
android·aigc·markdown
king王一帅9 天前
AI 时代真正流式解析+渲染双重优化的 Incremark
前端·ai编程·markdown
蓝冰露11 天前
把chatgpt聊天记录保存下来
chrome·ai·chatgpt·大模型·markdown·chrome devtools