From 08a80cbda6d505b845f4d857e8f5770df0ea162a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 8 Mar 2017 01:01:23 +0100 Subject: [PATCH 01/14] Replace hoedown with pull in rustdoc --- src/Cargo.lock | 2 + src/librustdoc/Cargo.toml | 1 + src/librustdoc/html/markdown.rs | 415 ++++++++++++++++++++++++-------- src/librustdoc/lib.rs | 1 + 4 files changed, 312 insertions(+), 107 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index a0b47f4f0b2bb..946818e7d2087 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -772,6 +772,8 @@ dependencies = [ "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.0.0", + "pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", "rustc_const_eval 0.0.0", diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 1c479ce1d0157..2222077aae80b 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -26,6 +26,7 @@ rustc_trans = { path = "../librustc_trans" } serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } +pulldown-cmark = "0.0.8" [build-dependencies] build_helper = { path = "../build_helper" } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index c7c5aabab97ae..a745ccc822cda 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -30,9 +30,9 @@ use libc; use std::ascii::AsciiExt; use std::cell::RefCell; use std::default::Default; -use std::ffi::CString; +//use std::ffi::CString; use std::fmt::{self, Write}; -use std::slice; +//use std::slice; use std::str; use syntax::feature_gate::UnstableFeatures; use syntax::codemap::Span; @@ -43,6 +43,8 @@ use html::highlight; use html::escape::Escape; use test; +use pulldown_cmark::{self, Parser}; + /// A unit struct which has the `fmt::Display` trait implemented. When /// formatted, this struct will emit the HTML corresponding to the rendered /// version of the contained markdown string. @@ -53,7 +55,7 @@ pub struct MarkdownWithToc<'a>(pub &'a str); /// A unit struct like `Markdown`, that renders the markdown escaping HTML tags. pub struct MarkdownHtml<'a>(pub &'a str); -const DEF_OUNIT: libc::size_t = 64; +/*const DEF_OUNIT: libc::size_t = 64; const HOEDOWN_EXT_NO_INTRA_EMPHASIS: libc::c_uint = 1 << 11; const HOEDOWN_EXT_TABLES: libc::c_uint = 1 << 0; const HOEDOWN_EXT_FENCED_CODE: libc::c_uint = 1 << 1; @@ -179,8 +181,8 @@ extern { fn hoedown_document_free(md: *mut hoedown_document); fn hoedown_buffer_new(unit: libc::size_t) -> *mut hoedown_buffer; - fn hoedown_buffer_put(b: *mut hoedown_buffer, c: *const libc::c_char, - n: libc::size_t); + /*fn hoedown_buffer_put(b: *mut hoedown_buffer, c: *const libc::c_char, + n: libc::size_t);*/ fn hoedown_buffer_puts(b: *mut hoedown_buffer, c: *const libc::c_char); fn hoedown_buffer_free(b: *mut hoedown_buffer); @@ -191,7 +193,7 @@ impl hoedown_buffer { fn as_bytes(&self) -> &[u8] { unsafe { slice::from_raw_parts(self.data, self.size as usize) } } -} +}*/ /// Returns Some(code) if `s` is a line that should be stripped from /// documentation but used in example code. `code` is the portion of @@ -226,8 +228,8 @@ thread_local!(pub static PLAYGROUND: RefCell, String)>> = pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool, - html_flags: libc::c_uint) -> fmt::Result { - extern fn block(ob: *mut hoedown_buffer, orig_text: *const hoedown_buffer, + _html_flags: libc::c_uint) -> fmt::Result { + /*extern fn block(ob: *mut hoedown_buffer, orig_text: *const hoedown_buffer, lang: *const hoedown_buffer, data: *const hoedown_renderer_data, line: libc::size_t) { unsafe { @@ -422,76 +424,274 @@ pub fn render(w: &mut fmt::Formatter, } hoedown_buffer_free(ob); ret + }*/ + + fn block(parser: &mut Parser, lang: &str, buffer: &mut String) { + let mut origtext = String::new(); + loop { + let event = parser.next(); + if let Some(event) = event { + match event { + pulldown_cmark::Event::End( + pulldown_cmark::Tag::CodeBlock(_)) => break, + pulldown_cmark::Event::Text(ref s) => { + origtext.push_str(s); + } + _ => {} + } + } else { + break + } + } + let origtext = origtext.trim_left(); + debug!("docblock: ==============\n{:?}\n=======", origtext); + let rendered = if lang.is_empty() || origtext.is_empty() { + false + } else { + if !LangString::parse(lang).rust { + /*(my_opaque.dfltblk)(ob, orig_text, lang, + opaque as *const hoedown_renderer_data, + line);*/ + // true + false + } else { + false + } + }; + + let lines = origtext.lines().filter(|l| { + stripped_filtered_line(*l).is_none() + }); + let text = lines.collect::>().join("\n"); + if rendered { return } + PLAYGROUND.with(|play| { + // insert newline to clearly separate it from the + // previous block so we can shorten the html output + let mut s = String::from("\n"); + let playground_button = play.borrow().as_ref().and_then(|&(ref krate, ref url)| { + if url.is_empty() { + return None; + } + let test = origtext.lines().map(|l| { + stripped_filtered_line(l).unwrap_or(l) + }).collect::>().join("\n"); + let krate = krate.as_ref().map(|s| &**s); + let test = test::maketest(&test, krate, false, + &Default::default()); + let channel = if test.contains("#![feature(") { + "&version=nightly" + } else { + "" + }; + // These characters don't need to be escaped in a URI. + // FIXME: use a library function for percent encoding. + fn dont_escape(c: u8) -> bool { + (b'a' <= c && c <= b'z') || + (b'A' <= c && c <= b'Z') || + (b'0' <= c && c <= b'9') || + c == b'-' || c == b'_' || c == b'.' || + c == b'~' || c == b'!' || c == b'\'' || + c == b'(' || c == b')' || c == b'*' + } + let mut test_escaped = String::new(); + for b in test.bytes() { + if dont_escape(b) { + test_escaped.push(char::from(b)); + } else { + write!(test_escaped, "%{:02X}", b).unwrap(); + } + } + Some(format!( + r#"Run"#, + url, test_escaped, channel + )) + }); + s.push_str(&highlight::render_with_highlighting( + &text, + Some("rust-example-rendered"), + None, + playground_button.as_ref().map(String::as_str))); + buffer.push_str(&s); + }); } -} -pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span) { - extern fn block(_ob: *mut hoedown_buffer, - text: *const hoedown_buffer, - lang: *const hoedown_buffer, - data: *const hoedown_renderer_data, - line: libc::size_t) { - unsafe { - if text.is_null() { return } - let block_info = if lang.is_null() { - LangString::all_false() + fn header(parser: &mut Parser, level: i32, toc_builder: &mut Option, + buffer: &mut String) { + let mut ret = String::new(); + loop { + let event = parser.next(); + if let Some(event) = event { + match event { + pulldown_cmark::Event::End( + pulldown_cmark::Tag::Header(_)) => break, + pulldown_cmark::Event::Text(ref s) => { + ret.push_str(s); + } + _ => {} + } } else { - let lang = (*lang).as_bytes(); - let s = str::from_utf8(lang).unwrap(); - LangString::parse(s) - }; - if !block_info.rust { return } - let text = (*text).as_bytes(); - let opaque = (*data).opaque as *mut hoedown_html_renderer_state; - let tests = &mut *((*opaque).opaque as *mut ::test::Collector); - let text = str::from_utf8(text).unwrap(); - let lines = text.lines().map(|l| { - stripped_filtered_line(l).unwrap_or(l) - }); - let text = lines.collect::>().join("\n"); - let line = tests.get_line() + line; - let filename = tests.get_filename(); - tests.add_test(text.to_owned(), - block_info.should_panic, block_info.no_run, - block_info.ignore, block_info.test_harness, - block_info.compile_fail, block_info.error_codes, - line, filename); + break + } } + + let id = ret.clone(); + // Discard '', '' tags and some escaped characters, + // transform the contents of the header into a hyphenated string + // without non-alphanumeric characters other than '-' and '_'. + // + // This is a terrible hack working around how hoedown gives us rendered + // html for text rather than the raw text. + let id = id.chars().filter_map(|c| { + if c.is_alphanumeric() || c == '-' || c == '_' { + if c.is_ascii() { + Some(c.to_ascii_lowercase()) + } else { + Some(c) + } + } else if c.is_whitespace() && c.is_ascii() { + Some('-') + } else { + None + } + }).collect::(); + + let id = derive_id(id); + + let sec = toc_builder.as_mut().map_or("".to_owned(), |builder| { + format!("{} ", builder.push(level as u32, ret.clone(), id.clone())) + }); + + // Render the HTML + buffer.push_str(&format!("\ + {sec}{}", + ret, lvl = level, id = id, sec = sec)); } - extern fn header(_ob: *mut hoedown_buffer, - text: *const hoedown_buffer, - level: libc::c_int, data: *const hoedown_renderer_data, - _: libc::size_t) { - unsafe { - let opaque = (*data).opaque as *mut hoedown_html_renderer_state; - let tests = &mut *((*opaque).opaque as *mut ::test::Collector); - if text.is_null() { - tests.register_header("", level as u32); + fn codespan(parser: &mut Parser, buffer: &mut String) { + let mut content = String::new(); + loop { + let event = parser.next(); + if let Some(event) = event { + match event { + pulldown_cmark::Event::End( + pulldown_cmark::Tag::Code) => break, + pulldown_cmark::Event::Text(ref s) => { + content.push_str(s); + } + _ => {} + } } else { - let text = (*text).as_bytes(); - let text = str::from_utf8(text).unwrap(); - tests.register_header(text, level as u32); + break } } + buffer.push_str(&format!("{}", Escape(&collapse_whitespace(&content)))); } - tests.set_position(position); - unsafe { - let ob = hoedown_buffer_new(DEF_OUNIT); - let renderer = hoedown_html_renderer_new(0, 0); - (*renderer).blockcode = Some(block); - (*renderer).header = Some(header); - (*((*renderer).opaque as *mut hoedown_html_renderer_state)).opaque - = tests as *mut _ as *mut libc::c_void; + let mut toc_builder = if print_toc { + Some(TocBuilder::new()) + } else { + None + }; + let mut buffer = String::new(); + let mut parser = Parser::new(s); + loop { + let next_event = parser.next(); + if let Some(event) = next_event { + match event { + pulldown_cmark::Event::Start(pulldown_cmark::Tag::CodeBlock(s)) => { + block(&mut parser, &*s, &mut buffer); + } + pulldown_cmark::Event::Start(pulldown_cmark::Tag::Header(level)) => { + header(&mut parser, level, &mut toc_builder, &mut buffer); + } + pulldown_cmark::Event::Start(pulldown_cmark::Tag::Code) => { + codespan(&mut parser, &mut buffer); + } + _ => {} + } + } else { + break + } + } + let mut ret = toc_builder.map_or(Ok(()), |builder| { + write!(w, "", builder.into_toc()) + }); - let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16); - hoedown_document_render(document, ob, doc.as_ptr(), - doc.len() as libc::size_t); - hoedown_document_free(document); + if ret.is_ok() { + ret = w.write_str(&buffer); + } + ret +} - hoedown_html_renderer_free(renderer); - hoedown_buffer_free(ob); +pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span) { + tests.set_position(position); + + let mut parser = Parser::new(doc); + let mut prev_offset = 0; + let mut nb_lines = 0; + let mut register_header = None; + 'main: loop { + let next_event = parser.next(); + if let Some(event) = next_event { + match event { + pulldown_cmark::Event::Start(pulldown_cmark::Tag::CodeBlock(s)) => { + let block_info = if s.is_empty() { + LangString::all_false() + } else { + LangString::parse(&*s) + }; + let mut test_s = String::new(); + let mut offset = None; + loop { + let event = parser.next(); + if let Some(event) = event { + match event { + pulldown_cmark::Event::End( + pulldown_cmark::Tag::CodeBlock(_)) => break, + pulldown_cmark::Event::Text(ref s) => { + test_s.push_str(s); + if offset.is_none() { + offset = Some(parser.get_offset()); + } + } + _ => {} + } + } else { + break 'main; + } + } + let offset = offset.unwrap_or(0); + let lines = test_s.lines().map(|l| { + stripped_filtered_line(l).unwrap_or(l) + }); + let text = lines.collect::>().join("\n"); + nb_lines += doc[prev_offset..offset].lines().count(); + let line = tests.get_line() + (nb_lines - 1); + let filename = tests.get_filename(); + tests.add_test(text.to_owned(), + block_info.should_panic, block_info.no_run, + block_info.ignore, block_info.test_harness, + block_info.compile_fail, block_info.error_codes, + line, filename); + prev_offset = offset; + } + pulldown_cmark::Event::Start(pulldown_cmark::Tag::Header(level)) => { + register_header = Some(level as u32); + } + pulldown_cmark::Event::Text(ref s) if register_header.is_some() => { + let level = register_header.unwrap(); + if s.is_empty() { + tests.register_header("", level); + } else { + tests.register_header(s, level); + } + register_header = None; + } + _ => {} + } + } else { + break + } } } @@ -589,57 +789,58 @@ impl<'a> fmt::Display for MarkdownHtml<'a> { let MarkdownHtml(md) = *self; // This is actually common enough to special-case if md.is_empty() { return Ok(()) } - render(fmt, md, false, HOEDOWN_HTML_ESCAPE) + render(fmt, md, false, /*HOEDOWN_HTML_ESCAPE*/0) } } pub fn plain_summary_line(md: &str) -> String { - extern fn link(_ob: *mut hoedown_buffer, - _link: *const hoedown_buffer, - _title: *const hoedown_buffer, - content: *const hoedown_buffer, - data: *const hoedown_renderer_data, - _: libc::size_t) -> libc::c_int - { - unsafe { - if !content.is_null() && (*content).size > 0 { - let ob = (*data).opaque as *mut hoedown_buffer; - hoedown_buffer_put(ob, (*content).data as *const libc::c_char, - (*content).size); - } - } - 1 + struct ParserWrapper<'a> { + inner: Parser<'a>, + is_in: isize, + is_first: bool, } - extern fn normal_text(_ob: *mut hoedown_buffer, - text: *const hoedown_buffer, - data: *const hoedown_renderer_data, - _: libc::size_t) - { - unsafe { - let ob = (*data).opaque as *mut hoedown_buffer; - hoedown_buffer_put(ob, (*text).data as *const libc::c_char, - (*text).size); + impl<'a> Iterator for ParserWrapper<'a> { + type Item = String; + + fn next(&mut self) -> Option { + let next_event = self.inner.next(); + if next_event.is_none() { + return None + } + let next_event = next_event.unwrap(); + let (ret, is_in) = match next_event { + pulldown_cmark::Event::Start(pulldown_cmark::Tag::Paragraph) => (None, 1), + pulldown_cmark::Event::Start( + pulldown_cmark::Tag::Link(_, ref t)) if !self.is_first => (Some(t.as_ref().to_owned()), 1), + pulldown_cmark::Event::Text(ref s) if self.is_in > 0 => (Some(s.as_ref().to_owned()), 0), + pulldown_cmark::Event::End(pulldown_cmark::Tag::Link(_, ref t)) => (Some(t.as_ref().to_owned()), -1), + pulldown_cmark::Event::End(pulldown_cmark::Tag::Paragraph) => (None, -1), + _ => (None, 0), + }; + if is_in > 0 || (is_in < 0 && self.is_in > 0) { + self.is_in += is_in; + } + if ret.is_some() { + self.is_first = false; + ret + } else { + Some(String::new()) + } } } - - unsafe { - let ob = hoedown_buffer_new(DEF_OUNIT); - let mut plain_renderer: hoedown_renderer = ::std::mem::zeroed(); - let renderer: *mut hoedown_renderer = &mut plain_renderer; - (*renderer).opaque = ob as *mut libc::c_void; - (*renderer).link = Some(link); - (*renderer).normal_text = Some(normal_text); - - let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16); - hoedown_document_render(document, ob, md.as_ptr(), - md.len() as libc::size_t); - hoedown_document_free(document); - let plain_slice = (*ob).as_bytes(); - let plain = str::from_utf8(plain_slice).unwrap_or("").to_owned(); - hoedown_buffer_free(ob); - plain + let mut s = String::with_capacity(md.len() * 3 / 2); + let mut p = ParserWrapper { + inner: Parser::new(md), + is_in: 0, + is_first: true, + }; + while let Some(t) = p.next() { + if !t.is_empty() { + s.push_str(&t); + } } + s } #[cfg(test)] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 8dd03f6edc4d5..efb51bdf471f4 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -48,6 +48,7 @@ extern crate test as testing; extern crate std_unicode; #[macro_use] extern crate log; extern crate rustc_errors as errors; +extern crate pulldown_cmark; extern crate serialize as rustc_serialize; // used by deriving From c9415eb98ff2a5cf679954e5eaf66274a24db1ee Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 8 Mar 2017 23:56:00 +0100 Subject: [PATCH 02/14] Remains to fix tables --- src/librustdoc/html/markdown.rs | 94 ++++++++++++++++++++++++++------- 1 file changed, 74 insertions(+), 20 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index a745ccc822cda..a36e99e80dfe9 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -43,7 +43,7 @@ use html::highlight; use html::escape::Escape; use test; -use pulldown_cmark::{self, Parser}; +use pulldown_cmark::{self, Event, Parser}; /// A unit struct which has the `fmt::Display` trait implemented. When /// formatted, this struct will emit the HTML corresponding to the rendered @@ -467,7 +467,7 @@ pub fn render(w: &mut fmt::Formatter, PLAYGROUND.with(|play| { // insert newline to clearly separate it from the // previous block so we can shorten the html output - let mut s = String::from("\n"); + buffer.push('\n'); let playground_button = play.borrow().as_ref().and_then(|&(ref krate, ref url)| { if url.is_empty() { return None; @@ -506,12 +506,11 @@ pub fn render(w: &mut fmt::Formatter, url, test_escaped, channel )) }); - s.push_str(&highlight::render_with_highlighting( - &text, - Some("rust-example-rendered"), - None, - playground_button.as_ref().map(String::as_str))); - buffer.push_str(&s); + buffer.push_str(&highlight::render_with_highlighting( + &text, + Some("rust-example-rendered"), + None, + playground_button.as_ref().map(String::as_str))); }); } @@ -587,29 +586,84 @@ pub fn render(w: &mut fmt::Formatter, buffer.push_str(&format!("{}", Escape(&collapse_whitespace(&content)))); } - let mut toc_builder = if print_toc { - Some(TocBuilder::new()) - } else { - None - }; - let mut buffer = String::new(); - let mut parser = Parser::new(s); - loop { - let next_event = parser.next(); + fn link(parser: &mut Parser, buffer: &mut String, url: &str, mut title: String) { + loop { + let event = parser.next(); + if let Some(event) = event { + match event { + pulldown_cmark::Event::End( + pulldown_cmark::Tag::Link(_, _)) => break, + pulldown_cmark::Event::Text(ref s) => { + title.push_str(s); + } + _ => {} + } + } else { + break + } + } + buffer.push_str(&format!("{}", url, title)); + } + + fn paragraph(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option) { + let mut content = String::new(); + loop { + let event = parser.next(); + if let Some(event) = event { + match event { + pulldown_cmark::Event::End( + pulldown_cmark::Tag::Paragraph) => break, + pulldown_cmark::Event::Text(ref s) => { + content.push_str(s); + } + x => { + looper(parser, &mut content, Some(x), toc_builder); + } + } + } else { + break + } + } + buffer.push_str(&format!("

{}

", content)); + } + + fn looper<'a>(parser: &'a mut Parser, buffer: &mut String, next_event: Option>, + toc_builder: &mut Option) -> bool { if let Some(event) = next_event { match event { pulldown_cmark::Event::Start(pulldown_cmark::Tag::CodeBlock(s)) => { - block(&mut parser, &*s, &mut buffer); + block(parser, &*s, buffer); } pulldown_cmark::Event::Start(pulldown_cmark::Tag::Header(level)) => { - header(&mut parser, level, &mut toc_builder, &mut buffer); + header(parser, level, toc_builder, buffer); } pulldown_cmark::Event::Start(pulldown_cmark::Tag::Code) => { - codespan(&mut parser, &mut buffer); + codespan(parser, buffer); + } + pulldown_cmark::Event::Start(pulldown_cmark::Tag::Paragraph) => { + paragraph(parser, buffer, toc_builder); + } + pulldown_cmark::Event::Start(pulldown_cmark::Tag::Link(ref url, ref t)) => { + link(parser, buffer, url, t.as_ref().to_owned()); } _ => {} } + true } else { + false + } + } + + let mut toc_builder = if print_toc { + Some(TocBuilder::new()) + } else { + None + }; + let mut buffer = String::new(); + let mut parser = Parser::new(s); + loop { + let next_event = parser.next(); + if !looper(&mut parser, &mut buffer, next_event, &mut toc_builder) { break } } From b96fef8411f26e357e31b8c1b584b6d994efafaa Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 10 Mar 2017 14:06:24 +0100 Subject: [PATCH 03/14] End of pulldown switch and remove completely hoedown --- .gitmodules | 4 - src/librustdoc/Cargo.toml | 1 - src/librustdoc/build.rs | 29 -- src/librustdoc/html/markdown.rs | 661 ++++++++++---------------------- src/librustdoc/html/render.rs | 8 +- src/librustdoc/markdown.rs | 2 +- src/rt/hoedown | 1 - 7 files changed, 216 insertions(+), 490 deletions(-) delete mode 100644 src/librustdoc/build.rs delete mode 160000 src/rt/hoedown diff --git a/.gitmodules b/.gitmodules index d2e1fb868a999..53d1787492409 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,10 +5,6 @@ [submodule "src/compiler-rt"] path = src/compiler-rt url = https://github.com/rust-lang/compiler-rt.git -[submodule "src/rt/hoedown"] - path = src/rt/hoedown - url = https://github.com/rust-lang/hoedown.git - branch = rust-2015-09-21-do-not-delete [submodule "src/jemalloc"] path = src/jemalloc url = https://github.com/rust-lang/jemalloc.git diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 2222077aae80b..ff18daa7aa098 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -2,7 +2,6 @@ authors = ["The Rust Project Developers"] name = "rustdoc" version = "0.0.0" -build = "build.rs" [lib] name = "rustdoc" diff --git a/src/librustdoc/build.rs b/src/librustdoc/build.rs deleted file mode 100644 index 9fa6406c1d8b6..0000000000000 --- a/src/librustdoc/build.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2015 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. - -extern crate build_helper; -extern crate gcc; - -fn main() { - let src_dir = std::path::Path::new("../rt/hoedown/src"); - build_helper::rerun_if_changed_anything_in_dir(src_dir); - let mut cfg = gcc::Config::new(); - cfg.file("../rt/hoedown/src/autolink.c") - .file("../rt/hoedown/src/buffer.c") - .file("../rt/hoedown/src/document.c") - .file("../rt/hoedown/src/escape.c") - .file("../rt/hoedown/src/html.c") - .file("../rt/hoedown/src/html_blocks.c") - .file("../rt/hoedown/src/html_smartypants.c") - .file("../rt/hoedown/src/stack.c") - .file("../rt/hoedown/src/version.c") - .include(src_dir) - .compile("libhoedown.a"); -} diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index a36e99e80dfe9..9ae6c443f9e06 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -26,7 +26,7 @@ #![allow(non_camel_case_types)] -use libc; +//use libc; use std::ascii::AsciiExt; use std::cell::RefCell; use std::default::Default; @@ -43,158 +43,19 @@ use html::highlight; use html::escape::Escape; use test; -use pulldown_cmark::{self, Event, Parser}; +use pulldown_cmark::{self, Event, Parser, Tag}; /// A unit struct which has the `fmt::Display` trait implemented. When /// formatted, this struct will emit the HTML corresponding to the rendered /// version of the contained markdown string. -pub struct Markdown<'a>(pub &'a str); +// The second parameter is whether we need a shorter version or not. +pub struct Markdown<'a>(pub &'a str, pub bool); /// A unit struct like `Markdown`, that renders the markdown with a /// table of contents. pub struct MarkdownWithToc<'a>(pub &'a str); /// A unit struct like `Markdown`, that renders the markdown escaping HTML tags. pub struct MarkdownHtml<'a>(pub &'a str); -/*const DEF_OUNIT: libc::size_t = 64; -const HOEDOWN_EXT_NO_INTRA_EMPHASIS: libc::c_uint = 1 << 11; -const HOEDOWN_EXT_TABLES: libc::c_uint = 1 << 0; -const HOEDOWN_EXT_FENCED_CODE: libc::c_uint = 1 << 1; -const HOEDOWN_EXT_AUTOLINK: libc::c_uint = 1 << 3; -const HOEDOWN_EXT_STRIKETHROUGH: libc::c_uint = 1 << 4; -const HOEDOWN_EXT_SUPERSCRIPT: libc::c_uint = 1 << 8; -const HOEDOWN_EXT_FOOTNOTES: libc::c_uint = 1 << 2; -const HOEDOWN_HTML_ESCAPE: libc::c_uint = 1 << 1; - -const HOEDOWN_EXTENSIONS: libc::c_uint = - HOEDOWN_EXT_NO_INTRA_EMPHASIS | HOEDOWN_EXT_TABLES | - HOEDOWN_EXT_FENCED_CODE | HOEDOWN_EXT_AUTOLINK | - HOEDOWN_EXT_STRIKETHROUGH | HOEDOWN_EXT_SUPERSCRIPT | - HOEDOWN_EXT_FOOTNOTES; - -enum hoedown_document {} - -type blockcodefn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, - *const hoedown_buffer, *const hoedown_renderer_data, - libc::size_t); - -type blockquotefn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, - *const hoedown_renderer_data, libc::size_t); - -type headerfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, - libc::c_int, *const hoedown_renderer_data, - libc::size_t); - -type blockhtmlfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, - *const hoedown_renderer_data, libc::size_t); - -type codespanfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, - *const hoedown_renderer_data, libc::size_t) -> libc::c_int; - -type linkfn = extern "C" fn (*mut hoedown_buffer, *const hoedown_buffer, - *const hoedown_buffer, *const hoedown_buffer, - *const hoedown_renderer_data, libc::size_t) -> libc::c_int; - -type entityfn = extern "C" fn (*mut hoedown_buffer, *const hoedown_buffer, - *const hoedown_renderer_data, libc::size_t); - -type normaltextfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, - *const hoedown_renderer_data, libc::size_t); - -#[repr(C)] -struct hoedown_renderer_data { - opaque: *mut libc::c_void, -} - -#[repr(C)] -struct hoedown_renderer { - opaque: *mut libc::c_void, - - blockcode: Option, - blockquote: Option, - header: Option, - - other_block_level_callbacks: [libc::size_t; 11], - - blockhtml: Option, - - /* span level callbacks - NULL or return 0 prints the span verbatim */ - autolink: libc::size_t, // unused - codespan: Option, - other_span_level_callbacks_1: [libc::size_t; 7], - link: Option, - other_span_level_callbacks_2: [libc::size_t; 6], - - /* low level callbacks - NULL copies input directly into the output */ - entity: Option, - normal_text: Option, - - /* header and footer */ - other_callbacks: [libc::size_t; 2], -} - -#[repr(C)] -struct hoedown_html_renderer_state { - opaque: *mut libc::c_void, - toc_data: html_toc_data, - flags: libc::c_uint, - link_attributes: Option, -} - -#[repr(C)] -struct html_toc_data { - header_count: libc::c_int, - current_level: libc::c_int, - level_offset: libc::c_int, - nesting_level: libc::c_int, -} - -struct MyOpaque { - dfltblk: extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, - *const hoedown_buffer, *const hoedown_renderer_data, - libc::size_t), - toc_builder: Option, -} - -#[repr(C)] -struct hoedown_buffer { - data: *const u8, - size: libc::size_t, - asize: libc::size_t, - unit: libc::size_t, -} - -extern { - fn hoedown_html_renderer_new(render_flags: libc::c_uint, - nesting_level: libc::c_int) - -> *mut hoedown_renderer; - fn hoedown_html_renderer_free(renderer: *mut hoedown_renderer); - - fn hoedown_document_new(rndr: *const hoedown_renderer, - extensions: libc::c_uint, - max_nesting: libc::size_t) -> *mut hoedown_document; - fn hoedown_document_render(doc: *mut hoedown_document, - ob: *mut hoedown_buffer, - document: *const u8, - doc_size: libc::size_t); - fn hoedown_document_free(md: *mut hoedown_document); - - fn hoedown_buffer_new(unit: libc::size_t) -> *mut hoedown_buffer; - /*fn hoedown_buffer_put(b: *mut hoedown_buffer, c: *const libc::c_char, - n: libc::size_t);*/ - fn hoedown_buffer_puts(b: *mut hoedown_buffer, c: *const libc::c_char); - fn hoedown_buffer_free(b: *mut hoedown_buffer); - -} - -// hoedown_buffer helpers -impl hoedown_buffer { - fn as_bytes(&self) -> &[u8] { - unsafe { slice::from_raw_parts(self.data, self.size as usize) } - } -}*/ - /// Returns Some(code) if `s` is a line that should be stripped from /// documentation but used in example code. `code` is the portion of /// `s` that should be used in tests. (None for lines that should be @@ -228,213 +89,15 @@ thread_local!(pub static PLAYGROUND: RefCell, String)>> = pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool, - _html_flags: libc::c_uint) -> fmt::Result { - /*extern fn block(ob: *mut hoedown_buffer, orig_text: *const hoedown_buffer, - lang: *const hoedown_buffer, data: *const hoedown_renderer_data, - line: libc::size_t) { - unsafe { - if orig_text.is_null() { return } - - let opaque = (*data).opaque as *mut hoedown_html_renderer_state; - let my_opaque: &MyOpaque = &*((*opaque).opaque as *const MyOpaque); - let text = (*orig_text).as_bytes(); - let origtext = str::from_utf8(text).unwrap(); - let origtext = origtext.trim_left(); - debug!("docblock: ==============\n{:?}\n=======", text); - let rendered = if lang.is_null() || origtext.is_empty() { - false - } else { - let rlang = (*lang).as_bytes(); - let rlang = str::from_utf8(rlang).unwrap(); - if !LangString::parse(rlang).rust { - (my_opaque.dfltblk)(ob, orig_text, lang, - opaque as *const hoedown_renderer_data, - line); - true - } else { - false - } - }; - - let lines = origtext.lines().filter(|l| { - stripped_filtered_line(*l).is_none() - }); - let text = lines.collect::>().join("\n"); - if rendered { return } - PLAYGROUND.with(|play| { - // insert newline to clearly separate it from the - // previous block so we can shorten the html output - let mut s = String::from("\n"); - let playground_button = play.borrow().as_ref().and_then(|&(ref krate, ref url)| { - if url.is_empty() { - return None; - } - let test = origtext.lines().map(|l| { - stripped_filtered_line(l).unwrap_or(l) - }).collect::>().join("\n"); - let krate = krate.as_ref().map(|s| &**s); - let test = test::maketest(&test, krate, false, - &Default::default()); - let channel = if test.contains("#![feature(") { - "&version=nightly" - } else { - "" - }; - // These characters don't need to be escaped in a URI. - // FIXME: use a library function for percent encoding. - fn dont_escape(c: u8) -> bool { - (b'a' <= c && c <= b'z') || - (b'A' <= c && c <= b'Z') || - (b'0' <= c && c <= b'9') || - c == b'-' || c == b'_' || c == b'.' || - c == b'~' || c == b'!' || c == b'\'' || - c == b'(' || c == b')' || c == b'*' - } - let mut test_escaped = String::new(); - for b in test.bytes() { - if dont_escape(b) { - test_escaped.push(char::from(b)); - } else { - write!(test_escaped, "%{:02X}", b).unwrap(); - } - } - Some(format!( - r#"Run"#, - url, test_escaped, channel - )) - }); - s.push_str(&highlight::render_with_highlighting( - &text, - Some("rust-example-rendered"), - None, - playground_button.as_ref().map(String::as_str))); - let output = CString::new(s).unwrap(); - hoedown_buffer_puts(ob, output.as_ptr()); - }) - } - } - - extern fn header(ob: *mut hoedown_buffer, text: *const hoedown_buffer, - level: libc::c_int, data: *const hoedown_renderer_data, - _: libc::size_t) { - // hoedown does this, we may as well too - unsafe { hoedown_buffer_puts(ob, "\n\0".as_ptr() as *const _); } - - // Extract the text provided - let s = if text.is_null() { - "".to_owned() - } else { - let s = unsafe { (*text).as_bytes() }; - str::from_utf8(&s).unwrap().to_owned() - }; - - // Discard '', '' tags and some escaped characters, - // transform the contents of the header into a hyphenated string - // without non-alphanumeric characters other than '-' and '_'. - // - // This is a terrible hack working around how hoedown gives us rendered - // html for text rather than the raw text. - let mut id = s.clone(); - let repl_sub = vec!["", "", "", "", - "", "", - "<", ">", "&", "'", """]; - for sub in repl_sub { - id = id.replace(sub, ""); - } - let id = id.chars().filter_map(|c| { - if c.is_alphanumeric() || c == '-' || c == '_' { - if c.is_ascii() { - Some(c.to_ascii_lowercase()) - } else { - Some(c) - } - } else if c.is_whitespace() && c.is_ascii() { - Some('-') - } else { - None - } - }).collect::(); - - let opaque = unsafe { (*data).opaque as *mut hoedown_html_renderer_state }; - let opaque = unsafe { &mut *((*opaque).opaque as *mut MyOpaque) }; - - let id = derive_id(id); - - let sec = opaque.toc_builder.as_mut().map_or("".to_owned(), |builder| { - format!("{} ", builder.push(level as u32, s.clone(), id.clone())) - }); - - // Render the HTML - let text = format!("\ - {sec}{}", - s, lvl = level, id = id, sec = sec); - - let text = CString::new(text).unwrap(); - unsafe { hoedown_buffer_puts(ob, text.as_ptr()) } - } - - extern fn codespan( - ob: *mut hoedown_buffer, - text: *const hoedown_buffer, - _: *const hoedown_renderer_data, - _: libc::size_t - ) -> libc::c_int { - let content = if text.is_null() { - "".to_owned() - } else { - let bytes = unsafe { (*text).as_bytes() }; - let s = str::from_utf8(bytes).unwrap(); - collapse_whitespace(s) - }; - - let content = format!("{}", Escape(&content)); - let element = CString::new(content).unwrap(); - unsafe { hoedown_buffer_puts(ob, element.as_ptr()); } - // Return anything except 0, which would mean "also print the code span verbatim". - 1 - } - - unsafe { - let ob = hoedown_buffer_new(DEF_OUNIT); - let renderer = hoedown_html_renderer_new(html_flags, 0); - let mut opaque = MyOpaque { - dfltblk: (*renderer).blockcode.unwrap(), - toc_builder: if print_toc {Some(TocBuilder::new())} else {None} - }; - (*((*renderer).opaque as *mut hoedown_html_renderer_state)).opaque - = &mut opaque as *mut _ as *mut libc::c_void; - (*renderer).blockcode = Some(block); - (*renderer).header = Some(header); - (*renderer).codespan = Some(codespan); - - let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16); - hoedown_document_render(document, ob, s.as_ptr(), - s.len() as libc::size_t); - hoedown_document_free(document); - - hoedown_html_renderer_free(renderer); - - let mut ret = opaque.toc_builder.map_or(Ok(()), |builder| { - write!(w, "", builder.into_toc()) - }); - - if ret.is_ok() { - let buf = (*ob).as_bytes(); - ret = w.write_str(str::from_utf8(buf).unwrap()); - } - hoedown_buffer_free(ob); - ret - }*/ - - fn block(parser: &mut Parser, lang: &str, buffer: &mut String) { + shorter: bool) -> fmt::Result { + fn block(parser: &mut Parser, buffer: &mut String, lang: &str) { let mut origtext = String::new(); loop { let event = parser.next(); if let Some(event) = event { match event { - pulldown_cmark::Event::End( - pulldown_cmark::Tag::CodeBlock(_)) => break, - pulldown_cmark::Event::Text(ref s) => { + Event::End(Tag::CodeBlock(_)) => break, + Event::Text(ref s) => { origtext.push_str(s); } _ => {} @@ -445,25 +108,21 @@ pub fn render(w: &mut fmt::Formatter, } let origtext = origtext.trim_left(); debug!("docblock: ==============\n{:?}\n=======", origtext); - let rendered = if lang.is_empty() || origtext.is_empty() { - false - } else { - if !LangString::parse(lang).rust { - /*(my_opaque.dfltblk)(ob, orig_text, lang, - opaque as *const hoedown_renderer_data, - line);*/ - // true - false - } else { - false - } - }; let lines = origtext.lines().filter(|l| { stripped_filtered_line(*l).is_none() }); let text = lines.collect::>().join("\n"); - if rendered { return } + let block_info = if lang.is_empty() { + LangString::all_false() + } else { + LangString::parse(lang) + }; + if !block_info.rust { + buffer.push_str(&format!("
{}
", + lang, text)); + return + } PLAYGROUND.with(|play| { // insert newline to clearly separate it from the // previous block so we can shorten the html output @@ -521,9 +180,8 @@ pub fn render(w: &mut fmt::Formatter, let event = parser.next(); if let Some(event) = event { match event { - pulldown_cmark::Event::End( - pulldown_cmark::Tag::Header(_)) => break, - pulldown_cmark::Event::Text(ref s) => { + Event::End(Tag::Header(_)) => break, + Event::Text(ref s) => { ret.push_str(s); } _ => {} @@ -561,8 +219,8 @@ pub fn render(w: &mut fmt::Formatter, }); // Render the HTML - buffer.push_str(&format!("\ - {sec}{}", + buffer.push_str(&format!("\ + {sec}{}", ret, lvl = level, id = id, sec = sec)); } @@ -572,9 +230,8 @@ pub fn render(w: &mut fmt::Formatter, let event = parser.next(); if let Some(event) = event { match event { - pulldown_cmark::Event::End( - pulldown_cmark::Tag::Code) => break, - pulldown_cmark::Event::Text(ref s) => { + Event::End(Tag::Code) => break, + Event::Text(ref s) => { content.push_str(s); } _ => {} @@ -591,9 +248,8 @@ pub fn render(w: &mut fmt::Formatter, let event = parser.next(); if let Some(event) = event { match event { - pulldown_cmark::Event::End( - pulldown_cmark::Tag::Link(_, _)) => break, - pulldown_cmark::Event::Text(ref s) => { + Event::End(Tag::Link(_, _)) => break, + Event::Text(ref s) => { title.push_str(s); } _ => {} @@ -605,19 +261,19 @@ pub fn render(w: &mut fmt::Formatter, buffer.push_str(&format!("{}", url, title)); } - fn paragraph(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option) { + fn paragraph(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + shorter: bool) { let mut content = String::new(); loop { let event = parser.next(); if let Some(event) = event { match event { - pulldown_cmark::Event::End( - pulldown_cmark::Tag::Paragraph) => break, - pulldown_cmark::Event::Text(ref s) => { + Event::End(Tag::Paragraph) => break, + Event::Text(ref s) => { content.push_str(s); } x => { - looper(parser, &mut content, Some(x), toc_builder); + looper(parser, &mut content, Some(x), toc_builder, shorter); } } } else { @@ -627,28 +283,135 @@ pub fn render(w: &mut fmt::Formatter, buffer.push_str(&format!("

{}

", content)); } + fn cell(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + shorter: bool) { + let mut content = String::new(); + loop { + let event = parser.next(); + if let Some(event) = event { + match event { + Event::End(Tag::TableHead) | + Event::End(Tag::Table(_)) | + Event::End(Tag::TableRow) | + Event::End(Tag::TableCell) => break, + Event::Text(ref s) => { + content.push_str(s); + } + x => { + looper(parser, &mut content, Some(x), toc_builder, shorter); + } + } + } else { + break + } + } + buffer.push_str(&format!("{}", content.trim())); + } + + fn row(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + shorter: bool) { + let mut content = String::new(); + loop { + let event = parser.next(); + if let Some(event) = event { + match event { + Event::End(Tag::TableHead) | + Event::End(Tag::Table(_)) | + Event::End(Tag::TableRow) => break, + Event::Start(Tag::TableCell) => { + cell(parser, &mut content, toc_builder, shorter); + } + x => { + looper(parser, &mut content, Some(x), toc_builder, shorter); + } + } + } else { + break + } + } + buffer.push_str(&format!("{}", content)); + } + + fn head(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + shorter: bool) { + let mut content = String::new(); + loop { + let event = parser.next(); + if let Some(event) = event { + match event { + Event::End(Tag::TableHead) | Event::End(Tag::Table(_)) => break, + Event::Start(Tag::TableCell) => { + cell(parser, &mut content, toc_builder, shorter); + } + x => { + looper(parser, &mut content, Some(x), toc_builder, shorter); + } + } + } else { + break + } + } + if content.is_empty() { + return + } + buffer.push_str(&format!("{}", content.replace("td>", "th>"))); + } + + fn table(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + shorter: bool) { + let mut content = String::new(); + let mut rows = String::new(); + loop { + let event = parser.next(); + if let Some(event) = event { + match event { + Event::End(Tag::Table(_)) => break, + Event::Start(Tag::TableHead) => { + head(parser, &mut content, toc_builder, shorter); + } + Event::Start(Tag::TableRow) => { + row(parser, &mut rows, toc_builder, shorter); + } + _ => {} + } + } else { + break + } + } + buffer.push_str(&format!("{}{}
", + content, + if shorter || rows.is_empty() { + String::new() + } else { + format!("{}", rows) + })); + } + fn looper<'a>(parser: &'a mut Parser, buffer: &mut String, next_event: Option>, - toc_builder: &mut Option) -> bool { + toc_builder: &mut Option, shorter: bool) -> bool { if let Some(event) = next_event { match event { - pulldown_cmark::Event::Start(pulldown_cmark::Tag::CodeBlock(s)) => { - block(parser, &*s, buffer); + Event::Start(Tag::CodeBlock(lang)) => { + block(parser, buffer, &*lang); } - pulldown_cmark::Event::Start(pulldown_cmark::Tag::Header(level)) => { + Event::Start(Tag::Header(level)) => { header(parser, level, toc_builder, buffer); } - pulldown_cmark::Event::Start(pulldown_cmark::Tag::Code) => { + Event::Start(Tag::Code) => { codespan(parser, buffer); } - pulldown_cmark::Event::Start(pulldown_cmark::Tag::Paragraph) => { - paragraph(parser, buffer, toc_builder); + Event::Start(Tag::Paragraph) => { + paragraph(parser, buffer, toc_builder, shorter); } - pulldown_cmark::Event::Start(pulldown_cmark::Tag::Link(ref url, ref t)) => { + Event::Start(Tag::Link(ref url, ref t)) => { link(parser, buffer, url, t.as_ref().to_owned()); } + Event::Start(Tag::Table(_)) => { + table(parser, buffer, toc_builder, shorter); + } _ => {} } - true + shorter == false } else { false } @@ -660,10 +423,10 @@ pub fn render(w: &mut fmt::Formatter, None }; let mut buffer = String::new(); - let mut parser = Parser::new(s); + let mut parser = Parser::new_ext(s, pulldown_cmark::OPTION_ENABLE_TABLES); loop { let next_event = parser.next(); - if !looper(&mut parser, &mut buffer, next_event, &mut toc_builder) { + if !looper(&mut parser, &mut buffer, next_event, &mut toc_builder, shorter) { break } } @@ -684,67 +447,64 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp let mut prev_offset = 0; let mut nb_lines = 0; let mut register_header = None; - 'main: loop { - let next_event = parser.next(); - if let Some(event) = next_event { - match event { - pulldown_cmark::Event::Start(pulldown_cmark::Tag::CodeBlock(s)) => { - let block_info = if s.is_empty() { - LangString::all_false() - } else { - LangString::parse(&*s) - }; - let mut test_s = String::new(); - let mut offset = None; - loop { - let event = parser.next(); - if let Some(event) = event { - match event { - pulldown_cmark::Event::End( - pulldown_cmark::Tag::CodeBlock(_)) => break, - pulldown_cmark::Event::Text(ref s) => { - test_s.push_str(s); - if offset.is_none() { - offset = Some(parser.get_offset()); - } + 'main: while let Some(event) = parser.next() { + match event { + Event::Start(Tag::CodeBlock(s)) => { + let block_info = if s.is_empty() { + LangString::all_false() + } else { + LangString::parse(&*s) + }; + if !block_info.rust { + continue + } + let mut test_s = String::new(); + let mut offset = None; + loop { + let event = parser.next(); + if let Some(event) = event { + match event { + Event::End(Tag::CodeBlock(_)) => break, + Event::Text(ref s) => { + test_s.push_str(s); + if offset.is_none() { + offset = Some(parser.get_offset()); } - _ => {} } - } else { - break 'main; + _ => {} } - } - let offset = offset.unwrap_or(0); - let lines = test_s.lines().map(|l| { - stripped_filtered_line(l).unwrap_or(l) - }); - let text = lines.collect::>().join("\n"); - nb_lines += doc[prev_offset..offset].lines().count(); - let line = tests.get_line() + (nb_lines - 1); - let filename = tests.get_filename(); - tests.add_test(text.to_owned(), - block_info.should_panic, block_info.no_run, - block_info.ignore, block_info.test_harness, - block_info.compile_fail, block_info.error_codes, - line, filename); - prev_offset = offset; - } - pulldown_cmark::Event::Start(pulldown_cmark::Tag::Header(level)) => { - register_header = Some(level as u32); - } - pulldown_cmark::Event::Text(ref s) if register_header.is_some() => { - let level = register_header.unwrap(); - if s.is_empty() { - tests.register_header("", level); } else { - tests.register_header(s, level); + break 'main; } - register_header = None; } - _ => {} + let offset = offset.unwrap_or(0); + let lines = test_s.lines().map(|l| { + stripped_filtered_line(l).unwrap_or(l) + }); + let text = lines.collect::>().join("\n"); + nb_lines += doc[prev_offset..offset].lines().count(); + let line = tests.get_line() + (nb_lines - 1); + let filename = tests.get_filename(); + tests.add_test(text.to_owned(), + block_info.should_panic, block_info.no_run, + block_info.ignore, block_info.test_harness, + block_info.compile_fail, block_info.error_codes, + line, filename); + prev_offset = offset; } - } else { - break + Event::Start(Tag::Header(level)) => { + register_header = Some(level as u32); + } + Event::Text(ref s) if register_header.is_some() => { + let level = register_header.unwrap(); + if s.is_empty() { + tests.register_header("", level); + } else { + tests.register_header(s, level); + } + register_header = None; + } + _ => {} } } } @@ -824,17 +584,17 @@ impl LangString { impl<'a> fmt::Display for Markdown<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let Markdown(md) = *self; + let Markdown(md, shorter) = *self; // This is actually common enough to special-case if md.is_empty() { return Ok(()) } - render(fmt, md, false, 0) + render(fmt, md, false, shorter) } } impl<'a> fmt::Display for MarkdownWithToc<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let MarkdownWithToc(md) = *self; - render(fmt, md, true, 0) + render(fmt, md, true, false) } } @@ -843,7 +603,7 @@ impl<'a> fmt::Display for MarkdownHtml<'a> { let MarkdownHtml(md) = *self; // This is actually common enough to special-case if md.is_empty() { return Ok(()) } - render(fmt, md, false, /*HOEDOWN_HTML_ESCAPE*/0) + render(fmt, md, false, false) } } @@ -864,12 +624,13 @@ pub fn plain_summary_line(md: &str) -> String { } let next_event = next_event.unwrap(); let (ret, is_in) = match next_event { - pulldown_cmark::Event::Start(pulldown_cmark::Tag::Paragraph) => (None, 1), - pulldown_cmark::Event::Start( - pulldown_cmark::Tag::Link(_, ref t)) if !self.is_first => (Some(t.as_ref().to_owned()), 1), - pulldown_cmark::Event::Text(ref s) if self.is_in > 0 => (Some(s.as_ref().to_owned()), 0), - pulldown_cmark::Event::End(pulldown_cmark::Tag::Link(_, ref t)) => (Some(t.as_ref().to_owned()), -1), - pulldown_cmark::Event::End(pulldown_cmark::Tag::Paragraph) => (None, -1), + Event::Start(Tag::Paragraph) => (None, 1), + Event::Start(Tag::Link(_, ref t)) if !self.is_first => { + (Some(t.as_ref().to_owned()), 1) + } + Event::Text(ref s) if self.is_in > 0 => (Some(s.as_ref().to_owned()), 0), + Event::End(Tag::Link(_, ref t)) => (Some(t.as_ref().to_owned()), -1), + Event::End(Tag::Paragraph) => (None, -1), _ => (None, 0), }; if is_in > 0 || (is_in < 0 && self.is_in > 0) { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 5c94032c6b9cf..8c1416b809799 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1650,7 +1650,7 @@ fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLin } else { format!("{}", &plain_summary_line(Some(s))) }; - write!(w, "
{}
", Markdown(&markdown))?; + write!(w, "
{}
", Markdown(&markdown, false))?; } Ok(()) } @@ -1683,7 +1683,7 @@ fn get_doc_value(item: &clean::Item) -> Option<&str> { fn document_full(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result { if let Some(s) = get_doc_value(item) { write!(w, "
{}
", - Markdown(&format!("{}{}", md_render_assoc_item(item), s)))?; + Markdown(&format!("{}{}", md_render_assoc_item(item), s), false))?; } Ok(()) } @@ -1871,7 +1871,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, ", name = *myitem.name.as_ref().unwrap(), stab_docs = stab_docs, - docs = shorter(Some(&Markdown(doc_value).to_string())), + docs = shorter(Some(&Markdown(doc_value, true).to_string())), class = myitem.type_(), stab = myitem.stability_class().unwrap_or("".to_string()), unsafety_flag = unsafety_flag, @@ -2901,7 +2901,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi write!(w, "")?; write!(w, "\n")?; if let Some(ref dox) = i.impl_item.doc_value() { - write!(w, "
{}
", Markdown(dox))?; + write!(w, "
{}
", Markdown(dox, false))?; } } diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index c67e2fdc2b027..a048750279e26 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -94,7 +94,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, let rendered = if include_toc { format!("{}", MarkdownWithToc(text)) } else { - format!("{}", Markdown(text)) + format!("{}", Markdown(text, false)) }; let err = write!( diff --git a/src/rt/hoedown b/src/rt/hoedown deleted file mode 160000 index da282f1bb7277..0000000000000 --- a/src/rt/hoedown +++ /dev/null @@ -1 +0,0 @@ -Subproject commit da282f1bb7277b4d30fa1599ee29ad8eb4dd2a92 From f6baea23bad46050e8f0840713c9d13a40edaf68 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 10 Mar 2017 18:35:15 +0100 Subject: [PATCH 04/14] Fix external doc errors --- src/libcore/result.rs | 2 +- src/tools/error_index_generator/main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 6ec8a37dfa433..c46b0c1324de6 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -838,10 +838,10 @@ impl Result { /// /// assert_eq!(1909, good_year); /// assert_eq!(0, bad_year); + /// ``` /// /// [`parse`]: ../../std/primitive.str.html#method.parse /// [`FromStr`]: ../../std/str/trait.FromStr.html - /// ``` #[inline] #[stable(feature = "result_unwrap_or_default", since = "1.16.0")] pub fn unwrap_or_default(self) -> T { diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index e33df0dfbc8de..2f4a38c16c1d9 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -100,7 +100,7 @@ impl Formatter for HTMLFormatter { // Description rendered as markdown. match info.description { - Some(ref desc) => write!(output, "{}", Markdown(desc))?, + Some(ref desc) => write!(output, "{}", Markdown(desc, false))?, None => write!(output, "

No description.

\n")?, } From d5b6c046de79bf357683d9db191ed6a97c24187c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 11 Mar 2017 01:43:36 +0100 Subject: [PATCH 05/14] Add missing markdown tags --- src/librustdoc/html/markdown.rs | 381 +++++++++++++++--------- src/librustdoc/html/render.rs | 13 +- src/librustdoc/markdown.rs | 4 +- src/tools/error_index_generator/main.rs | 4 +- 4 files changed, 251 insertions(+), 151 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 9ae6c443f9e06..e8c95c4a21c3f 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -26,13 +26,10 @@ #![allow(non_camel_case_types)] -//use libc; use std::ascii::AsciiExt; use std::cell::RefCell; use std::default::Default; -//use std::ffi::CString; use std::fmt::{self, Write}; -//use std::slice; use std::str; use syntax::feature_gate::UnstableFeatures; use syntax::codemap::Span; @@ -45,11 +42,33 @@ use test; use pulldown_cmark::{self, Event, Parser, Tag}; +#[derive(Copy, Clone)] +pub enum MarkdownOutputStyle { + Compact, + Fancy, +} + +impl MarkdownOutputStyle { + pub fn is_compact(&self) -> bool { + match *self { + MarkdownOutputStyle::Compact => true, + _ => false, + } + } + + pub fn is_fancy(&self) -> bool { + match *self { + MarkdownOutputStyle::Fancy => true, + _ => false, + } + } +} + /// A unit struct which has the `fmt::Display` trait implemented. When /// formatted, this struct will emit the HTML corresponding to the rendered /// version of the contained markdown string. // The second parameter is whether we need a shorter version or not. -pub struct Markdown<'a>(pub &'a str, pub bool); +pub struct Markdown<'a>(pub &'a str, pub MarkdownOutputStyle); /// A unit struct like `Markdown`, that renders the markdown with a /// table of contents. pub struct MarkdownWithToc<'a>(pub &'a str); @@ -85,25 +104,19 @@ thread_local!(pub static PLAYGROUND: RefCell, String)>> = RefCell::new(None) }); - pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool, - shorter: bool) -> fmt::Result { + shorter: MarkdownOutputStyle) -> fmt::Result { fn block(parser: &mut Parser, buffer: &mut String, lang: &str) { let mut origtext = String::new(); - loop { - let event = parser.next(); - if let Some(event) = event { - match event { - Event::End(Tag::CodeBlock(_)) => break, - Event::Text(ref s) => { - origtext.push_str(s); - } - _ => {} + while let Some(event) = parser.next() { + match event { + Event::End(Tag::CodeBlock(_)) => break, + Event::Text(ref s) => { + origtext.push_str(s); } - } else { - break + _ => {} } } let origtext = origtext.trim_left(); @@ -176,20 +189,19 @@ pub fn render(w: &mut fmt::Formatter, fn header(parser: &mut Parser, level: i32, toc_builder: &mut Option, buffer: &mut String) { let mut ret = String::new(); - loop { - let event = parser.next(); - if let Some(event) = event { - match event { - Event::End(Tag::Header(_)) => break, - Event::Text(ref s) => { - ret.push_str(s); - } - _ => {} + while let Some(event) = parser.next() { + match event { + Event::End(Tag::Header(_)) => break, + Event::Text(ref s) => { + ret.push_str(s); } - } else { - break + Event::SoftBreak | Event::HardBreak if !ret.is_empty() => { + ret.push(' '); + } + _ => {} } } + ret = ret.trim_right().to_owned(); let id = ret.clone(); // Discard '', '' tags and some escaped characters, @@ -226,169 +238,242 @@ pub fn render(w: &mut fmt::Formatter, fn codespan(parser: &mut Parser, buffer: &mut String) { let mut content = String::new(); - loop { - let event = parser.next(); - if let Some(event) = event { - match event { - Event::End(Tag::Code) => break, - Event::Text(ref s) => { - content.push_str(s); - } - _ => {} + while let Some(event) = parser.next() { + match event { + Event::End(Tag::Code) => break, + Event::Text(ref s) => { + content.push_str(s); } - } else { - break + Event::SoftBreak | Event::HardBreak if !content.is_empty() => { + content.push(' '); + } + _ => {} } } - buffer.push_str(&format!("{}", Escape(&collapse_whitespace(&content)))); + buffer.push_str(&format!("{}", Escape(&collapse_whitespace(content.trim_right())))); } - fn link(parser: &mut Parser, buffer: &mut String, url: &str, mut title: String) { - loop { - let event = parser.next(); - if let Some(event) = event { - match event { - Event::End(Tag::Link(_, _)) => break, - Event::Text(ref s) => { - title.push_str(s); - } - _ => {} + fn link(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + shorter: MarkdownOutputStyle, url: &str, mut title: String) { + while let Some(event) = parser.next() { + match event { + Event::End(Tag::Link(_, _)) => break, + Event::Text(ref s) => { + title.push_str(s); + } + Event::SoftBreak | Event::HardBreak if !title.is_empty() => { + title.push(' '); + } + x => { + looper(parser, &mut title, Some(x), toc_builder, shorter); } - } else { - break } } buffer.push_str(&format!("{}", url, title)); } fn paragraph(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: bool) { + shorter: MarkdownOutputStyle) { let mut content = String::new(); - loop { - let event = parser.next(); - if let Some(event) = event { - match event { - Event::End(Tag::Paragraph) => break, - Event::Text(ref s) => { - content.push_str(s); - } - x => { - looper(parser, &mut content, Some(x), toc_builder, shorter); - } + while let Some(event) = parser.next() { + match event { + Event::End(Tag::Paragraph) => break, + Event::Text(ref s) => { + content.push_str(s); + } + Event::SoftBreak | Event::HardBreak if !content.is_empty() => { + content.push(' '); + } + x => { + looper(parser, &mut content, Some(x), toc_builder, shorter); } - } else { - break } } - buffer.push_str(&format!("

{}

", content)); + buffer.push_str(&format!("

{}

", content.trim_right())); } fn cell(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: bool) { + shorter: MarkdownOutputStyle) { let mut content = String::new(); - loop { - let event = parser.next(); - if let Some(event) = event { - match event { - Event::End(Tag::TableHead) | - Event::End(Tag::Table(_)) | - Event::End(Tag::TableRow) | - Event::End(Tag::TableCell) => break, - Event::Text(ref s) => { - content.push_str(s); - } - x => { - looper(parser, &mut content, Some(x), toc_builder, shorter); - } + while let Some(event) = parser.next() { + match event { + Event::End(Tag::TableHead) | + Event::End(Tag::Table(_)) | + Event::End(Tag::TableRow) | + Event::End(Tag::TableCell) => break, + Event::Text(ref s) => { + content.push_str(s); + } + Event::SoftBreak | Event::HardBreak => { + content.push(' '); + } + x => { + looper(parser, &mut content, Some(x), toc_builder, shorter); } - } else { - break } } buffer.push_str(&format!("{}", content.trim())); } fn row(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: bool) { + shorter: MarkdownOutputStyle) { let mut content = String::new(); - loop { - let event = parser.next(); - if let Some(event) = event { - match event { - Event::End(Tag::TableHead) | - Event::End(Tag::Table(_)) | - Event::End(Tag::TableRow) => break, - Event::Start(Tag::TableCell) => { - cell(parser, &mut content, toc_builder, shorter); - } - x => { - looper(parser, &mut content, Some(x), toc_builder, shorter); - } + while let Some(event) = parser.next() { + match event { + Event::End(Tag::TableHead) | + Event::End(Tag::Table(_)) | + Event::End(Tag::TableRow) => break, + Event::Start(Tag::TableCell) => { + cell(parser, &mut content, toc_builder, shorter); + } + x => { + looper(parser, &mut content, Some(x), toc_builder, shorter); } - } else { - break } } buffer.push_str(&format!("{}", content)); } fn head(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: bool) { + shorter: MarkdownOutputStyle) { let mut content = String::new(); - loop { - let event = parser.next(); - if let Some(event) = event { - match event { - Event::End(Tag::TableHead) | Event::End(Tag::Table(_)) => break, - Event::Start(Tag::TableCell) => { - cell(parser, &mut content, toc_builder, shorter); - } - x => { - looper(parser, &mut content, Some(x), toc_builder, shorter); - } + while let Some(event) = parser.next() { + match event { + Event::End(Tag::TableHead) | Event::End(Tag::Table(_)) => break, + Event::Start(Tag::TableCell) => { + cell(parser, &mut content, toc_builder, shorter); + } + x => { + looper(parser, &mut content, Some(x), toc_builder, shorter); } - } else { - break } } - if content.is_empty() { - return + if !content.is_empty() { + buffer.push_str(&format!("{}", content.replace("td>", "th>"))); } - buffer.push_str(&format!("{}", content.replace("td>", "th>"))); } fn table(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: bool) { + shorter: MarkdownOutputStyle) { let mut content = String::new(); let mut rows = String::new(); - loop { - let event = parser.next(); - if let Some(event) = event { - match event { - Event::End(Tag::Table(_)) => break, - Event::Start(Tag::TableHead) => { - head(parser, &mut content, toc_builder, shorter); - } - Event::Start(Tag::TableRow) => { - row(parser, &mut rows, toc_builder, shorter); - } - _ => {} + while let Some(event) = parser.next() { + match event { + Event::End(Tag::Table(_)) => break, + Event::Start(Tag::TableHead) => { + head(parser, &mut content, toc_builder, shorter); } - } else { - break + Event::Start(Tag::TableRow) => { + row(parser, &mut rows, toc_builder, shorter); + } + _ => {} } } buffer.push_str(&format!("{}{}
", content, - if shorter || rows.is_empty() { + if shorter.is_compact() || rows.is_empty() { String::new() } else { format!("{}", rows) })); } + fn blockquote(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + shorter: MarkdownOutputStyle) { + let mut content = String::new(); + while let Some(event) = parser.next() { + match event { + Event::End(Tag::BlockQuote) => break, + Event::Text(ref s) => { + content.push_str(s); + } + Event::SoftBreak | Event::HardBreak if !content.is_empty() => { + content.push(' '); + } + x => { + looper(parser, &mut content, Some(x), toc_builder, shorter); + } + } + } + buffer.push_str(&format!("
{}
", content.trim_right())); + } + + fn list_item(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + shorter: MarkdownOutputStyle) { + let mut content = String::new(); + while let Some(event) = parser.next() { + match event { + Event::End(Tag::Item) => break, + Event::Text(ref s) => { + content.push_str(s); + } + x => { + looper(parser, &mut content, Some(x), toc_builder, shorter); + } + } + } + buffer.push_str(&format!("
  • {}
  • ", content)); + } + + fn list(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + shorter: MarkdownOutputStyle) { + let mut content = String::new(); + while let Some(event) = parser.next() { + match event { + Event::End(Tag::List(_)) => break, + Event::Start(Tag::Item) => { + list_item(parser, &mut content, toc_builder, shorter); + } + x => { + looper(parser, &mut content, Some(x), toc_builder, shorter); + } + } + } + buffer.push_str(&format!("
      {}
    ", content)); + } + + fn emphasis(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + shorter: MarkdownOutputStyle) { + let mut content = String::new(); + while let Some(event) = parser.next() { + match event { + Event::End(Tag::Emphasis) => break, + Event::Text(ref s) => { + content.push_str(s); + } + Event::SoftBreak | Event::HardBreak if !content.is_empty() => { + content.push(' '); + } + x => { + looper(parser, &mut content, Some(x), toc_builder, shorter); + } + } + } + buffer.push_str(&format!("{}", content)); + } + + fn strong(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + shorter: MarkdownOutputStyle) { + let mut content = String::new(); + while let Some(event) = parser.next() { + match event { + Event::End(Tag::Strong) => break, + Event::Text(ref s) => { + content.push_str(s); + } + Event::SoftBreak | Event::HardBreak if !content.is_empty() => { + content.push(' '); + } + x => { + looper(parser, &mut content, Some(x), toc_builder, shorter); + } + } + } + buffer.push_str(&format!("{}", content)); + } + fn looper<'a>(parser: &'a mut Parser, buffer: &mut String, next_event: Option>, - toc_builder: &mut Option, shorter: bool) -> bool { + toc_builder: &mut Option, shorter: MarkdownOutputStyle) -> bool { if let Some(event) = next_event { match event { Event::Start(Tag::CodeBlock(lang)) => { @@ -404,14 +489,26 @@ pub fn render(w: &mut fmt::Formatter, paragraph(parser, buffer, toc_builder, shorter); } Event::Start(Tag::Link(ref url, ref t)) => { - link(parser, buffer, url, t.as_ref().to_owned()); + link(parser, buffer, toc_builder, shorter, url, t.as_ref().to_owned()); } Event::Start(Tag::Table(_)) => { table(parser, buffer, toc_builder, shorter); } + Event::Start(Tag::BlockQuote) => { + blockquote(parser, buffer, toc_builder, shorter); + } + Event::Start(Tag::List(_)) => { + list(parser, buffer, toc_builder, shorter); + } + Event::Start(Tag::Emphasis) => { + emphasis(parser, buffer, toc_builder, shorter); + } + Event::Start(Tag::Strong) => { + strong(parser, buffer, toc_builder, shorter); + } _ => {} } - shorter == false + shorter.is_fancy() } else { false } @@ -594,7 +691,7 @@ impl<'a> fmt::Display for Markdown<'a> { impl<'a> fmt::Display for MarkdownWithToc<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let MarkdownWithToc(md) = *self; - render(fmt, md, true, false) + render(fmt, md, true, MarkdownOutputStyle::Fancy) } } @@ -603,7 +700,7 @@ impl<'a> fmt::Display for MarkdownHtml<'a> { let MarkdownHtml(md) = *self; // This is actually common enough to special-case if md.is_empty() { return Ok(()) } - render(fmt, md, false, false) + render(fmt, md, false, MarkdownOutputStyle::Fancy) } } @@ -660,7 +757,7 @@ pub fn plain_summary_line(md: &str) -> String { #[cfg(test)] mod tests { - use super::{LangString, Markdown, MarkdownHtml}; + use super::{LangString, Markdown, MarkdownHtml, MarkdownOutputStyle}; use super::plain_summary_line; use html::render::reset_ids; @@ -700,14 +797,14 @@ mod tests { #[test] fn issue_17736() { let markdown = "# title"; - format!("{}", Markdown(markdown)); + format!("{}", Markdown(markdown, MarkdownOutputStyle::Fancy)); reset_ids(true); } #[test] fn test_header() { fn t(input: &str, expect: &str) { - let output = format!("{}", Markdown(input)); + let output = format!("{}", Markdown(input, MarkdownOutputStyle::Fancy)); assert_eq!(output, expect); reset_ids(true); } @@ -729,7 +826,7 @@ mod tests { #[test] fn test_header_ids_multiple_blocks() { fn t(input: &str, expect: &str) { - let output = format!("{}", Markdown(input)); + let output = format!("{}", Markdown(input, MarkdownOutputStyle::Fancy)); assert_eq!(output, expect); } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 8c1416b809799..1fa348a1be4c4 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -72,7 +72,7 @@ use html::format::{TyParamBounds, WhereClause, href, AbiSpace}; use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace}; use html::format::fmt_impl_for_trait_page; use html::item_type::ItemType; -use html::markdown::{self, Markdown, MarkdownHtml}; +use html::markdown::{self, Markdown, MarkdownHtml, MarkdownOutputStyle}; use html::{highlight, layout}; /// A pair of name and its optional document. @@ -1650,7 +1650,8 @@ fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLin } else { format!("{}", &plain_summary_line(Some(s))) }; - write!(w, "
    {}
    ", Markdown(&markdown, false))?; + write!(w, "
    {}
    ", + Markdown(&markdown, MarkdownOutputStyle::Fancy))?; } Ok(()) } @@ -1683,7 +1684,8 @@ fn get_doc_value(item: &clean::Item) -> Option<&str> { fn document_full(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result { if let Some(s) = get_doc_value(item) { write!(w, "
    {}
    ", - Markdown(&format!("{}{}", md_render_assoc_item(item), s), false))?; + Markdown(&format!("{}{}", md_render_assoc_item(item), s), + MarkdownOutputStyle::Fancy))?; } Ok(()) } @@ -1871,7 +1873,8 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, ", name = *myitem.name.as_ref().unwrap(), stab_docs = stab_docs, - docs = shorter(Some(&Markdown(doc_value, true).to_string())), + docs = shorter(Some(&Markdown(doc_value, + MarkdownOutputStyle::Compact).to_string())), class = myitem.type_(), stab = myitem.stability_class().unwrap_or("".to_string()), unsafety_flag = unsafety_flag, @@ -2901,7 +2904,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi write!(w, "")?; write!(w, "\n")?; if let Some(ref dox) = i.impl_item.doc_value() { - write!(w, "
    {}
    ", Markdown(dox, false))?; + write!(w, "
    {}
    ", Markdown(dox, MarkdownOutputStyle::Fancy))?; } } diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index a048750279e26..d29e98f8fe105 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -25,7 +25,7 @@ use externalfiles::{ExternalHtml, LoadStringError, load_string}; use html::render::reset_ids; use html::escape::Escape; use html::markdown; -use html::markdown::{Markdown, MarkdownWithToc, find_testable_code}; +use html::markdown::{Markdown, MarkdownWithToc, MarkdownOutputStyle, find_testable_code}; use test::{TestOptions, Collector}; /// Separate any lines at the start of the file that begin with `%`. @@ -94,7 +94,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, let rendered = if include_toc { format!("{}", MarkdownWithToc(text)) } else { - format!("{}", Markdown(text, false)) + format!("{}", Markdown(text, MarkdownOutputStyle::Fancy)) }; let err = write!( diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index 2f4a38c16c1d9..1d4f2c60d544f 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -24,7 +24,7 @@ use std::path::PathBuf; use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap, ErrorMetadata}; -use rustdoc::html::markdown::{Markdown, PLAYGROUND}; +use rustdoc::html::markdown::{Markdown, MarkdownOutputStyle, PLAYGROUND}; use rustc_serialize::json; enum OutputFormat { @@ -100,7 +100,7 @@ impl Formatter for HTMLFormatter { // Description rendered as markdown. match info.description { - Some(ref desc) => write!(output, "{}", Markdown(desc, false))?, + Some(ref desc) => write!(output, "{}", Markdown(desc, MarkdownOutputStyle::Fancy))?, None => write!(output, "

    No description.

    \n")?, } From 6d470a9c4a41e97cf7b9d9ab2cc0045d7889d01f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 11 Mar 2017 16:27:54 +0100 Subject: [PATCH 06/14] Add a macro to improve code --- src/librustdoc/html/markdown.rs | 156 ++++++++------------------------ 1 file changed, 39 insertions(+), 117 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index e8c95c4a21c3f..3cc95260e3bd6 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -104,6 +104,25 @@ thread_local!(pub static PLAYGROUND: RefCell, String)>> = RefCell::new(None) }); +macro_rules! event_loop_break { + ($parser:expr, $toc_builder:expr, $shorter:expr, $buf:expr, $($end_event:pat)|*) => {{ + while let Some(event) = $parser.next() { + match event { + $($end_event)|* => break, + Event::Text(ref s) => { + $buf.push_str(s); + } + Event::SoftBreak | Event::HardBreak if !$buf.is_empty() => { + $buf.push(' '); + } + x => { + looper($parser, &mut $buf, Some(x), $toc_builder, $shorter); + } + } + } + }} +} + pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool, @@ -186,21 +205,10 @@ pub fn render(w: &mut fmt::Formatter, }); } - fn header(parser: &mut Parser, level: i32, toc_builder: &mut Option, - buffer: &mut String) { + fn header(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + shorter: MarkdownOutputStyle, level: i32) { let mut ret = String::new(); - while let Some(event) = parser.next() { - match event { - Event::End(Tag::Header(_)) => break, - Event::Text(ref s) => { - ret.push_str(s); - } - Event::SoftBreak | Event::HardBreak if !ret.is_empty() => { - ret.push(' '); - } - _ => {} - } - } + event_loop_break!(parser, toc_builder, shorter, ret, Event::End(Tag::Header(_))); ret = ret.trim_right().to_owned(); let id = ret.clone(); @@ -236,82 +244,35 @@ pub fn render(w: &mut fmt::Formatter, ret, lvl = level, id = id, sec = sec)); } - fn codespan(parser: &mut Parser, buffer: &mut String) { + fn codespan(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + shorter: MarkdownOutputStyle) { let mut content = String::new(); - while let Some(event) = parser.next() { - match event { - Event::End(Tag::Code) => break, - Event::Text(ref s) => { - content.push_str(s); - } - Event::SoftBreak | Event::HardBreak if !content.is_empty() => { - content.push(' '); - } - _ => {} - } - } - buffer.push_str(&format!("{}", Escape(&collapse_whitespace(content.trim_right())))); + event_loop_break!(parser, toc_builder, shorter, content, 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, shorter: MarkdownOutputStyle, url: &str, mut title: String) { - while let Some(event) = parser.next() { - match event { - Event::End(Tag::Link(_, _)) => break, - Event::Text(ref s) => { - title.push_str(s); - } - Event::SoftBreak | Event::HardBreak if !title.is_empty() => { - title.push(' '); - } - x => { - looper(parser, &mut title, Some(x), toc_builder, shorter); - } - } - } + event_loop_break!(parser, toc_builder, shorter, title, Event::End(Tag::Link(_, _))); buffer.push_str(&format!("{}", url, title)); } fn paragraph(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); - while let Some(event) = parser.next() { - match event { - Event::End(Tag::Paragraph) => break, - Event::Text(ref s) => { - content.push_str(s); - } - Event::SoftBreak | Event::HardBreak if !content.is_empty() => { - content.push(' '); - } - x => { - looper(parser, &mut content, Some(x), toc_builder, shorter); - } - } - } + event_loop_break!(parser, toc_builder, shorter, content, Event::End(Tag::Paragraph)); buffer.push_str(&format!("

    {}

    ", content.trim_right())); } fn cell(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); - while let Some(event) = parser.next() { - match event { - Event::End(Tag::TableHead) | - Event::End(Tag::Table(_)) | - Event::End(Tag::TableRow) | - Event::End(Tag::TableCell) => break, - Event::Text(ref s) => { - content.push_str(s); - } - Event::SoftBreak | Event::HardBreak => { - content.push(' '); - } - x => { - looper(parser, &mut content, Some(x), toc_builder, shorter); - } - } - } + event_loop_break!(parser, toc_builder, shorter, content, + Event::End(Tag::TableHead) | + Event::End(Tag::Table(_)) | + Event::End(Tag::TableRow) | + Event::End(Tag::TableCell)); buffer.push_str(&format!("{}", content.trim())); } @@ -381,20 +342,7 @@ pub fn render(w: &mut fmt::Formatter, fn blockquote(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); - while let Some(event) = parser.next() { - match event { - Event::End(Tag::BlockQuote) => break, - Event::Text(ref s) => { - content.push_str(s); - } - Event::SoftBreak | Event::HardBreak if !content.is_empty() => { - content.push(' '); - } - x => { - looper(parser, &mut content, Some(x), toc_builder, shorter); - } - } - } + event_loop_break!(parser, toc_builder, shorter, content, Event::End(Tag::BlockQuote)); buffer.push_str(&format!("
    {}
    ", content.trim_right())); } @@ -435,40 +383,14 @@ pub fn render(w: &mut fmt::Formatter, fn emphasis(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); - while let Some(event) = parser.next() { - match event { - Event::End(Tag::Emphasis) => break, - Event::Text(ref s) => { - content.push_str(s); - } - Event::SoftBreak | Event::HardBreak if !content.is_empty() => { - content.push(' '); - } - x => { - looper(parser, &mut content, Some(x), toc_builder, shorter); - } - } - } + event_loop_break!(parser, toc_builder, shorter, content, Event::End(Tag::Emphasis)); buffer.push_str(&format!("{}", content)); } fn strong(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); - while let Some(event) = parser.next() { - match event { - Event::End(Tag::Strong) => break, - Event::Text(ref s) => { - content.push_str(s); - } - Event::SoftBreak | Event::HardBreak if !content.is_empty() => { - content.push(' '); - } - x => { - looper(parser, &mut content, Some(x), toc_builder, shorter); - } - } - } + event_loop_break!(parser, toc_builder, shorter, content, Event::End(Tag::Strong)); buffer.push_str(&format!("{}", content)); } @@ -480,10 +402,10 @@ pub fn render(w: &mut fmt::Formatter, block(parser, buffer, &*lang); } Event::Start(Tag::Header(level)) => { - header(parser, level, toc_builder, buffer); + header(parser, buffer, toc_builder, shorter, level); } Event::Start(Tag::Code) => { - codespan(parser, buffer); + codespan(parser, buffer, toc_builder, shorter); } Event::Start(Tag::Paragraph) => { paragraph(parser, buffer, toc_builder, shorter); From 6a2190c18e53398191c9d5d9f37c8bcef296402d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 11 Mar 2017 16:37:35 +0100 Subject: [PATCH 07/14] Remove unneeded comment --- src/librustdoc/html/markdown.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 3cc95260e3bd6..09006d9ef8292 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -212,12 +212,6 @@ pub fn render(w: &mut fmt::Formatter, ret = ret.trim_right().to_owned(); let id = ret.clone(); - // Discard '', '' tags and some escaped characters, - // transform the contents of the header into a hyphenated string - // without non-alphanumeric characters other than '-' and '_'. - // - // This is a terrible hack working around how hoedown gives us rendered - // html for text rather than the raw text. let id = id.chars().filter_map(|c| { if c.is_alphanumeric() || c == '-' || c == '_' { if c.is_ascii() { From e51f3253beb60a011bfccc0c5a5eaf119993f175 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 11 Mar 2017 18:09:59 +0100 Subject: [PATCH 08/14] Handle html in markdown as well --- src/librustdoc/html/markdown.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 09006d9ef8292..d823e2bc1f56d 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -422,6 +422,9 @@ pub fn render(w: &mut fmt::Formatter, Event::Start(Tag::Strong) => { strong(parser, buffer, toc_builder, shorter); } + Event::Html(h) | Event::InlineHtml(h) => { + buffer.push_str(&*h); + } _ => {} } shorter.is_fancy() From 474cc0932536c3ade8609fabd9f8fd0c95fd65af Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 12 Mar 2017 20:28:36 +0100 Subject: [PATCH 09/14] Update pulldown version after fix merged --- src/Cargo.lock | 17 ++++++++++++++++- src/librustdoc/Cargo.toml | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 946818e7d2087..11c40fd7cd6c5 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -68,6 +68,11 @@ name = "bitflags" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitflags" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bootstrap" version = "0.0.0" @@ -358,6 +363,15 @@ dependencies = [ "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pulldown-cmark" +version = "0.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "qemu-test-client" version = "0.1.0" @@ -773,7 +787,7 @@ dependencies = [ "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.0.0", - "pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pulldown-cmark 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", "rustc_const_eval 0.0.0", @@ -1005,6 +1019,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842" "checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8" "checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41" +"checksum pulldown-cmark 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "ba85e41d8537ec513bee33aecca3f0bceb53c239807faa09800b39017ab4a965" "checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c" "checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01" "checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index ff18daa7aa098..cd996c0ff3aff 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -25,7 +25,7 @@ rustc_trans = { path = "../librustc_trans" } serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } -pulldown-cmark = "0.0.8" +pulldown-cmark = "0.0.9" [build-dependencies] build_helper = { path = "../build_helper" } From e133821b8914e03dcc80a2ebcf35277d9f11681e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 17 Mar 2017 01:05:21 +0100 Subject: [PATCH 10/14] Update to last pulldown version --- src/Cargo.lock | 62 +++++++++++++++++---------------------- src/librustdoc/Cargo.toml | 2 +- src/librustdoc/lib.rs | 2 +- 3 files changed, 29 insertions(+), 37 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 11c40fd7cd6c5..e2965a100d55c 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -8,7 +8,7 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -27,7 +27,7 @@ version = "0.0.0" dependencies = [ "build_helper 0.1.0", "core 0.0.0", - "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.0.0", ] @@ -65,12 +65,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitflags" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitflags" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -80,7 +75,7 @@ dependencies = [ "build_helper 0.1.0", "cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -109,12 +104,12 @@ version = "0.1.0" [[package]] name = "clap" -version = "2.21.1" +version = "2.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -127,7 +122,7 @@ name = "cmake" version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -145,7 +140,7 @@ version = "0.0.0" dependencies = [ "build_helper 0.1.0", "core 0.0.0", - "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -193,7 +188,7 @@ name = "flate" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -202,7 +197,7 @@ version = "0.0.0" [[package]] name = "gcc" -version = "0.3.44" +version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -220,7 +215,7 @@ version = "0.0.0" [[package]] name = "handlebars" -version = "0.25.1" +version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -277,9 +272,9 @@ name = "mdbook" version = "0.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clap 2.21.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "handlebars 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)", + "handlebars 0.25.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -365,11 +360,10 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.0.9" +version = "0.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -397,7 +391,7 @@ name = "regex" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -430,7 +424,7 @@ dependencies = [ name = "rustbook" version = "0.1.0" dependencies = [ - "clap 2.21.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)", "mdbook 0.0.18 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -607,7 +601,7 @@ name = "rustc_llvm" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_bitflags 0.0.0", ] @@ -783,11 +777,9 @@ version = "0.0.0" dependencies = [ "arena 0.0.0", "build_helper 0.1.0", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.0.0", - "pulldown-cmark 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", "rustc_const_eval 0.0.0", @@ -834,7 +826,7 @@ dependencies = [ "collections 0.0.0", "compiler_builtins 0.0.0", "core 0.0.0", - "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.0.0", "panic_abort 0.0.0", "panic_unwind 0.0.0", @@ -994,19 +986,19 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0638fd549427caa90c499814196d1b9e3725eb4d15d7339d6de073a680ed0ca2" +"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" "checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159" "checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23" -"checksum bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e1ab483fc81a8143faa7203c4a3c02888ebd1a782e37e41fa34753ba9a162" -"checksum clap 2.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "74a80f603221c9cd9aa27a28f52af452850051598537bb6b359c38a7d61e5cda" +"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" +"checksum clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e17a4a72ffea176f77d6e2db609c6c919ef221f23862c9915e687fb54d833485" "checksum cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "d18d68987ed4c516dcc3e7913659bfa4076f5182eea4a7e0038bb060953e76ac" "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" "checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83" "checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922" -"checksum gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)" = "a32cd40070d7611ab76343dcb3204b2bb28c8a9450989a83a3d590248142f439" +"checksum gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "40899336fb50db0c78710f53e87afc54d8c7266fb76262fecc78ca1a7f09deae" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" -"checksum handlebars 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b2249f6f0dc5a3bb2b3b1a8f797dfccbc4b053344d773d654ad565e51427d335" +"checksum handlebars 0.25.2 (registry+https://github.com/rust-lang/crates.io-index)" = "663e1728d8037fb0d4e13bcd1b1909fb5d913690a9929eb385922df157c2ff8f" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7291b1dd97d331f752620b02dfdbc231df7fc01bf282a00769e1cdb963c460dc" @@ -1018,8 +1010,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3" "checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842" "checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8" +"checksum pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ab1e588ef8efd702c7ed9d2bd774db5e6f4d878bb5a1a9f371828fbdff6973" "checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41" -"checksum pulldown-cmark 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "ba85e41d8537ec513bee33aecca3f0bceb53c239807faa09800b39017ab4a965" "checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c" "checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01" "checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index cd996c0ff3aff..52f5d99838dc7 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -25,7 +25,7 @@ rustc_trans = { path = "../librustc_trans" } serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } -pulldown-cmark = "0.0.9" +pulldown-cmark = { version = "0.0.14", default-features = false } [build-dependencies] build_helper = { path = "../build_helper" } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index efb51bdf471f4..447d60018d912 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -9,7 +9,7 @@ // except according to those terms. #![crate_name = "rustdoc"] -#![unstable(feature = "rustdoc", issue = "27812")] +#![unstable(feature = "rustc_private", issue = "27812")] #![crate_type = "dylib"] #![crate_type = "rlib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", From cba67ad8012c63ddae8b4c540bbb6f70a93c8ddf Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 24 Mar 2017 23:53:18 +0100 Subject: [PATCH 11/14] Add feature for rustdoc binary --- src/rustc/rustdoc.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rustc/rustdoc.rs b/src/rustc/rustdoc.rs index 6fecd3a27a8a4..ccedb9844bbac 100644 --- a/src/rustc/rustdoc.rs +++ b/src/rustc/rustdoc.rs @@ -9,6 +9,7 @@ // except according to those terms. #![feature(rustdoc)] +#![feature(rustc_private)] extern crate rustdoc; From 47e4abf47397438ca86e96ed3f848276dddd5738 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 25 Mar 2017 01:48:33 +0100 Subject: [PATCH 12/14] Fix plain_summary_line function --- src/librustdoc/html/markdown.rs | 84 ++++++++++++++++++++------------- src/rustc/rustdoc.rs | 1 - 2 files changed, 51 insertions(+), 34 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index d823e2bc1f56d..4d67e8b532999 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -106,11 +106,19 @@ thread_local!(pub static PLAYGROUND: RefCell, String)>> = macro_rules! event_loop_break { ($parser:expr, $toc_builder:expr, $shorter:expr, $buf:expr, $($end_event:pat)|*) => {{ + event_loop_break($parser, $toc_builder, $shorter, $buf, false, $($end_event:pat)|*); + }}; + ($parser:expr, $toc_builder:expr, $shorter:expr, $buf:expr, $escape:expr, + $($end_event:pat)|*) => {{ while let Some(event) = $parser.next() { match event { $($end_event)|* => break, Event::Text(ref s) => { - $buf.push_str(s); + if $escape { + $buf.push_str(&escape(s)); + } else { + $buf.push_str(s); + } } Event::SoftBreak | Event::HardBreak if !$buf.is_empty() => { $buf.push(' '); @@ -127,6 +135,13 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool, shorter: MarkdownOutputStyle) -> fmt::Result { + fn escape(entry: &str) -> String { + entry.replace("<", "<") + .replace("'", "'") + .replace(">", ">") + .replace("&", "&") + } + fn block(parser: &mut Parser, buffer: &mut String, lang: &str) { let mut origtext = String::new(); while let Some(event) = parser.next() { @@ -208,7 +223,7 @@ pub fn render(w: &mut fmt::Formatter, fn header(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle, level: i32) { let mut ret = String::new(); - event_loop_break!(parser, toc_builder, shorter, ret, Event::End(Tag::Header(_))); + event_loop_break!(parser, toc_builder, shorter, ret, true, Event::End(Tag::Header(_))); ret = ret.trim_right().to_owned(); let id = ret.clone(); @@ -241,28 +256,28 @@ pub fn render(w: &mut fmt::Formatter, fn codespan(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); - event_loop_break!(parser, toc_builder, shorter, content, Event::End(Tag::Code)); + event_loop_break!(parser, toc_builder, shorter, content, true, 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, shorter: MarkdownOutputStyle, url: &str, mut title: String) { - event_loop_break!(parser, toc_builder, shorter, title, Event::End(Tag::Link(_, _))); + event_loop_break!(parser, toc_builder, shorter, title, true, Event::End(Tag::Link(_, _))); buffer.push_str(&format!("{}", url, title)); } fn paragraph(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); - event_loop_break!(parser, toc_builder, shorter, content, Event::End(Tag::Paragraph)); + event_loop_break!(parser, toc_builder, shorter, content, true, Event::End(Tag::Paragraph)); buffer.push_str(&format!("

    {}

    ", content.trim_right())); } fn cell(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); - event_loop_break!(parser, toc_builder, shorter, content, + event_loop_break!(parser, toc_builder, shorter, content, true, Event::End(Tag::TableHead) | Event::End(Tag::Table(_)) | Event::End(Tag::TableRow) | @@ -336,7 +351,7 @@ pub fn render(w: &mut fmt::Formatter, fn blockquote(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); - event_loop_break!(parser, toc_builder, shorter, content, Event::End(Tag::BlockQuote)); + event_loop_break!(parser, toc_builder, shorter, content, true, Event::End(Tag::BlockQuote)); buffer.push_str(&format!("
    {}
    ", content.trim_right())); } @@ -347,7 +362,7 @@ pub fn render(w: &mut fmt::Formatter, match event { Event::End(Tag::Item) => break, Event::Text(ref s) => { - content.push_str(s); + content.push_str(&escape(s)); } x => { looper(parser, &mut content, Some(x), toc_builder, shorter); @@ -377,14 +392,14 @@ pub fn render(w: &mut fmt::Formatter, fn emphasis(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); - event_loop_break!(parser, toc_builder, shorter, content, Event::End(Tag::Emphasis)); + event_loop_break!(parser, toc_builder, shorter, content, true, Event::End(Tag::Emphasis)); buffer.push_str(&format!("{}", content)); } fn strong(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); - event_loop_break!(parser, toc_builder, shorter, content, Event::End(Tag::Strong)); + event_loop_break!(parser, toc_builder, shorter, content, true, Event::End(Tag::Strong)); buffer.push_str(&format!("{}", content)); } @@ -644,9 +659,12 @@ pub fn plain_summary_line(md: &str) -> String { Event::Start(Tag::Link(_, ref t)) if !self.is_first => { (Some(t.as_ref().to_owned()), 1) } + Event::Start(Tag::Code) => (Some("`".to_owned()), 1), + Event::End(Tag::Code) => (Some("`".to_owned()), -1), + Event::Start(Tag::Header(_)) => (None, 1), Event::Text(ref s) if self.is_in > 0 => (Some(s.as_ref().to_owned()), 0), Event::End(Tag::Link(_, ref t)) => (Some(t.as_ref().to_owned()), -1), - Event::End(Tag::Paragraph) => (None, -1), + Event::End(Tag::Paragraph) | Event::End(Tag::Header(_)) => (None, -1), _ => (None, 0), }; if is_in > 0 || (is_in < 0 && self.is_in > 0) { @@ -728,17 +746,17 @@ mod tests { reset_ids(true); } - t("# Foo bar", "\n

    \ - Foo bar

    "); - t("## Foo-bar_baz qux", "\n

    Foo-bar_baz qux

    "); + t("# Foo bar", "

    \ + Foo bar

    "); + t("## Foo-bar_baz qux", "

    Foo-bar_baz qux

    "); t("### **Foo** *bar* baz!?!& -_qux_-%", - "\n

    \ - Foo \ + "

    \ + Foo \ bar baz!?!& -_qux_-%

    "); t("####**Foo?** & \\*bar?!* _`baz`_ ❤ #qux", - "\n

    \ - Foo? & *bar?!* \ + "

    \ + Foo? & *bar?!* \ baz ❤ #qux

    "); } @@ -750,18 +768,18 @@ mod tests { } let test = || { - t("# Example", "\n

    \ - Example

    "); - t("# Panics", "\n

    \ - Panics

    "); - t("# Example", "\n

    \ - Example

    "); - t("# Main", "\n

    \ - Main

    "); - t("# Example", "\n

    \ - Example

    "); - t("# Panics", "\n

    \ - Panics

    "); + t("# Example", "

    \ + Example

    "); + t("# Panics", "

    \ + Panics

    "); + t("# Example", "

    \ + Example

    "); + t("# Main", "

    \ + Main

    "); + t("# Example", "

    \ + Example

    "); + t("# Panics", "

    \ + Panics

    "); }; test(); reset_ids(true); @@ -789,7 +807,7 @@ mod tests { assert_eq!(output, expect); } - t("`Struct<'a, T>`", "

    Struct<'a, T>

    \n"); - t("Struct<'a, T>", "

    Struct<'a, T>

    \n"); + t("`Struct<'a, T>`", "

    Struct<'a, T>

    "); + t("Struct<'a, T>", "

    Struct<'a, T>

    "); } } diff --git a/src/rustc/rustdoc.rs b/src/rustc/rustdoc.rs index ccedb9844bbac..a4f43c42623d3 100644 --- a/src/rustc/rustdoc.rs +++ b/src/rustc/rustdoc.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rustdoc)] #![feature(rustc_private)] extern crate rustdoc; From 286a51da9187971c2aa5bac89834f5be7cc96d86 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 25 Mar 2017 19:07:52 +0100 Subject: [PATCH 13/14] Fix id generation --- src/Cargo.lock | 9 +-- src/librustdoc/html/markdown.rs | 98 +++++++++++++++++---------------- 2 files changed, 56 insertions(+), 51 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index e2965a100d55c..a9021dc34e207 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -218,7 +218,7 @@ name = "handlebars" version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -243,7 +243,7 @@ dependencies = [ [[package]] name = "lazy_static" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -777,8 +777,9 @@ version = "0.0.0" dependencies = [ "arena 0.0.0", "build_helper 0.1.0", + "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.0.0", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", @@ -1001,7 +1002,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum handlebars 0.25.2 (registry+https://github.com/rust-lang/crates.io-index)" = "663e1728d8037fb0d4e13bcd1b1909fb5d913690a9929eb385922df157c2ff8f" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7291b1dd97d331f752620b02dfdbc231df7fc01bf282a00769e1cdb963c460dc" +"checksum lazy_static 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4732c563b9a21a406565c4747daa7b46742f082911ae4753f390dc9ec7ee1a97" "checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135" "checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" "checksum mdbook 0.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "06a68e8738e42b38a02755d3ce5fa12d559e17acb238e4326cbc3cc056e65280" diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 4d67e8b532999..e55f3fa91dcdc 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -105,17 +105,20 @@ thread_local!(pub static PLAYGROUND: RefCell, String)>> = }); macro_rules! event_loop_break { - ($parser:expr, $toc_builder:expr, $shorter:expr, $buf:expr, $($end_event:pat)|*) => {{ - event_loop_break($parser, $toc_builder, $shorter, $buf, false, $($end_event:pat)|*); - }}; - ($parser:expr, $toc_builder:expr, $shorter:expr, $buf:expr, $escape:expr, + ($parser:expr, $toc_builder:expr, $shorter:expr, $buf:expr, $escape:expr, $id:expr, $($end_event:pat)|*) => {{ + fn inner(id: &mut Option<&mut String>, s: &str) { + if let Some(ref mut id) = *id { + id.push_str(s); + } + } while let Some(event) = $parser.next() { match event { $($end_event)|* => break, Event::Text(ref s) => { + inner($id, s); if $escape { - $buf.push_str(&escape(s)); + $buf.push_str(&format!("{}", Escape(s))); } else { $buf.push_str(s); } @@ -124,7 +127,7 @@ macro_rules! event_loop_break { $buf.push(' '); } x => { - looper($parser, &mut $buf, Some(x), $toc_builder, $shorter); + looper($parser, &mut $buf, Some(x), $toc_builder, $shorter, $id); } } } @@ -135,13 +138,6 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool, shorter: MarkdownOutputStyle) -> fmt::Result { - fn escape(entry: &str) -> String { - entry.replace("<", "<") - .replace("'", "'") - .replace(">", ">") - .replace("&", "&") - } - fn block(parser: &mut Parser, buffer: &mut String, lang: &str) { let mut origtext = String::new(); while let Some(event) = parser.next() { @@ -223,10 +219,11 @@ pub fn render(w: &mut fmt::Formatter, fn header(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle, level: i32) { let mut ret = String::new(); - event_loop_break!(parser, toc_builder, shorter, ret, true, Event::End(Tag::Header(_))); + let mut id = String::new(); + event_loop_break!(parser, toc_builder, shorter, ret, true, &mut Some(&mut id), + Event::End(Tag::Header(_))); ret = ret.trim_right().to_owned(); - let id = ret.clone(); let id = id.chars().filter_map(|c| { if c.is_alphanumeric() || c == '-' || c == '_' { if c.is_ascii() { @@ -254,30 +251,33 @@ pub fn render(w: &mut fmt::Formatter, } fn codespan(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: MarkdownOutputStyle) { + shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) { let mut content = String::new(); - event_loop_break!(parser, toc_builder, shorter, content, true, Event::End(Tag::Code)); + 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, - shorter: MarkdownOutputStyle, url: &str, mut title: String) { - event_loop_break!(parser, toc_builder, shorter, title, true, Event::End(Tag::Link(_, _))); + 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)); } fn paragraph(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: MarkdownOutputStyle) { + shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) { let mut content = String::new(); - event_loop_break!(parser, toc_builder, shorter, content, true, Event::End(Tag::Paragraph)); + event_loop_break!(parser, toc_builder, shorter, content, true, id, + Event::End(Tag::Paragraph)); buffer.push_str(&format!("

    {}

    ", content.trim_right())); } fn cell(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); - event_loop_break!(parser, toc_builder, shorter, content, true, + event_loop_break!(parser, toc_builder, shorter, content, true, &mut None, Event::End(Tag::TableHead) | Event::End(Tag::Table(_)) | Event::End(Tag::TableRow) | @@ -297,7 +297,7 @@ pub fn render(w: &mut fmt::Formatter, cell(parser, &mut content, toc_builder, shorter); } x => { - looper(parser, &mut content, Some(x), toc_builder, shorter); + looper(parser, &mut content, Some(x), toc_builder, shorter, &mut None); } } } @@ -314,7 +314,7 @@ pub fn render(w: &mut fmt::Formatter, cell(parser, &mut content, toc_builder, shorter); } x => { - looper(parser, &mut content, Some(x), toc_builder, shorter); + looper(parser, &mut content, Some(x), toc_builder, shorter, &mut None); } } } @@ -351,7 +351,8 @@ pub fn render(w: &mut fmt::Formatter, fn blockquote(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, shorter: MarkdownOutputStyle) { let mut content = String::new(); - event_loop_break!(parser, toc_builder, shorter, content, true, Event::End(Tag::BlockQuote)); + event_loop_break!(parser, toc_builder, shorter, content, true, &mut None, + Event::End(Tag::BlockQuote)); buffer.push_str(&format!("
    {}
    ", content.trim_right())); } @@ -362,10 +363,10 @@ pub fn render(w: &mut fmt::Formatter, match event { Event::End(Tag::Item) => break, Event::Text(ref s) => { - content.push_str(&escape(s)); + content.push_str(&format!("{}", Escape(s))); } x => { - looper(parser, &mut content, Some(x), toc_builder, shorter); + looper(parser, &mut content, Some(x), toc_builder, shorter, &mut None); } } } @@ -382,7 +383,7 @@ pub fn render(w: &mut fmt::Formatter, list_item(parser, &mut content, toc_builder, shorter); } x => { - looper(parser, &mut content, Some(x), toc_builder, shorter); + looper(parser, &mut content, Some(x), toc_builder, shorter, &mut None); } } } @@ -390,21 +391,24 @@ pub fn render(w: &mut fmt::Formatter, } fn emphasis(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: MarkdownOutputStyle) { + shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) { let mut content = String::new(); - event_loop_break!(parser, toc_builder, shorter, content, true, Event::End(Tag::Emphasis)); + 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, - shorter: MarkdownOutputStyle) { + shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) { let mut content = String::new(); - event_loop_break!(parser, toc_builder, shorter, content, true, Event::End(Tag::Strong)); + event_loop_break!(parser, toc_builder, shorter, content, false, id, + Event::End(Tag::Strong)); buffer.push_str(&format!("{}", content)); } fn looper<'a>(parser: &'a mut Parser, buffer: &mut String, next_event: Option>, - toc_builder: &mut Option, shorter: MarkdownOutputStyle) -> bool { + toc_builder: &mut Option, shorter: MarkdownOutputStyle, + id: &mut Option<&mut String>) -> bool { if let Some(event) = next_event { match event { Event::Start(Tag::CodeBlock(lang)) => { @@ -414,13 +418,13 @@ pub fn render(w: &mut fmt::Formatter, header(parser, buffer, toc_builder, shorter, level); } Event::Start(Tag::Code) => { - codespan(parser, buffer, toc_builder, shorter); + codespan(parser, buffer, toc_builder, shorter, id); } Event::Start(Tag::Paragraph) => { - paragraph(parser, buffer, toc_builder, shorter); + 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()); + link(parser, buffer, toc_builder, shorter, url, t.as_ref().to_owned(), id); } Event::Start(Tag::Table(_)) => { table(parser, buffer, toc_builder, shorter); @@ -432,10 +436,10 @@ pub fn render(w: &mut fmt::Formatter, list(parser, buffer, toc_builder, shorter); } Event::Start(Tag::Emphasis) => { - emphasis(parser, buffer, toc_builder, shorter); + emphasis(parser, buffer, toc_builder, shorter, id); } Event::Start(Tag::Strong) => { - strong(parser, buffer, toc_builder, shorter); + strong(parser, buffer, toc_builder, shorter, id); } Event::Html(h) | Event::InlineHtml(h) => { buffer.push_str(&*h); @@ -457,7 +461,7 @@ pub fn render(w: &mut fmt::Formatter, let mut parser = Parser::new_ext(s, pulldown_cmark::OPTION_ENABLE_TABLES); loop { let next_event = parser.next(); - if !looper(&mut parser, &mut buffer, next_event, &mut toc_builder, shorter) { + if !looper(&mut parser, &mut buffer, next_event, &mut toc_builder, shorter, &mut None) { break } } @@ -742,7 +746,7 @@ mod tests { fn test_header() { fn t(input: &str, expect: &str) { let output = format!("{}", Markdown(input, MarkdownOutputStyle::Fancy)); - assert_eq!(output, expect); + assert_eq!(output, expect, "original: {}", input); reset_ids(true); } @@ -751,10 +755,10 @@ mod tests { t("## Foo-bar_baz qux", "

    Foo-bar_baz qux

    "); t("### **Foo** *bar* baz!?!& -_qux_-%", - "

    \ - Foo \ - bar baz!?!& -_qux_-%

    "); - t("####**Foo?** & \\*bar?!* _`baz`_ ❤ #qux", + "

    \ + Foo \ + bar baz!?!& -qux-%

    "); + t("#### **Foo?** & \\*bar?!* _`baz`_ ❤ #qux", "

    \ Foo? & *bar?!* \ baz ❤ #qux

    "); @@ -764,7 +768,7 @@ mod tests { fn test_header_ids_multiple_blocks() { fn t(input: &str, expect: &str) { let output = format!("{}", Markdown(input, MarkdownOutputStyle::Fancy)); - assert_eq!(output, expect); + assert_eq!(output, expect, "original: {}", input); } let test = || { @@ -790,7 +794,7 @@ mod tests { fn test_plain_summary_line() { fn t(input: &str, expect: &str) { let output = plain_summary_line(input); - assert_eq!(output, expect); + assert_eq!(output, expect, "original: {}", input); } t("hello [Rust](https://www.rust-lang.org) :)", "hello Rust :)"); @@ -804,7 +808,7 @@ mod tests { fn test_markdown_html_escape() { fn t(input: &str, expect: &str) { let output = format!("{}", MarkdownHtml(input)); - assert_eq!(output, expect); + assert_eq!(output, expect, "original: {}", input); } t("`Struct<'a, T>`", "

    Struct<'a, T>

    "); From a7c6d3e16a71fc0dcce4c9be09d031d746f84a69 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 28 Mar 2017 11:54:11 -0600 Subject: [PATCH 14/14] Improve function naming --- src/librustdoc/html/markdown.rs | 45 ++++++++++++++++----------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index e55f3fa91dcdc..117cfbabb52f7 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -10,17 +10,16 @@ //! Markdown formatting for rustdoc //! -//! This module implements markdown formatting through the hoedown C-library -//! (bundled into the rust runtime). This module self-contains the C bindings -//! and necessary legwork to render markdown, and exposes all of the +//! This module implements markdown formatting through the pulldown-cmark +//! rust-library. This module exposes all of the //! functionality through a unit-struct, `Markdown`, which has an implementation //! of `fmt::Display`. Example usage: //! //! ```rust,ignore -//! use rustdoc::html::markdown::Markdown; +//! use rustdoc::html::markdown::{Markdown, MarkdownOutputStyle}; //! //! let s = "My *markdown* _text_"; -//! let html = format!("{}", Markdown(s)); +//! let html = format!("{}", Markdown(s, MarkdownOutputStyle::Fancy)); //! // ... something using html //! ``` @@ -138,7 +137,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool, shorter: MarkdownOutputStyle) -> fmt::Result { - fn block(parser: &mut Parser, buffer: &mut String, lang: &str) { + fn code_block(parser: &mut Parser, buffer: &mut String, lang: &str) { let mut origtext = String::new(); while let Some(event) = parser.next() { match event { @@ -216,8 +215,8 @@ pub fn render(w: &mut fmt::Formatter, }); } - fn header(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: MarkdownOutputStyle, level: i32) { + fn heading(parser: &mut Parser, 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), @@ -250,8 +249,8 @@ pub fn render(w: &mut fmt::Formatter, ret, lvl = level, id = id, sec = sec)); } - fn codespan(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) { + fn inline_code(parser: &mut Parser, 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!("{}", @@ -274,8 +273,8 @@ pub fn render(w: &mut fmt::Formatter, buffer.push_str(&format!("

    {}

    ", content.trim_right())); } - fn cell(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: MarkdownOutputStyle) { + fn table_cell(parser: &mut Parser, 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) | @@ -285,8 +284,8 @@ pub fn render(w: &mut fmt::Formatter, buffer.push_str(&format!("{}", content.trim())); } - fn row(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: MarkdownOutputStyle) { + fn table_row(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + shorter: MarkdownOutputStyle) { let mut content = String::new(); while let Some(event) = parser.next() { match event { @@ -294,7 +293,7 @@ pub fn render(w: &mut fmt::Formatter, Event::End(Tag::Table(_)) | Event::End(Tag::TableRow) => break, Event::Start(Tag::TableCell) => { - cell(parser, &mut content, toc_builder, shorter); + table_cell(parser, &mut content, toc_builder, shorter); } x => { looper(parser, &mut content, Some(x), toc_builder, shorter, &mut None); @@ -304,14 +303,14 @@ pub fn render(w: &mut fmt::Formatter, buffer.push_str(&format!("{}", content)); } - fn head(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, - shorter: MarkdownOutputStyle) { + fn table_head(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option, + shorter: MarkdownOutputStyle) { let mut content = String::new(); while let Some(event) = parser.next() { match event { Event::End(Tag::TableHead) | Event::End(Tag::Table(_)) => break, Event::Start(Tag::TableCell) => { - cell(parser, &mut content, toc_builder, shorter); + table_cell(parser, &mut content, toc_builder, shorter); } x => { looper(parser, &mut content, Some(x), toc_builder, shorter, &mut None); @@ -331,10 +330,10 @@ pub fn render(w: &mut fmt::Formatter, match event { Event::End(Tag::Table(_)) => break, Event::Start(Tag::TableHead) => { - head(parser, &mut content, toc_builder, shorter); + table_head(parser, &mut content, toc_builder, shorter); } Event::Start(Tag::TableRow) => { - row(parser, &mut rows, toc_builder, shorter); + table_row(parser, &mut rows, toc_builder, shorter); } _ => {} } @@ -412,13 +411,13 @@ pub fn render(w: &mut fmt::Formatter, if let Some(event) = next_event { match event { Event::Start(Tag::CodeBlock(lang)) => { - block(parser, buffer, &*lang); + code_block(parser, buffer, &*lang); } Event::Start(Tag::Header(level)) => { - header(parser, buffer, toc_builder, shorter, level); + heading(parser, buffer, toc_builder, shorter, level); } Event::Start(Tag::Code) => { - codespan(parser, buffer, toc_builder, shorter, id); + inline_code(parser, buffer, toc_builder, shorter, id); } Event::Start(Tag::Paragraph) => { paragraph(parser, buffer, toc_builder, shorter, id);