From ae193f1d4852b2e8a751999693fa324fd462dc30 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 3 Sep 2014 20:53:47 -0400 Subject: [PATCH 1/6] update to latest hoedown to get builtin mathjax support --- src/rt/hoedown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rt/hoedown b/src/rt/hoedown index 238c4d57cce10..794d91b370202 160000 --- a/src/rt/hoedown +++ b/src/rt/hoedown @@ -1 +1 @@ -Subproject commit 238c4d57cce10d33b05cf52a91fc62a09f31ffbb +Subproject commit 794d91b37020242446c53713c7ce0c09b33b5f0c From d65092a7b537a7893afca57ffb877fe22fbebd15 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 3 Sep 2014 21:17:15 -0400 Subject: [PATCH 2/6] enable mathjax support in rustdoc --- src/librustdoc/html/layout.rs | 8 ++++++++ src/librustdoc/html/markdown.rs | 17 +++++++++++++++-- src/librustdoc/html/render.rs | 8 ++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 896d070c155ee..967828d6d84ac 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -20,6 +20,7 @@ pub struct Layout { pub external_html: ExternalHtml, pub krate: String, pub playground_url: String, + pub use_mathjax: bool, } pub struct Page<'a> { @@ -124,6 +125,7 @@ r##" {play_js} + {mathjax_js} "##, content = *t, @@ -156,6 +158,12 @@ r##" } else { format!(r#""#, page.root_path) }, + mathjax_js = if layout.use_mathjax { + r#""#.to_string() + } else { + "".to_string() + }, ) } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 305c18480f669..9103abfa25b04 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -56,6 +56,7 @@ static HOEDOWN_EXT_AUTOLINK: libc::c_uint = 1 << 3; static HOEDOWN_EXT_STRIKETHROUGH: libc::c_uint = 1 << 4; static HOEDOWN_EXT_SUPERSCRIPT: libc::c_uint = 1 << 8; static HOEDOWN_EXT_FOOTNOTES: libc::c_uint = 1 << 2; +static HOEDOWN_EXT_MATH: libc::c_uint = 1 << 13; static HOEDOWN_EXTENSIONS: libc::c_uint = HOEDOWN_EXT_NO_INTRA_EMPHASIS | HOEDOWN_EXT_TABLES | @@ -147,10 +148,22 @@ fn stripped_filtered_line<'a>(s: &'a str) -> Option<&'a str> { } } +fn hoedown_extensions() -> libc::c_uint { + let mut extensions = HOEDOWN_EXTENSIONS; + + match use_mathjax.get().as_ref() { + Some(use_math) if **use_math => { extensions |= HOEDOWN_EXT_MATH; } + _ => {} + } + + extensions +} + local_data_key!(used_header_map: RefCell>) local_data_key!(test_idx: Cell) // None == render an example, but there's no crate name local_data_key!(pub playground_krate: Option) +local_data_key!(pub use_mathjax: bool) pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { extern fn block(ob: *mut hoedown_buffer, text: *const hoedown_buffer, @@ -285,7 +298,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { (*renderer).blockcode = Some(block); (*renderer).header = Some(header); - let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16); + 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); @@ -363,7 +376,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) { (*renderer).header = Some(header); (*(*renderer).opaque).opaque = tests as *mut _ as *mut libc::c_void; - let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16); + 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); diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index fc8fd0d086bc0..043d313a54384 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -245,11 +245,14 @@ pub fn run(mut krate: clean::Crate, external_html: &ExternalHtml, dst: Path) -> external_html: external_html.clone(), krate: krate.name.clone(), playground_url: "".to_string(), + use_mathjax: false, }, include_sources: true, render_redirect_pages: false, }; + markdown::use_mathjax.replace(None); + try!(mkdir(&cx.dst)); // Crawl the crate, building a summary of the stability levels. NOTE: this @@ -284,6 +287,11 @@ pub fn run(mut krate: clean::Crate, external_html: &ExternalHtml, dst: Path) -> if "html_no_source" == x.as_slice() => { cx.include_sources = false; } + clean::Word(ref x) + if "enable_mathjax" == x.as_slice() => { + cx.layout.use_mathjax = true; + markdown::use_mathjax.replace(Some(true)); + } _ => {} } } From 18b5740f37b988d6bac8515ea790c2a853160124 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Thu, 4 Sep 2014 15:35:22 -0400 Subject: [PATCH 3/6] add new fields to hoedown structs --- src/librustdoc/html/markdown.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 9103abfa25b04..3ca80f289d43c 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -77,7 +77,7 @@ struct hoedown_renderer { *mut libc::c_void)>, header: Option, - other: [libc::size_t, ..28], + other: [libc::size_t, ..29], } #[repr(C)] @@ -110,6 +110,7 @@ struct hoedown_buffer { size: libc::size_t, asize: libc::size_t, unit: libc::size_t, + other: [libc::size_t, ..3], } // hoedown FFI From 04f39f8050406631195b8ee4fd5fe4ab82bdf216 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Thu, 4 Sep 2014 16:44:33 -0400 Subject: [PATCH 4/6] expand hoedown renderer struct --- src/librustdoc/html/markdown.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 3ca80f289d43c..51376a5852cae 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -110,7 +110,9 @@ struct hoedown_buffer { size: libc::size_t, asize: libc::size_t, unit: libc::size_t, - other: [libc::size_t, ..3], + data_realloc: *mut Option, + data_free: Option, + buffer_free: Option, } // hoedown FFI From 7affc428ae8688d36a1b6114b61d31b0f227e9aa Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Thu, 4 Sep 2014 16:58:39 -0400 Subject: [PATCH 5/6] fix renderer struct --- src/librustdoc/html/markdown.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 51376a5852cae..e70ca6d5a241a 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -65,6 +65,9 @@ static HOEDOWN_EXTENSIONS: libc::c_uint = HOEDOWN_EXT_FOOTNOTES; type hoedown_document = libc::c_void; // this is opaque to us +type hoedown_realloc_callback = extern "C" fn(*mut libc::c_void, libc::size_t) + -> *mut libc::size_t; +type hoedown_free_callback = extern "C" fn(*mut libc::c_void); #[repr(C)] struct hoedown_renderer { @@ -110,9 +113,9 @@ struct hoedown_buffer { size: libc::size_t, asize: libc::size_t, unit: libc::size_t, - data_realloc: *mut Option, - data_free: Option, - buffer_free: Option, + data_realloc: Option, + data_free: Option, + buffer_free: Option, } // hoedown FFI From 3388cd8081eecc66d57db23322c5da88dc608187 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Thu, 4 Sep 2014 19:51:34 -0400 Subject: [PATCH 6/6] huon patch with fixups --- src/librustdoc/html/layout.rs | 8 ++++- src/librustdoc/html/markdown.rs | 55 +++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 967828d6d84ac..46b89b3851526 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -12,6 +12,7 @@ use std::fmt; use std::io; use externalfiles::ExternalHtml; +use html::markdown; #[deriving(Clone)] pub struct Layout { @@ -35,6 +36,10 @@ pub fn render( dst: &mut io::Writer, layout: &Layout, page: &Page, sidebar: &S, t: &T) -> io::IoResult<()> { + // Reset state on whether we've seen math, so as to avoid loading mathjax + // on pages that don't actually *have* math. + markdown::math_seen.replace(Some(false)); + write!(dst, r##" @@ -158,7 +163,8 @@ r##" } else { format!(r#""#, page.root_path) }, - mathjax_js = if layout.use_mathjax { + // this must be last so that `math_seen` captures all possible $$'s on this page. + mathjax_js = if layout.use_mathjax && markdown::math_seen.get().map_or(false, |x| *x) { r#""#.to_string() } else { diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index e70ca6d5a241a..4d4b8ffd63e82 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -80,7 +80,9 @@ struct hoedown_renderer { *mut libc::c_void)>, header: Option, - other: [libc::size_t, ..29], + math: Option libc::c_int>, + other: [libc::size_t, ..28], } #[repr(C)] @@ -105,6 +107,8 @@ struct MyOpaque { dfltblk: extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, *const hoedown_buffer, *mut libc::c_void), toc_builder: Option, + math_enabled: bool, + math_seen: bool, } #[repr(C)] @@ -137,8 +141,13 @@ extern { fn hoedown_buffer_new(unit: libc::size_t) -> *mut hoedown_buffer; fn hoedown_buffer_puts(b: *mut hoedown_buffer, c: *const libc::c_char); - fn hoedown_buffer_free(b: *mut hoedown_buffer); + fn hoedown_buffer_put(b: *mut hoedown_buffer, data: *const libc::c_void, len: libc::size_t); + fn hoedown_buffer_free(b: *mut hoedown_buffer); + fn hoedown_escape_html(ob: *mut hoedown_buffer, + src: *const libc::uint8_t, + size: libc::size_t, + secure: libc::c_int); } /// Returns Some(code) if `s` is a line that should be stripped from @@ -170,6 +179,7 @@ local_data_key!(test_idx: Cell) // None == render an example, but there's no crate name local_data_key!(pub playground_krate: Option) local_data_key!(pub use_mathjax: bool) +local_data_key!(pub math_seen: bool) pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { extern fn block(ob: *mut hoedown_buffer, text: *const hoedown_buffer, @@ -192,6 +202,9 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { size: text.len() as libc::size_t, asize: text.len() as libc::size_t, unit: 0, + data_free: None, + data_realloc: None, + buffer_free: None, }; let rendered = if lang.is_null() { false @@ -293,16 +306,48 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { text.with_c_str(|p| unsafe { hoedown_buffer_puts(ob, p) }); } + extern fn math(ob: *mut hoedown_buffer, text: *const hoedown_buffer, + display_mode: libc::c_int, opaque: *mut libc::c_void) -> libc::c_int { + + let opaque = opaque as *mut hoedown_html_renderer_state; + let opaque = unsafe { &mut *((*opaque).opaque as *mut MyOpaque) }; + + opaque.math_seen = true; + + let (open, close) = if !opaque.math_enabled { + ("$$", "$$") + } else if display_mode == 1 { + ("\\[", "\\]") + } else { + ("\\(", "\\)") + }; + + open.with_c_str(|open| { + close.with_c_str(|close| { + unsafe { + hoedown_buffer_put(ob, open as *const libc::c_void, 2); + hoedown_escape_html(ob, (*text).data, (*text).size, 0); + hoedown_buffer_put(ob, close as *const libc::c_void, 2); + } + }) + }); + + 1 + } + unsafe { let ob = hoedown_buffer_new(DEF_OUNIT); let renderer = hoedown_html_renderer_new(0, 0); let mut opaque = MyOpaque { dfltblk: (*renderer).blockcode.unwrap(), - toc_builder: if print_toc {Some(TocBuilder::new())} else {None} + toc_builder: if print_toc {Some(TocBuilder::new())} else {None}, + math_enabled: use_mathjax.get().map_or(false, |x| *x), + math_seen: false, }; (*(*renderer).opaque).opaque = &mut opaque as *mut _ as *mut libc::c_void; (*renderer).blockcode = Some(block); (*renderer).header = Some(header); + (*renderer).math = Some(math); let document = hoedown_document_new(renderer, hoedown_extensions(), 16); hoedown_document_render(document, ob, s.as_ptr(), @@ -322,6 +367,10 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { }); } hoedown_buffer_free(ob); + + let old = math_seen.get().map_or(false, |x| *x); + math_seen.replace(Some(old || opaque.math_seen)); + ret } }