Skip to content

Commit f393e22

Browse files
authored
Merge pull request #2838 from ehuss/chapters-iterator
Add an iterator over chapters
2 parents e7b1527 + 3629e2c commit f393e22

File tree

6 files changed

+45
-49
lines changed

6 files changed

+45
-49
lines changed

crates/mdbook-core/src/book.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ impl Book {
4646
}
4747
}
4848

49+
/// A depth-first iterator over each [`Chapter`], skipping draft chapters.
50+
pub fn chapters(&self) -> impl Iterator<Item = &Chapter> {
51+
self.iter().filter_map(|item| match item {
52+
BookItem::Chapter(ch) if !ch.is_draft_chapter() => Some(ch),
53+
_ => None,
54+
})
55+
}
56+
4957
/// Recursively apply a closure to each item in the book, allowing you to
5058
/// mutate them.
5159
///
@@ -61,6 +69,26 @@ impl Book {
6169
for_each_mut(&mut func, &mut self.items);
6270
}
6371

72+
/// Recursively apply a closure to each non-draft chapter in the book,
73+
/// allowing you to mutate them.
74+
pub fn for_each_chapter_mut<F>(&mut self, mut func: F)
75+
where
76+
F: FnMut(&mut Chapter),
77+
{
78+
for_each_mut(
79+
&mut |item| {
80+
let BookItem::Chapter(ch) = item else {
81+
return;
82+
};
83+
if ch.is_draft_chapter() {
84+
return;
85+
}
86+
func(ch)
87+
},
88+
&mut self.items,
89+
);
90+
}
91+
6492
/// Append a `BookItem` to the `Book`.
6593
pub fn push_item<I: Into<BookItem>>(&mut self, item: I) -> &mut Self {
6694
self.items.push(item.into());

crates/mdbook-driver/src/builtin_renderers/markdown_renderer.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use anyhow::{Context, Result};
2-
use mdbook_core::book::BookItem;
32
use mdbook_core::utils;
43
use mdbook_renderer::{RenderContext, Renderer};
54
use std::fs;
@@ -33,16 +32,12 @@ impl Renderer for MarkdownRenderer {
3332
}
3433

3534
trace!("markdown render");
36-
for item in book.iter() {
37-
if let BookItem::Chapter(ref ch) = *item {
38-
if !ch.is_draft_chapter() {
39-
utils::fs::write_file(
40-
&ctx.destination,
41-
ch.path.as_ref().expect("Checked path exists before"),
42-
ch.content.as_bytes(),
43-
)?;
44-
}
45-
}
35+
for ch in book.chapters() {
36+
utils::fs::write_file(
37+
&ctx.destination,
38+
ch.path.as_ref().expect("Checked path exists before"),
39+
ch.content.as_bytes(),
40+
)?;
4641
}
4742

4843
fs::create_dir_all(destination)

crates/mdbook-html/src/html_handlebars/hbs_renderer.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -459,13 +459,7 @@ impl Renderer for HtmlHandlebars {
459459
utils::fs::write_file(destination, "CNAME", format!("{cname}\n").as_bytes())?;
460460
}
461461

462-
let chapters: Vec<_> = book
463-
.iter()
464-
.filter_map(|item| match item {
465-
BookItem::Chapter(ch) if !ch.is_draft_chapter() => Some(ch),
466-
_ => None,
467-
})
468-
.collect();
462+
let chapters: Vec<_> = book.chapters().collect();
469463
for (i, ch) in chapters.iter().enumerate() {
470464
let previous = (i != 0).then(|| chapters[i - 1]);
471465
let next = (i != chapters.len() - 1).then(|| chapters[i + 1]);

crates/mdbook-html/src/html_handlebars/search.rs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::static_files::StaticFiles;
22
use crate::theme::searcher;
33
use anyhow::{Context, Result, bail};
44
use elasticlunr::{Index, IndexBuilder};
5-
use mdbook_core::book::{Book, BookItem, Chapter};
5+
use mdbook_core::book::{Book, Chapter};
66
use mdbook_core::config::{Search, SearchChapterSettings};
77
use mdbook_core::utils;
88
use mdbook_markdown::HtmlRenderOptions;
@@ -43,11 +43,7 @@ pub(super) fn create_files(
4343
let chapter_configs = sort_search_config(&search_config.chapter);
4444
validate_chapter_config(&chapter_configs, book)?;
4545

46-
for item in book.iter() {
47-
let chapter = match item {
48-
BookItem::Chapter(ch) if !ch.is_draft_chapter() => ch,
49-
_ => continue,
50-
};
46+
for chapter in book.chapters() {
5147
if let Some(path) = settings_path(chapter) {
5248
let chapter_settings = get_chapter_settings(&chapter_configs, path);
5349
if !chapter_settings.enable.unwrap_or(true) {
@@ -349,11 +345,8 @@ fn validate_chapter_config(
349345
) -> Result<()> {
350346
for (path, _) in chapter_configs {
351347
let found = book
352-
.iter()
353-
.filter_map(|item| match item {
354-
BookItem::Chapter(ch) if !ch.is_draft_chapter() => settings_path(ch),
355-
_ => None,
356-
})
348+
.chapters()
349+
.filter_map(|ch| settings_path(ch))
357350
.any(|source_path| source_path.starts_with(path));
358351
if !found {
359352
bail!(

examples/remove-emphasis/mdbook-remove-emphasis/src/main.rs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! This is a demonstration of an mdBook preprocessor which parses markdown
22
//! and removes any instances of emphasis.
33
4-
use mdbook_preprocessor::book::{Book, BookItem, Chapter};
4+
use mdbook_preprocessor::book::{Book, Chapter};
55
use mdbook_preprocessor::errors::Result;
66
use mdbook_preprocessor::{Preprocessor, PreprocessorContext};
77
use pulldown_cmark::{Event, Parser, Tag, TagEnd};
@@ -36,17 +36,9 @@ impl Preprocessor for RemoveEmphasis {
3636

3737
fn run(&self, _ctx: &PreprocessorContext, mut book: Book) -> Result<Book> {
3838
let mut total = 0;
39-
book.for_each_mut(|item| {
40-
let BookItem::Chapter(ch) = item else {
41-
return;
42-
};
43-
if ch.is_draft_chapter() {
44-
return;
45-
}
46-
match remove_emphasis(&mut total, ch) {
47-
Ok(s) => ch.content = s,
48-
Err(e) => eprintln!("failed to process chapter: {e:?}"),
49-
}
39+
book.for_each_chapter_mut(|ch| match remove_emphasis(&mut total, ch) {
40+
Ok(s) => ch.content = s,
41+
Err(e) => eprintln!("failed to process chapter: {e:?}"),
5042
});
5143
eprintln!("removed {total} emphasis");
5244
Ok(book)

guide/guide-helper/src/lib.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Preprocessor for the mdBook guide.
22
3-
use mdbook_preprocessor::book::{Book, BookItem};
3+
use mdbook_preprocessor::book::Book;
44
use mdbook_preprocessor::errors::Result;
55
use mdbook_preprocessor::{Preprocessor, PreprocessorContext};
66
use semver::{Version, VersionReq};
@@ -53,13 +53,7 @@ fn insert_version(book: &mut Book) {
5353
let manifest: toml::Value = toml::from_str(&manifest_contents).unwrap();
5454
let version = manifest["package"]["version"].as_str().unwrap();
5555
const MARKER: &str = "{{ mdbook-version }}";
56-
book.for_each_mut(|item| {
57-
let BookItem::Chapter(ch) = item else {
58-
return;
59-
};
60-
if ch.is_draft_chapter() {
61-
return;
62-
}
56+
book.for_each_chapter_mut(|ch| {
6357
if ch.content.contains(MARKER) {
6458
ch.content = ch.content.replace(MARKER, version);
6559
}

0 commit comments

Comments
 (0)