From 08a741eabf3c223650bb29c5df30c8fd414cd86a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 29 Mar 2017 19:48:06 -0600 Subject: [PATCH 1/5] Add support for image, rules and footnotes --- src/librustdoc/html/markdown.rs | 139 ++++++++++++++---- src/test/rustdoc/check-rule-image-footnote.rs | 35 +++++ 2 files changed, 146 insertions(+), 28 deletions(-) create mode 100644 src/test/rustdoc/check-rule-image-footnote.rs diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 117cfbabb52f7..6c82dab94bcb3 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -133,11 +133,37 @@ macro_rules! event_loop_break { }} } +struct ParserWrapper<'a> { + parser: Parser<'a>, + footnotes: Vec, + current_footnote_id: u16, +} + +impl<'a> ParserWrapper<'a> { + pub fn new(s: &'a str) -> 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, + } + } + pub fn next(&mut self) -> Option> { + 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 render(w: &mut fmt::Formatter, s: &str, print_toc: bool, shorter: MarkdownOutputStyle) -> fmt::Result { - fn code_block(parser: &mut Parser, buffer: &mut String, lang: &str) { + fn code_block(parser: &mut ParserWrapper, buffer: &mut String, lang: &str) { let mut origtext = String::new(); while let Some(event) = parser.next() { match event { @@ -215,8 +241,8 @@ pub fn render(w: &mut fmt::Formatter, }); } - fn heading(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: MarkdownOutputStyle, level: i32) { + fn heading(parser: &mut ParserWrapper, buffer: &mut String, + toc_builder: &mut Option, shorter: MarkdownOutputStyle, level: i32) { let mut ret = String::new(); let mut id = String::new(); event_loop_break!(parser, toc_builder, shorter, ret, true, &mut Some(&mut id), @@ -249,32 +275,48 @@ pub fn render(w: &mut fmt::Formatter, ret, lvl = level, id = id, sec = sec)); } - fn inline_code(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) { + fn inline_code(parser: &mut ParserWrapper, buffer: &mut String, + toc_builder: &mut Option, shorter: MarkdownOutputStyle, + id: &mut Option<&mut String>) { let mut content = String::new(); event_loop_break!(parser, toc_builder, shorter, content, false, id, Event::End(Tag::Code)); buffer.push_str(&format!("{}", Escape(&collapse_whitespace(content.trim_right())))); } - fn link(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + fn link(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, + shorter: MarkdownOutputStyle, url: &str, title: &str, + id: &mut Option<&mut String>) { + let mut content = String::new(); + event_loop_break!(parser, toc_builder, shorter, content, true, id, + Event::End(Tag::Link(_, _))); + if title.is_empty() { + buffer.push_str(&format!("{}", url, content)); + } else { + buffer.push_str(&format!("{}", + url, Escape(title), content)); + } + } + + fn image(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle, url: &str, mut title: String, id: &mut Option<&mut String>) { event_loop_break!(parser, toc_builder, shorter, title, true, id, - Event::End(Tag::Link(_, _))); - buffer.push_str(&format!("{}", url, title)); + Event::End(Tag::Image(_, _))); + buffer.push_str(&format!("\"{}\"", url, title)); } - fn paragraph(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) { + fn paragraph(parser: &mut ParserWrapper, buffer: &mut String, + toc_builder: &mut Option, shorter: MarkdownOutputStyle, + id: &mut Option<&mut String>) { let mut content = String::new(); event_loop_break!(parser, toc_builder, shorter, content, true, id, Event::End(Tag::Paragraph)); buffer.push_str(&format!("

{}

", content.trim_right())); } - fn table_cell(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: MarkdownOutputStyle) { + fn table_cell(parser: &mut ParserWrapper, buffer: &mut String, + toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); event_loop_break!(parser, toc_builder, shorter, content, true, &mut None, Event::End(Tag::TableHead) | @@ -284,8 +326,8 @@ pub fn render(w: &mut fmt::Formatter, buffer.push_str(&format!("{}", content.trim())); } - fn table_row(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: MarkdownOutputStyle) { + fn table_row(parser: &mut ParserWrapper, buffer: &mut String, + toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); while let Some(event) = parser.next() { match event { @@ -303,8 +345,8 @@ pub fn render(w: &mut fmt::Formatter, buffer.push_str(&format!("{}", content)); } - fn table_head(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: MarkdownOutputStyle) { + fn table_head(parser: &mut ParserWrapper, buffer: &mut String, + toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); while let Some(event) = parser.next() { match event { @@ -322,7 +364,7 @@ pub fn render(w: &mut fmt::Formatter, } } - fn table(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + fn table(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); let mut rows = String::new(); @@ -347,16 +389,16 @@ pub fn render(w: &mut fmt::Formatter, })); } - fn blockquote(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: MarkdownOutputStyle) { + fn blockquote(parser: &mut ParserWrapper, buffer: &mut String, + toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); event_loop_break!(parser, toc_builder, shorter, content, true, &mut None, Event::End(Tag::BlockQuote)); buffer.push_str(&format!("
{}
", content.trim_right())); } - fn list_item(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: MarkdownOutputStyle) { + fn list_item(parser: &mut ParserWrapper, buffer: &mut String, + toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); while let Some(event) = parser.next() { match event { @@ -372,7 +414,7 @@ pub fn render(w: &mut fmt::Formatter, buffer.push_str(&format!("
  • {}
  • ", content)); } - fn list(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + fn list(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); while let Some(event) = parser.next() { @@ -389,15 +431,16 @@ pub fn render(w: &mut fmt::Formatter, buffer.push_str(&format!("
      {}
    ", content)); } - fn emphasis(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) { + fn emphasis(parser: &mut ParserWrapper, buffer: &mut String, + toc_builder: &mut Option, shorter: MarkdownOutputStyle, + id: &mut Option<&mut String>) { let mut content = String::new(); event_loop_break!(parser, toc_builder, shorter, content, false, id, Event::End(Tag::Emphasis)); buffer.push_str(&format!("{}", content)); } - fn strong(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + fn strong(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) { let mut content = String::new(); event_loop_break!(parser, toc_builder, shorter, content, false, id, @@ -405,7 +448,23 @@ pub fn render(w: &mut fmt::Formatter, buffer.push_str(&format!("{}", content)); } - fn looper<'a>(parser: &'a mut Parser, buffer: &mut String, next_event: Option>, + fn footnote(parser: &mut ParserWrapper, buffer: &mut String, + toc_builder: &mut Option, shorter: MarkdownOutputStyle, + mut definition: String, id: &mut Option<&mut String>) { + event_loop_break!(parser, toc_builder, shorter, definition, true, id, + Event::End(Tag::FootnoteDefinition(_))); + buffer.push_str(&definition); + } + + fn rule(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, + shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) { + let mut content = String::new(); + event_loop_break!(parser, toc_builder, shorter, content, true, id, + Event::End(Tag::Rule)); + buffer.push_str("
    "); + } + + fn looper<'a>(parser: &'a mut ParserWrapper, buffer: &mut String, next_event: Option>, toc_builder: &mut Option, shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) -> bool { if let Some(event) = next_event { @@ -423,7 +482,10 @@ pub fn render(w: &mut fmt::Formatter, paragraph(parser, buffer, toc_builder, shorter, id); } Event::Start(Tag::Link(ref url, ref t)) => { - link(parser, buffer, toc_builder, shorter, url, t.as_ref().to_owned(), id); + link(parser, buffer, toc_builder, shorter, url, t.as_ref(), id); + } + Event::Start(Tag::Image(ref url, ref t)) => { + image(parser, buffer, toc_builder, shorter, url, t.as_ref().to_owned(), id); } Event::Start(Tag::Table(_)) => { table(parser, buffer, toc_builder, shorter); @@ -440,6 +502,23 @@ pub fn render(w: &mut fmt::Formatter, Event::Start(Tag::Strong) => { strong(parser, buffer, toc_builder, shorter, id); } + Event::Start(Tag::Rule) => { + rule(parser, buffer, toc_builder, shorter, id); + } + 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!("
  • {}
  • ", + cur_len, content)); + } + Event::FootnoteReference(_) => { + buffer.push_str(&format!("{0}\ + ", + parser.get_next_footnote_id())); + } Event::Html(h) | Event::InlineHtml(h) => { buffer.push_str(&*h); } @@ -457,13 +536,17 @@ pub fn render(w: &mut fmt::Formatter, None }; let mut buffer = String::new(); - let mut parser = Parser::new_ext(s, pulldown_cmark::OPTION_ENABLE_TABLES); + let mut parser = ParserWrapper::new(s); loop { let next_event = parser.next(); if !looper(&mut parser, &mut buffer, next_event, &mut toc_builder, shorter, &mut None) { break } } + if !parser.footnotes.is_empty() { + buffer.push_str(&format!("

      {}
    ", + parser.footnotes.join(""))); + } let mut ret = toc_builder.map_or(Ok(()), |builder| { write!(w, "", builder.into_toc()) }); diff --git a/src/test/rustdoc/check-rule-image-footnote.rs b/src/test/rustdoc/check-rule-image-footnote.rs new file mode 100644 index 0000000000000..629e1a64e6fd0 --- /dev/null +++ b/src/test/rustdoc/check-rule-image-footnote.rs @@ -0,0 +1,35 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +// @has foo/fn.f.html +// @has - '

    hard break: after hard break


    ' +// @has - 'Rust' +// @has - '
  • ' +// @has - '1' +/// markdown test +/// +/// this is a [link]. +/// +/// [link]: https://example.com "this is a title" +/// +/// hard break: +/// after hard break +/// +/// ----------- +/// +/// a footnote[^footnote]. +/// +/// [^footnote]: Thing +/// +/// ![Rust](https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png) +#[deprecated(note = "Struct")] +pub fn f() {} From 36b15f0409fae948b3de7dee1d6b2cb995c5784d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 30 Mar 2017 17:29:54 -0600 Subject: [PATCH 2/5] Fix multiple footnotes and improve testing --- src/librustdoc/html/markdown.rs | 54 +++++++++++-------- 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 6c82dab94bcb3..e8acabde4081a 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, - current_footnote_id: u16, + // The key is the footnote reference. The value is the footnote definition and the id. + footnotes: HashMap, } 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> { 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, 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, @@ -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!("
  • {}
  • ", - 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!("
  • {} 

  • ", + cur_id, + if content.ends_with("

    ") { + &content[..content.len() - 4] + } else { + &content + })); + } + Event::FootnoteReference(ref reference) => { + let entry = parser.get_entry(reference.as_ref()); buffer.push_str(&format!("{0}\ ", - 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!("

      {}
    ", - parser.footnotes.join(""))); + parser.footnotes.values() + .map(|&(ref s, _)| s.as_str()) + .collect::>() + .join(""))); } let mut ret = toc_builder.map_or(Ok(()), |builder| { write!(w, "", builder.into_toc()) diff --git a/src/test/rustdoc/check-rule-image-footnote.rs b/src/test/rustdoc/check-rule-image-footnote.rs index 629e1a64e6fd0..4d3bea20ba895 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 - '

    hard break: after hard break


    ' -// @has - 'Rust' -// @has - '
  • ' -// @has - '1' +// @has - '

    markdown test

    this is a link.

    hard break: after hard break


    a footnote1.

    another footnote2.

    Rust


    1. Thing 

    2. Another Thing 

    ' /// 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")] pub fn f() {} From 51d3cec38794beb644f67e80b1e7718ee14facf0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 31 Mar 2017 11:02:46 -0600 Subject: [PATCH 3/5] Fix hard break issue --- src/librustdoc/html/markdown.rs | 36 ++++++++++++++++++++-- src/librustdoc/passes/unindent_comments.rs | 13 +++++++- src/test/rustdoc/check-hard-break.rs | 19 ++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 src/test/rustdoc/check-hard-break.rs diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index e8acabde4081a..d1f2948bc2532 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -116,6 +116,7 @@ macro_rules! event_loop_break { match event { $($end_event)|* => break, Event::Text(ref s) => { + debug!("Text"); inner($id, s); if $escape { $buf.push_str(&format!("{}", Escape(s))); @@ -123,8 +124,11 @@ macro_rules! event_loop_break { $buf.push_str(s); } } - Event::SoftBreak | Event::HardBreak if !$buf.is_empty() => { - $buf.push(' '); + Event::SoftBreak => { + debug!("SoftBreak"); + if !$buf.is_empty() { + $buf.push(' '); + } } x => { looper($parser, &mut $buf, Some(x), $toc_builder, $shorter, $id); @@ -165,6 +169,7 @@ pub fn render(w: &mut fmt::Formatter, print_toc: bool, shorter: MarkdownOutputStyle) -> fmt::Result { fn code_block(parser: &mut ParserWrapper, buffer: &mut String, lang: &str) { + debug!("CodeBlock"); let mut origtext = String::new(); while let Some(event) = parser.next() { match event { @@ -244,6 +249,7 @@ pub fn render(w: &mut fmt::Formatter, fn heading(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle, level: i32) { + debug!("Heading"); let mut ret = String::new(); let mut id = String::new(); event_loop_break!(parser, toc_builder, shorter, ret, true, &mut Some(&mut id), @@ -279,6 +285,7 @@ pub fn render(w: &mut fmt::Formatter, fn inline_code(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) { + debug!("InlineCode"); let mut content = String::new(); event_loop_break!(parser, toc_builder, shorter, content, false, id, Event::End(Tag::Code)); buffer.push_str(&format!("{}", @@ -288,6 +295,7 @@ pub fn render(w: &mut fmt::Formatter, fn link(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle, url: &str, title: &str, id: &mut Option<&mut String>) { + debug!("Link"); let mut content = String::new(); event_loop_break!(parser, toc_builder, shorter, content, true, id, Event::End(Tag::Link(_, _))); @@ -302,6 +310,7 @@ pub fn render(w: &mut fmt::Formatter, fn image(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle, url: &str, mut title: String, id: &mut Option<&mut String>) { + debug!("Image"); event_loop_break!(parser, toc_builder, shorter, title, true, id, Event::End(Tag::Image(_, _))); buffer.push_str(&format!("\"{}\"", url, title)); @@ -310,6 +319,7 @@ pub fn render(w: &mut fmt::Formatter, fn paragraph(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) { + debug!("Paragraph"); let mut content = String::new(); event_loop_break!(parser, toc_builder, shorter, content, true, id, Event::End(Tag::Paragraph)); @@ -318,6 +328,7 @@ pub fn render(w: &mut fmt::Formatter, fn table_cell(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { + debug!("TableCell"); let mut content = String::new(); event_loop_break!(parser, toc_builder, shorter, content, true, &mut None, Event::End(Tag::TableHead) | @@ -329,6 +340,7 @@ pub fn render(w: &mut fmt::Formatter, fn table_row(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { + debug!("TableRow"); let mut content = String::new(); while let Some(event) = parser.next() { match event { @@ -348,6 +360,7 @@ pub fn render(w: &mut fmt::Formatter, fn table_head(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { + debug!("TableHead"); let mut content = String::new(); while let Some(event) = parser.next() { match event { @@ -367,6 +380,7 @@ pub fn render(w: &mut fmt::Formatter, fn table(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { + debug!("Table"); let mut content = String::new(); let mut rows = String::new(); while let Some(event) = parser.next() { @@ -392,6 +406,7 @@ pub fn render(w: &mut fmt::Formatter, fn blockquote(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { + debug!("BlockQuote"); let mut content = String::new(); event_loop_break!(parser, toc_builder, shorter, content, true, &mut None, Event::End(Tag::BlockQuote)); @@ -400,6 +415,7 @@ pub fn render(w: &mut fmt::Formatter, fn list_item(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { + debug!("ListItem"); let mut content = String::new(); while let Some(event) = parser.next() { match event { @@ -417,6 +433,7 @@ pub fn render(w: &mut fmt::Formatter, fn list(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { + debug!("List"); let mut content = String::new(); while let Some(event) = parser.next() { match event { @@ -435,6 +452,7 @@ pub fn render(w: &mut fmt::Formatter, fn emphasis(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) { + debug!("Emphasis"); let mut content = String::new(); event_loop_break!(parser, toc_builder, shorter, content, false, id, Event::End(Tag::Emphasis)); @@ -443,6 +461,7 @@ pub fn render(w: &mut fmt::Formatter, fn strong(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) { + debug!("Strong"); let mut content = String::new(); event_loop_break!(parser, toc_builder, shorter, content, false, id, Event::End(Tag::Strong)); @@ -452,6 +471,7 @@ pub fn render(w: &mut fmt::Formatter, fn footnote(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) { + debug!("FootnoteDefinition"); let mut content = String::new(); event_loop_break!(parser, toc_builder, shorter, content, true, id, Event::End(Tag::FootnoteDefinition(_))); @@ -460,6 +480,7 @@ pub fn render(w: &mut fmt::Formatter, fn rule(parser: &mut ParserWrapper, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) { + debug!("Rule"); let mut content = String::new(); event_loop_break!(parser, toc_builder, shorter, content, true, id, Event::End(Tag::Rule)); @@ -508,6 +529,7 @@ pub fn render(w: &mut fmt::Formatter, rule(parser, buffer, toc_builder, shorter, id); } Event::Start(Tag::FootnoteDefinition(ref def)) => { + debug!("FootnoteDefinition"); let mut content = String::new(); let def = def.as_ref(); footnote(parser, &mut content, toc_builder, shorter, id); @@ -523,12 +545,22 @@ pub fn render(w: &mut fmt::Formatter, })); } Event::FootnoteReference(ref reference) => { + debug!("FootnoteReference"); let entry = parser.get_entry(reference.as_ref()); buffer.push_str(&format!("{0}\ ", (*entry).1)); } + Event::HardBreak => { + debug!("HardBreak"); + if shorter.is_fancy() { + buffer.push_str("
    "); + } else if !buffer.is_empty() { + buffer.push(' '); + } + } Event::Html(h) | Event::InlineHtml(h) => { + debug!("Html/InlineHtml"); buffer.push_str(&*h); } _ => {} diff --git a/src/librustdoc/passes/unindent_comments.rs b/src/librustdoc/passes/unindent_comments.rs index 4d94c30847852..59fef8d20271b 100644 --- a/src/librustdoc/passes/unindent_comments.rs +++ b/src/librustdoc/passes/unindent_comments.rs @@ -82,7 +82,7 @@ fn unindent(s: &str) -> String { }); if !lines.is_empty() { - let mut unindented = vec![ lines[0].trim().to_string() ]; + let mut unindented = vec![ lines[0].trim_left().to_string() ]; unindented.extend_from_slice(&lines[1..].iter().map(|&line| { if line.chars().all(|c| c.is_whitespace()) { line.to_string() @@ -160,4 +160,15 @@ mod unindent_tests { let r = unindent(&s); assert_eq!(r, "line1\nline2"); } + + #[test] + fn should_not_trim() { + let s = "\t line1 \n\t line2".to_string(); + let r = unindent(&s); + assert_eq!(r, "line1 \nline2"); + + let s = " \tline1 \n \tline2".to_string(); + let r = unindent(&s); + assert_eq!(r, "line1 \nline2"); + } } diff --git a/src/test/rustdoc/check-hard-break.rs b/src/test/rustdoc/check-hard-break.rs new file mode 100644 index 0000000000000..4604639c3c8d5 --- /dev/null +++ b/src/test/rustdoc/check-hard-break.rs @@ -0,0 +1,19 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +// ignore-tidy-linelength + +// @has foo/fn.f.html +// @has - '

    hard break:
    after hard break

    ' +/// hard break: +/// after hard break +pub fn f() {} From 4de4a955052febfbcd28fd156a7585b90b5dd184 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 31 Mar 2017 12:08:31 -0600 Subject: [PATCH 4/5] Add end whitespace ignore flag for tidy --- src/test/rustdoc/check-hard-break.rs | 2 +- src/tools/tidy/src/style.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/rustdoc/check-hard-break.rs b/src/test/rustdoc/check-hard-break.rs index 4604639c3c8d5..5c5e3f8136c73 100644 --- a/src/test/rustdoc/check-hard-break.rs +++ b/src/test/rustdoc/check-hard-break.rs @@ -10,7 +10,7 @@ #![crate_name = "foo"] -// ignore-tidy-linelength +// ignore-tidy-end-whitespace // @has foo/fn.f.html // @has - '

    hard break:
    after hard break

    ' diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 2233f8c352974..012301299e0c5 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -110,6 +110,7 @@ pub fn check(path: &Path, bad: &mut bool) { let skip_cr = contents.contains("ignore-tidy-cr"); let skip_tab = contents.contains("ignore-tidy-tab"); let skip_length = contents.contains("ignore-tidy-linelength"); + let skip_end_whitespace = contents.contains("ignore-tidy-end-whitespace"); for (i, line) in contents.split("\n").enumerate() { let mut err = |msg: &str| { println!("{}:{}: {}", file.display(), i + 1, msg); @@ -122,7 +123,7 @@ pub fn check(path: &Path, bad: &mut bool) { if line.contains("\t") && !skip_tab { err("tab character"); } - if line.ends_with(" ") || line.ends_with("\t") { + if !skip_end_whitespace && (line.ends_with(" ") || line.ends_with("\t")) { err("trailing whitespace"); } if line.contains("\r") && !skip_cr { From ef01ae7fe0652c050ec9af8f70990bb01309ffbc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 1 Apr 2017 00:31:37 -0600 Subject: [PATCH 5/5] Force footnote references to be sorted by id --- src/librustdoc/html/markdown.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index d1f2948bc2532..0b098fb14f190 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -585,11 +585,13 @@ pub fn render(w: &mut fmt::Formatter, } } if !parser.footnotes.is_empty() { + let mut v: Vec<_> = parser.footnotes.values().collect(); + v.sort_by(|a, b| a.1.cmp(&b.1)); buffer.push_str(&format!("

      {}
    ", - parser.footnotes.values() - .map(|&(ref s, _)| s.as_str()) - .collect::>() - .join(""))); + v.iter() + .map(|s| s.0.as_str()) + .collect::>() + .join(""))); } let mut ret = toc_builder.map_or(Ok(()), |builder| { write!(w, "", builder.into_toc())