Switch all public types to non_exhaustive
This switches all public types to use non_exhaustive to make it easier to make additions without a semver-breaking change. Some of the ergonomics are hampered due to the lack of exhaustiveness checking. Hopefully some day in the future, non_exhaustive_omitted_patterns_lint or something like it will get stabilized. Closes https://github.com/rust-lang/mdBook/issues/1835
This commit is contained in:
parent
c25e866796
commit
5956092b4b
18 changed files with 90 additions and 122 deletions
|
|
@ -9,6 +9,9 @@ members = [
|
||||||
all = { level = "allow", priority = -2 }
|
all = { level = "allow", priority = -2 }
|
||||||
correctness = { level = "warn", priority = -1 }
|
correctness = { level = "warn", priority = -1 }
|
||||||
complexity = { level = "warn", priority = -1 }
|
complexity = { level = "warn", priority = -1 }
|
||||||
|
exhaustive_enums = "warn"
|
||||||
|
exhaustive_structs = "warn"
|
||||||
|
manual_non_exhaustive = "warn"
|
||||||
|
|
||||||
[workspace.lints.rust]
|
[workspace.lints.rust]
|
||||||
missing_docs = "warn"
|
missing_docs = "warn"
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,10 @@ use std::path::PathBuf;
|
||||||
/// [`iter()`]: #method.iter
|
/// [`iter()`]: #method.iter
|
||||||
/// [`for_each_mut()`]: #method.for_each_mut
|
/// [`for_each_mut()`]: #method.for_each_mut
|
||||||
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct Book {
|
pub struct Book {
|
||||||
/// The sections in this book.
|
/// The sections in this book.
|
||||||
pub sections: Vec<BookItem>,
|
pub sections: Vec<BookItem>,
|
||||||
__non_exhaustive: (),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Book {
|
impl Book {
|
||||||
|
|
@ -30,10 +30,7 @@ impl Book {
|
||||||
|
|
||||||
/// Creates a new book with the given items.
|
/// Creates a new book with the given items.
|
||||||
pub fn new_with_items(items: Vec<BookItem>) -> Book {
|
pub fn new_with_items(items: Vec<BookItem>) -> Book {
|
||||||
Book {
|
Book { sections: items }
|
||||||
sections: items,
|
|
||||||
__non_exhaustive: (),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a depth-first iterator over the items in the book.
|
/// Get a depth-first iterator over the items in the book.
|
||||||
|
|
@ -81,6 +78,7 @@ where
|
||||||
|
|
||||||
/// Enum representing any type of item which can be added to a book.
|
/// Enum representing any type of item which can be added to a book.
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub enum BookItem {
|
pub enum BookItem {
|
||||||
/// A nested chapter.
|
/// A nested chapter.
|
||||||
Chapter(Chapter),
|
Chapter(Chapter),
|
||||||
|
|
@ -99,6 +97,7 @@ impl From<Chapter> for BookItem {
|
||||||
/// The representation of a "chapter", usually mapping to a single file on
|
/// The representation of a "chapter", usually mapping to a single file on
|
||||||
/// disk however it may contain multiple sub-chapters.
|
/// disk however it may contain multiple sub-chapters.
|
||||||
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct Chapter {
|
pub struct Chapter {
|
||||||
/// The chapter's name.
|
/// The chapter's name.
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ use toml::value::Table;
|
||||||
/// The overall configuration object for MDBook, essentially an in-memory
|
/// The overall configuration object for MDBook, essentially an in-memory
|
||||||
/// representation of `book.toml`.
|
/// representation of `book.toml`.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// Metadata about the book.
|
/// Metadata about the book.
|
||||||
pub book: BookConfig,
|
pub book: BookConfig,
|
||||||
|
|
@ -386,6 +387,7 @@ fn is_legacy_format(table: &Value) -> bool {
|
||||||
/// loading it from disk.
|
/// loading it from disk.
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(default, rename_all = "kebab-case")]
|
#[serde(default, rename_all = "kebab-case")]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct BookConfig {
|
pub struct BookConfig {
|
||||||
/// The book's title.
|
/// The book's title.
|
||||||
pub title: Option<String>,
|
pub title: Option<String>,
|
||||||
|
|
@ -429,6 +431,7 @@ impl BookConfig {
|
||||||
|
|
||||||
/// Text direction to use for HTML output
|
/// Text direction to use for HTML output
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub enum TextDirection {
|
pub enum TextDirection {
|
||||||
/// Left to right.
|
/// Left to right.
|
||||||
#[serde(rename = "ltr")]
|
#[serde(rename = "ltr")]
|
||||||
|
|
@ -454,6 +457,7 @@ impl TextDirection {
|
||||||
/// Configuration for the build procedure.
|
/// Configuration for the build procedure.
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(default, rename_all = "kebab-case")]
|
#[serde(default, rename_all = "kebab-case")]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct BuildConfig {
|
pub struct BuildConfig {
|
||||||
/// Where to put built artefacts relative to the book's root directory.
|
/// Where to put built artefacts relative to the book's root directory.
|
||||||
pub build_dir: PathBuf,
|
pub build_dir: PathBuf,
|
||||||
|
|
@ -481,13 +485,15 @@ impl Default for BuildConfig {
|
||||||
/// Configuration for the Rust compiler(e.g., for playground)
|
/// Configuration for the Rust compiler(e.g., for playground)
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(default, rename_all = "kebab-case")]
|
#[serde(default, rename_all = "kebab-case")]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct RustConfig {
|
pub struct RustConfig {
|
||||||
/// Rust edition used in playground
|
/// Rust edition used in playground
|
||||||
pub edition: Option<RustEdition>,
|
pub edition: Option<RustEdition>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
|
||||||
/// Rust edition to use for the code.
|
/// Rust edition to use for the code.
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub enum RustEdition {
|
pub enum RustEdition {
|
||||||
/// The 2024 edition of Rust
|
/// The 2024 edition of Rust
|
||||||
#[serde(rename = "2024")]
|
#[serde(rename = "2024")]
|
||||||
|
|
@ -506,6 +512,7 @@ pub enum RustEdition {
|
||||||
/// Configuration for the HTML renderer.
|
/// Configuration for the HTML renderer.
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(default, rename_all = "kebab-case")]
|
#[serde(default, rename_all = "kebab-case")]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct HtmlConfig {
|
pub struct HtmlConfig {
|
||||||
/// The theme directory, if specified.
|
/// The theme directory, if specified.
|
||||||
pub theme: Option<PathBuf>,
|
pub theme: Option<PathBuf>,
|
||||||
|
|
@ -625,6 +632,7 @@ impl HtmlConfig {
|
||||||
/// Configuration for how to render the print icon, print.html, and print.css.
|
/// Configuration for how to render the print icon, print.html, and print.css.
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(default, rename_all = "kebab-case")]
|
#[serde(default, rename_all = "kebab-case")]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct Print {
|
pub struct Print {
|
||||||
/// Whether print support is enabled.
|
/// Whether print support is enabled.
|
||||||
pub enable: bool,
|
pub enable: bool,
|
||||||
|
|
@ -644,6 +652,7 @@ impl Default for Print {
|
||||||
/// Configuration for how to fold chapters of sidebar.
|
/// Configuration for how to fold chapters of sidebar.
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(default, rename_all = "kebab-case")]
|
#[serde(default, rename_all = "kebab-case")]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct Fold {
|
pub struct Fold {
|
||||||
/// When off, all folds are open. Default: `false`.
|
/// When off, all folds are open. Default: `false`.
|
||||||
pub enable: bool,
|
pub enable: bool,
|
||||||
|
|
@ -656,6 +665,7 @@ pub struct Fold {
|
||||||
/// Configuration for tweaking how the HTML renderer handles the playground.
|
/// Configuration for tweaking how the HTML renderer handles the playground.
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(default, rename_all = "kebab-case")]
|
#[serde(default, rename_all = "kebab-case")]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct Playground {
|
pub struct Playground {
|
||||||
/// Should playground snippets be editable? Default: `false`.
|
/// Should playground snippets be editable? Default: `false`.
|
||||||
pub editable: bool,
|
pub editable: bool,
|
||||||
|
|
@ -685,6 +695,7 @@ impl Default for Playground {
|
||||||
/// Configuration for tweaking how the HTML renderer handles code blocks.
|
/// Configuration for tweaking how the HTML renderer handles code blocks.
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(default, rename_all = "kebab-case")]
|
#[serde(default, rename_all = "kebab-case")]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct Code {
|
pub struct Code {
|
||||||
/// A prefix string to hide lines per language (one or more chars).
|
/// A prefix string to hide lines per language (one or more chars).
|
||||||
pub hidelines: HashMap<String, String>,
|
pub hidelines: HashMap<String, String>,
|
||||||
|
|
@ -693,6 +704,7 @@ pub struct Code {
|
||||||
/// Configuration of the search functionality of the HTML renderer.
|
/// Configuration of the search functionality of the HTML renderer.
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(default, rename_all = "kebab-case")]
|
#[serde(default, rename_all = "kebab-case")]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct Search {
|
pub struct Search {
|
||||||
/// Enable the search feature. Default: `true`.
|
/// Enable the search feature. Default: `true`.
|
||||||
pub enable: bool,
|
pub enable: bool,
|
||||||
|
|
@ -750,6 +762,7 @@ impl Default for Search {
|
||||||
/// Search options for chapters (or paths).
|
/// Search options for chapters (or paths).
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
|
||||||
#[serde(default, rename_all = "kebab-case")]
|
#[serde(default, rename_all = "kebab-case")]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct SearchChapterSettings {
|
pub struct SearchChapterSettings {
|
||||||
/// Whether or not indexing is enabled, default `true`.
|
/// Whether or not indexing is enabled, default `true`.
|
||||||
pub enable: Option<bool>,
|
pub enable: Option<bool>,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ use std::{path::Path, sync::LazyLock};
|
||||||
/// A preprocessor for converting file name `README.md` to `index.md` since
|
/// A preprocessor for converting file name `README.md` to `index.md` since
|
||||||
/// `README.md` is the de facto index file in markdown-based documentation.
|
/// `README.md` is the de facto index file in markdown-based documentation.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct IndexPreprocessor;
|
pub struct IndexPreprocessor;
|
||||||
|
|
||||||
impl IndexPreprocessor {
|
impl IndexPreprocessor {
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ const MAX_LINK_NESTED_DEPTH: usize = 10;
|
||||||
/// - `{{# playground}}` - Insert runnable Rust files
|
/// - `{{# playground}}` - Insert runnable Rust files
|
||||||
/// - `{{# title}}` - Override \<title\> of a webpage.
|
/// - `{{# title}}` - Override \<title\> of a webpage.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct LinkPreprocessor;
|
pub struct LinkPreprocessor;
|
||||||
|
|
||||||
impl LinkPreprocessor {
|
impl LinkPreprocessor {
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,10 @@ use mdbook_core::utils;
|
||||||
use mdbook_renderer::{RenderContext, Renderer};
|
use mdbook_renderer::{RenderContext, Renderer};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
/// A renderer to output the Markdown after the preprocessors have run. Mostly useful
|
/// A renderer to output the Markdown after the preprocessors have run. Mostly useful
|
||||||
/// when debugging preprocessors.
|
/// when debugging preprocessors.
|
||||||
|
#[derive(Default)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct MarkdownRenderer;
|
pub struct MarkdownRenderer;
|
||||||
|
|
||||||
impl MarkdownRenderer {
|
impl MarkdownRenderer {
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ fn load_summary_item<P: AsRef<Path> + Clone>(
|
||||||
SummaryItem::Separator => Ok(BookItem::Separator),
|
SummaryItem::Separator => Ok(BookItem::Separator),
|
||||||
SummaryItem::Link(link) => load_chapter(link, src_dir, parent_names).map(BookItem::Chapter),
|
SummaryItem::Link(link) => load_chapter(link, src_dir, parent_names).map(BookItem::Chapter),
|
||||||
SummaryItem::PartTitle(title) => Ok(BookItem::PartTitle(title.clone())),
|
SummaryItem::PartTitle(title) => Ok(BookItem::PartTitle(title.clone())),
|
||||||
|
_ => panic!("SummaryItem {item:?} not covered"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -252,28 +253,21 @@ And here is some \
|
||||||
fn load_recursive_link_with_separators() {
|
fn load_recursive_link_with_separators() {
|
||||||
let (root, temp) = nested_links();
|
let (root, temp) = nested_links();
|
||||||
|
|
||||||
let nested = Chapter {
|
let mut nested = Chapter::new(
|
||||||
name: String::from("Nested Chapter 1"),
|
"Nested Chapter 1",
|
||||||
content: String::from("Hello World!"),
|
String::from("Hello World!"),
|
||||||
number: Some(SectionNumber::new([1, 2])),
|
"second.md",
|
||||||
path: Some(PathBuf::from("second.md")),
|
vec![String::from("Chapter 1")],
|
||||||
source_path: Some(PathBuf::from("second.md")),
|
);
|
||||||
parent_names: vec![String::from("Chapter 1")],
|
nested.number = Some(SectionNumber::new([1, 2]));
|
||||||
sub_items: Vec::new(),
|
let mut chapter =
|
||||||
};
|
Chapter::new("Chapter 1", String::from(DUMMY_SRC), "chapter_1.md", vec![]);
|
||||||
let should_be = BookItem::Chapter(Chapter {
|
chapter.sub_items = vec![
|
||||||
name: String::from("Chapter 1"),
|
|
||||||
content: String::from(DUMMY_SRC),
|
|
||||||
number: None,
|
|
||||||
path: Some(PathBuf::from("chapter_1.md")),
|
|
||||||
source_path: Some(PathBuf::from("chapter_1.md")),
|
|
||||||
parent_names: Vec::new(),
|
|
||||||
sub_items: vec![
|
|
||||||
BookItem::Chapter(nested.clone()),
|
BookItem::Chapter(nested.clone()),
|
||||||
BookItem::Separator,
|
BookItem::Separator,
|
||||||
BookItem::Chapter(nested),
|
BookItem::Chapter(nested),
|
||||||
],
|
];
|
||||||
});
|
let should_be = BookItem::Chapter(chapter);
|
||||||
|
|
||||||
let got = load_summary_item(&SummaryItem::Link(root), temp.path(), Vec::new()).unwrap();
|
let got = load_summary_item(&SummaryItem::Link(root), temp.path(), Vec::new()).unwrap();
|
||||||
assert_eq!(got, should_be);
|
assert_eq!(got, should_be);
|
||||||
|
|
@ -282,17 +276,15 @@ And here is some \
|
||||||
#[test]
|
#[test]
|
||||||
fn load_a_book_with_a_single_chapter() {
|
fn load_a_book_with_a_single_chapter() {
|
||||||
let (link, temp) = dummy_link();
|
let (link, temp) = dummy_link();
|
||||||
let summary = Summary {
|
let mut summary = Summary::default();
|
||||||
numbered_chapters: vec![SummaryItem::Link(link)],
|
summary.numbered_chapters = vec![SummaryItem::Link(link)];
|
||||||
..Default::default()
|
let chapter = Chapter::new(
|
||||||
};
|
"Chapter 1",
|
||||||
let sections = vec![BookItem::Chapter(Chapter {
|
String::from(DUMMY_SRC),
|
||||||
name: String::from("Chapter 1"),
|
PathBuf::from("chapter_1.md"),
|
||||||
content: String::from(DUMMY_SRC),
|
vec![],
|
||||||
path: Some(PathBuf::from("chapter_1.md")),
|
);
|
||||||
source_path: Some(PathBuf::from("chapter_1.md")),
|
let sections = vec![BookItem::Chapter(chapter)];
|
||||||
..Default::default()
|
|
||||||
})];
|
|
||||||
let should_be = Book::new_with_items(sections);
|
let should_be = Book::new_with_items(sections);
|
||||||
|
|
||||||
let got = load_book_from_disk(&summary, temp.path()).unwrap();
|
let got = load_book_from_disk(&summary, temp.path()).unwrap();
|
||||||
|
|
@ -303,16 +295,9 @@ And here is some \
|
||||||
#[test]
|
#[test]
|
||||||
fn cant_load_chapters_with_an_empty_path() {
|
fn cant_load_chapters_with_an_empty_path() {
|
||||||
let (_, temp) = dummy_link();
|
let (_, temp) = dummy_link();
|
||||||
let summary = Summary {
|
let mut summary = Summary::default();
|
||||||
numbered_chapters: vec![SummaryItem::Link(Link {
|
let link = Link::new("Empty", "");
|
||||||
name: String::from("Empty"),
|
summary.numbered_chapters = vec![SummaryItem::Link(link)];
|
||||||
location: Some(PathBuf::from("")),
|
|
||||||
..Default::default()
|
|
||||||
})],
|
|
||||||
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let got = load_book_from_disk(&summary, temp.path());
|
let got = load_book_from_disk(&summary, temp.path());
|
||||||
assert!(got.is_err());
|
assert!(got.is_err());
|
||||||
}
|
}
|
||||||
|
|
@ -323,14 +308,9 @@ And here is some \
|
||||||
let dir = temp.path().join("nested");
|
let dir = temp.path().join("nested");
|
||||||
fs::create_dir(&dir).unwrap();
|
fs::create_dir(&dir).unwrap();
|
||||||
|
|
||||||
let summary = Summary {
|
let mut summary = Summary::default();
|
||||||
numbered_chapters: vec![SummaryItem::Link(Link {
|
let link = Link::new("nested", dir);
|
||||||
name: String::from("nested"),
|
summary.numbered_chapters = vec![SummaryItem::Link(link)];
|
||||||
location: Some(dir),
|
|
||||||
..Default::default()
|
|
||||||
})],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let got = load_book_from_disk(&summary, temp.path());
|
let got = load_book_from_disk(&summary, temp.path());
|
||||||
assert!(got.is_err());
|
assert!(got.is_err());
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,7 @@ impl MDBook {
|
||||||
/// BookItem::Chapter(ref chapter) => {},
|
/// BookItem::Chapter(ref chapter) => {},
|
||||||
/// BookItem::Separator => {},
|
/// BookItem::Separator => {},
|
||||||
/// BookItem::PartTitle(ref title) => {}
|
/// BookItem::PartTitle(ref title) => {}
|
||||||
|
/// _ => {}
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
|
|
@ -329,6 +330,7 @@ impl MDBook {
|
||||||
RustEdition::E2024 => {
|
RustEdition::E2024 => {
|
||||||
cmd.args(["--edition", "2024"]);
|
cmd.args(["--edition", "2024"]);
|
||||||
}
|
}
|
||||||
|
_ => panic!("RustEdition {edition:?} not covered"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -230,7 +230,7 @@ fn config_respects_preprocessor_selection() {
|
||||||
|
|
||||||
let cfg = Config::from_str(cfg_str).unwrap();
|
let cfg = Config::from_str(cfg_str).unwrap();
|
||||||
|
|
||||||
let html_renderer = HtmlHandlebars;
|
let html_renderer = HtmlHandlebars::default();
|
||||||
let pre = LinkPreprocessor::new();
|
let pre = LinkPreprocessor::new();
|
||||||
|
|
||||||
let should_run = preprocessor_should_run(&pre, &html_renderer, &cfg).unwrap();
|
let should_run = preprocessor_should_run(&pre, &html_renderer, &cfg).unwrap();
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ use std::sync::LazyLock;
|
||||||
|
|
||||||
/// The HTML renderer for mdBook.
|
/// The HTML renderer for mdBook.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct HtmlHandlebars;
|
pub struct HtmlHandlebars;
|
||||||
|
|
||||||
impl HtmlHandlebars {
|
impl HtmlHandlebars {
|
||||||
|
|
@ -656,6 +657,7 @@ fn make_data(
|
||||||
BookItem::Separator => {
|
BookItem::Separator => {
|
||||||
chapter.insert("spacer".to_owned(), json!("_spacer_"));
|
chapter.insert("spacer".to_owned(), json!("_spacer_"));
|
||||||
}
|
}
|
||||||
|
_ => panic!("BookItem {item:?} not covered"),
|
||||||
}
|
}
|
||||||
|
|
||||||
chapters.push(chapter);
|
chapters.push(chapter);
|
||||||
|
|
@ -778,6 +780,7 @@ fn add_playground_pre(
|
||||||
Some(RustEdition::E2018) => " edition2018",
|
Some(RustEdition::E2018) => " edition2018",
|
||||||
Some(RustEdition::E2021) => " edition2021",
|
Some(RustEdition::E2021) => " edition2021",
|
||||||
Some(RustEdition::E2024) => " edition2024",
|
Some(RustEdition::E2024) => " edition2024",
|
||||||
|
Some(_) => panic!("edition {edition:?} not covered"),
|
||||||
None => "",
|
None => "",
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1085,14 +1088,9 @@ mod tests {
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
for (src, should_be) in &inputs {
|
for (src, should_be) in &inputs {
|
||||||
let got = add_playground_pre(
|
let mut p = Playground::default();
|
||||||
src,
|
p.editable = true;
|
||||||
&Playground {
|
let got = add_playground_pre(src, &p, None);
|
||||||
editable: true,
|
|
||||||
..Playground::default()
|
|
||||||
},
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
assert_eq!(&*got, *should_be);
|
assert_eq!(&*got, *should_be);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1117,14 +1115,9 @@ mod tests {
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
for (src, should_be) in &inputs {
|
for (src, should_be) in &inputs {
|
||||||
let got = add_playground_pre(
|
let mut p = Playground::default();
|
||||||
src,
|
p.editable = true;
|
||||||
&Playground {
|
let got = add_playground_pre(src, &p, Some(RustEdition::E2015));
|
||||||
editable: true,
|
|
||||||
..Playground::default()
|
|
||||||
},
|
|
||||||
Some(RustEdition::E2015),
|
|
||||||
);
|
|
||||||
assert_eq!(&*got, *should_be);
|
assert_eq!(&*got, *should_be);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1149,14 +1142,9 @@ mod tests {
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
for (src, should_be) in &inputs {
|
for (src, should_be) in &inputs {
|
||||||
let got = add_playground_pre(
|
let mut p = Playground::default();
|
||||||
src,
|
p.editable = true;
|
||||||
&Playground {
|
let got = add_playground_pre(src, &p, Some(RustEdition::E2018));
|
||||||
editable: true,
|
|
||||||
..Playground::default()
|
|
||||||
},
|
|
||||||
Some(RustEdition::E2018),
|
|
||||||
);
|
|
||||||
assert_eq!(&*got, *should_be);
|
assert_eq!(&*got, *should_be);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1181,14 +1169,9 @@ mod tests {
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
for (src, should_be) in &inputs {
|
for (src, should_be) in &inputs {
|
||||||
let got = add_playground_pre(
|
let mut p = Playground::default();
|
||||||
src,
|
p.editable = true;
|
||||||
&Playground {
|
let got = add_playground_pre(src, &p, Some(RustEdition::E2021));
|
||||||
editable: true,
|
|
||||||
..Playground::default()
|
|
||||||
},
|
|
||||||
Some(RustEdition::E2021),
|
|
||||||
);
|
|
||||||
assert_eq!(&*got, *should_be);
|
assert_eq!(&*got, *should_be);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1248,17 +1231,10 @@ mod tests {
|
||||||
"<code class=\"language-python hidelines=!!!\"><span class=\"boring\">hidden()\n</span>nothidden():\n<span class=\"boring\"> hidden()\n</span><span class=\"boring\"> hidden()\n</span> nothidden()\n</code>",
|
"<code class=\"language-python hidelines=!!!\"><span class=\"boring\">hidden()\n</span>nothidden():\n<span class=\"boring\"> hidden()\n</span><span class=\"boring\"> hidden()\n</span> nothidden()\n</code>",
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
let mut code = Code::default();
|
||||||
|
code.hidelines.insert("python".to_string(), "~".to_string());
|
||||||
for (src, should_be) in &inputs {
|
for (src, should_be) in &inputs {
|
||||||
let got = hide_lines(
|
let got = hide_lines(src, &code);
|
||||||
src,
|
|
||||||
&Code {
|
|
||||||
hidelines: {
|
|
||||||
let mut map = HashMap::new();
|
|
||||||
map.insert("python".to_string(), "~".to_string());
|
|
||||||
map
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
assert_eq!(&*got, *should_be);
|
assert_eq!(&*got, *should_be);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -409,9 +409,11 @@ fn chapter_settings_priority() {
|
||||||
("cli/inner/index.md", Some(true)),
|
("cli/inner/index.md", Some(true)),
|
||||||
("cli/inner/foo.md", Some(false)),
|
("cli/inner/foo.md", Some(false)),
|
||||||
] {
|
] {
|
||||||
|
let mut settings = SearchChapterSettings::default();
|
||||||
|
settings.enable = enable;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_chapter_settings(&chapter_configs, Path::new(path)),
|
get_chapter_settings(&chapter_configs, Path::new(path)),
|
||||||
SearchChapterSettings { enable }
|
settings
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ pub static FONT_AWESOME_OTF: &[u8] = include_bytes!("../../front-end/fonts/FontA
|
||||||
/// You should only ever use the static variables directly if you want to
|
/// You should only ever use the static variables directly if you want to
|
||||||
/// override the user's theme with the defaults.
|
/// override the user's theme with the defaults.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct Theme {
|
pub struct Theme {
|
||||||
pub index: Vec<u8>,
|
pub index: Vec<u8>,
|
||||||
pub head: Vec<u8>,
|
pub head: Vec<u8>,
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ pub trait Preprocessor {
|
||||||
/// Extra information for a `Preprocessor` to give them more context when
|
/// Extra information for a `Preprocessor` to give them more context when
|
||||||
/// processing a book.
|
/// processing a book.
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct PreprocessorContext {
|
pub struct PreprocessorContext {
|
||||||
/// The location of the book directory on disk.
|
/// The location of the book directory on disk.
|
||||||
pub root: PathBuf,
|
pub root: PathBuf,
|
||||||
|
|
@ -62,8 +63,6 @@ pub struct PreprocessorContext {
|
||||||
/// This should not be used outside of mdbook's internals.
|
/// This should not be used outside of mdbook's internals.
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub chapter_titles: RefCell<HashMap<PathBuf, String>>,
|
pub chapter_titles: RefCell<HashMap<PathBuf, String>>,
|
||||||
#[serde(skip)]
|
|
||||||
__non_exhaustive: (),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PreprocessorContext {
|
impl PreprocessorContext {
|
||||||
|
|
@ -75,7 +74,6 @@ impl PreprocessorContext {
|
||||||
renderer,
|
renderer,
|
||||||
mdbook_version: crate::MDBOOK_VERSION.to_string(),
|
mdbook_version: crate::MDBOOK_VERSION.to_string(),
|
||||||
chapter_titles: RefCell::new(HashMap::new()),
|
chapter_titles: RefCell::new(HashMap::new()),
|
||||||
__non_exhaustive: (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ pub trait Renderer {
|
||||||
|
|
||||||
/// The context provided to all renderers.
|
/// The context provided to all renderers.
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct RenderContext {
|
pub struct RenderContext {
|
||||||
/// Which version of `mdbook` did this come from (as written in `mdbook`'s
|
/// Which version of `mdbook` did this come from (as written in `mdbook`'s
|
||||||
/// `Cargo.toml`). Useful if you know the renderer is only compatible with
|
/// `Cargo.toml`). Useful if you know the renderer is only compatible with
|
||||||
|
|
@ -57,8 +58,6 @@ pub struct RenderContext {
|
||||||
/// This should not be used outside of mdbook's internals.
|
/// This should not be used outside of mdbook's internals.
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub chapter_titles: HashMap<PathBuf, String>,
|
pub chapter_titles: HashMap<PathBuf, String>,
|
||||||
#[serde(skip)]
|
|
||||||
__non_exhaustive: (),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderContext {
|
impl RenderContext {
|
||||||
|
|
@ -75,7 +74,6 @@ impl RenderContext {
|
||||||
root: root.into(),
|
root: root.into(),
|
||||||
destination: destination.into(),
|
destination: destination.into(),
|
||||||
chapter_titles: HashMap::new(),
|
chapter_titles: HashMap::new(),
|
||||||
__non_exhaustive: (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ pub fn parse_summary(summary: &str) -> Result<Summary> {
|
||||||
|
|
||||||
/// The parsed `SUMMARY.md`, specifying how the book should be laid out.
|
/// The parsed `SUMMARY.md`, specifying how the book should be laid out.
|
||||||
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct Summary {
|
pub struct Summary {
|
||||||
/// An optional title for the `SUMMARY.md`, currently just ignored.
|
/// An optional title for the `SUMMARY.md`, currently just ignored.
|
||||||
pub title: Option<String>,
|
pub title: Option<String>,
|
||||||
|
|
@ -79,6 +80,7 @@ pub struct Summary {
|
||||||
///
|
///
|
||||||
/// This is roughly the equivalent of `[Some section](./path/to/file.md)`.
|
/// This is roughly the equivalent of `[Some section](./path/to/file.md)`.
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct Link {
|
pub struct Link {
|
||||||
/// The name of the chapter.
|
/// The name of the chapter.
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
@ -114,8 +116,9 @@ impl Default for Link {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An item in `SUMMARY.md` which could be either a separator or a `Link`.
|
/// An item in `SUMMARY.md`.
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub enum SummaryItem {
|
pub enum SummaryItem {
|
||||||
/// A link to a chapter.
|
/// A link to a chapter.
|
||||||
Link(Link),
|
Link(Link),
|
||||||
|
|
|
||||||
|
|
@ -146,8 +146,7 @@ mod nop_lib {
|
||||||
"parent_names": []
|
"parent_names": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"__non_exhaustive": null
|
|
||||||
}
|
}
|
||||||
]"##;
|
]"##;
|
||||||
let input_json = input_json.as_bytes();
|
let input_json = input_json.as_bytes();
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,6 @@ fn backends_receive_render_context_via_stdin() {
|
||||||
str![[r##"
|
str![[r##"
|
||||||
{
|
{
|
||||||
"book": {
|
"book": {
|
||||||
"__non_exhaustive": null,
|
|
||||||
"sections": [
|
"sections": [
|
||||||
{
|
{
|
||||||
"Chapter": {
|
"Chapter": {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use mdbook_core::book::{BookItem, Chapter};
|
use mdbook_core::book::{BookItem, Chapter};
|
||||||
use snapbox::file;
|
use snapbox::file;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::Path;
|
||||||
|
|
||||||
fn read_book_index(root: &Path) -> serde_json::Value {
|
fn read_book_index(root: &Path) -> serde_json::Value {
|
||||||
let index = root.join("book/searchindex.js");
|
let index = root.join("book/searchindex.js");
|
||||||
|
|
@ -116,15 +116,7 @@ fn can_disable_individual_chapters() {
|
||||||
fn with_no_source_path() {
|
fn with_no_source_path() {
|
||||||
let test = BookTest::from_dir("search/reasonable_search_index");
|
let test = BookTest::from_dir("search/reasonable_search_index");
|
||||||
let mut book = test.load_book();
|
let mut book = test.load_book();
|
||||||
let chapter = Chapter {
|
let chapter = Chapter::new("Sample chapter", String::new(), "sample.html", vec![]);
|
||||||
name: "Sample chapter".to_string(),
|
|
||||||
content: "".to_string(),
|
|
||||||
number: None,
|
|
||||||
sub_items: Vec::new(),
|
|
||||||
path: Some(PathBuf::from("sample.html")),
|
|
||||||
source_path: None,
|
|
||||||
parent_names: Vec::new(),
|
|
||||||
};
|
|
||||||
book.book.sections.push(BookItem::Chapter(chapter));
|
book.book.sections.push(BookItem::Chapter(chapter));
|
||||||
book.build().unwrap();
|
book.build().unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue