comprehensive-rust 的 mdbook-course 预处理器Frontmatter、课程结构与日程指令详解【免费下载链接】comprehensive-rustThis is the Rust course used by the Android team at Google. It provides you the material to quickly teach Rust.项目地址: https://gitcode.com/GitHub_Trending/co/comprehensive-rustcomprehensive-rust 是 Google Android 团队用于快速教授 Rust 的课程仓库而 mdbook-course/README.md 介绍的是支撑整套课程体系的 mdBook 预处理器preprocessor。本文以该文档为核心结合仓库源码深入讲解 mdbook-course 的三个命令行工具、frontmatter 字段约定、课程层级结构与时间估算机制以及{{%...}}指令的替换原理帮助读者理解这门多课程、多会话的 Rust 课程是如何被自动组织、计时并生成授课大纲的。概述mdbook-course 是什么mdbook-course 是一个专为 comprehensive-rust 定制的 mdBook 预处理器用于处理课程的若干特殊细节解析 Markdown 文件开头的 YAML frontmatter 并将其从渲染结果中剥离依据 frontmatter 中的course/session字段与 mdBook 的章节层级推导出课程 → 会话 → 分段 → 幻灯片的层级结构汇总各章节声明的教学分钟数自动插入分段间的休息时间输出各层级的时长估算用正则替换{{%segment outline}}、{{%session outline}}、{{%course outline}}等指令在页面内生成大纲与日程表。从 Cargo.toml 可见它基于mdbook-preprocessor0.5.3 与mdbook-driver0.5.3 开发使用mattercrate 解析 frontmatter、serde_yaml反序列化、regex匹配指令并通过clap解析命令行参数包版本为 0.1.0、edition 2024、Apache-2.0 许可。三个二进制工具mdbook-course 编译出三个可执行文件见 lib.rs 的模块声明与 BUILD.bazel 的构建目标二进制作用mdbook-course实际的 mdBook 预处理器从 stdin 读取 JSON 格式的 book处理后写回 stdoutcourse-schedule打印带时长的课程日程session/segment 汇总默认从当前目录加载书course-content将全部课程内容按顺序 dump 到 stdoutcourse-schedule在 src/bin/course-schedule.rs 中还实现了三个子命令默认等价于sessions输出会话汇总、segments输出分段汇总、pr输出适合贴在 GitHub Pull Request 评论里的日程摘要。Frontmatter课程元数据的入口mdBook 的章节是一个 Markdown 文件。mdbook-course 会把文件开头夹在两个---之间的 YAML 视为 frontmatter解析后从渲染结果中移除。支持的字段frontmatter.rs 定义了Frontmatter结构体全部字段均为可选minutes: NNN target_minutes: NNN course: COURSE NAME session: SESSION NAME字段类型含义minutes整数分钟该章节slide预计占用的教学时间target_minutes整数分钟会话session的目标时长course字符串所属课程名特殊值none表示非教学材料session字符串所属会话名如 Day 1 Morningfrontmatter 可省略。解析时split_frontmatter先调用matter()判断是否存在 frontmatter若存在再交给serde_yaml反序列化解析失败会报错并附上对应的章节源码路径frontmatter.rs。仓库中的真实示例课程的第一天欢迎页 src/welcome-day-1.md 是这样写的--- minutes: 5 course: Fundamentals session: Day 1 Morning target_minutes: 180 ---可见 frontmatter 同时承担三重职责声明本 slide 教学 5 分钟、宣告本文件开启 Fundamentals 课程中的 Day 1 Morning 会话、并把该会话目标时长设为 180 分钟。类似的写法还出现在各 Day 的欢迎页、src/running-the-course/course-structure.md 等文件以及大量课程正文页的minutes字段中。课程结构从 mdBook 层级推导出四层模型course.rs 的文档注释清晰地描述了层级模型Courses -- a collection of courses Course -- the level of content at which students enroll (fundamentals, android, etc.) Session -- a block of instructional time (typically morning or afternoon) Segment -- a collection of slides with a related theme Slide -- a single topic (may be represented by multiple mdBook chapters)对应到授课实际一本书可含多个课程Rust Fundamentals、Rust in Android、Bare-Metal Rust 等每个课程由若干会话组成通常一天两段上午/下午会话由若干分段组成分段之间安排休息每个分段由若干幻灯片组成一张幻灯片可能由多个 mdBook 章节构成。从 SUMMARY.md 与 frontmatter 推导结构信息完全由SUMMARY.md中的章节顺序与各章节 frontmatter 注解组合推导而来course.rs每个顶层章节top-level item被视为一个 segment其第一个子章节就是该 segment 的第一张 slide顶层章节下的第二层子章节各自作为一张 slide更深层嵌套的章节被并入其父 slide顶层章节若在 frontmatter 中带course字段则开启一个新课程带session字段则开启一个新会话。原文档给出的示例结构- Frobnication - Integer Frobnication - Frob Expansion - Structs - Enums - [Exercise](https://link.gitcode.com/i/94a2db44bbb04275490b033337b76a9f) - Solution在这个 segment 中共有四张 slideFrobnication、Integer Frobnication、Frob Expansion 与 Exercise其中后两张由多个章节组成Frob Expansion 含 Structs/Enums 两个章节Exercise 含 Solution 章节。源码中的推导规则Courses::extract_structurecourse.rs是核心入口它遍历 book 的顶层 items只处理Chapter跳过 part 标题与分隔符先剥离 frontmatter 并把正文写回章节若 frontmatter 含course重置当前会话none表示退出任何课程如课程介绍类材料否则切换到该课程若含session切换当前会话若出现course而无session直接bail!报错session must appear in frontmatter when course appearscourse.rs当课程与会话都存在时把该章节作为 segment 加入会话session.add_segment会把顶层章节作为第一张 slide、其直接子章节作为后续 slidecourse.rs子章节递归收集时若被设置了course/session会报错course.rs。计时机制minutes 汇总与自动休息三层时长计算Slideminutes字段或其子章节 minutes 之和即其教学时长course.rsSegment所含 slide 时长之和course.rsSession教学时间加上分段间自动插入的休息。BREAK_DURATION常量固定为 10 分钟course.rs休息数 有正时长的分段数 - 1course.rsCourse所含 session 时长之和休息计入、会话之间的间隔不计course.rs。每个 session 还应声明target_minutes作为目标时长course.rs当target_minutes为 0 时会话/课程会被视为非教学材料从日程输出中跳过。时长的可读化输出markdown.rs 的duration()会把分钟数格式化为人类可读文本规则包括超过 5 分钟向上取整到 5 的倍数例如 7 分钟显示为 10 minutes超过 60 分钟拆分为 X hours and Y minutes。这一点也体现在course-schedule对目标时长的对比上timediff允许 15 分钟会话级或 5 分钟PR 级的容差slop超时会标注too long、不足会标注shortcourse-schedule.rs。指令Directives自动生成大纲与日程在课程材料中可以写以下指令预处理时会被替换为对应层级的大纲或日程{{%segment outline}} {{%session outline}} {{%course outline}} {{%course outline COURSENAME}}前三条分别输出当前 segment、session、course 的 Markdown 大纲最后一条可按名称引用其他课程主要用于 Running the Course 章节如 src/running-the-course/course-structure.md 中的{{%course outline Fundamentals}}、{{%course outline Concurrency}}。替换实现replacements.rs 用lazy_static定义正则\{\{%([^}]*)}}匹配所有{{%...}}指令随后在replace()中按指令词拆分匹配[session, outline]→ 调用Session::outline()[segment, outline]→ 调用Segment::outline()[course, outline]→ 调用当前Course::schedule()[course, outline, name...]→ 按名称在Courses中查找对应课程并输出其schedule()找不到时原样保留指令文本not found - ...其余未知指令保留原始字符串。Session::outline()输出形如 Including 10 minute breaks, this session should take about X. It contains: ... 的表格Segment::outline()输出 This segment should take about X. It contains: ...两者都跳过零时长分段Course::schedule()则以 Course schedule: 开头逐会话列出course.rs、course.rs、course.rs。演讲者备注中的计时信息除大纲外timing_info.rs 的insert_timing_info还会把 slide 的预计时长注入演讲者备注当 slide 有正时长、属于 segment 的首章且正文含details时在details后插入 This slide (and its sub-slides) should take about N minutes. 的提示。这正是 src/welcome-day-1.md 中details块能配合课程安排使用的机制。主流程与构建方式预处理主流程src/bin/mdbook-course.rs 的preprocess()展示了完整调用链从 stdin 用mdbook_preprocessor::parse_input解析 mdBook JSONCourses::extract_structure(book)推导课程结构并剥离 frontmatter遍历每个章节find_slide定位其所属的 (course, session, segment, slide)在课程内调用timing_info::insert_timing_info与replacements::replace课程之外的章节如course: none的前言只做指令替换把处理后的 book 以 JSON 写回 stdout。同时它实现了 mdBook preprocessor 协议所需的supports子命令对所有 renderer 均返回成功src/bin/mdbook-course.rs。构建与运行标准 Cargo 方式在仓库根目录执行cargo build --release产物中包含上述三个二进制Bazel 方式BUILD.bazel 定义了mdbook-course-lib库目标与mdbook-course二进制目标course-schedule与course-content通过mdbook_driver::MDBook::load(.)从当前目录加载书course-schedule.rs、course-content.rs因此需在包含book.toml与src/SUMMARY.md的仓库根目录运行。在 book.toml 中把mdbook-course配置为 preprocessor 后mdbook build即会自动执行 frontmatter 剥离、结构推导、指令替换与计时信息注入。小结mdbook-course 通过frontmatter 声明 SUMMARY.md 层级推导这一约定把庞大、多课程的 comprehensive-rust 组织成语义清晰的 Course → Session → Segment → Slide 四层结构并自动完成三件事剥离元数据、汇总教学时长并插入 10 分钟休息、替换大纲指令生成授课日程。这套机制让课程维护者只需在章节头部维护minutes/target_minutes/course/session四个字段即可让全书的时间安排、演讲者备注与 PR 日程评审保持自动同步。想进一步深入可阅读 course.rs结构推导、frontmatter.rs元数据解析、replacements.rs指令替换与 timing_info.rs计时注入四个核心模块。【免费下载链接】comprehensive-rustThis is the Rust course used by the Android team at Google. It provides you the material to quickly teach Rust.项目地址: https://gitcode.com/GitHub_Trending/co/comprehensive-rust创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
