ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

mdBook 的 index 预处理器:README.md 如何自动转换为 index.html

mdBook 的 index 预处理器:README.md 如何自动转换为 index.html 开发工具文档【免费下载链接】mdBookCreate book from markdown files. Like Gitbook but implemented in Rust项目地址https://gitcode.com/gh_mirrors/md/mdBook点击查看免费下载mdBook 内置了一个名为index的预处理器它遵循 Markdown 文档生态中“README 即默认首页”的惯例在渲染阶段把所有名为README的章节文件改名为index.md从而在输出的 HTML 站点中生成index.html首页。本文以仓库中真实的集成测试夹具basic_readme为线索结合IndexPreprocessor源码、配置项与官方指南完整剖析这一转换规则的匹配细节、触发条件、配置开关及冲突处理方式。读完本文你将能准确预测任意命名形态的README文件在 mdBook 中的最终渲染路径并掌握通过use-default-preprocessors或[preprocessor.index]控制该行为的方法。测试夹具一个刻意“花式命名”的 README 场景本文的关联文档是 tests/testsuite/index/basic_readme/src/README.md它属于集成测试目录tests/testsuite/index/basic_readme/是用于验证 index 预处理器行为的真实测试用例而非常规的说明书文档。该目录结构如下tests/testsuite/index/basic_readme/ ├── book.toml └── src/ ├── README.md # 内容# Intro ├── SUMMARY.md ├── first/ │ └── README # 内容# First无扩展名 └── second/ └── Readme.md # 内容# Second大小写混写其中 book.toml 仅声明了书名未做任何预处理器定制[book] title basic_readme而 SUMMARY.md 定义了章节导航恰好覆盖了三种不同的 README 命名形态# Summary [Intro](https://link.gitcode.com/i/d199df842ed1b2721604bd905a589c5d) - [First](https://link.gitcode.com/i/87cb5aaa51baa66b896cfdc50752cdee) - [Second](https://link.gitcode.com/i/f76064bfded6b3bad03686faf60091f2)这个夹具的巧妙之处在于三个章节分别使用了标准命名README.md、无扩展名的README以及大小写混写的Readme.md一次性覆盖了 index 预处理器匹配规则的全部边界情况为下文分析“哪些文件会被视为 README”提供了完整的实证样本。核心机制IndexPreprocessor 做了什么index 预处理器位于 crates/mdbook-driver/src/builtin_preprocessors/index.rs其文档注释明确了设计动机A preprocessor for converting file nameREADME.mdtoindex.mdsinceREADME.mdis the de facto index file in markdown-based documentation.将README.md转换为index.md的预处理器因为README.md是基于 Markdown 的文档体系中事实上的索引文件。IndexPreprocessor::run的核心逻辑index.rs遍历整本书的所有章节对每个章节的源文件路径执行判定与改写fn run(self, ctx: PreprocessorContext, mut book: Book) - ResultBook { let source_dir ctx.root.join(ctx.config.book.src); book.for_each_mut(|section: mut BookItem| { if let BookItem::Chapter(ref mut ch) *section { if let Some(ref mut path) ch.path { if is_readme_file(path) { let mut index_md source_dir.join(path.with_file_name(index.md)); if index_md.exists() { warn_readme_name_conflict(path, mut index_md); } path.set_file_name(index.md); } } } }); Ok(book) }可见该预处理器只重写章节文件的file_name将README*改为index.md而不改变章节在目录树中的位置。因此输出站点的 URL 结构完全继承源目录结构只是文件名被归一化为index.html。匹配规则大小写不敏感的文件名精确匹配判定函数is_readme_fileindex.rs是理解全部行为的关键fn is_readme_fileP: AsRefPath(path: P) - bool { static_regex!(README, r(?i)^readme$); README.is_match( path.as_ref() .file_stem() .and_then(std::ffi::OsStr::to_str) .unwrap_or_default(), ) }规则要点如下只看文件名主干file_stem忽略扩展名README.md、README.markdown、甚至无扩展名的README都能命中正则(?i)^readme$锚定精确匹配且大小写不敏感Readme、README、rEaDmE等任意大小写组合均被视为 README不会误伤近似名称README-README.md这类文件名因无法通过^readme$的精确锚定而不被转换。这些边界行为在源码自带的单元测试index.rs中被逐一断言let path path/to/Readme.md; assert!(is_readme_file(path)); let path path/to/README.md; assert!(is_readme_file(path)); let path path/to/rEaDmE.md; assert!(is_readme_file(path)); let path path/to/README.markdown; assert!(is_readme_file(path)); let path path/to/README; assert!(is_readme_file(path)); let path path/to/README-README.md; assert!(!is_readme_file(path));回到测试夹具src/README.md、src/first/README无扩展名与src/second/Readme.md混写大小写三者在转换后分别变为src/index.md、src/first/index.md、src/second/index.md从而在输出目录中生成对应的index.html。同名冲突警告如果某目录下同时存在README.md和index.mdmdBook 默认仍会把 README 转换成index.md此时warn_readme_name_conflictindex.rs会输出一组警告提示可能出现“预期之外的行为”并给出两条解决建议调整书籍目录结构或禁用 index 预处理器以停止转换。集成测试实证渲染结果与 URL 断言basic_readme夹具由集成测试 tests/testsuite/index.rs 中的readme_to_index用例驱动其断言精确到最终的 HTML 输出与导航脚本可直接作为“行为契约”阅读book/index.html必须存在且包含h1 idintro标题来自# Introbook/first/index.html存在包含h1 idfirstbook/second/index.html存在包含h1 idsecondbook/README.html必须不存在assert!(!test.dir.join(book/README.html).exists())证明 README 确实被重命名而非复制生成的toc.js中导航链接分别指向index.html、first/index.html、second/index.html。也就是说无论 README 以何种大小写、何种扩展名形态出现最终都以干净的index.html暴露给读者与搜索引擎避免了 README 与 index 两套首页并存导致内容重复的问题。配置控制默认启用、可开关、可覆盖默认预处理器集合index 与links并列为 mdBook 的默认预处理器。在 crates/mdbook-driver/src/mdbook.rs 中定义const DEFAULT_PREPROCESSORS: [str] [links, index]; fn is_default_preprocessor(pre: dyn Preprocessor) - bool { let name pre.name(); name LinkPreprocessor::NAME || name IndexPreprocessor::NAME }determine_preprocessorsmdbook.rs在config.build.use_default_preprocessors为真时把两个默认预处理器加入执行队列并通过拓扑排序处理与自定义预处理器之间的先后依赖预处理器实例在此处按名称创建index Box::new(IndexPreprocessor::new())。mdBook 的官方指南 preprocessors.md 也确认了这一默认行为。build.use-default-preprocessors开关官方配置文档 general.md 中build表的完整形态为[build] build-dir book # the directory where the output is placed create-missing true # whether or not to create missing pages use-default-preprocessors true # use the default preprocessors extra-watch-dirs [] # directories to watch for triggering builds关于use-default-preprocessors的语义指南明确说明未做任何预处理器配置时默认的links与index都会运行设置use-default-preprocessors false会禁用这两个默认预处理器但如果显式声明了[preprocessor.links]或[preprocessor.index]表则无论该开关如何对应预处理器都会运行。因此若你希望保留 README→index 转换例如目录中已有index.md、不想让 README 抢占首页只需在book.toml中写[preprocessor.index]该配置由 index.rs 中的pub use self::index::IndexPreprocessor与 mdbook.rs 的调度逻辑共同支撑[preprocessor.index]表的存在会强制启用 index 预处理器use-default-preprocessors此时不影响它。与 links 预处理器的执行顺序index 与links同为默认预处理器。links负责展开{{ #playground }}、{{ #include }}、{{ #rustdoc_include }}等 include 类 Handlebars 指令见 preprocessors.md。由于 index 只改写章节文件路径名、不触碰 Markdown 正文内容两者职责正交若你开发的自定义预处理器需要按特定先后顺序运行可在其表中用before/after字段声明与index、links的依赖关系源码会通过拓扑排序保证顺序并检测循环依赖mdbook.rs。实用要点与注意事项综合测试夹具、源码与官方指南可归纳出以下可直接落地的结论命名即首页mdBook 约定README含任意扩展名与大小写组合就是该目录的首页README.md、README.markdown、README、Readme.md均等价。输出路径归一化转换只改文件名不改目录层级src/sub/Readme.md最终渲染为book/sub/index.html。不会误伤README-README.md、readme_v2.md等不精确匹配^readme$的文件不会被转换。冲突需自行规避同一目录下避免同时放置README.md与index.md否则仅产生警告不会报错但可能引发预期之外的行为。可整体禁用use-default-preprocessors false会连同links一起关闭 index 预处理器若只想禁用 index 而保留 links可考虑在保持默认开关的同时显式配置[preprocessor.links]并利用renderers []等渲染器绑定手段做更细粒度的控制详见 preprocessors.md。如果你希望深入了解预处理器扩展体系自定义预处理器协议、命令式调用、optional降级等官方开发指南 for_developers/preprocessors.md 提供了完整说明而 crates/mdbook-driver/src/builtin_preprocessors/ 目录则汇集了links、index、cmd三类内置预处理的全部实现是阅读源码时的最佳起点。赞分享开发工具文档【免费下载链接】mdBookCreate book from markdown files. Like Gitbook but implemented in Rust项目地址https://gitcode.com/gh_mirrors/md/mdBook点击查看免费下载相关推荐mdBook 索引章节机制剖析README.md 如何生成 index.html 与侧边栏高亮逻辑mdBook 索引章节机制剖析README.md 如何生成 index.html 与侧边栏高亮逻辑 本指南以仓库中 tests/gui/books/index开发工具文档抖音TikTok数据采集工具DouK-Downloader一次配置解锁五大高阶玩法抖音TikTok数据采集工具DouK Downloader一次配置解锁五大高阶玩法 你是不是也遇到过这样的尴尬刷到一个宝藏账号想一口气把它的作品都存下来网页爬虫Czkawka 磁盘清理实用教程重复文件与空文件夹一次扫清Czkawka 磁盘清理实用教程重复文件与空文件夹一次扫清 存储空间不足弹出时最折磨人的是手动翻文件夹又慢又容易漏。Czkawka 是一款免费开源的桌面应用上一篇librespot Connect 模块实战指南构建、配置与理解你自己的 Spotify Connect 设备下一篇Lc0性能调优终极指南CPU与GPU后端的最佳实践创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表