Revert "Support anchors in SUMMARY (#1173)"

This reverts commit 2baed040c2.
This commit is contained in:
Dylan DPC 2020-03-24 23:22:53 +01:00 committed by GitHub
parent 21a16c9b75
commit de4a6fe94a
5 changed files with 21 additions and 84 deletions

View File

@ -153,8 +153,6 @@ pub struct Chapter {
pub sub_items: Vec<BookItem>, pub sub_items: Vec<BookItem>,
/// The chapter's location, relative to the `SUMMARY.md` file. /// The chapter's location, relative to the `SUMMARY.md` file.
pub path: PathBuf, pub path: PathBuf,
/// An optional anchor in the original link.
pub anchor: Option<String>,
/// An ordered list of the names of each chapter above this one, in the hierarchy. /// An ordered list of the names of each chapter above this one, in the hierarchy.
pub parent_names: Vec<String>, pub parent_names: Vec<String>,
} }
@ -245,7 +243,6 @@ fn load_chapter<P: AsRef<Path>>(
let mut sub_item_parents = parent_names.clone(); let mut sub_item_parents = parent_names.clone();
let mut ch = Chapter::new(&link.name, content, stripped, parent_names); let mut ch = Chapter::new(&link.name, content, stripped, parent_names);
ch.number = link.number.clone(); ch.number = link.number.clone();
ch.anchor = link.anchor.clone();
sub_item_parents.push(link.name.clone()); sub_item_parents.push(link.name.clone());
let sub_items = link let sub_items = link
@ -323,7 +320,7 @@ And here is some \
.write_all(DUMMY_SRC.as_bytes()) .write_all(DUMMY_SRC.as_bytes())
.unwrap(); .unwrap();
let link = Link::new("Chapter 1", chapter_path, None); let link = Link::new("Chapter 1", chapter_path);
(link, temp) (link, temp)
} }
@ -339,7 +336,7 @@ And here is some \
.write_all(b"Hello World!") .write_all(b"Hello World!")
.unwrap(); .unwrap();
let mut second = Link::new("Nested Chapter 1", &second_path, None); let mut second = Link::new("Nested Chapter 1", &second_path);
second.number = Some(SectionNumber(vec![1, 2])); second.number = Some(SectionNumber(vec![1, 2]));
root.nested_items.push(second.clone().into()); root.nested_items.push(second.clone().into());
@ -365,7 +362,7 @@ And here is some \
#[test] #[test]
fn cant_load_a_nonexistent_chapter() { fn cant_load_a_nonexistent_chapter() {
let link = Link::new("Chapter 1", "/foo/bar/baz.md", None); let link = Link::new("Chapter 1", "/foo/bar/baz.md");
let got = load_chapter(&link, "", Vec::new()); let got = load_chapter(&link, "", Vec::new());
assert!(got.is_err()); assert!(got.is_err());
@ -382,7 +379,6 @@ And here is some \
path: PathBuf::from("second.md"), path: PathBuf::from("second.md"),
parent_names: vec![String::from("Chapter 1")], parent_names: vec![String::from("Chapter 1")],
sub_items: Vec::new(), sub_items: Vec::new(),
anchor: None,
}; };
let should_be = BookItem::Chapter(Chapter { let should_be = BookItem::Chapter(Chapter {
name: String::from("Chapter 1"), name: String::from("Chapter 1"),
@ -395,7 +391,6 @@ And here is some \
BookItem::Separator, BookItem::Separator,
BookItem::Chapter(nested.clone()), BookItem::Chapter(nested.clone()),
], ],
anchor: None,
}); });
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();
@ -470,7 +465,6 @@ And here is some \
Vec::new(), Vec::new(),
)), )),
], ],
anchor: None,
}), }),
BookItem::Separator, BookItem::Separator,
], ],
@ -523,7 +517,6 @@ And here is some \
Vec::new(), Vec::new(),
)), )),
], ],
anchor: None,
}), }),
BookItem::Separator, BookItem::Separator,
], ],

View File

@ -72,8 +72,6 @@ pub struct Link {
/// The location of the chapter's source file, taking the book's `src` /// The location of the chapter's source file, taking the book's `src`
/// directory as the root. /// directory as the root.
pub location: PathBuf, pub location: PathBuf,
/// An optional anchor in the original link.
pub anchor: Option<String>,
/// The section number, if this chapter is in the numbered section. /// The section number, if this chapter is in the numbered section.
pub number: Option<SectionNumber>, pub number: Option<SectionNumber>,
/// Any nested items this chapter may contain. /// Any nested items this chapter may contain.
@ -82,15 +80,10 @@ pub struct Link {
impl Link { impl Link {
/// Create a new link with no nested items. /// Create a new link with no nested items.
pub fn new<S: Into<String>, P: AsRef<Path>>( pub fn new<S: Into<String>, P: AsRef<Path>>(name: S, location: P) -> Link {
name: S,
location: P,
anchor: Option<String>,
) -> Link {
Link { Link {
name: name.into(), name: name.into(),
location: location.as_ref().to_path_buf(), location: location.as_ref().to_path_buf(),
anchor,
number: None, number: None,
nested_items: Vec::new(), nested_items: Vec::new(),
} }
@ -102,7 +95,6 @@ impl Default for Link {
Link { Link {
name: String::new(), name: String::new(),
location: PathBuf::new(), location: PathBuf::new(),
anchor: None,
number: None, number: None,
nested_items: Vec::new(), nested_items: Vec::new(),
} }
@ -284,18 +276,15 @@ impl<'a> SummaryParser<'a> {
let link_content = collect_events!(self.stream, end Tag::Link(..)); let link_content = collect_events!(self.stream, end Tag::Link(..));
let name = stringify_events(link_content); let name = stringify_events(link_content);
let mut split = href.splitn(2, '#'); if href.is_empty() {
let (href, anchor) = (split.next(), split.next()); Err(self.parse_error("You can't have an empty link."))
} else {
match href { Ok(Link {
Some(href) if !href.is_empty() => Ok(Link {
name, name,
location: PathBuf::from(href.to_string()), location: PathBuf::from(href.to_string()),
anchor: anchor.map(String::from),
number: None, number: None,
nested_items: Vec::new(), nested_items: Vec::new(),
}), })
_ => Err(self.parse_error("You can't have an empty link.")),
} }
} }
@ -687,12 +676,10 @@ mod tests {
SummaryItem::Link(Link { SummaryItem::Link(Link {
name: String::from("First"), name: String::from("First"),
location: PathBuf::from("./first.md"), location: PathBuf::from("./first.md"),
anchor: None,
number: Some(SectionNumber(vec![1])), number: Some(SectionNumber(vec![1])),
nested_items: vec![SummaryItem::Link(Link { nested_items: vec![SummaryItem::Link(Link {
name: String::from("Nested"), name: String::from("Nested"),
location: PathBuf::from("./nested.md"), location: PathBuf::from("./nested.md"),
anchor: None,
number: Some(SectionNumber(vec![1, 1])), number: Some(SectionNumber(vec![1, 1])),
nested_items: Vec::new(), nested_items: Vec::new(),
})], })],
@ -700,7 +687,6 @@ mod tests {
SummaryItem::Link(Link { SummaryItem::Link(Link {
name: String::from("Second"), name: String::from("Second"),
location: PathBuf::from("./second.md"), location: PathBuf::from("./second.md"),
anchor: None,
number: Some(SectionNumber(vec![2])), number: Some(SectionNumber(vec![2])),
nested_items: Vec::new(), nested_items: Vec::new(),
}), }),
@ -722,14 +708,12 @@ mod tests {
SummaryItem::Link(Link { SummaryItem::Link(Link {
name: String::from("First"), name: String::from("First"),
location: PathBuf::from("./first.md"), location: PathBuf::from("./first.md"),
anchor: None,
number: Some(SectionNumber(vec![1])), number: Some(SectionNumber(vec![1])),
nested_items: Vec::new(), nested_items: Vec::new(),
}), }),
SummaryItem::Link(Link { SummaryItem::Link(Link {
name: String::from("Second"), name: String::from("Second"),
location: PathBuf::from("./second.md"), location: PathBuf::from("./second.md"),
anchor: None,
number: Some(SectionNumber(vec![2])), number: Some(SectionNumber(vec![2])),
nested_items: Vec::new(), nested_items: Vec::new(),
}), }),
@ -743,26 +727,6 @@ mod tests {
assert_eq!(got, should_be); assert_eq!(got, should_be);
} }
#[test]
fn parse_anchors() {
let src = "- [Link to anchor](./page.md#Foo)";
let should_be = vec![SummaryItem::Link(Link {
name: String::from("Link to anchor"),
location: PathBuf::from("./page.md"),
anchor: Some("Foo".to_string()),
number: Some(SectionNumber(vec![1])),
nested_items: Vec::new(),
})];
let mut parser = SummaryParser::new(src);
let _ = parser.stream.next();
let got = parser.parse_numbered().unwrap();
assert_eq!(got, should_be);
}
/// This test ensures the book will continue to pass because it breaks the /// This test ensures the book will continue to pass because it breaks the
/// `SUMMARY.md` up using level 2 headers ([example]). /// `SUMMARY.md` up using level 2 headers ([example]).
/// ///
@ -774,14 +738,12 @@ mod tests {
SummaryItem::Link(Link { SummaryItem::Link(Link {
name: String::from("First"), name: String::from("First"),
location: PathBuf::from("./first.md"), location: PathBuf::from("./first.md"),
anchor: None,
number: Some(SectionNumber(vec![1])), number: Some(SectionNumber(vec![1])),
nested_items: Vec::new(), nested_items: Vec::new(),
}), }),
SummaryItem::Link(Link { SummaryItem::Link(Link {
name: String::from("Second"), name: String::from("Second"),
location: PathBuf::from("./second.md"), location: PathBuf::from("./second.md"),
anchor: None,
number: Some(SectionNumber(vec![2])), number: Some(SectionNumber(vec![2])),
nested_items: Vec::new(), nested_items: Vec::new(),
}), }),
@ -797,13 +759,12 @@ mod tests {
#[test] #[test]
fn an_empty_link_location_is_an_error() { fn an_empty_link_location_is_an_error() {
for src in &["- [Empty]()\n", "- [Empty](#Foo)\n"] { let src = "- [Empty]()\n";
let mut parser = SummaryParser::new(src); let mut parser = SummaryParser::new(src);
parser.stream.next(); parser.stream.next();
let got = parser.parse_numbered(); let got = parser.parse_numbered();
assert!(got.is_err()); assert!(got.is_err());
}
} }
/// Regression test for https://github.com/rust-lang/mdBook/issues/779 /// Regression test for https://github.com/rust-lang/mdBook/issues/779
@ -818,7 +779,6 @@ mod tests {
location: PathBuf::from("./first.md"), location: PathBuf::from("./first.md"),
number: Some(SectionNumber(vec![1])), number: Some(SectionNumber(vec![1])),
nested_items: Vec::new(), nested_items: Vec::new(),
anchor: None,
}), }),
SummaryItem::Separator, SummaryItem::Separator,
SummaryItem::Link(Link { SummaryItem::Link(Link {
@ -826,13 +786,11 @@ mod tests {
location: PathBuf::from("./second.md"), location: PathBuf::from("./second.md"),
number: Some(SectionNumber(vec![2])), number: Some(SectionNumber(vec![2])),
nested_items: Vec::new(), nested_items: Vec::new(),
anchor: None,
}), }),
SummaryItem::Separator, SummaryItem::Separator,
SummaryItem::Link(Link { SummaryItem::Link(Link {
name: String::from("Third"), name: String::from("Third"),
location: PathBuf::from("./third.md"), location: PathBuf::from("./third.md"),
anchor: None,
number: Some(SectionNumber(vec![3])), number: Some(SectionNumber(vec![3])),
nested_items: Vec::new(), nested_items: Vec::new(),
}), }),

View File

@ -31,7 +31,8 @@ impl HtmlHandlebars {
) -> Result<()> { ) -> Result<()> {
// FIXME: This should be made DRY-er and rely less on mutable state // FIXME: This should be made DRY-er and rely less on mutable state
if let BookItem::Chapter(ref ch) = *item { if let BookItem::Chapter(ref ch) = *item {
let content = utils::render_markdown(&ch.content, ctx.html_config.curly_quotes); let content = ch.content.clone();
let content = utils::render_markdown(&content, ctx.html_config.curly_quotes);
let fixed_content = utils::render_markdown_with_path( let fixed_content = utils::render_markdown_with_path(
&ch.content, &ch.content,
@ -80,10 +81,6 @@ impl HtmlHandlebars {
.insert("section".to_owned(), json!(section.to_string())); .insert("section".to_owned(), json!(section.to_string()));
} }
if let Some(anchor) = &ch.anchor {
ctx.data.insert("anchor".to_owned(), json!(anchor));
}
// Render the handlebars template with the data // Render the handlebars template with the data
debug!("Render template"); debug!("Render template");
let rendered = ctx.handlebars.render("index", &ctx.data)?; let rendered = ctx.handlebars.render("index", &ctx.data)?;
@ -523,10 +520,6 @@ fn make_data(
.to_str() .to_str()
.chain_err(|| "Could not convert path to str")?; .chain_err(|| "Could not convert path to str")?;
chapter.insert("path".to_owned(), json!(path)); chapter.insert("path".to_owned(), json!(path));
if let Some(anchor) = &ch.anchor {
chapter.insert("anchor".to_owned(), json!(anchor));
}
} }
BookItem::Separator => { BookItem::Separator => {
chapter.insert("spacer".to_owned(), json!("_spacer_")); chapter.insert("spacer".to_owned(), json!("_spacer_"));

View File

@ -72,8 +72,8 @@ fn find_chapter(
Target::Next => match chapters Target::Next => match chapters
.iter() .iter()
.filter(|chapter| { .filter(|chapter| {
// Skip things like "spacer" or sub-links // Skip things like "spacer"
chapter.contains_key("path") && !chapter.contains_key("anchor") chapter.contains_key("path")
}) })
.skip(1) .skip(1)
.next() .next()
@ -90,7 +90,7 @@ fn find_chapter(
for item in chapters { for item in chapters {
match item.get("path") { match item.get("path") {
Some(path) if !path.is_empty() && item.get("anchor").is_none() => { Some(path) if !path.is_empty() => {
if let Some(previous) = previous { if let Some(previous) = previous {
if let Some(item) = target.find(&base_path, &path, &item, &previous)? { if let Some(item) = target.find(&base_path, &path, &item, &previous)? {
return Ok(Some(item)); return Ok(Some(item));

View File

@ -111,7 +111,7 @@ impl HelperDef for RenderToc {
if !path.is_empty() { if !path.is_empty() {
out.write("<a href=\"")?; out.write("<a href=\"")?;
let tmp = Path::new(path) let tmp = Path::new(item.get("path").expect("Error: path should be Some(_)"))
.with_extension("html") .with_extension("html")
.to_str() .to_str()
.unwrap() .unwrap()
@ -121,16 +121,9 @@ impl HelperDef for RenderToc {
// Add link // Add link
out.write(&utils::fs::path_to_root(&current_path))?; out.write(&utils::fs::path_to_root(&current_path))?;
out.write(&tmp)?; out.write(&tmp)?;
let anchor = item.get("anchor");
if let Some(anchor) = anchor {
out.write("#")?;
out.write(anchor)?;
}
out.write("\"")?; out.write("\"")?;
if anchor.is_none() && path == &current_path { if path == &current_path {
out.write(" class=\"active\"")?; out.write(" class=\"active\"")?;
} }