- 开发工具
- 文档
【免费下载链接】mdBook
Create book from markdown files. Like Gitbook but implemented in Rust
mdBook("Create book from markdown files. Like Gitbook but implemented in Rust")的核心工作全部通过mdbook命令行工具完成:它负责创建书籍骨架、渲染 Markdown 为静态站点、监听文件变更自动重建、提供本地预览服务器,以及测试书中的 Rust 代码示例。本文以官方 CLI 指南为骨架,结合仓库源码(入口文件、各子命令实现)逐命令展开,读完你将掌握mdbook全部七个核心子命令的用法、参数语义与底层实现原理,能独立完成从"初始化一本书"到"持续预览、自动化测试、清理产物"的完整工作流。
mdbook CLI 总览:安装后从mdbook help开始
mdbook命令行工具用于创建和构建书籍。在完成安装之后,终端中运行mdbook help即可查看所有可用命令;运行mdbook <command> --help可以查看某个子命令的详细参数说明。
从源码看,命令树由 clap 在 src/main.rs 的create_clap_command()中构建,并且设置了arg_required_else_help(true)——即不带任何子命令直接运行mdbook时,会直接打印帮助信息而不是报错。所有子命令的入口分发在 main.rs:init、build、clean、test、completions始终可用,而watch与serve分别受watch、serve两个 Cargo feature 控制(对应#[cfg(feature = "watch")]/#[cfg(feature = "serve")])。
官方指南给出的七个命令总览如下:
| 命令 | 作用 |
|---|---|
mdbook init <directory> | 创建一本书,附带最小的样板文件(boilerplate) |
mdbook build | 渲染(构建)这本书 |
mdbook watch | 源文件一有变动就自动重建 |
mdbook serve | 启动 Web 服务器预览书籍,并在变更时重建 |
mdbook test | 测试书中的 Rust 代码示例 |
mdbook clean | 删除渲染输出 |
mdbook completions | 为常见 Shell 生成自动补全脚本 |
所有需要"指定书籍根目录"的子命令都接受一个可选的目录位置参数,省略时默认使用当前工作目录;在 main.rs 的get_book_dir()中,相对路径会被拼接上当前目录解析为绝对路径。
mdbook init:用最小样板创建新书
每本新书都有一些固定不变的样板结构,init命令正是为此设计的:
mdbook init首次执行init后,会生成如下文件结构:
book-test/ ├── book └── src ├── chapter_1.md └── SUMMARY.md各部分的含义:
src目录:书写书籍 Markdown 源文件的目录,包含所有源文件、配置文件等;book目录:书籍渲染输出目录,其中的内容已可直接上传到服务器供读者访问;SUMMARY.md:整本书的"骨架"(章节结构清单),详细语法见 format/summary.md。
技巧:从已有的 SUMMARY.md 反向生成章节
如果当前目录已存在SUMMARY.md,init会先解析它,再按照其中列出的路径自动生成缺失的章节文件。这样你可以先在头脑中(或直接写好)规划整本书的章节树,然后让 mdBook 一次性把对应的.md文件全部建好。
指定书籍目录
init支持把目录作为参数传入,用它作为书籍根目录而非当前目录:
mdbook init path/to/book--theme:导出默认主题以便定制
使用--theme标志时,mdBook 会把默认主题复制到源目录下的theme目录中,供你修改:
mdbook init --theme主题是"选择性覆盖"(selectively overwritten)的:如果你不想覆盖某个具体文件,直接删掉它,渲染时就会回退使用默认文件。
从 src/cmd/init.rs 的实现可以看到,若目标theme目录已存在且未加--force,命令会先打印警告并交互式询问 "Are you sure you want to continue? (y/N)",确认后才调用copy_theme(true)执行复制,避免误覆盖已有文件。
--title:指定书名
用--title直接指定书籍标题;若不提供,会进入交互式提示要求输入标题:
mdbook init --title="my amazing book"--ignore:生成 VCS 忽略文件
创建配置好忽略book构建目录的.gitignore文件;若不指定,会交互式询问是否创建。取值只有两个:
mdbook init --ignore=nonemdbook init --ignore=git--force:跳过所有交互提示
加上--force后,会跳过创建.gitignore和询问书名这两个交互提示(标题将保持为空,等待后续在book.toml中配置)。
init 的源码细节
src/cmd/init.rs 展示了完整流程:解析--ignore决定是否调用create_gitignore;根据--title/--force决定书名来源;随后会执行git config --get user.name尝试从 Git 配置中读取作者名写入config.book.authors(见 init.rs);最后调用builder.build()完成骨架创建并输出 "All done, no errors..."。
mdbook build:渲染整本书
build命令负责把书籍渲染为静态输出(默认是 HTML)。虽然官方 CLI 指南列表中提到它,仓库中并没有独立的build.md文档,其完整参数可以从源码 src/cmd/build.rs 确认:
mdbook build支持与init相同的目录参数,以及两个选项:
-d, --dest-dir <dest-dir>:覆盖输出目录。相对路径相对于当前目录解析;省略时使用book.toml中的build.build-dir配置,若未配置则默认./book。参数定义见 src/cmd/command_prelude.rs。-o, --open:构建完成后在默认浏览器中打开渲染结果(build.rs中会定位到build_dir_for("html")/index.html,若文件不存在会报错退出)。
build命令内部通过MDBook::load(book_dir)加载配置,经set_dest_dir应用覆盖参数后调用book.build()完成渲染管线(预处理器 → 渲染器)。
mdbook watch:文件变更自动重建
watch命令适用于"每次改动都要重新渲染"的场景。你当然可以每次手动执行mdbook build,但使用watch只需启动一次:它会监视文件,一旦你修改了某个文件就自动触发构建——这包括重新创建SUMMARY.md中仍被引用但已被删除的文件。
mdbook watch常用选项
- 指定目录:
mdbook watch path/to/book,以该目录作为书籍根目录。 --open(-o):构建后在默认浏览器中打开渲染结果。--dest-dir(-d):更改书籍输出目录,语义与build相同(相对当前目录解析;默认取build.build-dir,兜底./book)。
--watcher:文件监视后端
watch(以及serve)支持两种文件变更检测后端,由--watcher指定:
poll(默认)——通过每秒扫描文件系统来检查文件是否被修改;native——使用操作系统原生设施接收文件变更通知,常驻开销更低,但可靠性可能不如基于轮询的方式(官方文档提及多个相关历史 issue:#383、#1441、#1707、#2035、#2102)。
从源码看,参数解析在 src/cmd/command_prelude.rs 中完成,poll是默认值;src/cmd/watch.rs 的rebuild_on_change()根据WatcherKind分别路由到poller或native实现。
排除模式:.gitignore生效规则
watch不会为书籍根目录下.gitignore文件中列出的文件自动触发构建。.gitignore可包含 gitignore 文档 描述的任意文件模式,常用于忽略编辑器产生的临时文件。
注意:只有书籍根目录的
.gitignore生效,全局$HOME/.gitignore或父目录中的.gitignore不会被使用。
值得补充的源码细节:src/cmd/watch.rs 的find_gitignore()实际是沿书籍根目录的祖先链向上查找最近的.gitignore,而官方文档则明确声明只使用书根目录的版本——若你依赖"全局忽略"来过滤监视路径,请以官方文档表述为准,不要依赖祖先目录的忽略文件。poller用ignore::gitignore::Gitignore解析该文件并过滤被扫描的路径(src/cmd/watch/poller.rs)。
poll 后端的工作原理
src/cmd/watch/poller.rs 揭示了默认后端的工作方式:主循环每sleep(Duration::new(1, 0))即每秒扫描一次,通过比较每个文件的mtime(修改时间)与size(大小)判断是否变化(PathData结构体,见 poller.rs);检测到变化后重新MDBook::load并执行build(),同时跟踪约 60 次扫描的平均耗时用于诊断(见 poller.rs)。这也是poll被设为默认后端的原因:原生通知在多种操作系统/文件系统组合下历史上出现过较多可靠性问题(见 poller.rs 的模块注释)。
mdbook serve:本地 HTTP 预览与热重载
serve命令用于预览书籍,默认通过 HTTP 在localhost:3000提供服务:
mdbook serveserve会监视书籍的src目录,每次变更都自动重建并刷新客户端页面;同样包括重新创建SUMMARY.md中仍被引用但已删除的文件。客户端刷新通过 WebSocket 连接触发。
注意:
serve命令仅用于测试书籍的 HTML 输出,并非面向生产环境的完整 HTTP 服务器,不要把线上站点直接挂在它上面。
服务器选项
hostname 默认localhost,端口默认3000,两者均可在命令行覆盖:
mdbook serve path/to/book -p 8000 -n 127.0.0.1-p, --port <port>:HTTP 服务端口,默认3000(定义见 src/cmd/serve.rs);-n, --hostname <hostname>:监听的 hostname,默认localhost(见 serve.rs)。
其他选项与watch一致:目录参数、--open(-o,服务器启动后在默认浏览器打开)、--dest-dir(-d)、--watcher(poll/native),以及同样的.gitignore排除规则(同样只有书根目录的.gitignore生效,全局与父目录的忽略文件不参与)。
serve 的热重载实现
src/cmd/serve.rs 定义了热重载 WebSocket 端点常量LIVE_RELOAD_ENDPOINT = "__livereload"。执行时会把该端点写入output.html.live-reload-endpoint配置,并将output.html.site-url覆盖为/以正确服务本地 404 页面(serve.rs)。服务器基于 axum 构建:路由/__livereload处理 WebSocket 升级,其余请求由ServeDir静态目录服务兜底,404 时回退到html_config.get_404_output_file()(serve.rs)。重建完成时通过tokio::sync::broadcast通道向所有已连接客户端广播"reload"消息,触发浏览器刷新(serve.rs)。
mdbook test:测试书中的 Rust 代码示例
写书时往往需要自动化测试。例如《The Rust Programming Book》包含大量容易过时的代码示例,因此自动验证这些示例非常重要。mdBook 提供test命令运行书中所有可用测试——目前只支持 Rust 测试。
哪些代码块会被测试
测试行为与 rustdoc 的代码块测试规则一致:
包含
ignore属性的代码块不会被测试:fn main() {}指定了非 Rust 语言的代码块不会被测试:
**Foo**: _bar_未指定任何语言的代码块会被测试(因此会被当作 Rust 代码编译执行):
This is going to cause an error!
基本用法
mdbook test与其他命令一致,可传入目录参数指定书籍根目录:
mdbook test path/to/book--library-path(-L):添加依赖搜索路径
该选项向 rustdoc 构建/测试示例时使用的库搜索路径追加目录。多个目录可用多个选项(-L foo -L bar)或用逗号分隔的列表(-L foo,bar)。路径应指向 Cargo 构建缓存中的deps目录,即包含你项目构建输出的位置。例如 Rust 项目my-book的书籍位于该目录下时,可用如下命令让示例链接上 crate 的依赖:
mdbook test my-book -L target/debug/deps/更详细的行为请参考 rustdoc 关于
-L/--library-path的命令行文档。
--chapter(-c):只测试指定章节
通过章节名或章节的相对路径,只测试特定章节:
mdbook test my-book -c chapter_1test 的源码实现
CLI 参数解析在 src/cmd/test.rs,执行逻辑根据是否有--chapter分别调用book.test(library_paths)或book.test_chapter(library_paths, chapter)(test.rs)。在 crates/mdbook-driver/src/mdbook.rs 中,test()等价于test_chapter(paths, None)全量测试;test_chapter会先创建mdbook-前缀的临时目录(TempFileBuilder),把每个-L路径规范为绝对路径拼成["-L", path]参数对,再交给内部定义的TestRenderer调用 rustdoc 完成编译与测试。
mdbook clean:删除渲染产物
clean命令用于删除已生成的书籍输出及其他构建产物:
mdbook clean指定目录与--dest-dir
可传入目录参数作为书籍根目录:
mdbook clean path/to/book--dest-dir(-d)选项允许覆盖将被删除的输出目录,相对路径相对于当前目录解析;省略时默认取book.toml中build.build-dir的值,否则为./book:
mdbook clean --dest-dir=path/to/bookpath/to/book既可以是绝对路径也可以是相对路径。
从源码 src/cmd/clean.rs 看,clean先MDBook::load书籍,优先使用命令行--dest-dir(拼上当前目录),否则回退到book.root.join(&book.config.build.build_dir);随后递归遍历目标目录并统计被删除的文件数、目录数与字节数,最后以人类可读的 SI 单位输出,例如 "Removed 42 files, 3.50MiB total"(格式化逻辑见 clean.rs 与human_readable_bytes)。
mdbook completions:Shell 自动补全
completions命令用于为常见 Shell 生成自动补全脚本:安装后,在 Shell 中输入mdbook再按自动补全键(通常是 Tab),即可看到合法选项或补全部分输入。
补全脚本需要先安装到你的 Shell 中,例如:
# bash mdbook completions bash > ~/.local/share/bash-completion/completions/mdbook # oh-my-zsh mdbook completions zsh > ~/.oh-my-zsh/completions/_mdbook autoload -U compinit && compinit命令会把对应 Shell 的补全脚本打印到标准输出,运行mdbook completions --help可查看支持的 Shell 列表。脚本的具体放置位置取决于你所用的 Shell 与操作系统,请查阅对应 Shell 的文档。
实现上,src/main.rs 为completions子命令注册了必填的shell位置参数(通过 clap_complete 的Shell值解析器枚举支持),并在分发时调用clap_complete::generate把基于当前命令树的补全脚本写入标准输出(main.rs);cmd::build等子命令模块则由 src/cmd/mod.rs 统一组织。
命令速查与适用场景小结
| 场景 | 命令 |
|---|---|
| 从零创建书籍(含从 SUMMARY.md 反向生成章节) | mdbook init/mdbook init --title="..." --force |
| 一次性渲染静态站点 | mdbook build |
| 编辑时持续重建 | mdbook watch/mdbook serve |
| 本地浏览器预览 + 热重载 | mdbook serve -p 8000 -n 127.0.0.1 |
| 验证 Rust 代码示例(含指定章节、依赖路径) | mdbook test/mdbook test -c chapter_1 -L target/debug/deps/ |
| 清理构建产物 | mdbook clean/mdbook clean --dest-dir=... |
| 启用 Shell 补全 | mdbook completions bash/zsh/ 等 |
组合使用建议:日常写作推荐mdbook serve(默认 3000 端口,自带 WebSocket 热重载与 404 支持);对外发布前用mdbook build生成book目录并整体上传;配合 CI 可用mdbook test保证书中 Rust 示例不腐化,用mdbook clean保证构建从干净状态开始。各命令的参数解析集中在 src/cmd/command_prelude.rs,--dest-dir、目录参数、--open、--watcher等通用选项在build/watch/serve/clean/test之间保持一致,掌握一套即可触类旁通。
- 开发工具
- 文档
【免费下载链接】mdBook
Create book from markdown files. Like Gitbook but implemented in Rust
相关推荐
VitePress CLI 命令行完全指南:dev、build、preview 与 init 命令详解
VitePress CLI 命令行完全指南:dev、build、preview 与 init 命令详解 VitePress 是一套基于 Vite 与 Vue 的
前端文档Wails CLI工具完全指南:init、build、dev命令详解
Wails CLI工具完全指南:init、build、dev命令详解 Wails是一个强大的Go框架,用于使用Web技术构建跨平台桌面应用程序。本文将深入解析W
桌面应用跨平台CLI前端VitePress 命令行接口(CLI)完全指南:dev / build / preview / init 命令详解
VitePress 命令行接口(CLI)完全指南:dev / build / preview / init 命令详解 导读 VitePress 是使用 Vite
前端文档
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考