Skip to content

Commit 5777a0e

Browse files
committed
Fix issue with None source_path
This fixes an issue where mdbook would panic if a non-draft chapter has a None source_path when generating the search index. The code was assuming that only draft chapters would have that behavior. However, API users can inject synthetic chapters that have no path on disk. This updates it to fall back to the path, or skip if neither is set.
1 parent 53c3a92 commit 5777a0e

File tree

3 files changed

+13
-11
lines changed

3 files changed

+13
-11
lines changed

src/book/book.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ pub struct Chapter {
173173
/// `index.md` via the [`Chapter::path`] field. The `source_path` field
174174
/// exists if you need access to the true file path.
175175
///
176-
/// This is `None` for a draft chapter.
176+
/// This is `None` for a draft chapter, or a synthetically generated
177+
/// chapter that has no file on disk.
177178
pub source_path: Option<PathBuf>,
178179
/// An ordered list of the names of each chapter above this one in the hierarchy.
179180
pub parent_names: Vec<String>,

src/renderer/html_handlebars/search.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ pub fn create_files(search_config: &Search, destination: &Path, book: &Book) ->
4343
BookItem::Chapter(ch) if !ch.is_draft_chapter() => ch,
4444
_ => continue,
4545
};
46-
let chapter_settings =
47-
get_chapter_settings(&chapter_configs, chapter.source_path.as_ref().unwrap());
48-
if !chapter_settings.enable.unwrap_or(true) {
49-
continue;
46+
if let Some(path) = settings_path(chapter) {
47+
let chapter_settings = get_chapter_settings(&chapter_configs, path);
48+
if !chapter_settings.enable.unwrap_or(true) {
49+
continue;
50+
}
5051
}
5152
render_item(&mut index, search_config, &mut doc_urls, chapter)?;
5253
}
@@ -321,6 +322,10 @@ fn clean_html(html: &str) -> String {
321322
AMMONIA.clean(html).to_string()
322323
}
323324

325+
fn settings_path(ch: &Chapter) -> Option<&Path> {
326+
ch.source_path.as_deref().or_else(|| ch.path.as_deref())
327+
}
328+
324329
fn validate_chapter_config(
325330
chapter_configs: &[(PathBuf, SearchChapterSettings)],
326331
book: &Book,
@@ -329,13 +334,10 @@ fn validate_chapter_config(
329334
let found = book
330335
.iter()
331336
.filter_map(|item| match item {
332-
BookItem::Chapter(ch) if !ch.is_draft_chapter() => Some(ch),
337+
BookItem::Chapter(ch) if !ch.is_draft_chapter() => settings_path(ch),
333338
_ => None,
334339
})
335-
.any(|chapter| {
336-
let ch_path = chapter.source_path.as_ref().unwrap();
337-
ch_path.starts_with(path)
338-
});
340+
.any(|source_path| source_path.starts_with(path));
339341
if !found {
340342
bail!(
341343
"[output.html.search.chapter] key `{}` does not match any chapter paths",

tests/rendered_output.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1034,7 +1034,6 @@ fn custom_header_attributes() {
10341034
}
10351035

10361036
#[test]
1037-
#[should_panic]
10381037
fn with_no_source_path() {
10391038
// Test for a regression where search would fail if source_path is None.
10401039
let temp = DummyBook::new().build().unwrap();

0 commit comments

Comments
 (0)