diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2014-06-06 09:12:18 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2014-06-06 20:00:16 -0700 |
| commit | e5bbbca33e11d9e22dbbe32c975f908710d4155c (patch) | |
| tree | 5095bb40b83e840f373b22f9fe62b0228d3a3453 /src/librustdoc/html | |
| parent | cc63d4c61bb83fcbcef5ccfffcd9b26b1bf2d20a (diff) | |
| download | rust-e5bbbca33e11d9e22dbbe32c975f908710d4155c.tar.gz rust-e5bbbca33e11d9e22dbbe32c975f908710d4155c.zip | |
rustdoc: Submit examples to play.rust-lang.org
This grows a new option inside of rustdoc to add the ability to submit examples to an external website. If the `--markdown-playground-url` command line option or crate doc attribute `html_playground_url` is present, then examples will have a button on hover to submit the code to the playground specified. This commit enables submission of example code to play.rust-lang.org. The code submitted is that which is tested by rustdoc, not necessarily the exact code shown in the example. Closes #14654
Diffstat (limited to 'src/librustdoc/html')
| -rw-r--r-- | src/librustdoc/html/highlight.rs | 13 | ||||
| -rw-r--r-- | src/librustdoc/html/layout.rs | 13 | ||||
| -rw-r--r-- | src/librustdoc/html/markdown.rs | 35 | ||||
| -rw-r--r-- | src/librustdoc/html/render.rs | 15 | ||||
| -rw-r--r-- | src/librustdoc/html/static/main.css | 13 | ||||
| -rw-r--r-- | src/librustdoc/html/static/main.js | 2 | ||||
| -rw-r--r-- | src/librustdoc/html/static/playpen.js | 29 |
7 files changed, 105 insertions, 15 deletions
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index f544e1e0973..3c9358b03a9 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -25,7 +25,7 @@ use html::escape::Escape; use t = syntax::parse::token; /// Highlights some source code, returning the HTML output. -pub fn highlight(src: &str, class: Option<&str>) -> String { +pub fn highlight(src: &str, class: Option<&str>, id: Option<&str>) -> String { debug!("highlighting: ================\n{}\n==============", src); let sess = parse::new_parse_sess(); let fm = parse::string_to_filemap(&sess, @@ -36,6 +36,7 @@ pub fn highlight(src: &str, class: Option<&str>) -> String { doit(&sess, lexer::StringReader::new(&sess.span_diagnostic, fm), class, + id, &mut out).unwrap(); str::from_utf8_lossy(out.unwrap().as_slice()).to_string() } @@ -47,11 +48,17 @@ pub fn highlight(src: &str, class: Option<&str>) -> String { /// it's used. All source code emission is done as slices from the source map, /// not from the tokens themselves, in order to stay true to the original /// source. -fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader, class: Option<&str>, +fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader, + class: Option<&str>, id: Option<&str>, out: &mut Writer) -> io::IoResult<()> { use syntax::parse::lexer::Reader; - try!(write!(out, "<pre class='rust {}'>\n", class.unwrap_or(""))); + try!(write!(out, "<pre ")); + match id { + Some(id) => try!(write!(out, "id='{}' ", id)), + None => {} + } + try!(write!(out, "class='rust {}'>\n", class.unwrap_or(""))); let mut last = BytePos(0); let mut is_attribute = false; let mut is_macro = false; diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 80653878247..e2fa57148c2 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -16,6 +16,7 @@ pub struct Layout { pub logo: String, pub favicon: String, pub krate: String, + pub playground_url: String, } pub struct Page<'a> { @@ -108,11 +109,13 @@ r##"<!DOCTYPE html> </div> <script> - var rootPath = "{root_path}"; - var currentCrate = "{krate}"; + window.rootPath = "{root_path}"; + window.currentCrate = "{krate}"; + window.playgroundUrl = "{play_url}"; </script> <script src="{root_path}jquery.js"></script> <script src="{root_path}main.js"></script> + {play_js} <script async src="{root_path}search-index.js"></script> </body> </html>"##, @@ -124,6 +127,12 @@ r##"<!DOCTYPE html> favicon = nonestr(layout.favicon.as_slice()), sidebar = *sidebar, krate = layout.krate, + play_url = layout.playground_url, + play_js = if layout.playground_url.len() == 0 { + "".to_string() + } else { + format!(r#"<script src="{}playpen.js"></script>"#, page.root_path) + }, ) } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index d1e2b5dffdd..260d26c5437 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -27,7 +27,7 @@ #![allow(non_camel_case_types)] use libc; -use std::cell::RefCell; +use std::cell::{RefCell, Cell}; use std::fmt; use std::slice; use std::str; @@ -35,6 +35,8 @@ use std::collections::HashMap; use html::toc::TocBuilder; use html::highlight; +use html::escape::Escape; +use test; /// A unit struct which has the `fmt::Show` trait implemented. When /// formatted, this struct will emit the HTML corresponding to the rendered @@ -139,6 +141,9 @@ fn stripped_filtered_line<'a>(s: &'a str) -> Option<&'a str> { } local_data_key!(used_header_map: RefCell<HashMap<String, uint>>) +local_data_key!(test_idx: Cell<uint>) +// None == render an example, but there's no crate name +local_data_key!(pub playground_krate: Option<String>) pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { extern fn block(ob: *mut hoedown_buffer, text: *hoedown_buffer, @@ -149,9 +154,9 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { let opaque = opaque as *mut hoedown_html_renderer_state; let my_opaque: &MyOpaque = &*((*opaque).opaque as *MyOpaque); slice::raw::buf_as_slice((*text).data, (*text).size as uint, |text| { - let text = str::from_utf8(text).unwrap(); + let origtext = str::from_utf8(text).unwrap(); debug!("docblock: ==============\n{}\n=======", text); - let mut lines = text.lines().filter(|l| { + let mut lines = origtext.lines().filter(|l| { stripped_filtered_line(*l).is_none() }); let text = lines.collect::<Vec<&str>>().connect("\n"); @@ -180,9 +185,26 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { }; if !rendered { - let output = highlight::highlight(text.as_slice(), - None).as_slice() - .to_c_str(); + let mut s = String::new(); + let id = playground_krate.get().map(|krate| { + let idx = test_idx.get().unwrap(); + let i = idx.get(); + idx.set(i + 1); + + let test = origtext.lines().map(|l| { + stripped_filtered_line(l).unwrap_or(l) + }).collect::<Vec<&str>>().connect("\n"); + let krate = krate.as_ref().map(|s| s.as_slice()); + let test = test::maketest(test.as_slice(), krate, false); + s.push_str(format!("<span id='rust-example-raw-{}' \ + class='rusttest'>{}</span>", + i, Escape(test.as_slice())).as_slice()); + format!("rust-example-rendered-{}", i) + }); + let id = id.as_ref().map(|a| a.as_slice()); + s.push_str(highlight::highlight(text.as_slice(), None, id) + .as_slice()); + let output = s.to_c_str(); output.with_ref(|r| { hoedown_buffer_puts(ob, r) }) @@ -377,6 +399,7 @@ fn parse_lang_string(string: &str) -> (bool,bool,bool,bool) { /// previous state (if any). pub fn reset_headers() { used_header_map.replace(Some(RefCell::new(HashMap::new()))); + test_idx.replace(Some(Cell::new(0))); } impl<'a> fmt::Show for Markdown<'a> { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 20d4d677bc0..eab4a2c137a 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -230,6 +230,7 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> { logo: "".to_string(), favicon: "".to_string(), krate: krate.name.clone(), + playground_url: "".to_string(), }, include_sources: true, render_redirect_pages: false, @@ -250,6 +251,14 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> { if "html_logo_url" == x.as_slice() => { cx.layout.logo = s.to_string(); } + clean::NameValue(ref x, ref s) + if "html_playground_url" == x.as_slice() => { + cx.layout.playground_url = s.to_string(); + let name = krate.name.clone(); + if markdown::playground_krate.get().is_none() { + markdown::playground_krate.replace(Some(Some(name))); + } + } clean::Word(ref x) if "html_no_source" == x.as_slice() => { cx.include_sources = false; @@ -450,6 +459,7 @@ fn write_shared(cx: &Context, try!(write(cx.dst.join("jquery.js"), include_bin!("static/jquery-2.1.0.min.js"))); try!(write(cx.dst.join("main.js"), include_bin!("static/main.js"))); + try!(write(cx.dst.join("playpen.js"), include_bin!("static/playpen.js"))); try!(write(cx.dst.join("main.css"), include_bin!("static/main.css"))); try!(write(cx.dst.join("normalize.css"), include_bin!("static/normalize.css"))); @@ -2055,14 +2065,15 @@ impl<'a> fmt::Show for Source<'a> { try!(write!(fmt, "<span id='{0:u}'>{0:1$u}</span>\n", i, cols)); } try!(write!(fmt, "</pre>")); - try!(write!(fmt, "{}", highlight::highlight(s.as_slice(), None))); + try!(write!(fmt, "{}", highlight::highlight(s.as_slice(), None, None))); Ok(()) } } fn item_macro(w: &mut fmt::Formatter, it: &clean::Item, t: &clean::Macro) -> fmt::Result { - try!(w.write(highlight::highlight(t.source.as_slice(), Some("macro")).as_bytes())); + try!(w.write(highlight::highlight(t.source.as_slice(), Some("macro"), + None).as_bytes())); document(w, it) } diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css index 7831f10ab91..07dd1a6c173 100644 --- a/src/librustdoc/html/static/main.css +++ b/src/librustdoc/html/static/main.css @@ -156,7 +156,7 @@ nav.sub { padding: 0 10px; margin-bottom: 10px; } -.block h2 { +.block h2 { margin-top: 0; text-align: center; } @@ -396,6 +396,17 @@ pre.rust .doccomment { color: #4D4D4C; } pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; } pre.rust .lifetime { color: #B76514; } +.rusttest { display: none; } +pre.rust { position: relative; } +pre.rust a { transform: scaleX(-1); } +.test-arrow { + display: inline-block; + position: absolute; + top: 0; + right: 10px; + font-size: 150%; +} + .methods .section-header { /* Override parent class attributes. */ border-bottom: none !important; diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 440b829c80c..195028c85bf 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -678,7 +678,7 @@ window.register_implementors(window.pending_implementors); } - // See documentaiton in html/render.rs for what this is doing. + // See documentation in html/render.rs for what this is doing. var query = getQueryStringParams(); if (query['gotosrc']) { window.location = $('#src-' + query['gotosrc']).attr('href'); diff --git a/src/librustdoc/html/static/playpen.js b/src/librustdoc/html/static/playpen.js new file mode 100644 index 00000000000..5d2fe9c2166 --- /dev/null +++ b/src/librustdoc/html/static/playpen.js @@ -0,0 +1,29 @@ +// Copyright 2014 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*jslint browser: true, es5: true */ +/*globals $: true, rootPath: true */ + +(function() { + if (window.playgroundUrl) { + $('pre.rust').hover(function() { + var id = '#' + $(this).attr('id').replace('rendered', 'raw'); + var a = $('<a>').text('⇱').attr('class', 'test-arrow'); + var code = $(id).text(); + a.attr('href', window.playgroundUrl + '?code=' + + encodeURIComponent(code)); + a.attr('target', '_blank'); + $(this).append(a); + }, function() { + $(this).find('a').remove(); + }); + } +}()); + |
