- 开发工具
- 文档
【免费下载链接】mdBook
Create book from markdown files. Like Gitbook but implemented in Rust
mdBook 的渲染器(Renderers,也称 backends)负责把经过预处理器处理后的书籍内容转换为最终输出——无论是浏览器中的 HTML 站点,还是用于调试预处理器产物的 Markdown 文件。本指南以官方文档 guide/src/format/configuration/renderers.md 为骨架,深入剖析book.toml中[output.*]表的完整配置体系,并结合仓库源码揭示每个选项的底层实现,帮助你在配置自定义后端、调优 HTML 输出、排查预处理器问题时做到有的放矢。
一、渲染器是什么:两种内置后端与社区生态
渲染器负责生成书籍的输出。仓库内置了两类后端:
html:将书籍渲染为 HTML 站点,是默认后端。若book.toml中没有定义任何[output]表,它会被自动启用。markdown:在预处理器运行完毕后,将处理后的 Markdown 直接输出,主要用于调试预处理器。
社区还发展出了大量第三方后端,官方文档的 [Third Party Plugins] wiki 页维护了一份清单。如何编写自己的后端,可参考 Backends for Developers 章节——注意,该章节中链接原文使用了相对路径../../for_developers/backends.md,按仓库根目录换算后实际指向guide/src/for_developers/backends.md。
从源码看,后端是实现了Renderertrait 的对象。crates/mdbook-driver/src/mdbook.rs 中的determine_renderers()函数读取配置,决定使用哪些渲染器:名为html的键创建HtmlHandlebars,名为markdown的键创建MarkdownRenderer,其余键则生成CmdRenderer——即把渲染工作外包给外部可执行程序。若解析后一个渲染器都没有,则自动兜底插入 HTML 渲染器,这正是"未定义[output]表时默认启用 html"的源码依据。
二、输出表(Output Tables):如何启用一个后端
在book.toml中加入一个以output开头的表即可启用对应后端。例如,若你安装了名为mdbook-wordcount的后端:
[output.wordcount]mdBook 就会执行mdbook-wordcount。该表还可以携带任意键值对作为后端专属配置:
[output.wordcount] ignores = ["Example Chapter"]2.1 关键行为:显式输出表会"关闭"默认 HTML
一旦你在book.toml中定义了任何[output]表,html后端就不再默认启用。若想保留 HTML 输出,需要显式写回:
[book] title = "My Awesome Book" [output.wordcount] [output.html]2.2 输出目录布局:单后端与多后端截然不同
输出目录的位置由build.build-dir控制(默认是book)。行为规则如下:
- 只有一个后端时,输出直接放在
book目录内; - 有多个后端时,每个后端分别放在
book下的独立子目录中。上面的例子会生成book/html和book/wordcount两个目录。
从 crates/mdbook-driver/src/lib.rs 附近的渲染流程看,每个Renderer的render()都会拿到属于自己的destination路径,多后端时该路径即book/<backend-name>。
2.3 自定义后端命令(command)
默认情况下,添加[output.foo]表会让 mdBook 尝试执行mdbook-foo可执行文件。若想换用其他程序名或传入命令行参数,可以用command字段覆盖:
[output.random] command = "python random.py"这一逻辑在源码中有清晰体现:crates/mdbook-driver/src/mdbook.rs 使用table.command.unwrap_or_else(|| format!("mdbook-{key}"))决定实际命令;crates/mdbook-driver/src/builtin_renderers/mod.rs 的CmdRenderer会以ctx.destination为当前目录 spawn 该命令,并把序列化后的RenderContext通过 stdin 传给子进程。测试 crates/mdbook-driver/src/mdbook/tests.rs 也验证了command = "python random.py"的解析结果。
2.4 可选后端(optional)
启用一个未安装的后端时,默认行为是报错。若将该后端标记为optional = true,错误会降级为警告:
[output.wordcount] optional = true源码层面,CmdRenderer::render()会先读取output.<name>.optional(crates/mdbook-driver/src/builtin_renderers/mod.rs),spawn 失败时调用handle_command_error(crates/mdbook-driver/src/lib.rs):若为 optional 则仅打印"命令未找到但标记为 optional"的警告,否则提示用户安装该后端或设置optional = true。
三、HTML 渲染器选项([output.html])
HTML 渲染器支持大量选项,全部写在book.toml的[output.html]表中。以下配置示例包含了全部可用选项:
# Example book.toml file with all output options. [book] title = "Example book" authors = ["John Doe", "Jane Doe"] description = "The example book covers examples." [output.html] theme = "my-theme" default-theme = "light" preferred-dark-theme = "navy" smart-punctuation = true definition-lists = true admonitions = true mathjax-support = false additional-css = ["custom.css", "custom2.css"] additional-js = ["custom.js"] no-section-label = false git-repository-url = "https://github.com/rust-lang/mdBook" git-repository-icon = "fab-github" edit-url-template = "https://github.com/rust-lang/mdBook/edit/main/guide/{path}" site-url = "/example-book/" cname = "myproject.rs" input-404 = "not-found.md" sidebar-header-nav = true zoomable-images = true这些字段与 crates/mdbook-core/src/config.rs 中的HtmlConfig结构体一一对应(该结构体标注了rename_all = "kebab-case",即 TOML 中的连字符命名)。下面按类别逐一说明。
3.1 主题类
- theme:mdBook 自带默认主题及全部资源文件;设置此项后,mdBook 会用指定文件夹中的文件选择性覆盖主题文件。未设置时默认从根目录下的
theme文件夹读取,见HtmlConfig::theme_dir()(crates/mdbook-core/src/config.rs)。 - default-theme:'Change Theme' 下拉菜单默认选中的内置主题,合法值为
light、rust、coal、navy、ayu,默认light。 - preferred-dark-theme:浏览器通过
prefers-color-schemeCSS 媒体查询请求暗色版本时使用的内置主题,合法值与上面相同,默认navy。
3.2 Markdown 解析与排版类
- smart-punctuation:把直引号转换为弯引号、
...转换为…、--转换为 en-dash、---转换为 em-dash,默认true。详见 Smart Punctuation。 - definition-lists:启用定义列表,默认
true。详见 Definition Lists。 - admonitions:启用提示块(admonitions),默认
true。详见 Admonitions。 - mathjax-support:添加 MathJax 支持,默认
false。
从源码可印证这三项 Markdown 开关的底层行为:crates/mdbook-markdown/src/lib.rs 的new_cmark_parser()会根据MarkdownOptions向 pulldown-cmark 注入ENABLE_SMART_PUNCTUATION、ENABLE_DEFINITION_LIST、ENABLE_GFM(admonitions 依赖 GFM 扩展)等解析选项,且MarkdownOptions的默认值同样是三者全为true。
3.3 资源注入类
- additional-css:在默认样式之后加载一组额外样式表,用于在不整体覆盖主题的情况下微调外观。
- additional-js:在默认脚本之外加载一组 JavaScript 文件,用于在不移除现有行为的前提下补充交互。
3.4 目录与页面结构类
- no-section-label:默认情况下 mdBook 会在目录(TOC)列添加数字章节标签(如 "1."、"2.1"),设为
true可禁用,默认false。 - sidebar-header-nav:若为
true,侧边栏会包含当前页标题的导航。默认true。
3.5 代码库集成类
- git-repository-url:书籍的 git 仓库地址。设置后会在书籍菜单栏输出一个图标链接。
- git-repository-icon:git 仓库链接使用的 Font Awesome 图标类名,默认
fab-github(即 GitHub 图标)。非 GitHub 项目可考虑fas-code-fork。字符串前缀规则:fa-为常规图标、fas-为实心图标、fab-为品牌图标,完整图标列表见 Font Awesome 官网。 - edit-url-template:编辑 URL 模板,设置后显示 "Suggest an edit" 按钮(铅笔图标),用于直接跳转编辑当前页面。GitHub 项目可设为
https://github.com/<owner>/<repo>/edit/<branch>/{path},Bitbucket 项目可设为https://bitbucket.org/<owner>/<repo>/src/<branch>/{path}?mode=edit,其中{path}会被替换为文件在仓库中的完整路径。
3.6 部署与 SEO 类
- input-404:用于缺失文件的 Markdown 文件名,输出文件为同名但扩展名换成
html的文件,默认404.md。源码中get_404_output_file()(crates/mdbook-core/src/config.rs)会把.md替换为.html。 - site-url:书籍将托管的基础 URL。即使从子目录访问 URL,也必须设置它,以确保 404 文件中的导航链接和脚本/CSS 引用正确。默认
/。设置site-url后,资源请使用文档相对链接(不要以/开头)。 - canonical-site-url:设置书籍的 canonical URL,供搜索引擎判断内容的权威 URL。当站点以多个 URL 部署(例如为不同版本分别部署)时使用,可将所有 URL 指向最新版本,避免内容重复被降权以及访客访问到过期版本。
- cname:托管书籍的 DNS 子域或顶级域。该字符串会被写入站点根目录下名为
CNAME的文件,符合 GitHub Pages 自定义域名的要求。 - hash-files:在静态资源文件名中嵌入文件内容的加密"指纹",文件内容变化时文件名也随之变化,例如
css/chrome.css可能变成css/chrome-9b8f428e.css。章节 HTML 文件不会被重命名,静态 CSS/JS 之间可用{{ resource "filename" }}指令互相引用。默认true。 - zoomable-images:若为
true,点击图片时会打开一个模态框展示放大视图。默认true。
3.7 子表:[output.html.print]
控制打印输出。默认情况下 mdBook 会在书页右上角显示打印图标(可将全书打印为单页)。
[output.html.print] enable = true # include support for printable output page-break = true # insert page-break after each chapter- enable:是否渲染打印支持,设为
false时不渲染任何打印相关输出,默认true。 - page-break:在章节之间插入分页符,默认
true。
对应源码为 crates/mdbook-core/src/config.rs 的Print结构体,两个字段默认值均为true。
3.8 子表:[output.html.fold]
控制侧边栏章节列表的折叠行为:
[output.html.fold] enable = false # whether or not to enable section folding level = 0 # the depth to start folding- enable:是否启用章节折叠,关闭时所有折叠全部展开,默认
false。 - level:数值越大,保持展开的折叠区域越多;为
0时所有折叠都关闭,默认0。
对应源码为Fold结构体(crates/mdbook-core/src/config.rs),level字段类型为u8。
3.9 子表:[output.html.playground]
控制 Rust 示例代码块及其与 Rust Playground 的集成(Ace 编辑器):
[output.html.playground] editable = false # allows editing the source code copyable = true # include the copy button for copying code snippets copy-js = true # includes the JavaScript for the code editor line-numbers = false # displays line numbers for editable code runnable = true # displays a run button for rust code- editable:是否允许编辑源代码,默认
false。 - copyable:是否在代码片段上显示复制按钮,默认
true。 - copy-js:是否把编辑器的 JavaScript 文件复制到输出目录,默认
true。 - line-numbers:是否在可编辑代码段显示行号。需要
editable与copy-js同时为true,默认false。 - runnable:是否显示 Rust 代码片段的运行按钮;设为
false将全局禁用 "run in playground" 功能,默认true。
对应源码为Playground结构体(crates/mdbook-core/src/config.rs),注意它在 serde 中设置了别名playpen,即旧版配置playpen依然兼容。
3.10 子表:[output.html.code]
控制代码块渲染:
[output.html.code] # A prefix string per language (one or more chars). # Any line starting with whitespace+prefix is hidden. hidelines = { python = "~" }- hidelines:定义各语言的 隐藏代码行 规则。键是语言名,值是一个字符串前缀;代码行以(空白 +)该前缀开头时会被隐藏。
对应源码为Code结构体(crates/mdbook-core/src/config.rs),其hidelines是HashMap<String, String>,语言与前缀一一映射。
3.11 子表:[output.html.search]
控制内置全文搜索。mdBook 编译时需启用searchfeature(默认开启)。搜索相关文档见 guide/src/guide/reading.md#search:
[output.html.search] enable = true # enables the search feature limit-results = 30 # maximum number of search results teaser-word-count = 30 # number of words used for a search result teaser use-boolean-and = true # multiple search terms must all match boost-title = 2 # ranking boost factor for matches in headers boost-hierarchy = 1 # ranking boost factor for matches in page names boost-paragraph = 1 # ranking boost factor for matches in text expand = true # partial words will match longer terms heading-split-level = 3 # link results to heading levels copy-js = true # include Javascript code for search- enable:是否启用搜索功能,默认
true。 - limit-results:最大搜索结果数,默认
30。 - teaser-word-count:每条搜索结果摘要(teaser)的单词数,默认
30。 - use-boolean-and:多个搜索词之间的逻辑关系;为
true时每个结果必须包含所有搜索词,默认false。 - boost-title:搜索词出现在标题(header)时的排名加分因子,默认
2。 - boost-hierarchy:搜索词出现在层级(hierarchy,包含所有父文档标题与父级标题)时的加分因子,默认
1。 - boost-paragraph:搜索词出现在正文文本时的加分因子,默认
1。 - expand:为
true时部分单词可匹配更长的词,如搜micro可匹配microwave,默认true。 - heading-split-level:搜索结果链接到包含结果的文档章节。文档按"小于等于该级别"的标题切分成小节,默认
3(即###三级标题)。 - copy-js:是否把搜索实现的 JavaScript 文件复制到输出目录,默认
true。
对应源码为Search结构体(crates/mdbook-core/src/config.rs),默认值与文档完全一致,源码注释甚至提示"修改默认值时请同步更新文档"。
按章节定制:[output.html.search.chapter]
该表允许对单个章节或目录覆盖搜索设置。键是章节源文件或目录的路径,值是应用于该路径的设置表。设置会递归合并,更具体的路径优先:
[output.html.search.chapter] # Disables search indexing for all chapters in the `appendix` directory. "appendix" = { enable = false } # Enables search indexing for just this one appendix chapter. "appendix/glossary.md" = { enable = true }- enable:是否对给定章节建立搜索索引,默认
true。注意它不会覆盖总开关output.html.search.enable——总开关必须为true搜索功能才存在。禁用索引需谨慎,用户搜索时找不到期望内容可能造成困惑,仅应在保留章节会导致搜索结果质量问题时使用。
对应源码为SearchChapterSettings结构体(crates/mdbook-core/src/config.rs),目前仅含enable: Option<bool>一个字段。
3.12 子表:[output.html.redirect]
为页面添加重定向,在移动、重命名或删除页面时保证旧 URL 能跳转到新位置:
[output.html.redirect] "/appendices/bibliography.html" = "https://rustc-dev-guide.rust-lang.org/appendix/bibliography.html" "/other-installation-methods.html" = "../infra/other-installation-methods.html" # Fragment redirects also work. "/some-existing-page.html#old-fragment" = "some-existing-page.html#new-fragment" # Fragment redirects also work for deleted pages. "/old-page.html" = "new-page.html" "/old-page.html#old-fragment" = "new-page.html#new-fragment"规则要点:
- 表内键值对中,键是需要生成重定向文件的位置,以构建目录为起点的绝对路径表示(如
/appendices/bibliography.html);值可以是浏览器跳转到的任意合法 URI(如https://rust-lang.org/、/overview.html或../bibliography.html)。 - 每个条目都会生成一个自动跳转到目标位置的 HTML 页面。
- 指定片段重定向(含
#fragment)时,页面必须使用 JavaScript 才能跳转到正确位置。这对重命名或移动章节标题非常有用;片段重定向对现存页面和已删除页面均适用。
对应源码为HtmlConfig.redirect字段,类型为HashMap<String, String>(crates/mdbook-core/src/config.rs),与文档描述的键值映射一致。
四、Markdown 渲染器([output.markdown])
Markdown 渲染器会先运行预处理器,再输出处理后的 Markdown。它主要用于调试预处理器,尤其适合配合mdbook test查看 mdBook 实际传给rustdoc的 Markdown 内容。
该渲染器随 mdBook 分发但默认禁用,启用方式是在book.toml中添加一个空表:
[output.markdown]目前 Markdown 渲染器没有任何配置选项,只有启用与禁用之分。若需控制哪些预处理器在它之前运行,可参考 preprocessors 文档。
从源码看,MarkdownRenderer(crates/mdbook-driver/src/builtin_renderers/markdown_renderer.rs)会把书中每个章节的内容原样写入destination下对应的.md文件(先清理旧的输出目录),不经过任何 HTML 处理,因此能忠实呈现预处理器之后的 Markdown 状态。
五、结语:一套配置,三类后端
- 自定义后端:
[output.foo]表启用mdbook-foo,可用command改命令、optional降级错误; - HTML 后端:
[output.html]及其print、fold、playground、code、search、redirect子表,覆盖主题、Markdown 解析、资源注入、搜索、重定向等全部产出细节; - Markdown 后端:
[output.markdown]空表即启用,是预处理器调试利器。
所有选项都能在 crates/mdbook-core/src/config.rs 的HtmlConfig、Search、Playground、Print、Fold、Code、SearchChapterSettings等结构体中找到一一对应的字段定义与默认值;渲染器装配与执行逻辑则可查阅 crates/mdbook-driver/src/mdbook.rs 与 crates/mdbook-driver/src/builtin_renderers/mod.rs。把握"输出表驱动"这一核心思想,你就能自由组合后端,构建出符合自己发布与调试需求的书籍构建流程。
- 开发工具
- 文档
【免费下载链接】mdBook
Create book from markdown files. Like Gitbook but implemented in Rust
相关推荐
用 mdbook-renderer 构建自定义 mdBook 渲染器(Backend):从 RenderContext 协议到完整插件实现
用 mdbook renderer 构建自定义 mdBook 渲染器(Backend):从 RenderContext 协议到完整插件实现 本指南面向希望在 m
开发工具文档RapidSMS 消息测试器 httptester 使用指南:不花一分钱调试短信应用
RapidSMS 消息测试器 httptester 使用指南:不花一分钱调试短信应用 RapidSMS 是一个用 Python 构建短信应用的成熟开源框架,而
mdBook 自定义后端(Backend)开发完全指南:从零实现一个渲染插件
mdBook 自定义后端(Backend)开发完全指南:从零实现一个渲染插件 本指南以 mdBook 官方开发者文档为主线,系统讲解如何为 mdBook 编写自
开发工具文档
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考