Skip to content

Commit

Permalink
Auto merge of #37098 - ollie27:rustdoc_playground, r=GuillaumeGomez
Browse files Browse the repository at this point in the history
rustdoc: Improve playground run buttons

The main change is to stop using javascript to generate the URLs and use
rustdoc instead.

This also adds run buttons to the error index examples.

You can test the changes at https://ollie27.github.io/rust_doc_test/.

Fixes #36621
Fixes #36910
  • Loading branch information
bors committed Oct 16, 2016
2 parents 98a3502 + 0b2746c commit 6dc035e
Show file tree
Hide file tree
Showing 15 changed files with 131 additions and 115 deletions.
1 change: 0 additions & 1 deletion src/doc/footer.inc
Expand Up @@ -5,4 +5,3 @@ or the <a href="https://opensource.org/licenses/MIT">MIT license</a>, at your op
</p><p>
This file may not be copied, modified, or distributed except according to those terms.
</p></footer>
<script type="text/javascript" src="playpen.js"></script>
8 changes: 5 additions & 3 deletions src/doc/rust.css
Expand Up @@ -336,20 +336,22 @@ table th {

/* Code snippets */

.rusttest { display: none; }
pre.rust { position: relative; }
a.test-arrow {
background-color: rgba(78, 139, 202, 0.2);
display: inline-block;
position: absolute;

background-color: #4e8bca;
color: #f5f5f5;
padding: 5px 10px 5px 10px;
border-radius: 5px;
font-size: 130%;
top: 5px;
right: 5px;
}
a.test-arrow:hover{
background-color: #4e8bca;
text-decoration: none;
}

.unstable-feature {
border: 2px solid red;
Expand Down
9 changes: 0 additions & 9 deletions src/librustdoc/html/layout.rs
Expand Up @@ -19,7 +19,6 @@ pub struct Layout {
pub favicon: String,
pub external_html: ExternalHtml,
pub krate: String,
pub playground_url: String,
}

pub struct Page<'a> {
Expand Down Expand Up @@ -136,11 +135,9 @@ r##"<!DOCTYPE html>
<script>
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 defer src="{root_path}search-index.js"></script>
</body>
</html>"##,
Expand Down Expand Up @@ -174,12 +171,6 @@ r##"<!DOCTYPE html>
after_content = layout.external_html.after_content,
sidebar = *sidebar,
krate = layout.krate,
play_url = layout.playground_url,
play_js = if layout.playground_url.is_empty() {
format!(r#"<script src="{}extra.js"></script>"#, page.root_path)
} else {
format!(r#"<script src="{}playpen.js"></script>"#, page.root_path)
}
)
}

Expand Down
43 changes: 37 additions & 6 deletions src/librustdoc/html/markdown.rs
Expand Up @@ -31,7 +31,7 @@ use std::ascii::AsciiExt;
use std::cell::RefCell;
use std::default::Default;
use std::ffi::CString;
use std::fmt;
use std::fmt::{self, Write};
use std::slice;
use std::str;
use syntax::feature_gate::UnstableFeatures;
Expand Down Expand Up @@ -214,7 +214,9 @@ fn collapse_whitespace(s: &str) -> String {
s.split_whitespace().collect::<Vec<_>>().join(" ")
}

thread_local!(pub static PLAYGROUND_KRATE: RefCell<Option<Option<String>>> = {
// Information about the playground if a URL has been specified, containing an
// optional crate name and the URL.
thread_local!(pub static PLAYGROUND: RefCell<Option<(Option<String>, String)>> = {
RefCell::new(None)
});

Expand Down Expand Up @@ -248,24 +250,53 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
});
let text = lines.collect::<Vec<&str>>().join("\n");
if rendered { return }
PLAYGROUND_KRATE.with(|krate| {
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");
krate.borrow().as_ref().map(|krate| {
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::<Vec<&str>>().join("\n");
let krate = krate.as_ref().map(|s| &**s);
let test = test::maketest(&test, krate, false,
&Default::default());
s.push_str(&format!("<span class='rusttest'>{}</span>", Escape(&test)));
let channel = if test.contains("#![feature(") {
"&amp;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#"<a class="test-arrow" target="_blank" href="{}?code={}{}">Run</a>"#,
url, test_escaped, channel
))
});
s.push_str(&highlight::render_with_highlighting(
&text,
Some("rust-example-rendered"),
None,
Some("<a class='test-arrow' target='_blank' href=''>Run</a>")));
playground_button.as_ref().map(String::as_str)));
let output = CString::new(s).unwrap();
hoedown_buffer_puts(ob, output.as_ptr());
})
Expand Down
8 changes: 2 additions & 6 deletions src/librustdoc/html/render.rs
Expand Up @@ -449,7 +449,6 @@ pub fn run(mut krate: clean::Crate,
favicon: "".to_string(),
external_html: external_html.clone(),
krate: krate.name.clone(),
playground_url: "".to_string(),
},
css_file_extension: css_file_extension.clone(),
};
Expand All @@ -469,11 +468,10 @@ pub fn run(mut krate: clean::Crate,
}
clean::NameValue(ref x, ref s)
if "html_playground_url" == *x => {
scx.layout.playground_url = s.to_string();
markdown::PLAYGROUND_KRATE.with(|slot| {
markdown::PLAYGROUND.with(|slot| {
if slot.borrow().is_none() {
let name = krate.name.clone();
*slot.borrow_mut() = Some(Some(name));
*slot.borrow_mut() = Some((Some(name), s.clone()));
}
});
}
Expand Down Expand Up @@ -659,8 +657,6 @@ fn write_shared(cx: &Context,
include_bytes!("static/jquery-2.1.4.min.js"))?;
write(cx.dst.join("main.js"),
include_bytes!("static/main.js"))?;
write(cx.dst.join("playpen.js"),
include_bytes!("static/playpen.js"))?;
write(cx.dst.join("rustdoc.css"),
include_bytes!("static/rustdoc.css"))?;
write(cx.dst.join("main.css"),
Expand Down
25 changes: 0 additions & 25 deletions src/librustdoc/html/static/extra.js

This file was deleted.

48 changes: 0 additions & 48 deletions src/librustdoc/html/static/playpen.js

This file was deleted.

1 change: 0 additions & 1 deletion src/librustdoc/html/static/rustdoc.css
Expand Up @@ -575,7 +575,6 @@ pre.rust .question-mark {
font-weight: bold;
}

.rusttest { display: none; }
pre.rust { position: relative; }
a.test-arrow {
background-color: rgba(78, 139, 202, 0.2);
Expand Down
10 changes: 2 additions & 8 deletions src/librustdoc/markdown.rs
Expand Up @@ -63,11 +63,9 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
Err(LoadStringError::ReadFail) => return 1,
Err(LoadStringError::BadUtf8) => return 2,
};
let playground = matches.opt_str("markdown-playground-url");
if playground.is_some() {
markdown::PLAYGROUND_KRATE.with(|s| { *s.borrow_mut() = Some(None); });
if let Some(playground) = matches.opt_str("markdown-playground-url") {
markdown::PLAYGROUND.with(|s| { *s.borrow_mut() = Some((None, playground)); });
}
let playground = playground.unwrap_or("".to_string());

let mut out = match File::create(&output) {
Err(e) => {
Expand Down Expand Up @@ -119,9 +117,6 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
{before_content}
<h1 class="title">{title}</h1>
{text}
<script type="text/javascript">
window.playgroundUrl = "{playground}";
</script>
{after_content}
</body>
</html>"#,
Expand All @@ -131,7 +126,6 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
before_content = external_html.before_content,
text = rendered,
after_content = external_html.after_content,
playground = playground,
);

match err {
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/test.rs
Expand Up @@ -355,7 +355,7 @@ pub fn maketest(s: &str, cratename: Option<&str>, dont_insert_main: bool,
if dont_insert_main || s.contains("fn main") {
prog.push_str(&everything_else);
} else {
prog.push_str("fn main() {\n ");
prog.push_str("fn main() {\n");
prog.push_str(&everything_else);
prog = prog.trim().into();
prog.push_str("\n}");
Expand Down
21 changes: 21 additions & 0 deletions src/test/rustdoc/playground-empty.rs
@@ -0,0 +1,21 @@
// Copyright 2016 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.

#![crate_name = "foo"]

#![doc(html_playground_url = "")]

//! module docs
//!
//! ```
//! println!("Hello, world!");
//! ```

// @!has foo/index.html '//a[@class="test-arrow"]' "Run"
19 changes: 19 additions & 0 deletions src/test/rustdoc/playground-none.rs
@@ -0,0 +1,19 @@
// Copyright 2016 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.

#![crate_name = "foo"]

//! module docs
//!
//! ```
//! println!("Hello, world!");
//! ```

// @!has foo/index.html '//a[@class="test-arrow"]' "Run"
39 changes: 39 additions & 0 deletions src/test/rustdoc/playground.rs
@@ -0,0 +1,39 @@
// Copyright 2016 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.

// ignore-tidy-linelength

#![crate_name = "foo"]

#![doc(html_playground_url = "https://www.example.com/")]

//! module docs
//!
//! ```
//! println!("Hello, world!");
//! ```
//!
//! ```
//! fn main() {
//! println!("Hello, world!");
//! }
//! ```
//!
//! ```
//! #![feature(something)]
//!
//! fn main() {
//! println!("Hello, world!");
//! }
//! ```

// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=fn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D%0A"]' "Run"
// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=fn%20main()%20%7B%0Aprintln!(%22Hello%2C%20world!%22)%3B%0A%7D"]' "Run"
// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Bfeature(something)%5D%0A%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D%0A&version=nightly"]' "Run"
5 changes: 4 additions & 1 deletion src/tools/error_index_generator/main.rs
Expand Up @@ -24,7 +24,7 @@ use std::path::PathBuf;

use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap, ErrorMetadata};

use rustdoc::html::markdown::Markdown;
use rustdoc::html::markdown::{Markdown, PLAYGROUND};
use rustc_serialize::json;

enum OutputFormat {
Expand Down Expand Up @@ -201,6 +201,9 @@ fn parse_args() -> (OutputFormat, PathBuf) {
}

fn main() {
PLAYGROUND.with(|slot| {
*slot.borrow_mut() = Some((None, String::from("https://play.rust-lang.org/")));
});
let (format, dst) = parse_args();
if let Err(e) = main_with_result(format, &dst) {
panic!("{}", e.description());
Expand Down

0 comments on commit 6dc035e

Please sign in to comment.