diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
commit | dc0db358abe19481e475e10c32149b53370f1a1c (patch) | |
tree | ab8ce99c4b255ce46f99ef402c27916055b899ee /vendor/mdbook/src | |
parent | Releasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff) | |
download | rustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip |
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/mdbook/src')
-rw-r--r-- | vendor/mdbook/src/book/book.rs | 8 | ||||
-rw-r--r-- | vendor/mdbook/src/book/init.rs | 7 | ||||
-rw-r--r-- | vendor/mdbook/src/book/mod.rs | 12 | ||||
-rw-r--r-- | vendor/mdbook/src/cmd/build.rs | 2 | ||||
-rw-r--r-- | vendor/mdbook/src/cmd/clean.rs | 2 | ||||
-rw-r--r-- | vendor/mdbook/src/cmd/init.rs | 8 | ||||
-rw-r--r-- | vendor/mdbook/src/cmd/serve.rs | 4 | ||||
-rw-r--r-- | vendor/mdbook/src/cmd/test.rs | 2 | ||||
-rw-r--r-- | vendor/mdbook/src/cmd/watch.rs | 34 | ||||
-rw-r--r-- | vendor/mdbook/src/config.rs | 23 | ||||
-rw-r--r-- | vendor/mdbook/src/preprocess/links.rs | 4 | ||||
-rw-r--r-- | vendor/mdbook/src/renderer/html_handlebars/hbs_renderer.rs | 334 | ||||
-rw-r--r-- | vendor/mdbook/src/renderer/html_handlebars/helpers/navigation.rs | 2 | ||||
-rw-r--r-- | vendor/mdbook/src/renderer/html_handlebars/search.rs | 6 | ||||
-rw-r--r-- | vendor/mdbook/src/renderer/markdown_renderer.rs | 4 | ||||
-rw-r--r-- | vendor/mdbook/src/theme/book.js | 18 | ||||
-rw-r--r-- | vendor/mdbook/src/theme/index.hbs | 24 | ||||
-rw-r--r-- | vendor/mdbook/src/theme/tomorrow-night.css | 4 | ||||
-rw-r--r-- | vendor/mdbook/src/utils/fs.rs | 35 | ||||
-rw-r--r-- | vendor/mdbook/src/utils/mod.rs | 1 |
20 files changed, 366 insertions, 168 deletions
diff --git a/vendor/mdbook/src/book/book.rs b/vendor/mdbook/src/book/book.rs index b46843df5..96c70abc4 100644 --- a/vendor/mdbook/src/book/book.rs +++ b/vendor/mdbook/src/book/book.rs @@ -39,9 +39,7 @@ fn create_missing(src_dir: &Path, summary: &Summary) -> Result<()> { .chain(summary.suffix_chapters.iter()) .collect(); - while !items.is_empty() { - let next = items.pop().expect("already checked"); - + while let Some(next) = items.pop() { if let SummaryItem::Link(ref link) = *next { if let Some(ref location) = link.location { let filename = src_dir.join(location); @@ -277,7 +275,7 @@ fn load_chapter<P: AsRef<Path>>( } let stripped = location - .strip_prefix(&src_dir) + .strip_prefix(src_dir) .expect("Chapters are always inside a book"); Chapter::new(&link.name, content, stripped, parent_names.clone()) @@ -317,7 +315,7 @@ impl<'a> Iterator for BookItems<'a> { fn next(&mut self) -> Option<Self::Item> { let item = self.items.pop_front(); - if let Some(&BookItem::Chapter(ref ch)) = item { + if let Some(BookItem::Chapter(ch)) = item { // if we wanted a breadth-first iterator we'd `extend()` here for sub_item in ch.sub_items.iter().rev() { self.items.push_front(sub_item); diff --git a/vendor/mdbook/src/book/init.rs b/vendor/mdbook/src/book/init.rs index ebcdd9349..faca1d09a 100644 --- a/vendor/mdbook/src/book/init.rs +++ b/vendor/mdbook/src/book/init.rs @@ -198,8 +198,7 @@ impl BookBuilder { writeln!(f, "- [Chapter 1](./chapter_1.md)")?; let chapter_1 = src_dir.join("chapter_1.md"); - let mut f = - File::create(&chapter_1).with_context(|| "Unable to create chapter_1.md")?; + let mut f = File::create(chapter_1).with_context(|| "Unable to create chapter_1.md")?; writeln!(f, "# Chapter 1")?; } else { trace!("Existing summary found, no need to create stub files."); @@ -212,10 +211,10 @@ impl BookBuilder { fs::create_dir_all(&self.root)?; let src = self.root.join(&self.config.book.src); - fs::create_dir_all(&src)?; + fs::create_dir_all(src)?; let build = self.root.join(&self.config.build.build_dir); - fs::create_dir_all(&build)?; + fs::create_dir_all(build)?; Ok(()) } diff --git a/vendor/mdbook/src/book/mod.rs b/vendor/mdbook/src/book/mod.rs index 33fe93f7f..a5e3e78c6 100644 --- a/vendor/mdbook/src/book/mod.rs +++ b/vendor/mdbook/src/book/mod.rs @@ -99,7 +99,7 @@ impl MDBook { let root = book_root.into(); let src_dir = root.join(&config.book.src); - let book = book::load_book(&src_dir, &config.build)?; + let book = book::load_book(src_dir, &config.build)?; let renderers = determine_renderers(&config); let preprocessors = determine_preprocessors(&config)?; @@ -122,7 +122,7 @@ impl MDBook { let root = book_root.into(); let src_dir = root.join(&config.book.src); - let book = book::load_book_from_disk(&summary, &src_dir)?; + let book = book::load_book_from_disk(&summary, src_dir)?; let renderers = determine_renderers(&config); let preprocessors = determine_preprocessors(&config)?; @@ -309,7 +309,7 @@ impl MDBook { info!("Testing chapter '{}': {:?}", ch.name, chapter_path); // write preprocessed file to tempdir - let path = temp_dir.path().join(&chapter_path); + let path = temp_dir.path().join(chapter_path); let mut tmpf = utils::fs::create_file(&path)?; tmpf.write_all(ch.content.as_bytes())?; @@ -319,13 +319,13 @@ impl MDBook { if let Some(edition) = self.config.rust.edition { match edition { RustEdition::E2015 => { - cmd.args(&["--edition", "2015"]); + cmd.args(["--edition", "2015"]); } RustEdition::E2018 => { - cmd.args(&["--edition", "2018"]); + cmd.args(["--edition", "2018"]); } RustEdition::E2021 => { - cmd.args(&["--edition", "2021"]); + cmd.args(["--edition", "2021"]); } } } diff --git a/vendor/mdbook/src/cmd/build.rs b/vendor/mdbook/src/cmd/build.rs index 14a9fec6e..e40e5c0c7 100644 --- a/vendor/mdbook/src/cmd/build.rs +++ b/vendor/mdbook/src/cmd/build.rs @@ -16,7 +16,7 @@ pub fn make_subcommand() -> Command { // Build command implementation pub fn execute(args: &ArgMatches) -> Result<()> { let book_dir = get_book_dir(args); - let mut book = MDBook::load(&book_dir)?; + let mut book = MDBook::load(book_dir)?; if let Some(dest_dir) = args.get_one::<PathBuf>("dest-dir") { book.config.build.build_dir = dest_dir.into(); diff --git a/vendor/mdbook/src/cmd/clean.rs b/vendor/mdbook/src/cmd/clean.rs index 3ec605fea..48b4147ca 100644 --- a/vendor/mdbook/src/cmd/clean.rs +++ b/vendor/mdbook/src/cmd/clean.rs @@ -16,7 +16,7 @@ pub fn make_subcommand() -> Command { // Clean command implementation pub fn execute(args: &ArgMatches) -> mdbook::errors::Result<()> { let book_dir = get_book_dir(args); - let book = MDBook::load(&book_dir)?; + let book = MDBook::load(book_dir)?; let dir_to_remove = match args.get_one::<PathBuf>("dest-dir") { Some(dest_dir) => dest_dir.into(), diff --git a/vendor/mdbook/src/cmd/init.rs b/vendor/mdbook/src/cmd/init.rs index d8ce93d16..2c6415b6d 100644 --- a/vendor/mdbook/src/cmd/init.rs +++ b/vendor/mdbook/src/cmd/init.rs @@ -56,7 +56,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> { "git" => builder.create_gitignore(true), _ => builder.create_gitignore(false), }; - } else { + } else if !args.get_flag("force") { println!("\nDo you want a .gitignore to be created? (y/n)"); if confirm() { builder.create_gitignore(true); @@ -65,6 +65,8 @@ pub fn execute(args: &ArgMatches) -> Result<()> { config.book.title = if args.contains_id("title") { args.get_one::<String>("title").map(String::from) + } else if args.get_flag("force") { + None } else { request_book_title() }; @@ -84,7 +86,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> { /// Obtains author name from git config file by running the `git config` command. fn get_author_name() -> Option<String> { let output = Command::new("git") - .args(&["config", "--get", "user.name"]) + .args(["config", "--get", "user.name"]) .output() .ok()?; @@ -114,5 +116,5 @@ fn confirm() -> bool { io::stdout().flush().unwrap(); let mut s = String::new(); io::stdin().read_line(&mut s).ok(); - matches!(&*s.trim(), "Y" | "y" | "yes" | "Yes") + matches!(s.trim(), "Y" | "y" | "yes" | "Yes") } diff --git a/vendor/mdbook/src/cmd/serve.rs b/vendor/mdbook/src/cmd/serve.rs index 88898567e..eeb19cb37 100644 --- a/vendor/mdbook/src/cmd/serve.rs +++ b/vendor/mdbook/src/cmd/serve.rs @@ -48,7 +48,7 @@ pub fn make_subcommand() -> Command { // Serve command implementation pub fn execute(args: &ArgMatches) -> Result<()> { let book_dir = get_book_dir(args); - let mut book = MDBook::load(&book_dir)?; + let mut book = MDBook::load(book_dir)?; let port = args.get_one::<String>("port").unwrap(); let hostname = args.get_one::<String>("hostname").unwrap(); @@ -102,7 +102,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> { info!("Building book..."); // FIXME: This area is really ugly because we need to re-set livereload :( - let result = MDBook::load(&book_dir).and_then(|mut b| { + let result = MDBook::load(book_dir).and_then(|mut b| { update_config(&mut b); b.build() }); diff --git a/vendor/mdbook/src/cmd/test.rs b/vendor/mdbook/src/cmd/test.rs index 3efe130b1..69f99f409 100644 --- a/vendor/mdbook/src/cmd/test.rs +++ b/vendor/mdbook/src/cmd/test.rs @@ -44,7 +44,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> { let chapter: Option<&str> = args.get_one::<String>("chapter").map(|s| s.as_str()); let book_dir = get_book_dir(args); - let mut book = MDBook::load(&book_dir)?; + let mut book = MDBook::load(book_dir)?; if let Some(dest_dir) = args.get_one::<PathBuf>("dest-dir") { book.config.build.build_dir = dest_dir.to_path_buf(); diff --git a/vendor/mdbook/src/cmd/watch.rs b/vendor/mdbook/src/cmd/watch.rs index bbc6bde71..e9806e1cd 100644 --- a/vendor/mdbook/src/cmd/watch.rs +++ b/vendor/mdbook/src/cmd/watch.rs @@ -1,5 +1,6 @@ use super::command_prelude::*; use crate::{get_book_dir, open}; +use ignore::gitignore::Gitignore; use mdbook::errors::Result; use mdbook::utils; use mdbook::MDBook; @@ -20,7 +21,7 @@ pub fn make_subcommand() -> Command { // Watch command implementation pub fn execute(args: &ArgMatches) -> Result<()> { let book_dir = get_book_dir(args); - let mut book = MDBook::load(&book_dir)?; + let mut book = MDBook::load(book_dir)?; let update_config = |book: &mut MDBook| { if let Some(dest_dir) = args.get_one::<PathBuf>("dest-dir") { @@ -41,7 +42,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> { trigger_on_change(&book, |paths, book_dir| { info!("Files changed: {:?}\nBuilding book...\n", paths); - let result = MDBook::load(&book_dir).and_then(|mut b| { + let result = MDBook::load(book_dir).and_then(|mut b| { update_config(&mut b); b.build() }); @@ -62,14 +63,14 @@ fn remove_ignored_files(book_root: &Path, paths: &[PathBuf]) -> Vec<PathBuf> { match find_gitignore(book_root) { Some(gitignore_path) => { - match gitignore::File::new(gitignore_path.as_path()) { - Ok(exclusion_checker) => filter_ignored_files(exclusion_checker, paths), - Err(_) => { - // We're unable to read the .gitignore file, so we'll silently allow everything. - // Please see discussion: https://github.com/rust-lang/mdBook/pull/1051 - paths.iter().map(|path| path.to_path_buf()).collect() - } + let (ignore, err) = Gitignore::new(&gitignore_path); + if let Some(err) = err { + warn!( + "error reading gitignore `{}`: {err}", + gitignore_path.display() + ); } + filter_ignored_files(ignore, paths) } None => { // There is no .gitignore file. @@ -85,18 +86,13 @@ fn find_gitignore(book_root: &Path) -> Option<PathBuf> { .find(|p| p.exists()) } -fn filter_ignored_files(exclusion_checker: gitignore::File, paths: &[PathBuf]) -> Vec<PathBuf> { +fn filter_ignored_files(ignore: Gitignore, paths: &[PathBuf]) -> Vec<PathBuf> { paths .iter() - .filter(|path| match exclusion_checker.is_excluded(path) { - Ok(exclude) => !exclude, - Err(error) => { - warn!( - "Unable to determine if {:?} is excluded: {:?}. Including it.", - &path, error - ); - true - } + .filter(|path| { + !ignore + .matched_path_or_any_parents(path, path.is_dir()) + .is_ignore() }) .map(|path| path.to_path_buf()) .collect() diff --git a/vendor/mdbook/src/config.rs b/vendor/mdbook/src/config.rs index 0c367d848..4641d1a26 100644 --- a/vendor/mdbook/src/config.rs +++ b/vendor/mdbook/src/config.rs @@ -308,7 +308,7 @@ impl<'de> serde::Deserialize<'de> for Config { warn!("`description` under a table called `[book]`, move the `destination` entry"); warn!("from `[output.html]`, renamed to `build-dir`, under a table called"); warn!("`[build]`, and it should all work."); - warn!("Documentation: http://rust-lang.github.io/mdBook/format/config.html"); + warn!("Documentation: https://rust-lang.github.io/mdBook/format/config.html"); return Ok(Config::from_legacy(raw)); } @@ -504,6 +504,8 @@ pub struct HtmlConfig { /// Playground settings. #[serde(alias = "playpen")] pub playground: Playground, + /// Code settings. + pub code: Code, /// Print settings. pub print: Print, /// Don't render section labels. @@ -556,6 +558,7 @@ impl Default for HtmlConfig { additional_js: Vec::new(), fold: Fold::default(), playground: Playground::default(), + code: Code::default(), print: Print::default(), no_section_label: false, search: None, @@ -642,6 +645,22 @@ impl Default for Playground { } } +/// Configuration for tweaking how the the HTML renderer handles code blocks. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(default, rename_all = "kebab-case")] +pub struct Code { + /// A prefix string to hide lines per language (one or more chars). + pub hidelines: HashMap<String, String>, +} + +impl Default for Code { + fn default() -> Code { + Code { + hidelines: HashMap::new(), + } + } +} + /// Configuration of the search functionality of the HTML renderer. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(default, rename_all = "kebab-case")] @@ -703,7 +722,7 @@ trait Updateable<'de>: Serialize + Deserialize<'de> { let mut raw = Value::try_from(&self).expect("unreachable"); if let Ok(value) = Value::try_from(value) { - let _ = raw.insert(key, value); + raw.insert(key, value); } else { return; } diff --git a/vendor/mdbook/src/preprocess/links.rs b/vendor/mdbook/src/preprocess/links.rs index c2c81f522..0af211960 100644 --- a/vendor/mdbook/src/preprocess/links.rs +++ b/vendor/mdbook/src/preprocess/links.rs @@ -93,7 +93,7 @@ where for link in find_links(s) { replaced.push_str(&s[previous_end_index..link.start_index]); - match link.render_with_path(&path, chapter_title) { + match link.render_with_path(path, chapter_title) { Ok(new_content) => { if depth < MAX_LINK_NESTED_DEPTH { if let Some(rel_path) = link.link_type.relative_path(path) { @@ -327,7 +327,7 @@ impl<'a> Link<'a> { let base = base.as_ref(); match self.link_type { // omit the escape char - LinkType::Escaped => Ok((&self.link_text[1..]).to_owned()), + LinkType::Escaped => Ok(self.link_text[1..].to_owned()), LinkType::Include(ref pat, ref range_or_anchor) => { let target = base.join(pat); diff --git a/vendor/mdbook/src/renderer/html_handlebars/hbs_renderer.rs b/vendor/mdbook/src/renderer/html_handlebars/hbs_renderer.rs index e170e2fcd..709aa0667 100644 --- a/vendor/mdbook/src/renderer/html_handlebars/hbs_renderer.rs +++ b/vendor/mdbook/src/renderer/html_handlebars/hbs_renderer.rs @@ -1,5 +1,5 @@ use crate::book::{Book, BookItem}; -use crate::config::{BookConfig, Config, HtmlConfig, Playground, RustEdition}; +use crate::config::{BookConfig, Code, Config, HtmlConfig, Playground, RustEdition}; use crate::errors::*; use crate::renderer::html_handlebars::helpers; use crate::renderer::{RenderContext, Renderer}; @@ -99,7 +99,7 @@ impl HtmlHandlebars { ctx.data.insert("title".to_owned(), json!(title)); ctx.data.insert( "path_to_root".to_owned(), - json!(utils::fs::path_to_root(&path)), + json!(utils::fs::path_to_root(path)), ); if let Some(ref section) = ch.number { ctx.data @@ -110,7 +110,12 @@ impl HtmlHandlebars { debug!("Render template"); let rendered = ctx.handlebars.render("index", &ctx.data)?; - let rendered = self.post_process(rendered, &ctx.html_config.playground, ctx.edition); + let rendered = self.post_process( + rendered, + &ctx.html_config.playground, + &ctx.html_config.code, + ctx.edition, + ); // Write to file debug!("Creating {}", filepath.display()); @@ -121,8 +126,12 @@ impl HtmlHandlebars { ctx.data.insert("path_to_root".to_owned(), json!("")); ctx.data.insert("is_index".to_owned(), json!(true)); let rendered_index = ctx.handlebars.render("index", &ctx.data)?; - let rendered_index = - self.post_process(rendered_index, &ctx.html_config.playground, ctx.edition); + let rendered_index = self.post_process( + rendered_index, + &ctx.html_config.playground, + &ctx.html_config.code, + ctx.edition, + ); debug!("Creating index.html from {}", ctx_path); utils::fs::write_file(&ctx.destination, "index.html", rendered_index.as_bytes())?; } @@ -182,8 +191,12 @@ impl HtmlHandlebars { data_404.insert("title".to_owned(), json!(title)); let rendered = handlebars.render("index", &data_404)?; - let rendered = - self.post_process(rendered, &html_config.playground, ctx.config.rust.edition); + let rendered = self.post_process( + rendered, + &html_config.playground, + &html_config.code, + ctx.config.rust.edition, + ); let output_file = get_404_output_file(&html_config.input_404); utils::fs::write_file(destination, output_file, rendered.as_bytes())?; debug!("Creating 404.html ✓"); @@ -195,11 +208,13 @@ impl HtmlHandlebars { &self, rendered: String, playground_config: &Playground, + code_config: &Code, edition: Option<RustEdition>, ) -> String { let rendered = build_header_links(&rendered); let rendered = fix_code_blocks(&rendered); let rendered = add_playground_pre(&rendered, playground_config, edition); + let rendered = hide_lines(&rendered, code_config); rendered } @@ -275,7 +290,8 @@ impl HtmlHandlebars { "FontAwesome/fonts/FontAwesome.ttf", theme::FONT_AWESOME_TTF, )?; - if html_config.copy_fonts { + // Don't copy the stock fonts if the user has specified their own fonts to use. + if html_config.copy_fonts && theme.fonts_css.is_none() { write_file(destination, "fonts/fonts.css", theme::fonts::CSS)?; for (file_name, contents) in theme::fonts::LICENSES.iter() { write_file(destination, file_name, contents)?; @@ -291,20 +307,13 @@ impl HtmlHandlebars { } if let Some(fonts_css) = &theme.fonts_css { if !fonts_css.is_empty() { - if html_config.copy_fonts { - warn!( - "output.html.copy_fonts is deprecated.\n\ - Set copy_fonts=false and ensure the fonts you want are in \ - the `theme/fonts/` directory." - ); - } - write_file(destination, "fonts/fonts.css", &fonts_css)?; + write_file(destination, "fonts/fonts.css", fonts_css)?; } } if !html_config.copy_fonts && theme.fonts_css.is_none() { warn!( - "output.html.copy_fonts is deprecated.\n\ - This book appears to have copy_fonts=false without a fonts.css file.\n\ + "output.html.copy-fonts is deprecated.\n\ + This book appears to have copy-fonts=false in book.toml without a fonts.css file.\n\ Add an empty `theme/fonts/fonts.css` file to squelch this warning." ); } @@ -553,7 +562,7 @@ impl Renderer for HtmlHandlebars { // Print version let mut print_content = String::new(); - fs::create_dir_all(&destination) + fs::create_dir_all(destination) .with_context(|| "Unexpected error when constructing destination path")?; let mut is_index = true; @@ -589,8 +598,12 @@ impl Renderer for HtmlHandlebars { debug!("Render template"); let rendered = handlebars.render("index", &data)?; - let rendered = - self.post_process(rendered, &html_config.playground, ctx.config.rust.edition); + let rendered = self.post_process( + rendered, + &html_config.playground, + &html_config.code, + ctx.config.rust.edition, + ); utils::fs::write_file(destination, "print.html", rendered.as_bytes())?; debug!("Creating print.html ✓"); @@ -795,8 +808,10 @@ fn make_data( /// Goes through the rendered HTML, making sure all header tags have /// an anchor respectively so people can link to sections directly. fn build_header_links(html: &str) -> String { - static BUILD_HEADER_LINKS: Lazy<Regex> = - Lazy::new(|| Regex::new(r"<h(\d)>(.*?)</h\d>").unwrap()); + static BUILD_HEADER_LINKS: Lazy<Regex> = Lazy::new(|| { + Regex::new(r#"<h(\d)(?: id="([^"]+)")?(?: class="([^"]+)")?>(.*?)</h\d>"#).unwrap() + }); + static IGNORE_CLASS: &[&str] = &["menu-title"]; let mut id_counter = HashMap::new(); @@ -806,7 +821,22 @@ fn build_header_links(html: &str) -> String { .parse() .expect("Regex should ensure we only ever get numbers here"); - insert_link_into_header(level, &caps[2], &mut id_counter) + // Ignore .menu-title because now it's getting detected by the regex. + if let Some(classes) = caps.get(3) { + for class in classes.as_str().split(" ") { + if IGNORE_CLASS.contains(&class) { + return caps[0].to_string(); + } + } + } + + insert_link_into_header( + level, + &caps[4], + caps.get(2).map(|x| x.as_str().to_string()), + caps.get(3).map(|x| x.as_str().to_string()), + &mut id_counter, + ) }) .into_owned() } @@ -816,15 +846,21 @@ fn build_header_links(html: &str) -> String { fn insert_link_into_header( level: usize, content: &str, + id: Option<String>, + classes: Option<String>, id_counter: &mut HashMap<String, usize>, ) -> String { - let id = utils::unique_id_from_content(content, id_counter); + let id = id.unwrap_or_else(|| utils::unique_id_from_content(content, id_counter)); + let classes = classes + .map(|s| format!(" class=\"{s}\"")) + .unwrap_or_default(); format!( - r##"<h{level} id="{id}"><a class="header" href="#{id}">{text}</a></h{level}>"##, + r##"<h{level} id="{id}"{classes}><a class="header" href="#{id}">{text}</a></h{level}>"##, level = level, id = id, - text = content + text = content, + classes = classes ) } @@ -856,67 +892,64 @@ fn fix_code_blocks(html: &str) -> String { .into_owned() } +static CODE_BLOCK_RE: Lazy<Regex> = + Lazy::new(|| Regex::new(r##"((?s)<code[^>]?class="([^"]+)".*?>(.*?)</code>)"##).unwrap()); + fn add_playground_pre( html: &str, playground_config: &Playground, edition: Option<RustEdition>, ) -> String { - static ADD_PLAYGROUND_PRE: Lazy<Regex> = - Lazy::new(|| Regex::new(r##"((?s)<code[^>]?class="([^"]+)".*?>(.*?)</code>)"##).unwrap()); - - ADD_PLAYGROUND_PRE + CODE_BLOCK_RE .replace_all(html, |caps: &Captures<'_>| { let text = &caps[1]; let classes = &caps[2]; let code = &caps[3]; - if classes.contains("language-rust") { - if (!classes.contains("ignore") + if classes.contains("language-rust") + && ((!classes.contains("ignore") && !classes.contains("noplayground") && !classes.contains("noplaypen") && playground_config.runnable) - || classes.contains("mdbook-runnable") - { - let contains_e2015 = classes.contains("edition2015"); - let contains_e2018 = classes.contains("edition2018"); - let contains_e2021 = classes.contains("edition2021"); - let edition_class = if contains_e2015 || contains_e2018 || contains_e2021 { - // the user forced edition, we should not overwrite it - "" - } else { - match edition { - Some(RustEdition::E2015) => " edition2015", - Some(RustEdition::E2018) => " edition2018", - Some(RustEdition::E2021) => " edition2021", - None => "", - } - }; - - // wrap the contents in an external pre block - format!( - "<pre class=\"playground\"><code class=\"{}{}\">{}</code></pre>", - classes, - edition_class, - { - let content: Cow<'_, str> = if playground_config.editable - && classes.contains("editable") - || text.contains("fn main") - || text.contains("quick_main!") - { - code.into() - } else { - // we need to inject our own main - let (attrs, code) = partition_source(code); - - format!("# #![allow(unused)]\n{}#fn main() {{\n{}#}}", attrs, code) - .into() - }; - hide_lines(&content) - } - ) + || classes.contains("mdbook-runnable")) + { + let contains_e2015 = classes.contains("edition2015"); + let contains_e2018 = classes.contains("edition2018"); + let contains_e2021 = classes.contains("edition2021"); + let edition_class = if contains_e2015 || contains_e2018 || contains_e2021 { + // the user forced edition, we should not overwrite it + "" } else { - format!("<code class=\"{}\">{}</code>", classes, hide_lines(code)) - } + match edition { + Some(RustEdition::E2015) => " edition2015", + Some(RustEdition::E2018) => " edition2018", + Some(RustEdition::E2021) => " edition2021", + None => "", + } + }; + + // wrap the contents in an external pre block + format!( + "<pre class=\"playground\"><code class=\"{}{}\">{}</code></pre>", + classes, + edition_class, + { + let content: Cow<'_, str> = if playground_config.editable + && classes.contains("editable") + || text.contains("fn main") + || text.contains("quick_main!") + { + code.into() + } else { + // we need to inject our own main + let (attrs, code) = partition_source(code); + + format!("# #![allow(unused)]\n{}#fn main() {{\n{}#}}", attrs, code) + .into() + }; + content + } + ) } else { // not language-rust, so no-op text.to_owned() @@ -925,7 +958,50 @@ fn add_playground_pre( .into_owned() } -fn hide_lines(content: &str) -> String { +/// Modifies all `<code>` blocks to convert "hidden" lines and to wrap them in +/// a `<span class="boring">`. +fn hide_lines(html: &str, code_config: &Code) -> String { + let language_regex = Regex::new(r"\blanguage-(\w+)\b").unwrap(); + let hidelines_regex = Regex::new(r"\bhidelines=(\S+)").unwrap(); + CODE_BLOCK_RE + .replace_all(html, |caps: &Captures<'_>| { + let text = &caps[1]; + let classes = &caps[2]; + let code = &caps[3]; + + if classes.contains("language-rust") { + format!( + "<code class=\"{}\">{}</code>", + classes, + hide_lines_rust(code) + ) + } else { + // First try to get the prefix from the code block + let hidelines_capture = hidelines_regex.captures(classes); + let hidelines_prefix = match &hidelines_capture { + Some(capture) => Some(&capture[1]), + None => { + // Then look up the prefix by language + language_regex.captures(classes).and_then(|capture| { + code_config.hidelines.get(&capture[1]).map(|p| p.as_str()) + }) + } + }; + + match hidelines_prefix { + Some(prefix) => format!( + "<code class=\"{}\">{}</code>", + classes, + hide_lines_with_prefix(code, prefix) + ), + None => text.to_owned(), + } + } + }) + .into_owned() +} + +fn hide_lines_rust(content: &str) -> String { static BORING_LINES_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"^(\s*)#(.?)(.*)$").unwrap()); let mut result = String::with_capacity(content.len()); @@ -958,6 +1034,26 @@ fn hide_lines(content: &str) -> String { result } +fn hide_lines_with_prefix(content: &str, prefix: &str) -> String { + let mut result = String::with_capacity(content.len()); + for line in content.lines() { + if line.trim_start().starts_with(prefix) { + let pos = line.find(prefix).unwrap(); + let (ws, rest) = (&line[..pos], &line[pos + prefix.len()..]); + + result += "<span class=\"boring\">"; + result += ws; + result += rest; + result += "\n"; + result += "</span>"; + continue; + } + result += line; + result += "\n"; + } + result +} + fn partition_source(s: &str) -> (String, String) { let mut after_header = false; let mut before = String::new(); @@ -993,6 +1089,7 @@ struct RenderItemContext<'a> { #[cfg(test)] mod tests { use super::*; + use pretty_assertions::assert_eq; #[test] fn original_build_header_links() { @@ -1021,6 +1118,21 @@ mod tests { "<h1>Foo</h1><h3>Foo</h3>", r##"<h1 id="foo"><a class="header" href="#foo">Foo</a></h1><h3 id="foo-1"><a class="header" href="#foo-1">Foo</a></h3>"##, ), + // id only + ( + r##"<h1 id="foobar">Foo</h1>"##, + r##"<h1 id="foobar"><a class="header" href="#foobar">Foo</a></h1>"##, + ), + // class only + ( + r##"<h1 class="class1 class2">Foo</h1>"##, + r##"<h1 id="foo" class="class1 class2"><a class="header" href="#foo">Foo</a></h1>"##, + ), + // both id and class + ( + r##"<h1 id="foobar" class="class1 class2">Foo</h1>"##, + r##"<h1 id="foobar" class="class1 class2"><a class="header" href="#foobar">Foo</a></h1>"##, + ), ]; for (src, should_be) in inputs { @@ -1033,17 +1145,17 @@ mod tests { fn add_playground() { let inputs = [ ("<code class=\"language-rust\">x()</code>", - "<pre class=\"playground\"><code class=\"language-rust\"><span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}</span></code></pre>"), + "<pre class=\"playground\"><code class=\"language-rust\"># #![allow(unused)]\n#fn main() {\nx()\n#}</code></pre>"), ("<code class=\"language-rust\">fn main() {}</code>", "<pre class=\"playground\"><code class=\"language-rust\">fn main() {}</code></pre>"), ("<code class=\"language-rust editable\">let s = \"foo\n # bar\n\";</code>", - "<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";</code></pre>"), - ("<code class=\"language-rust editable\">let s = \"foo\n ## bar\n\";</code>", "<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n # bar\n\";</code></pre>"), + ("<code class=\"language-rust editable\">let s = \"foo\n ## bar\n\";</code>", + "<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n ## bar\n\";</code></pre>"), ("<code class=\"language-rust editable\">let s = \"foo\n # bar\n#\n\";</code>", - "<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n<span class=\"boring\"> bar\n</span><span class=\"boring\">\n</span>\";</code></pre>"), + "<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n # bar\n#\n\";</code></pre>"), ("<code class=\"language-rust ignore\">let s = \"foo\n # bar\n\";</code>", - "<code class=\"language-rust ignore\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";</code>"), + "<code class=\"language-rust ignore\">let s = \"foo\n # bar\n\";</code>"), ("<code class=\"language-rust editable\">#![no_std]\nlet s = \"foo\";\n #[some_attr]</code>", "<pre class=\"playground\"><code class=\"language-rust editable\">#![no_std]\nlet s = \"foo\";\n #[some_attr]</code></pre>"), ]; @@ -1063,7 +1175,7 @@ mod tests { fn add_playground_edition2015() { let inputs = [ ("<code class=\"language-rust\">x()</code>", - "<pre class=\"playground\"><code class=\"language-rust edition2015\"><span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}</span></code></pre>"), + "<pre class=\"playground\"><code class=\"language-rust edition2015\"># #![allow(unused)]\n#fn main() {\nx()\n#}</code></pre>"), ("<code class=\"language-rust\">fn main() {}</code>", "<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"), ("<code class=\"language-rust edition2015\">fn main() {}</code>", @@ -1087,7 +1199,7 @@ mod tests { fn add_playground_edition2018() { let inputs = [ ("<code class=\"language-rust\">x()</code>", - "<pre class=\"playground\"><code class=\"language-rust edition2018\"><span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}</span></code></pre>"), + "<pre class=\"playground\"><code class=\"language-rust edition2018\"># #![allow(unused)]\n#fn main() {\nx()\n#}</code></pre>"), ("<code class=\"language-rust\">fn main() {}</code>", "<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"), ("<code class=\"language-rust edition2015\">fn main() {}</code>", @@ -1111,7 +1223,7 @@ mod tests { fn add_playground_edition2021() { let inputs = [ ("<code class=\"language-rust\">x()</code>", - "<pre class=\"playground\"><code class=\"language-rust edition2021\"><span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}</span></code></pre>"), + "<pre class=\"playground\"><code class=\"language-rust edition2021\"># #![allow(unused)]\n#fn main() {\nx()\n#}</code></pre>"), ("<code class=\"language-rust\">fn main() {}</code>", "<pre class=\"playground\"><code class=\"language-rust edition2021\">fn main() {}</code></pre>"), ("<code class=\"language-rust edition2015\">fn main() {}</code>", @@ -1131,4 +1243,60 @@ mod tests { assert_eq!(&*got, *should_be); } } + + #[test] + fn hide_lines_language_rust() { + let inputs = [ + ( + "<pre class=\"playground\"><code class=\"language-rust\">\n# #![allow(unused)]\n#fn main() {\nx()\n#}</code></pre>", + "<pre class=\"playground\"><code class=\"language-rust\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}</span></code></pre>",), + ( + "<pre class=\"playground\"><code class=\"language-rust\">fn main() {}</code></pre>", + "<pre class=\"playground\"><code class=\"language-rust\">fn main() {}</code></pre>",), + ( + "<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n # bar\n\";</code></pre>", + "<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";</code></pre>",), + ( + "<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n ## bar\n\";</code></pre>", + "<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n # bar\n\";</code></pre>",), + ( + "<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n # bar\n#\n\";</code></pre>", + "<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n<span class=\"boring\"> bar\n</span><span class=\"boring\">\n</span>\";</code></pre>",), + ( + "<code class=\"language-rust ignore\">let s = \"foo\n # bar\n\";</code>", + "<code class=\"language-rust ignore\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";</code>",), + ( + "<pre class=\"playground\"><code class=\"language-rust editable\">#![no_std]\nlet s = \"foo\";\n #[some_attr]</code></pre>", + "<pre class=\"playground\"><code class=\"language-rust editable\">#![no_std]\nlet s = \"foo\";\n #[some_attr]</code></pre>",), + ]; + for (src, should_be) in &inputs { + let got = hide_lines(src, &Code::default()); + assert_eq!(&*got, *should_be); + } + } + + #[test] + fn hide_lines_language_other() { + let inputs = [ + ( + "<code class=\"language-python\">~hidden()\nnothidden():\n~ hidden()\n ~hidden()\n nothidden()</code>", + "<code class=\"language-python\"><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=!!!\">!!!hidden()\nnothidden():\n!!! hidden()\n !!!hidden()\n nothidden()</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>",), + ]; + for (src, should_be) in &inputs { + let got = hide_lines( + src, + &Code { + hidelines: { + let mut map = HashMap::new(); + map.insert("python".to_string(), "~".to_string()); + map + }, + }, + ); + assert_eq!(&*got, *should_be); + } + } } diff --git a/vendor/mdbook/src/renderer/html_handlebars/helpers/navigation.rs b/vendor/mdbook/src/renderer/html_handlebars/helpers/navigation.rs index b184c4410..968a67016 100644 --- a/vendor/mdbook/src/renderer/html_handlebars/helpers/navigation.rs +++ b/vendor/mdbook/src/renderer/html_handlebars/helpers/navigation.rs @@ -127,7 +127,7 @@ fn render( context.insert( "path_to_root".to_owned(), - json!(utils::fs::path_to_root(&base_path)), + json!(utils::fs::path_to_root(base_path)), ); chapter diff --git a/vendor/mdbook/src/renderer/html_handlebars/search.rs b/vendor/mdbook/src/renderer/html_handlebars/search.rs index a9e2f5ca6..24d62fda2 100644 --- a/vendor/mdbook/src/renderer/html_handlebars/search.rs +++ b/vendor/mdbook/src/renderer/html_handlebars/search.rs @@ -138,9 +138,11 @@ fn render_item( in_heading = true; } - Event::End(Tag::Heading(i, ..)) if i as u32 <= max_section_depth => { + Event::End(Tag::Heading(i, id, _classes)) if i as u32 <= max_section_depth => { in_heading = false; - section_id = Some(utils::unique_id_from_content(&heading, &mut id_counter)); + section_id = id + .map(|id| id.to_string()) + .or_else(|| Some(utils::unique_id_from_content(&heading, &mut id_counter))); breadcrumbs.push(heading.clone()); } Event::Start(Tag::FootnoteDefinition(name)) => { diff --git a/vendor/mdbook/src/renderer/markdown_renderer.rs b/vendor/mdbook/src/renderer/markdown_renderer.rs index 13bd05cc3..4a5a5c2af 100644 --- a/vendor/mdbook/src/renderer/markdown_renderer.rs +++ b/vendor/mdbook/src/renderer/markdown_renderer.rs @@ -37,14 +37,14 @@ impl Renderer for MarkdownRenderer { if !ch.is_draft_chapter() { utils::fs::write_file( &ctx.destination, - &ch.path.as_ref().expect("Checked path exists before"), + ch.path.as_ref().expect("Checked path exists before"), ch.content.as_bytes(), )?; } } } - fs::create_dir_all(&destination) + fs::create_dir_all(destination) .with_context(|| "Unexpected error when constructing destination path")?; Ok(()) diff --git a/vendor/mdbook/src/theme/book.js b/vendor/mdbook/src/theme/book.js index e303ebb45..67a8a5b08 100644 --- a/vendor/mdbook/src/theme/book.js +++ b/vendor/mdbook/src/theme/book.js @@ -68,7 +68,7 @@ function playground_text(playground, hidden = true) { } // updates the visibility of play button based on `no_run` class and - // used crates vs ones available on http://play.rust-lang.org + // used crates vs ones available on https://play.rust-lang.org function update_play_button(pre_block, playground_crates) { var play_button = pre_block.querySelector(".play-button"); @@ -179,7 +179,7 @@ function playground_text(playground, hidden = true) { // even if highlighting doesn't apply code_nodes.forEach(function (block) { block.classList.add('hljs'); }); - Array.from(document.querySelectorAll("code.language-rust")).forEach(function (block) { + Array.from(document.querySelectorAll("code.hljs")).forEach(function (block) { var lines = Array.from(block.querySelectorAll('.boring')); // If no lines were hidden, return @@ -551,13 +551,6 @@ function playground_text(playground, hidden = true) { firstContact = null; } }, { passive: true }); - - // Scroll sidebar to current active section - var activeSection = document.getElementById("sidebar").querySelector(".active"); - if (activeSection) { - // https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView - activeSection.scrollIntoView({ block: 'center' }); - } })(); (function chapterNavigation() { @@ -676,13 +669,14 @@ function playground_text(playground, hidden = true) { }, { passive: true }); })(); (function controllBorder() { - menu.classList.remove('bordered'); - document.addEventListener('scroll', function () { + function updateBorder() { if (menu.offsetTop === 0) { menu.classList.remove('bordered'); } else { menu.classList.add('bordered'); } - }, { passive: true }); + } + updateBorder(); + document.addEventListener('scroll', updateBorder, { passive: true }); })(); })(); diff --git a/vendor/mdbook/src/theme/index.hbs b/vendor/mdbook/src/theme/index.hbs index 6f3948c65..80315c48f 100644 --- a/vendor/mdbook/src/theme/index.hbs +++ b/vendor/mdbook/src/theme/index.hbs @@ -110,12 +110,34 @@ <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div> </nav> + <!-- Track and set sidebar scroll position --> + <script> + var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox'); + sidebarScrollbox.addEventListener('click', function(e) { + if (e.target.tagName === 'A') { + sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop); + } + }, { passive: true }); + var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll'); + sessionStorage.removeItem('sidebar-scroll'); + if (sidebarScrollTop) { + // preserve sidebar scroll position when navigating via links within sidebar + sidebarScrollbox.scrollTop = sidebarScrollTop; + } else { + // scroll sidebar to current active section when navigating via "next/previous chapter" buttons + var activeSection = document.querySelector('#sidebar .active'); + if (activeSection) { + activeSection.scrollIntoView({ block: 'center' }); + } + } + </script> + <div id="page-wrapper" class="page-wrapper"> <div class="page"> {{> header}} <div id="menu-bar-hover-placeholder"></div> - <div id="menu-bar" class="menu-bar sticky bordered"> + <div id="menu-bar" class="menu-bar sticky"> <div class="left-buttons"> <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar"> <i class="fa fa-bars"></i> diff --git a/vendor/mdbook/src/theme/tomorrow-night.css b/vendor/mdbook/src/theme/tomorrow-night.css index 5b4aca77c..81fe276e7 100644 --- a/vendor/mdbook/src/theme/tomorrow-night.css +++ b/vendor/mdbook/src/theme/tomorrow-night.css @@ -1,7 +1,7 @@ /* Tomorrow Night Theme */ -/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ +/* https://github.com/jmblog/color-themes-for-highlightjs */ /* Original theme - https://github.com/chriskempson/tomorrow-theme */ -/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ +/* https://github.com/jmblog/color-themes-for-highlightjs */ /* Tomorrow Comment */ .hljs-comment { diff --git a/vendor/mdbook/src/utils/fs.rs b/vendor/mdbook/src/utils/fs.rs index 67f7062db..8ad5aad8b 100644 --- a/vendor/mdbook/src/utils/fs.rs +++ b/vendor/mdbook/src/utils/fs.rs @@ -210,39 +210,36 @@ mod tests { }; // Create a couple of files - if let Err(err) = fs::File::create(&tmp.path().join("file.txt")) { + if let Err(err) = fs::File::create(tmp.path().join("file.txt")) { panic!("Could not create file.txt: {}", err); } - if let Err(err) = fs::File::create(&tmp.path().join("file.md")) { + if let Err(err) = fs::File::create(tmp.path().join("file.md")) { panic!("Could not create file.md: {}", err); } - if let Err(err) = fs::File::create(&tmp.path().join("file.png")) { + if let Err(err) = fs::File::create(tmp.path().join("file.png")) { panic!("Could not create file.png: {}", err); } - if let Err(err) = fs::create_dir(&tmp.path().join("sub_dir")) { + if let Err(err) = fs::create_dir(tmp.path().join("sub_dir")) { panic!("Could not create sub_dir: {}", err); } - if let Err(err) = fs::File::create(&tmp.path().join("sub_dir/file.png")) { + if let Err(err) = fs::File::create(tmp.path().join("sub_dir/file.png")) { panic!("Could not create sub_dir/file.png: {}", err); } - if let Err(err) = fs::create_dir(&tmp.path().join("sub_dir_exists")) { + if let Err(err) = fs::create_dir(tmp.path().join("sub_dir_exists")) { panic!("Could not create sub_dir_exists: {}", err); } - if let Err(err) = fs::File::create(&tmp.path().join("sub_dir_exists/file.txt")) { + if let Err(err) = fs::File::create(tmp.path().join("sub_dir_exists/file.txt")) { panic!("Could not create sub_dir_exists/file.txt: {}", err); } - if let Err(err) = symlink( - &tmp.path().join("file.png"), - &tmp.path().join("symlink.png"), - ) { + if let Err(err) = symlink(tmp.path().join("file.png"), tmp.path().join("symlink.png")) { panic!("Could not symlink file.png: {}", err); } // Create output dir - if let Err(err) = fs::create_dir(&tmp.path().join("output")) { + if let Err(err) = fs::create_dir(tmp.path().join("output")) { panic!("Could not create output: {}", err); } - if let Err(err) = fs::create_dir(&tmp.path().join("output/sub_dir_exists")) { + if let Err(err) = fs::create_dir(tmp.path().join("output/sub_dir_exists")) { panic!("Could not create output/sub_dir_exists: {}", err); } @@ -253,22 +250,22 @@ mod tests { } // Check if the correct files where created - if !(&tmp.path().join("output/file.txt")).exists() { + if !tmp.path().join("output/file.txt").exists() { panic!("output/file.txt should exist") } - if (&tmp.path().join("output/file.md")).exists() { + if tmp.path().join("output/file.md").exists() { panic!("output/file.md should not exist") } - if !(&tmp.path().join("output/file.png")).exists() { + if !tmp.path().join("output/file.png").exists() { panic!("output/file.png should exist") } - if !(&tmp.path().join("output/sub_dir/file.png")).exists() { + if !tmp.path().join("output/sub_dir/file.png").exists() { panic!("output/sub_dir/file.png should exist") } - if !(&tmp.path().join("output/sub_dir_exists/file.txt")).exists() { + if !tmp.path().join("output/sub_dir_exists/file.txt").exists() { panic!("output/sub_dir/file.png should exist") } - if !(&tmp.path().join("output/symlink.png")).exists() { + if !tmp.path().join("output/symlink.png").exists() { panic!("output/symlink.png should exist") } } diff --git a/vendor/mdbook/src/utils/mod.rs b/vendor/mdbook/src/utils/mod.rs index 9f67deda7..9156916ea 100644 --- a/vendor/mdbook/src/utils/mod.rs +++ b/vendor/mdbook/src/utils/mod.rs @@ -183,6 +183,7 @@ pub fn new_cmark_parser(text: &str, curly_quotes: bool) -> Parser<'_, '_> { opts.insert(Options::ENABLE_FOOTNOTES); opts.insert(Options::ENABLE_STRIKETHROUGH); opts.insert(Options::ENABLE_TASKLISTS); + opts.insert(Options::ENABLE_HEADING_ATTRIBUTES); if curly_quotes { opts.insert(Options::ENABLE_SMART_PUNCTUATION); } |