mirror of
https://github.com/rust-lang/mdBook
synced 2024-11-14 00:37:15 +00:00
Don't try to render summary links as markdown.
This commit is contained in:
parent
ba324cddb6
commit
ceff050bb4
5 changed files with 75 additions and 33 deletions
|
@ -7,6 +7,7 @@ use std::path::{Path, PathBuf};
|
|||
use super::summary::{parse_summary, Link, SectionNumber, Summary, SummaryItem};
|
||||
use crate::config::BuildConfig;
|
||||
use crate::errors::*;
|
||||
use crate::utils::bracket_escape;
|
||||
|
||||
/// Load a book into memory from its `src/` directory.
|
||||
pub fn load_book<P: AsRef<Path>>(src_dir: P, cfg: &BuildConfig) -> Result<Book> {
|
||||
|
@ -53,7 +54,7 @@ fn create_missing(src_dir: &Path, summary: &Summary) -> Result<()> {
|
|||
let mut f = File::create(&filename).with_context(|| {
|
||||
format!("Unable to create missing file: {}", filename.display())
|
||||
})?;
|
||||
writeln!(f, "# {}", link.name)?;
|
||||
writeln!(f, "# {}", bracket_escape(&link.name))?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::utils;
|
||||
use crate::utils::bracket_escape;
|
||||
|
||||
use handlebars::{Context, Handlebars, Helper, HelperDef, Output, RenderContext, RenderError};
|
||||
use pulldown_cmark::{html, Event, Parser};
|
||||
|
||||
// Handlebars helper to construct TOC
|
||||
#[derive(Clone, Copy)]
|
||||
|
@ -103,7 +102,7 @@ impl HelperDef for RenderToc {
|
|||
// Part title
|
||||
if let Some(title) = item.get("part") {
|
||||
out.write("<li class=\"part-title\">")?;
|
||||
write_escaped(out, title)?;
|
||||
out.write(&bracket_escape(title))?;
|
||||
out.write("</li>")?;
|
||||
continue;
|
||||
}
|
||||
|
@ -148,20 +147,7 @@ impl HelperDef for RenderToc {
|
|||
}
|
||||
|
||||
if let Some(name) = item.get("name") {
|
||||
// Render only inline code blocks
|
||||
|
||||
// filter all events that are not inline code blocks
|
||||
let parser = Parser::new(name).filter(|event| match *event {
|
||||
Event::Code(_) | Event::Html(_) | Event::Text(_) => true,
|
||||
_ => false,
|
||||
});
|
||||
|
||||
// render markdown to html
|
||||
let mut markdown_parsed_name = String::with_capacity(name.len() * 3 / 2);
|
||||
html::push_html(&mut markdown_parsed_name, parser);
|
||||
|
||||
// write to the handlebars template
|
||||
write_escaped(out, &markdown_parsed_name)?;
|
||||
out.write(&bracket_escape(name))?
|
||||
}
|
||||
|
||||
if path_exists {
|
||||
|
@ -205,18 +191,3 @@ fn write_li_open_tag(
|
|||
li.push_str("\">");
|
||||
out.write(&li)
|
||||
}
|
||||
|
||||
fn write_escaped(out: &mut dyn Output, mut title: &str) -> io::Result<()> {
|
||||
let needs_escape: &[char] = &['<', '>'];
|
||||
while let Some(next) = title.find(needs_escape) {
|
||||
out.write(&title[..next])?;
|
||||
match title.as_bytes()[next] {
|
||||
b'<' => out.write("<")?,
|
||||
b'>' => out.write(">")?,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
title = &title[next + 1..];
|
||||
}
|
||||
out.write(title)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -233,8 +233,26 @@ pub fn log_backtrace(e: &Error) {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn bracket_escape(mut s: &str) -> String {
|
||||
let mut escaped = String::with_capacity(s.len());
|
||||
let needs_escape: &[char] = &['<', '>'];
|
||||
while let Some(next) = s.find(needs_escape) {
|
||||
escaped.push_str(&s[..next]);
|
||||
match s.as_bytes()[next] {
|
||||
b'<' => escaped.push_str("<"),
|
||||
b'>' => escaped.push_str(">"),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
s = &s[next + 1..];
|
||||
}
|
||||
escaped.push_str(s);
|
||||
escaped
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::bracket_escape;
|
||||
|
||||
mod render_markdown {
|
||||
use super::super::render_markdown;
|
||||
|
||||
|
@ -431,4 +449,14 @@ more text with spaces
|
|||
assert_eq!(unique_id_from_content("## Über", &mut id_counter), "Über-2");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn escaped_brackets() {
|
||||
assert_eq!(bracket_escape(""), "");
|
||||
assert_eq!(bracket_escape("<"), "<");
|
||||
assert_eq!(bracket_escape(">"), ">");
|
||||
assert_eq!(bracket_escape("<>"), "<>");
|
||||
assert_eq!(bracket_escape("<test>"), "<test>");
|
||||
assert_eq!(bracket_escape("a<test>b"), "a<test>b");
|
||||
}
|
||||
}
|
||||
|
|
6
tests/dummy_book/summary-formatting/SUMMARY.md
Normal file
6
tests/dummy_book/summary-formatting/SUMMARY.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Summary formatting tests
|
||||
|
||||
- [*Italic* `code` \*escape\* \`escape2\`](formatted-summary.md)
|
||||
- [Soft
|
||||
line break](soft.md)
|
||||
- [\<escaped tag\>](escaped-tag.md)
|
|
@ -621,6 +621,42 @@ fn remove_absolute_components(path: &Path) -> impl Iterator<Item = Component> +
|
|||
})
|
||||
}
|
||||
|
||||
/// Checks formatting of summary names with inline elements.
|
||||
#[test]
|
||||
fn summary_with_markdown_formatting() {
|
||||
let temp = DummyBook::new().build().unwrap();
|
||||
let mut cfg = Config::default();
|
||||
cfg.set("book.src", "summary-formatting").unwrap();
|
||||
let md = MDBook::load_with_config(temp.path(), cfg).unwrap();
|
||||
md.build().unwrap();
|
||||
|
||||
let rendered_path = temp.path().join("book/formatted-summary.html");
|
||||
assert_contains_strings(
|
||||
rendered_path,
|
||||
&[
|
||||
r#"<a href="formatted-summary.html" class="active"><strong aria-hidden="true">1.</strong> Italic code *escape* `escape2`</a>"#,
|
||||
r#"<a href="soft.html"><strong aria-hidden="true">2.</strong> Soft line break</a>"#,
|
||||
r#"<a href="escaped-tag.html"><strong aria-hidden="true">3.</strong> <escaped tag></a>"#,
|
||||
],
|
||||
);
|
||||
|
||||
let generated_md = temp.path().join("summary-formatting/formatted-summary.md");
|
||||
assert_eq!(
|
||||
fs::read_to_string(generated_md).unwrap(),
|
||||
"# Italic code *escape* `escape2`\n"
|
||||
);
|
||||
let generated_md = temp.path().join("summary-formatting/soft.md");
|
||||
assert_eq!(
|
||||
fs::read_to_string(generated_md).unwrap(),
|
||||
"# Soft line break\n"
|
||||
);
|
||||
let generated_md = temp.path().join("summary-formatting/escaped-tag.md");
|
||||
assert_eq!(
|
||||
fs::read_to_string(generated_md).unwrap(),
|
||||
"# <escaped tag>\n"
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "search")]
|
||||
mod search {
|
||||
use crate::dummy_book::DummyBook;
|
||||
|
|
Loading…
Reference in a new issue