diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index ffa2a922f9..d83c571dda 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -57,7 +57,7 @@ impl HtmlHandlebars { let content = ch.content.clone(); let content = utils::render_markdown(&content, ctx.html_config.curly_quotes); - let fixed_content = utils::render_markdown_with_path_and_redirects( + let printed_item = utils::render_markdown_with_path_and_redirects( &ch.content, ctx.html_config.curly_quotes, Some(path), @@ -70,7 +70,7 @@ impl HtmlHandlebars { print_content .push_str(r#"
"#); } - let path_id = { + let print_page_id = { let mut base = path.display().to_string(); if base.ends_with(".md") { base.truncate(base.len() - 3); @@ -84,10 +84,10 @@ impl HtmlHandlebars { // We have to build header links in advance so that we can know the ranges // for the headers in one page. // Insert a dummy div to make sure that we can locate the specific page. - print_content.push_str(&(format!(r#"
"#, &path_id))); + print_content.push_str(&(format!(r#"
"#))); print_content.push_str(&build_header_links( - &build_print_element_id(&fixed_content, &path_id), - Some(path_id), + &build_print_element_id(&printed_item, &print_page_id), + Some(print_page_id), )); // Update the context with data for this file @@ -234,6 +234,22 @@ impl HtmlHandlebars { edition: Option, ) -> String { let rendered = build_header_links(&rendered, None); + let rendered = self.post_process_common(rendered, &playground_config, code_config, edition); + + rendered + } + + /// Applies some post-processing to the HTML to apply some adjustments. + /// + /// This common function is used for both normal chapters (via + /// `post_process`) and the combined print page. + fn post_process_common( + &self, + rendered: String, + playground_config: &Playground, + code_config: &Code, + edition: Option, + ) -> String { let rendered = fix_code_blocks(&rendered); let rendered = add_playground_pre(&rendered, playground_config, edition); let rendered = hide_lines(&rendered, code_config); @@ -620,7 +636,7 @@ impl Renderer for HtmlHandlebars { debug!("Render template"); let rendered = handlebars.render("index", &data)?; - let rendered = self.post_process( + let rendered = self.post_process_common( rendered, &html_config.playground, &html_config.code, @@ -833,7 +849,7 @@ fn make_data( /// Go through the rendered print page HTML, /// add path id prefix to all the elements id as well as footnote links. -fn build_print_element_id(html: &str, path_id: &str) -> String { +fn build_print_element_id(html: &str, print_page_id: &str) -> String { static ALL_ID: Lazy = Lazy::new(|| Regex::new(r#"(<[^>]*?id=")([^"]+?)""#).unwrap()); static FOOTNOTE_ID: Lazy = Lazy::new(|| { Regex::new( @@ -843,19 +859,22 @@ fn build_print_element_id(html: &str, path_id: &str) -> String { }); let temp_html = ALL_ID.replace_all(html, |caps: &Captures<'_>| { - format!("{}{}-{}\"", &caps[1], path_id, &caps[2]) + format!("{}{}-{}\"", &caps[1], print_page_id, &caps[2]) }); FOOTNOTE_ID .replace_all(&temp_html, |caps: &Captures<'_>| { - format!("{}{}-{}\"", &caps[1], path_id, &caps[2]) + format!("{}{}-{}\"", &caps[1], print_page_id, &caps[2]) }) .into_owned() } /// 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, path_id: Option<&str>) -> String { +/// +/// `print_page_id` should be set to the print page ID prefix when adjusting the +/// print page. +fn build_header_links(html: &str, print_page_id: Option<&str>) -> String { static BUILD_HEADER_LINKS: Lazy = Lazy::new(|| { Regex::new(r#"(.*?)"#).unwrap() }); @@ -884,7 +903,7 @@ fn build_header_links(html: &str, path_id: Option<&str>) -> String { caps.get(2).map(|x| x.as_str().to_string()), caps.get(3).map(|x| x.as_str().to_string()), &mut id_counter, - path_id, + print_page_id, ) }) .into_owned() @@ -900,10 +919,11 @@ fn insert_link_into_header( id: Option, classes: Option, id_counter: &mut HashMap, - path_id: Option<&str>, + print_page_id: Option<&str>, ) -> String { - let id = if let Some(path_id) = path_id { - id.unwrap_or_else(|| utils::unique_id_from_content_with_path(content, id_counter, path_id)) + let id = if let Some(print_page_id) = print_page_id { + let with_prefix = format!("{} {}", print_page_id, content); + id.unwrap_or_else(|| utils::unique_id_from_content(&with_prefix, id_counter)) } else { id.unwrap_or_else(|| utils::unique_id_from_content(content, id_counter)) }; diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 3fb7d6c8ba..1f8c1f8f2d 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -83,14 +83,6 @@ pub fn unique_id_from_content(content: &str, id_counter: &mut HashMap, - path_id: &str, -) -> String { - unique_id_from_content(&format!("{} {}", path_id, content), id_counter) -} - /// Improve the path to try remove and solve .. token, /// This assumes that `a/b/../c` is `a/c`. /// @@ -120,7 +112,7 @@ fn normalize_path>(path: P) -> String { } /// Converts a relative URL path to a reference ID for the print page. -fn normalize_path_id(mut path: String) -> String { +fn normalize_print_page_id(mut path: String) -> String { path = path .replace("/", "-") .replace(".html#", "-") @@ -136,13 +128,8 @@ fn normalize_path_id(mut path: String) -> String { /// /// This adjusts links, such as turning `.md` extensions to `.html`. /// -/// `path` is the path to the page being rendered relative to the root of the -/// book. This is used for the `print.html` page so that links on the print -/// page go to the anchors that has a path id prefix. Normal page rendering -/// sets `path` to None. -/// -/// `redirects` is also only for the print page. It's for adjusting links to -/// a redirected location to go to the correct spot on the `print.html` page. +/// See [`render_markdown_with_path_and_redirects`] for a description of +/// `path` and `redirects`. fn adjust_links<'a>( event: Event<'a>, path: Option<&Path>, @@ -231,7 +218,7 @@ fn adjust_links<'a>( let mut fixed_anchor_for_print = String::new(); fixed_anchor_for_print.push_str("#"); - fixed_anchor_for_print.push_str(&normalize_path_id(normalized_path)); + fixed_anchor_for_print.push_str(&normalize_print_page_id(normalized_path)); CowStr::from(fixed_anchor_for_print) } @@ -266,7 +253,7 @@ fn adjust_links<'a>( } format!( "#{}{}", - normalize_path_id(normalize_path(base)), + normalize_print_page_id(normalize_path(base)), dest.replace("#", "-") ) .into() @@ -378,7 +365,16 @@ pub fn new_cmark_parser(text: &str, curly_quotes: bool) -> Parser<'_, '_> { Parser::new_ext(text, opts) } -pub fn render_markdown_with_path_and_redirects( +/// Renders markdown to HTML. +/// +/// `path` is the path to the page being rendered relative to the root of the +/// book. This is used for the `print.html` page so that links on the print +/// page go to the anchors that has a path id prefix. Normal page rendering +/// sets `path` to None. +/// +/// `redirects` is also only for the print page. It's for adjusting links to +/// a redirected location to go to the correct spot on the `print.html` page. +pub(crate) fn render_markdown_with_path_and_redirects( text: &str, curly_quotes: bool, path: Option<&Path>,