diff options
| -rw-r--r-- | src/librustdoc/html/markdown.rs | 54 | ||||
| -rw-r--r-- | src/test/rustdoc/check-rule-image-footnote.rs | 13 |
2 files changed, 42 insertions, 25 deletions
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 6c82dab94bc..e8acabde408 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -27,6 +27,7 @@ use std::ascii::AsciiExt; use std::cell::RefCell; +use std::collections::HashMap; use std::default::Default; use std::fmt::{self, Write}; use std::str; @@ -135,8 +136,8 @@ macro_rules! event_loop_break { struct ParserWrapper<'a> { parser: Parser<'a>, - footnotes: Vec<String>, - current_footnote_id: u16, + // The key is the footnote reference. The value is the footnote definition and the id. + footnotes: HashMap<String, (String, u16)>, } impl<'a> ParserWrapper<'a> { @@ -144,18 +145,18 @@ impl<'a> ParserWrapper<'a> { ParserWrapper { parser: Parser::new_ext(s, pulldown_cmark::OPTION_ENABLE_TABLES | pulldown_cmark::OPTION_ENABLE_FOOTNOTES), - footnotes: Vec::new(), - current_footnote_id: 1, + footnotes: HashMap::new(), } } + pub fn next(&mut self) -> Option<Event<'a>> { self.parser.next() } - pub fn get_next_footnote_id(&mut self) -> u16 { - let tmp = self.current_footnote_id; - self.current_footnote_id += 1; - tmp + pub fn get_entry(&mut self, key: &str) -> &mut (String, u16) { + let new_id = self.footnotes.keys().count() + 1; + let key = key.to_owned(); + self.footnotes.entry(key).or_insert((String::new(), new_id as u16)) } } @@ -450,10 +451,11 @@ pub fn render(w: &mut fmt::Formatter, fn footnote(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option<TocBuilder>, shorter: MarkdownOutputStyle, - mut definition: String, id: &mut Option<&mut String>) { - event_loop_break!(parser, toc_builder, shorter, definition, true, id, + id: &mut Option<&mut String>) { + let mut content = String::new(); + event_loop_break!(parser, toc_builder, shorter, content, true, id, Event::End(Tag::FootnoteDefinition(_))); - buffer.push_str(&definition); + buffer.push_str(&content); } fn rule(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option<TocBuilder>, @@ -507,17 +509,24 @@ pub fn render(w: &mut fmt::Formatter, } Event::Start(Tag::FootnoteDefinition(ref def)) => { let mut content = String::new(); - footnote(parser, &mut content, toc_builder, shorter, def.as_ref().to_owned(), - id); - let cur_len = parser.footnotes.len() + 1; - parser.footnotes.push(format!("<li id=\"ref{}\">{}<a href=\"#supref{0}\" \ - rev=\"footnote\">↩</a></li>", - cur_len, content)); - } - Event::FootnoteReference(_) => { + let def = def.as_ref(); + footnote(parser, &mut content, toc_builder, shorter, id); + let entry = parser.get_entry(def); + let cur_id = (*entry).1; + (*entry).0.push_str(&format!("<li id=\"ref{}\">{} <a href=\"#supref{0}\" \ + rev=\"footnote\">↩</a></p></li>", + cur_id, + if content.ends_with("</p>") { + &content[..content.len() - 4] + } else { + &content + })); + } + Event::FootnoteReference(ref reference) => { + let entry = parser.get_entry(reference.as_ref()); buffer.push_str(&format!("<sup id=\"supref{0}\"><a href=\"#ref{0}\">{0}</a>\ </sup>", - parser.get_next_footnote_id())); + (*entry).1)); } Event::Html(h) | Event::InlineHtml(h) => { buffer.push_str(&*h); @@ -545,7 +554,10 @@ pub fn render(w: &mut fmt::Formatter, } if !parser.footnotes.is_empty() { buffer.push_str(&format!("<div class=\"footnotes\"><hr><ol>{}</ol></div>", - parser.footnotes.join(""))); + parser.footnotes.values() + .map(|&(ref s, _)| s.as_str()) + .collect::<Vec<_>>() + .join(""))); } let mut ret = toc_builder.map_or(Ok(()), |builder| { write!(w, "<nav id=\"TOC\">{}</nav>", builder.into_toc()) diff --git a/src/test/rustdoc/check-rule-image-footnote.rs b/src/test/rustdoc/check-rule-image-footnote.rs index 629e1a64e6f..4d3bea20ba8 100644 --- a/src/test/rustdoc/check-rule-image-footnote.rs +++ b/src/test/rustdoc/check-rule-image-footnote.rs @@ -10,11 +10,10 @@ #![crate_name = "foo"] +// ignore-tidy-linelength + // @has foo/fn.f.html -// @has - '<p>hard break: after hard break</p><hr>' -// @has - '<img src="https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png" alt="Rust">' -// @has - '<li id="ref1">' -// @has - '<sup id="supref1"><a href="#ref1">1</a></sup>' +// @has - '<p>markdown test</p><p>this is a <a href="https://example.com" title="this is a title">link</a>.</p><p>hard break: after hard break</p><hr><p>a footnote<sup id="supref1"><a href="#ref1">1</a></sup>.</p><p>another footnote<sup id="supref2"><a href="#ref2">2</a></sup>.</p><p><img src="https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png" alt="Rust"></p><div class="footnotes"><hr><ol><li id="ref1"><p>Thing <a href="#supref1" rev="footnote">↩</a></p></li><li id="ref2"><p>Another Thing <a href="#supref2" rev="footnote">↩</a></p></li></ol></div>' /// markdown test /// /// this is a [link]. @@ -28,8 +27,14 @@ /// /// a footnote[^footnote]. /// +/// another footnote[^footnotebis]. +/// /// [^footnote]: Thing /// +/// +/// [^footnotebis]: Another Thing +/// +/// ///  #[deprecated(note = "Struct<T>")] pub fn f() {} |
