Skip to content

Commit 0b2746c

Browse files
committedOct 15, 2016
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.
1 parent 8e05e7e commit 0b2746c

File tree

15 files changed

+131
-115
lines changed

15 files changed

+131
-115
lines changed
 

‎src/doc/footer.inc

-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,3 @@ or the <a href="https://opensource.org/licenses/MIT">MIT license</a>, at your op
55
</p><p>
66
This file may not be copied, modified, or distributed except according to those terms.
77
</p></footer>
8-
<script type="text/javascript" src="playpen.js"></script>

‎src/doc/rust.css

+5-3
Original file line numberDiff line numberDiff line change
@@ -336,20 +336,22 @@ table th {
336336

337337
/* Code snippets */
338338

339-
.rusttest { display: none; }
340339
pre.rust { position: relative; }
341340
a.test-arrow {
341+
background-color: rgba(78, 139, 202, 0.2);
342342
display: inline-block;
343343
position: absolute;
344-
345-
background-color: #4e8bca;
346344
color: #f5f5f5;
347345
padding: 5px 10px 5px 10px;
348346
border-radius: 5px;
349347
font-size: 130%;
350348
top: 5px;
351349
right: 5px;
352350
}
351+
a.test-arrow:hover{
352+
background-color: #4e8bca;
353+
text-decoration: none;
354+
}
353355

354356
.unstable-feature {
355357
border: 2px solid red;

‎src/librustdoc/html/layout.rs

-9
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ pub struct Layout {
1919
pub favicon: String,
2020
pub external_html: ExternalHtml,
2121
pub krate: String,
22-
pub playground_url: String,
2322
}
2423

2524
pub struct Page<'a> {
@@ -136,11 +135,9 @@ r##"<!DOCTYPE html>
136135
<script>
137136
window.rootPath = "{root_path}";
138137
window.currentCrate = "{krate}";
139-
window.playgroundUrl = "{play_url}";
140138
</script>
141139
<script src="{root_path}jquery.js"></script>
142140
<script src="{root_path}main.js"></script>
143-
{play_js}
144141
<script defer src="{root_path}search-index.js"></script>
145142
</body>
146143
</html>"##,
@@ -174,12 +171,6 @@ r##"<!DOCTYPE html>
174171
after_content = layout.external_html.after_content,
175172
sidebar = *sidebar,
176173
krate = layout.krate,
177-
play_url = layout.playground_url,
178-
play_js = if layout.playground_url.is_empty() {
179-
format!(r#"<script src="{}extra.js"></script>"#, page.root_path)
180-
} else {
181-
format!(r#"<script src="{}playpen.js"></script>"#, page.root_path)
182-
}
183174
)
184175
}
185176

‎src/librustdoc/html/markdown.rs

+37-6
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use std::ascii::AsciiExt;
3131
use std::cell::RefCell;
3232
use std::default::Default;
3333
use std::ffi::CString;
34-
use std::fmt;
34+
use std::fmt::{self, Write};
3535
use std::slice;
3636
use std::str;
3737
use syntax::feature_gate::UnstableFeatures;
@@ -214,7 +214,9 @@ fn collapse_whitespace(s: &str) -> String {
214214
s.split_whitespace().collect::<Vec<_>>().join(" ")
215215
}
216216

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

@@ -248,24 +250,53 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
248250
});
249251
let text = lines.collect::<Vec<&str>>().join("\n");
250252
if rendered { return }
251-
PLAYGROUND_KRATE.with(|krate| {
253+
PLAYGROUND.with(|play| {
252254
// insert newline to clearly separate it from the
253255
// previous block so we can shorten the html output
254256
let mut s = String::from("\n");
255-
krate.borrow().as_ref().map(|krate| {
257+
let playground_button = play.borrow().as_ref().and_then(|&(ref krate, ref url)| {
258+
if url.is_empty() {
259+
return None;
260+
}
256261
let test = origtext.lines().map(|l| {
257262
stripped_filtered_line(l).unwrap_or(l)
258263
}).collect::<Vec<&str>>().join("\n");
259264
let krate = krate.as_ref().map(|s| &**s);
260265
let test = test::maketest(&test, krate, false,
261266
&Default::default());
262-
s.push_str(&format!("<span class='rusttest'>{}</span>", Escape(&test)));
267+
let channel = if test.contains("#![feature(") {
268+
"&amp;version=nightly"
269+
} else {
270+
""
271+
};
272+
// These characters don't need to be escaped in a URI.
273+
// FIXME: use a library function for percent encoding.
274+
fn dont_escape(c: u8) -> bool {
275+
(b'a' <= c && c <= b'z') ||
276+
(b'A' <= c && c <= b'Z') ||
277+
(b'0' <= c && c <= b'9') ||
278+
c == b'-' || c == b'_' || c == b'.' ||
279+
c == b'~' || c == b'!' || c == b'\'' ||
280+
c == b'(' || c == b')' || c == b'*'
281+
}
282+
let mut test_escaped = String::new();
283+
for b in test.bytes() {
284+
if dont_escape(b) {
285+
test_escaped.push(char::from(b));
286+
} else {
287+
write!(test_escaped, "%{:02X}", b).unwrap();
288+
}
289+
}
290+
Some(format!(
291+
r#"<a class="test-arrow" target="_blank" href="{}?code={}{}">Run</a>"#,
292+
url, test_escaped, channel
293+
))
263294
});
264295
s.push_str(&highlight::render_with_highlighting(
265296
&text,
266297
Some("rust-example-rendered"),
267298
None,
268-
Some("<a class='test-arrow' target='_blank' href=''>Run</a>")));
299+
playground_button.as_ref().map(String::as_str)));
269300
let output = CString::new(s).unwrap();
270301
hoedown_buffer_puts(ob, output.as_ptr());
271302
})

‎src/librustdoc/html/render.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,6 @@ pub fn run(mut krate: clean::Crate,
449449
favicon: "".to_string(),
450450
external_html: external_html.clone(),
451451
krate: krate.name.clone(),
452-
playground_url: "".to_string(),
453452
},
454453
css_file_extension: css_file_extension.clone(),
455454
};
@@ -469,11 +468,10 @@ pub fn run(mut krate: clean::Crate,
469468
}
470469
clean::NameValue(ref x, ref s)
471470
if "html_playground_url" == *x => {
472-
scx.layout.playground_url = s.to_string();
473-
markdown::PLAYGROUND_KRATE.with(|slot| {
471+
markdown::PLAYGROUND.with(|slot| {
474472
if slot.borrow().is_none() {
475473
let name = krate.name.clone();
476-
*slot.borrow_mut() = Some(Some(name));
474+
*slot.borrow_mut() = Some((Some(name), s.clone()));
477475
}
478476
});
479477
}
@@ -659,8 +657,6 @@ fn write_shared(cx: &Context,
659657
include_bytes!("static/jquery-2.1.4.min.js"))?;
660658
write(cx.dst.join("main.js"),
661659
include_bytes!("static/main.js"))?;
662-
write(cx.dst.join("playpen.js"),
663-
include_bytes!("static/playpen.js"))?;
664660
write(cx.dst.join("rustdoc.css"),
665661
include_bytes!("static/rustdoc.css"))?;
666662
write(cx.dst.join("main.css"),

‎src/librustdoc/html/static/extra.js

-25
This file was deleted.

‎src/librustdoc/html/static/playpen.js

-48
This file was deleted.

‎src/librustdoc/html/static/rustdoc.css

-1
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,6 @@ pre.rust .question-mark {
575575
font-weight: bold;
576576
}
577577

578-
.rusttest { display: none; }
579578
pre.rust { position: relative; }
580579
a.test-arrow {
581580
background-color: rgba(78, 139, 202, 0.2);

‎src/librustdoc/markdown.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,9 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
6363
Err(LoadStringError::ReadFail) => return 1,
6464
Err(LoadStringError::BadUtf8) => return 2,
6565
};
66-
let playground = matches.opt_str("markdown-playground-url");
67-
if playground.is_some() {
68-
markdown::PLAYGROUND_KRATE.with(|s| { *s.borrow_mut() = Some(None); });
66+
if let Some(playground) = matches.opt_str("markdown-playground-url") {
67+
markdown::PLAYGROUND.with(|s| { *s.borrow_mut() = Some((None, playground)); });
6968
}
70-
let playground = playground.unwrap_or("".to_string());
7169

7270
let mut out = match File::create(&output) {
7371
Err(e) => {
@@ -119,9 +117,6 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
119117
{before_content}
120118
<h1 class="title">{title}</h1>
121119
{text}
122-
<script type="text/javascript">
123-
window.playgroundUrl = "{playground}";
124-
</script>
125120
{after_content}
126121
</body>
127122
</html>"#,
@@ -131,7 +126,6 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
131126
before_content = external_html.before_content,
132127
text = rendered,
133128
after_content = external_html.after_content,
134-
playground = playground,
135129
);
136130

137131
match err {

‎src/librustdoc/test.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ pub fn maketest(s: &str, cratename: Option<&str>, dont_insert_main: bool,
355355
if dont_insert_main || s.contains("fn main") {
356356
prog.push_str(&everything_else);
357357
} else {
358-
prog.push_str("fn main() {\n ");
358+
prog.push_str("fn main() {\n");
359359
prog.push_str(&everything_else);
360360
prog = prog.trim().into();
361361
prog.push_str("\n}");

‎src/test/rustdoc/playground-empty.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![crate_name = "foo"]
12+
13+
#![doc(html_playground_url = "")]
14+
15+
//! module docs
16+
//!
17+
//! ```
18+
//! println!("Hello, world!");
19+
//! ```
20+
21+
// @!has foo/index.html '//a[@class="test-arrow"]' "Run"

‎src/test/rustdoc/playground-none.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![crate_name = "foo"]
12+
13+
//! module docs
14+
//!
15+
//! ```
16+
//! println!("Hello, world!");
17+
//! ```
18+
19+
// @!has foo/index.html '//a[@class="test-arrow"]' "Run"

‎src/test/rustdoc/playground.rs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// ignore-tidy-linelength
12+
13+
#![crate_name = "foo"]
14+
15+
#![doc(html_playground_url = "https://www.example.com/")]
16+
17+
//! module docs
18+
//!
19+
//! ```
20+
//! println!("Hello, world!");
21+
//! ```
22+
//!
23+
//! ```
24+
//! fn main() {
25+
//! println!("Hello, world!");
26+
//! }
27+
//! ```
28+
//!
29+
//! ```
30+
//! #![feature(something)]
31+
//!
32+
//! fn main() {
33+
//! println!("Hello, world!");
34+
//! }
35+
//! ```
36+
37+
// @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"
38+
// @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"
39+
// @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"

‎src/tools/error_index_generator/main.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use std::path::PathBuf;
2424

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

27-
use rustdoc::html::markdown::Markdown;
27+
use rustdoc::html::markdown::{Markdown, PLAYGROUND};
2828
use rustc_serialize::json;
2929

3030
enum OutputFormat {
@@ -201,6 +201,9 @@ fn parse_args() -> (OutputFormat, PathBuf) {
201201
}
202202

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

‎src/tools/rustbook/build.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> {
131131
{
132132
let mut buffer = BufWriter::new(File::create(&postlude)?);
133133
writeln!(&mut buffer, "<script src='rustbook.js'></script>")?;
134-
writeln!(&mut buffer, "<script src='playpen.js'></script>")?;
135134
writeln!(&mut buffer, "</div></div>")?;
136135
}
137136

@@ -143,7 +142,7 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> {
143142
format!("-o{}", out_path.display()),
144143
format!("--html-before-content={}", prelude.display()),
145144
format!("--html-after-content={}", postlude.display()),
146-
format!("--markdown-playground-url=https://play.rust-lang.org"),
145+
format!("--markdown-playground-url=https://play.rust-lang.org/"),
147146
format!("--markdown-css={}", item.path_to_root.join("rustbook.css").display()),
148147
"--markdown-no-toc".to_string(),
149148
];
@@ -158,10 +157,6 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> {
158157
// create index.html from the root README
159158
fs::copy(&tgt.join("README.html"), &tgt.join("index.html"))?;
160159

161-
// Copy js for playpen
162-
let mut playpen = File::create(tgt.join("playpen.js"))?;
163-
let js = include_bytes!("../../librustdoc/html/static/playpen.js");
164-
playpen.write_all(js)?;
165160
Ok(())
166161
}
167162

0 commit comments

Comments
 (0)
Please sign in to comment.