about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorOliver Middleton <olliemail27@gmail.com>2016-10-11 09:56:30 +0100
committerOliver Middleton <olliemail27@gmail.com>2016-10-15 18:32:03 +0100
commit0b2746c8db6fc11965b1b6fd1d8536309a0d98b6 (patch)
treeadbfb9474dbe8dd1810f1669fefaf757627fd42e /src
parent8e05e7ee3c19a5594b79d67c8390cef78970be7c (diff)
downloadrust-0b2746c8db6fc11965b1b6fd1d8536309a0d98b6.tar.gz
rust-0b2746c8db6fc11965b1b6fd1d8536309a0d98b6.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/doc/footer.inc1
-rw-r--r--src/doc/rust.css8
-rw-r--r--src/librustdoc/html/layout.rs9
-rw-r--r--src/librustdoc/html/markdown.rs43
-rw-r--r--src/librustdoc/html/render.rs8
-rw-r--r--src/librustdoc/html/static/extra.js25
-rw-r--r--src/librustdoc/html/static/playpen.js48
-rw-r--r--src/librustdoc/html/static/rustdoc.css1
-rw-r--r--src/librustdoc/markdown.rs10
-rw-r--r--src/librustdoc/test.rs2
-rw-r--r--src/test/rustdoc/playground-empty.rs21
-rw-r--r--src/test/rustdoc/playground-none.rs19
-rw-r--r--src/test/rustdoc/playground.rs39
-rw-r--r--src/tools/error_index_generator/main.rs5
-rw-r--r--src/tools/rustbook/build.rs7
15 files changed, 131 insertions, 115 deletions
diff --git a/src/doc/footer.inc b/src/doc/footer.inc
index 7513e524e73..77e151235e8 100644
--- a/src/doc/footer.inc
+++ b/src/doc/footer.inc
@@ -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>
diff --git a/src/doc/rust.css b/src/doc/rust.css
index 262db5673e8..932594b9912 100644
--- a/src/doc/rust.css
+++ b/src/doc/rust.css
@@ -336,13 +336,11 @@ 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;
@@ -350,6 +348,10 @@ a.test-arrow {
     top: 5px;
     right: 5px;
 }
+a.test-arrow:hover{
+    background-color: #4e8bca;
+    text-decoration: none;
+}
 
 .unstable-feature {
     border: 2px solid red;
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index b7c5876c4f9..5353642e294 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -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> {
@@ -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>"##,
@@ -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)
-    }
     )
 }
 
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index e9a1f650c9b..f12349e5b7c 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -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;
@@ -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)
 });
 
@@ -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());
             })
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index d8dba00e7d5..77a5ff3243a 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -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(),
     };
@@ -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()));
                         }
                     });
                 }
@@ -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"),
diff --git a/src/librustdoc/html/static/extra.js b/src/librustdoc/html/static/extra.js
deleted file mode 100644
index d9d97d9b883..00000000000
--- a/src/librustdoc/html/static/extra.js
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2014-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.
-
-/*jslint browser: true, es5: true */
-/*globals $: true, rootPath: true */
-
-document.addEventListener('DOMContentLoaded', function() {
-    'use strict';
-
-    if (!window.playgroundUrl) {
-        var runButtons = document.querySelectorAll(".test-arrow");
-
-        for (var i = 0; i < runButtons.length; i++) {
-            runButtons[i].classList.remove("test-arrow");
-        }
-        return;
-    }
-});
diff --git a/src/librustdoc/html/static/playpen.js b/src/librustdoc/html/static/playpen.js
deleted file mode 100644
index 8d8953d56e1..00000000000
--- a/src/librustdoc/html/static/playpen.js
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2014-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 <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 */
-
-document.addEventListener('DOMContentLoaded', function() {
-    'use strict';
-
-    if (!window.playgroundUrl) {
-        var runButtons = document.querySelectorAll(".test-arrow");
-
-        for (var i = 0; i < runButtons.length; i++) {
-            runButtons[i].classList.remove("test-arrow");
-        }
-        return;
-    }
-
-    var featureRegexp = new RegExp('^\s*#!\\[feature\\(\.*?\\)\\]');
-    var elements = document.querySelectorAll('pre.rust-example-rendered');
-
-    Array.prototype.forEach.call(elements, function(el) {
-        el.onmouseover = function(e) {
-            if (el.contains(e.relatedTarget)) {
-                return;
-            }
-
-            var a = el.querySelectorAll('a.test-arrow')[0];
-
-            var code = el.previousElementSibling.textContent;
-
-            var channel = '';
-            if (featureRegexp.test(code)) {
-                channel = '&version=nightly';
-            }
-
-            a.setAttribute('href', window.playgroundUrl + '?code=' +
-                           encodeURIComponent(code) + channel);
-        };
-    });
-});
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 85ec4fe3f3f..f49b8556f66 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -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);
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index f708aa54619..b617acfabbb 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -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) => {
@@ -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>"#,
@@ -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 {
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 15fdb0341cb..d1d2b14806f 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -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}");
diff --git a/src/test/rustdoc/playground-empty.rs b/src/test/rustdoc/playground-empty.rs
new file mode 100644
index 00000000000..00881a62dd0
--- /dev/null
+++ b/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"
diff --git a/src/test/rustdoc/playground-none.rs b/src/test/rustdoc/playground-none.rs
new file mode 100644
index 00000000000..83c312d7ab2
--- /dev/null
+++ b/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"
diff --git a/src/test/rustdoc/playground.rs b/src/test/rustdoc/playground.rs
new file mode 100644
index 00000000000..9eb8dec51a7
--- /dev/null
+++ b/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"
diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs
index 7bdf1343aa9..e33df0dfbc8 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;
+use rustdoc::html::markdown::{Markdown, PLAYGROUND};
 use rustc_serialize::json;
 
 enum OutputFormat {
@@ -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());
diff --git a/src/tools/rustbook/build.rs b/src/tools/rustbook/build.rs
index 09c2d2510e3..d88ff48843a 100644
--- a/src/tools/rustbook/build.rs
+++ b/src/tools/rustbook/build.rs
@@ -131,7 +131,6 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> {
         {
             let mut buffer = BufWriter::new(File::create(&postlude)?);
             writeln!(&mut buffer, "<script src='rustbook.js'></script>")?;
-            writeln!(&mut buffer, "<script src='playpen.js'></script>")?;
             writeln!(&mut buffer, "</div></div>")?;
         }
 
@@ -143,7 +142,7 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> {
             format!("-o{}", out_path.display()),
             format!("--html-before-content={}", prelude.display()),
             format!("--html-after-content={}", postlude.display()),
-            format!("--markdown-playground-url=https://play.rust-lang.org"),
+            format!("--markdown-playground-url=https://play.rust-lang.org/"),
             format!("--markdown-css={}", item.path_to_root.join("rustbook.css").display()),
             "--markdown-no-toc".to_string(),
         ];
@@ -158,10 +157,6 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> {
     // create index.html from the root README
     fs::copy(&tgt.join("README.html"), &tgt.join("index.html"))?;
 
-    // Copy js for playpen
-    let mut playpen = File::create(tgt.join("playpen.js"))?;
-    let js = include_bytes!("../../librustdoc/html/static/playpen.js");
-    playpen.write_all(js)?;
     Ok(())
 }