diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 20cf48915c3..7a922f570da 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -414,11 +414,13 @@ impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> { } } +type SpannedEvent<'a> = (Event<'a>, Range); + /// Make headings links with anchor IDs and build up TOC. struct HeadingLinks<'a, 'b, 'ids, I> { inner: I, toc: Option<&'b mut TocBuilder>, - buf: VecDeque>, + buf: VecDeque>, id_map: &'ids mut IdMap, } @@ -428,8 +430,10 @@ impl<'a, 'b, 'ids, I> HeadingLinks<'a, 'b, 'ids, I> { } } -impl<'a, 'b, 'ids, I: Iterator>> Iterator for HeadingLinks<'a, 'b, 'ids, I> { - type Item = Event<'a>; +impl<'a, 'b, 'ids, I: Iterator>> Iterator + for HeadingLinks<'a, 'b, 'ids, I> +{ + type Item = SpannedEvent<'a>; fn next(&mut self) -> Option { if let Some(e) = self.buf.pop_front() { @@ -437,31 +441,29 @@ impl<'a, 'b, 'ids, I: Iterator>> Iterator for HeadingLinks<'a, } let event = self.inner.next(); - if let Some(Event::Start(Tag::Heading(level))) = event { + if let Some((Event::Start(Tag::Heading(level)), _)) = event { let mut id = String::new(); for event in &mut self.inner { - match &event { + match &event.0 { Event::End(Tag::Heading(..)) => break, + Event::Start(Tag::Link(_, _, _)) | Event::End(Tag::Link(..)) => {} Event::Text(text) | Event::Code(text) => { id.extend(text.chars().filter_map(slugify)); + self.buf.push_back(event); } - _ => {} - } - match event { - Event::Start(Tag::Link(_, _, _)) | Event::End(Tag::Link(..)) => {} - event => self.buf.push_back(event), + _ => self.buf.push_back(event), } } let id = self.id_map.derive(id); if let Some(ref mut builder) = self.toc { let mut html_header = String::new(); - html::push_html(&mut html_header, self.buf.iter().cloned()); + html::push_html(&mut html_header, self.buf.iter().map(|(ev, _)| ev.clone())); let sec = builder.push(level as u32, html_header, id.clone()); - self.buf.push_front(Event::Html(format!("{} ", sec).into())); + self.buf.push_front((Event::Html(format!("{} ", sec).into()), 0..0)); } - self.buf.push_back(Event::Html(format!("", level).into())); + self.buf.push_back((Event::Html(format!("", level).into()), 0..0)); let start_tags = format!( "\ @@ -469,7 +471,7 @@ impl<'a, 'b, 'ids, I: Iterator>> Iterator for HeadingLinks<'a, id = id, level = level ); - return Some(Event::Html(start_tags.into())); + return Some((Event::Html(start_tags.into()), 0..0)); } event } @@ -560,23 +562,23 @@ impl<'a, I> Footnotes<'a, I> { } } -impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> { - type Item = Event<'a>; +impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> { + type Item = SpannedEvent<'a>; fn next(&mut self) -> Option { loop { match self.inner.next() { - Some(Event::FootnoteReference(ref reference)) => { + Some((Event::FootnoteReference(ref reference), range)) => { let entry = self.get_entry(&reference); let reference = format!( "{0}", (*entry).1 ); - return Some(Event::Html(reference.into())); + return Some((Event::Html(reference.into()), range)); } - Some(Event::Start(Tag::FootnoteDefinition(def))) => { + Some((Event::Start(Tag::FootnoteDefinition(def)), _)) => { let mut content = Vec::new(); - for event in &mut self.inner { + for (event, _) in &mut self.inner { if let Event::End(Tag::FootnoteDefinition(..)) = event { break; } @@ -607,7 +609,7 @@ impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> { ret.push_str(""); } ret.push_str(""); - return Some(Event::Html(ret.into())); + return Some((Event::Html(ret.into()), 0..0)); } else { return None; } @@ -917,13 +919,14 @@ impl Markdown<'_> { }; let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut replacer)); + let p = p.into_offset_iter(); let mut s = String::with_capacity(md.len() * 3 / 2); let p = HeadingLinks::new(p, None, &mut ids); - let p = LinkReplacer::new(p, links); - let p = CodeBlocks::new(p, codes, edition, playground); let p = Footnotes::new(p); + let p = LinkReplacer::new(p.map(|(ev, _)| ev), links); + let p = CodeBlocks::new(p, codes, edition, playground); html::push_html(&mut s, p); s @@ -934,7 +937,7 @@ impl MarkdownWithToc<'_> { crate fn into_string(self) -> String { let MarkdownWithToc(md, mut ids, codes, edition, playground) = self; - let p = Parser::new_ext(md, opts()); + let p = Parser::new_ext(md, opts()).into_offset_iter(); let mut s = String::with_capacity(md.len() * 3 / 2); @@ -942,8 +945,8 @@ impl MarkdownWithToc<'_> { { let p = HeadingLinks::new(p, Some(&mut toc), &mut ids); - let p = CodeBlocks::new(p, codes, edition, playground); let p = Footnotes::new(p); + let p = CodeBlocks::new(p.map(|(ev, _)| ev), codes, edition, playground); html::push_html(&mut s, p); } @@ -959,19 +962,19 @@ impl MarkdownHtml<'_> { if md.is_empty() { return String::new(); } - let p = Parser::new_ext(md, opts()); + let p = Parser::new_ext(md, opts()).into_offset_iter(); // Treat inline HTML as plain text. - let p = p.map(|event| match event { - Event::Html(text) => Event::Text(text), + let p = p.map(|event| match event.0 { + Event::Html(text) => (Event::Text(text), event.1), _ => event, }); let mut s = String::with_capacity(md.len() * 3 / 2); let p = HeadingLinks::new(p, None, &mut ids); - let p = CodeBlocks::new(p, codes, edition, playground); let p = Footnotes::new(p); + let p = CodeBlocks::new(p.map(|(ev, _)| ev), codes, edition, playground); html::push_html(&mut s, p); s @@ -1153,7 +1156,8 @@ crate fn markdown_links(md: &str) -> Vec<(String, Option>)> { shortcut_links.push((link.reference.to_owned(), locate(link.reference))); None }; - let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut push)); + let p = + Parser::new_with_broken_link_callback(md, opts(), Some(&mut push)).into_offset_iter(); // There's no need to thread an IdMap through to here because // the IDs generated aren't going to be emitted anywhere. @@ -1161,7 +1165,7 @@ crate fn markdown_links(md: &str) -> Vec<(String, Option>)> { let iter = Footnotes::new(HeadingLinks::new(p, None, &mut ids)); for ev in iter { - if let Event::Start(Tag::Link(_, dest, _)) = ev { + if let Event::Start(Tag::Link(_, dest, _)) = ev.0 { debug!("found link: {}", dest); links.push(match dest { CowStr::Borrowed(s) => (s.to_owned(), locate(s)),