Fix multiple footnotes and improve testing

This commit is contained in:
Guillaume Gomez 2017-03-30 17:29:54 -06:00
parent 08a741eabf
commit 36b15f0409
2 changed files with 41 additions and 24 deletions

View File

@ -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));
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{}\">{}&nbsp;<a href=\"#supref{0}\" \
rev=\"footnote\">↩</a></p></li>",
cur_id,
if content.ends_with("</p>") {
&content[..content.len() - 4]
} else {
&content
}));
}
Event::FootnoteReference(_) => {
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())

View File

@ -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&nbsp;<a href="#supref1" rev="footnote">↩</a></p></li><li id="ref2"><p>Another Thing&nbsp;<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
///
///
/// ![Rust](https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png)
#[deprecated(note = "Struct<T>")]
pub fn f() {}