Rename playpen to playground. (#1241)

looks good
This commit is contained in:
Eric Huss 2020-06-22 07:34:25 -07:00 committed by GitHub
parent fe1ba71d45
commit bc23d08fa5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 194 additions and 172 deletions

View File

@ -148,7 +148,7 @@ preprocessors are:
all `README.md` chapters to `index.md` so `foo/README.md` can be accessed via all `README.md` chapters to `index.md` so `foo/README.md` can be accessed via
the url `foo/` when published to a browser the url `foo/` when published to a browser
- `links` - a built-in preprocessor (enabled by default) for expanding the - `links` - a built-in preprocessor (enabled by default) for expanding the
`{{# playpen}}` and `{{# include}}` helpers in a chapter. `{{# playground}}` and `{{# include}}` helpers in a chapter.
Renderers are given the final book so they can do something with it. This is Renderers are given the final book so they can do something with it. This is
typically used for, as the name suggests, rendering the document in a particular typically used for, as the name suggests, rendering the document in a particular

View File

@ -10,7 +10,7 @@ edition = "2018"
[output.html] [output.html]
mathjax-support = true mathjax-support = true
[output.html.playpen] [output.html.playground]
editable = true editable = true
line-numbers = true line-numbers = true

View File

@ -100,7 +100,7 @@ This controls the build process of your book.
The following preprocessors are available and included by default: The following preprocessors are available and included by default:
- `links`: Expand the `{{ #playpen }}`, `{{ #include }}`, and `{{ #rustdoc_include }}` handlebars - `links`: Expand the `{{ #playground }}`, `{{ #include }}`, and `{{ #rustdoc_include }}` handlebars
helpers in a chapter to include the contents of a file. helpers in a chapter to include the contents of a file.
- `index`: Convert all chapter files named `README.md` into `index.md`. That is - `index`: Convert all chapter files named `README.md` into `index.md`. That is
to say, all `README.md` would be rendered to an index file `index.html` in the to say, all `README.md` would be rendered to an index file `index.html` in the
@ -191,7 +191,7 @@ The following configuration options are available:
contents column. For example, "1.", "2.1". Set this option to true to disable contents column. For example, "1.", "2.1". Set this option to true to disable
those labels. Defaults to `false`. those labels. Defaults to `false`.
- **fold:** A subtable for configuring sidebar section-folding behavior. - **fold:** A subtable for configuring sidebar section-folding behavior.
- **playpen:** A subtable for configuring various playpen settings. - **playground:** A subtable for configuring various playground settings.
- **search:** A subtable for configuring the in-browser search functionality. - **search:** A subtable for configuring the in-browser search functionality.
mdBook must be compiled with the `search` feature enabled (on by default). mdBook must be compiled with the `search` feature enabled (on by default).
- **git-repository-url:** A url to the git repository for the book. If provided - **git-repository-url:** A url to the git repository for the book. If provided
@ -212,7 +212,7 @@ Available configuration options for the `[output.html.fold]` table:
- **level:** The higher the more folded regions are open. When level is 0, all - **level:** The higher the more folded regions are open. When level is 0, all
folds are closed. Defaults to `0`. folds are closed. Defaults to `0`.
Available configuration options for the `[output.html.playpen]` table: Available configuration options for the `[output.html.playground]` table:
- **editable:** Allow editing the source code. Defaults to `false`. - **editable:** Allow editing the source code. Defaults to `false`.
- **copyable:** Display the copy button on code snippets. Defaults to `true`. - **copyable:** Display the copy button on code snippets. Defaults to `true`.
@ -271,7 +271,7 @@ git-repository-icon = "fa-github"
enable = false enable = false
level = 0 level = 0
[output.html.playpen] [output.html.playground]
editable = false editable = false
copy-js = true copy-js = true
line-numbers = false line-numbers = false

View File

@ -92,17 +92,17 @@ impl System for MySystem { ... }
Then in the book, all you have to do is: Then in the book, all you have to do is:
````hbs ````hbs
Here is a component: Here is a component:
```rust,no_run,noplaypen ```rust,no_run,noplayground
\{{#include file.rs:component}} \{{#include file.rs:component}}
``` ```
Here is a system: Here is a system:
```rust,no_run,noplaypen ```rust,no_run,noplayground
\{{#include file.rs:system}} \{{#include file.rs:system}}
``` ```
This is the full file. This is the full file.
```rust,no_run,noplaypen ```rust,no_run,noplayground
\{{#include file.rs:all}} \{{#include file.rs:all}}
``` ```
```` ````
@ -178,17 +178,17 @@ That is, it looks like this (click the "expand" icon to see the rest of the file
With the following syntax, you can insert runnable Rust files into your book: With the following syntax, you can insert runnable Rust files into your book:
```hbs ```hbs
\{{#playpen file.rs}} \{{#playground file.rs}}
``` ```
The path to the Rust file has to be relative from the current source file. The path to the Rust file has to be relative from the current source file.
When play is clicked, the code snippet will be sent to the [Rust Playpen] to be When play is clicked, the code snippet will be sent to the [Rust Playground] to be
compiled and run. The result is sent back and displayed directly underneath the compiled and run. The result is sent back and displayed directly underneath the
code. code.
Here is what a rendered code snippet looks like: Here is what a rendered code snippet looks like:
{{#playpen example.rs}} {{#playground example.rs}}
[Rust Playpen]: https://play.rust-lang.org/ [Rust Playground]: https://play.rust-lang.org/

View File

@ -1,11 +1,11 @@
# Editor # Editor
In addition to providing runnable code playpens, mdBook optionally allows them In addition to providing runnable code playgrounds, mdBook optionally allows them
to be editable. In order to enable editable code blocks, the following needs to to be editable. In order to enable editable code blocks, the following needs to
be added to the ***book.toml***: be added to the ***book.toml***:
```toml ```toml
[output.html.playpen] [output.html.playground]
editable = true editable = true
``` ```
@ -19,7 +19,7 @@ fn main() {
} }
```</code></pre> ```</code></pre>
The above will result in this editable playpen: The above will result in this editable playground:
```rust,editable ```rust,editable
fn main() { fn main() {
@ -28,7 +28,7 @@ fn main() {
} }
``` ```
Note the new `Undo Changes` button in the editable playpens. Note the new `Undo Changes` button in the editable playgrounds.
## Customizing the Editor ## Customizing the Editor
@ -36,7 +36,7 @@ By default, the editor is the [Ace](https://ace.c9.io/) editor, but, if desired,
the functionality may be overriden by providing a different folder: the functionality may be overriden by providing a different folder:
```toml ```toml
[output.html.playpen] [output.html.playground]
editable = true editable = true
editor = "/path/to/editor" editor = "/path/to/editor"
``` ```

View File

@ -158,7 +158,7 @@ impl Config {
/// Fetch an arbitrary item from the `Config` as a `toml::Value`. /// Fetch an arbitrary item from the `Config` as a `toml::Value`.
/// ///
/// You can use dotted indices to access nested items (e.g. /// You can use dotted indices to access nested items (e.g.
/// `output.html.playpen` will fetch the "playpen" out of the html output /// `output.html.playground` will fetch the "playground" out of the html output
/// table). /// table).
pub fn get(&self, key: &str) -> Option<&Value> { pub fn get(&self, key: &str) -> Option<&Value> {
self.rest.read(key) self.rest.read(key)
@ -451,11 +451,11 @@ impl Default for BuildConfig {
} }
} }
/// Configuration for the Rust compiler(e.g., for playpen) /// Configuration for the Rust compiler(e.g., for playground)
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
#[serde(default, rename_all = "kebab-case")] #[serde(default, rename_all = "kebab-case")]
pub struct RustConfig { pub struct RustConfig {
/// Rust edition used in playpen /// Rust edition used in playground
pub edition: Option<RustEdition>, pub edition: Option<RustEdition>,
} }
@ -496,8 +496,9 @@ pub struct HtmlConfig {
pub additional_js: Vec<PathBuf>, pub additional_js: Vec<PathBuf>,
/// Fold settings. /// Fold settings.
pub fold: Fold, pub fold: Fold,
/// Playpen settings. /// Playground settings.
pub playpen: Playpen, #[serde(alias = "playpen")]
pub playground: Playground,
/// Don't render section labels. /// Don't render section labels.
pub no_section_label: bool, pub no_section_label: bool,
/// Search settings. If `None`, the default will be used. /// Search settings. If `None`, the default will be used.
@ -533,7 +534,7 @@ impl Default for HtmlConfig {
additional_css: Vec::new(), additional_css: Vec::new(),
additional_js: Vec::new(), additional_js: Vec::new(),
fold: Fold::default(), fold: Fold::default(),
playpen: Playpen::default(), playground: Playground::default(),
no_section_label: false, no_section_label: false,
search: None, search: None,
git_repository_url: None, git_repository_url: None,
@ -567,24 +568,24 @@ pub struct Fold {
pub level: u8, pub level: u8,
} }
/// Configuration for tweaking how the the HTML renderer handles the playpen. /// Configuration for tweaking how the the HTML renderer handles the playground.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(default, rename_all = "kebab-case")] #[serde(default, rename_all = "kebab-case")]
pub struct Playpen { pub struct Playground {
/// Should playpen snippets be editable? Default: `false`. /// Should playground snippets be editable? Default: `false`.
pub editable: bool, pub editable: bool,
/// Display the copy button. Default: `true`. /// Display the copy button. Default: `true`.
pub copyable: bool, pub copyable: bool,
/// Copy JavaScript files for the editor to the output directory? /// Copy JavaScript files for the editor to the output directory?
/// Default: `true`. /// Default: `true`.
pub copy_js: bool, pub copy_js: bool,
/// Display line numbers on playpen snippets. Default: `false`. /// Display line numbers on playground snippets. Default: `false`.
pub line_numbers: bool, pub line_numbers: bool,
} }
impl Default for Playpen { impl Default for Playground {
fn default() -> Playpen { fn default() -> Playground {
Playpen { Playground {
editable: false, editable: false,
copyable: true, copyable: true,
copy_js: true, copy_js: true,
@ -694,7 +695,7 @@ mod tests {
git-repository-url = "https://foo.com/" git-repository-url = "https://foo.com/"
git-repository-icon = "fa-code-fork" git-repository-icon = "fa-code-fork"
[output.html.playpen] [output.html.playground]
editable = true editable = true
editor = "ace" editor = "ace"
@ -725,7 +726,7 @@ mod tests {
use_default_preprocessors: true, use_default_preprocessors: true,
}; };
let rust_should_be = RustConfig { edition: None }; let rust_should_be = RustConfig { edition: None };
let playpen_should_be = Playpen { let playground_should_be = Playground {
editable: true, editable: true,
copyable: true, copyable: true,
copy_js: true, copy_js: true,
@ -737,7 +738,7 @@ mod tests {
additional_css: vec![PathBuf::from("./foo/bar/baz.css")], additional_css: vec![PathBuf::from("./foo/bar/baz.css")],
theme: Some(PathBuf::from("./themedir")), theme: Some(PathBuf::from("./themedir")),
default_theme: Some(String::from("rust")), default_theme: Some(String::from("rust")),
playpen: playpen_should_be, playground: playground_should_be,
git_repository_url: Some(String::from("https://foo.com/")), git_repository_url: Some(String::from("https://foo.com/")),
git_repository_icon: Some(String::from("fa-code-fork")), git_repository_icon: Some(String::from("fa-code-fork")),
redirect: vec![ redirect: vec![
@ -854,7 +855,7 @@ mod tests {
// is happy... // is happy...
let src = COMPLEX_CONFIG; let src = COMPLEX_CONFIG;
let mut config = Config::from_str(src).unwrap(); let mut config = Config::from_str(src).unwrap();
let key = "output.html.playpen.editable"; let key = "output.html.playground.editable";
assert_eq!(config.get(key).unwrap(), &Value::Boolean(true)); assert_eq!(config.get(key).unwrap(), &Value::Boolean(true));
*config.get_mut(key).unwrap() = Value::Boolean(false); *config.get_mut(key).unwrap() = Value::Boolean(false);

View File

@ -22,7 +22,7 @@ const MAX_LINK_NESTED_DEPTH: usize = 10;
///. specified or the lines between specified anchors, and include the rest of the file behind `#`. ///. specified or the lines between specified anchors, and include the rest of the file behind `#`.
/// This hides the lines from initial display but shows them when the reader expands the code /// This hides the lines from initial display but shows them when the reader expands the code
/// block and provides them to Rustdoc for testing. /// block and provides them to Rustdoc for testing.
/// - `{{# playpen}}` - Insert runnable Rust files /// - `{{# playground}}` - Insert runnable Rust files
#[derive(Default)] #[derive(Default)]
pub struct LinkPreprocessor; pub struct LinkPreprocessor;
@ -114,7 +114,7 @@ where
enum LinkType<'a> { enum LinkType<'a> {
Escaped, Escaped,
Include(PathBuf, RangeOrAnchor), Include(PathBuf, RangeOrAnchor),
Playpen(PathBuf, Vec<&'a str>), Playground(PathBuf, Vec<&'a str>),
RustdocInclude(PathBuf, RangeOrAnchor), RustdocInclude(PathBuf, RangeOrAnchor),
} }
@ -183,7 +183,7 @@ impl<'a> LinkType<'a> {
match self { match self {
LinkType::Escaped => None, LinkType::Escaped => None,
LinkType::Include(p, _) => Some(return_relative_path(base, &p)), LinkType::Include(p, _) => Some(return_relative_path(base, &p)),
LinkType::Playpen(p, _) => Some(return_relative_path(base, &p)), LinkType::Playground(p, _) => Some(return_relative_path(base, &p)),
LinkType::RustdocInclude(p, _) => Some(return_relative_path(base, &p)), LinkType::RustdocInclude(p, _) => Some(return_relative_path(base, &p)),
} }
} }
@ -262,7 +262,15 @@ impl<'a> Link<'a> {
match (typ.as_str(), file_arg) { match (typ.as_str(), file_arg) {
("include", Some(pth)) => Some(parse_include_path(pth)), ("include", Some(pth)) => Some(parse_include_path(pth)),
("playpen", Some(pth)) => Some(LinkType::Playpen(pth.into(), props)), ("playground", Some(pth)) => Some(LinkType::Playground(pth.into(), props)),
("playpen", Some(pth)) => {
warn!(
"the {{{{#playpen}}}} expression has been \
renamed to {{{{#playground}}}}, \
please update your book to use the new name"
);
Some(LinkType::Playground(pth.into(), props))
}
("rustdoc_include", Some(pth)) => Some(parse_rustdoc_include_path(pth)), ("rustdoc_include", Some(pth)) => Some(parse_rustdoc_include_path(pth)),
_ => None, _ => None,
} }
@ -324,7 +332,7 @@ impl<'a> Link<'a> {
) )
}) })
} }
LinkType::Playpen(ref pat, ref attrs) => { LinkType::Playground(ref pat, ref attrs) => {
let target = base.join(pat); let target = base.join(pat);
let contents = fs::read_to_string(&target).with_context(|| { let contents = fs::read_to_string(&target).with_context(|| {
@ -406,7 +414,7 @@ mod tests {
#[test] #[test]
fn test_find_links_partial_link() { fn test_find_links_partial_link() {
let s = "Some random text with {{#playpen..."; let s = "Some random text with {{#playground...";
assert!(find_links(s).collect::<Vec<_>>() == vec![]); assert!(find_links(s).collect::<Vec<_>>() == vec![]);
let s = "Some random text with {{#include..."; let s = "Some random text with {{#include...";
assert!(find_links(s).collect::<Vec<_>>() == vec![]); assert!(find_links(s).collect::<Vec<_>>() == vec![]);
@ -416,19 +424,19 @@ mod tests {
#[test] #[test]
fn test_find_links_empty_link() { fn test_find_links_empty_link() {
let s = "Some random text with {{#playpen}} and {{#playpen }} {{}} {{#}}..."; let s = "Some random text with {{#playground}} and {{#playground }} {{}} {{#}}...";
assert!(find_links(s).collect::<Vec<_>>() == vec![]); assert!(find_links(s).collect::<Vec<_>>() == vec![]);
} }
#[test] #[test]
fn test_find_links_unknown_link_type() { fn test_find_links_unknown_link_type() {
let s = "Some random text with {{#playpenz ar.rs}} and {{#incn}} {{baz}} {{#bar}}..."; let s = "Some random text with {{#playgroundz ar.rs}} and {{#incn}} {{baz}} {{#bar}}...";
assert!(find_links(s).collect::<Vec<_>>() == vec![]); assert!(find_links(s).collect::<Vec<_>>() == vec![]);
} }
#[test] #[test]
fn test_find_links_simple_link() { fn test_find_links_simple_link() {
let s = "Some random text with {{#playpen file.rs}} and {{#playpen test.rs }}..."; let s = "Some random text with {{#playground file.rs}} and {{#playground test.rs }}...";
let res = find_links(s).collect::<Vec<_>>(); let res = find_links(s).collect::<Vec<_>>();
println!("\nOUTPUT: {:?}\n", res); println!("\nOUTPUT: {:?}\n", res);
@ -438,15 +446,15 @@ mod tests {
vec![ vec![
Link { Link {
start_index: 22, start_index: 22,
end_index: 42, end_index: 45,
link_type: LinkType::Playpen(PathBuf::from("file.rs"), vec![]), link_type: LinkType::Playground(PathBuf::from("file.rs"), vec![]),
link_text: "{{#playpen file.rs}}", link_text: "{{#playground file.rs}}",
}, },
Link { Link {
start_index: 47, start_index: 50,
end_index: 68, end_index: 74,
link_type: LinkType::Playpen(PathBuf::from("test.rs"), vec![]), link_type: LinkType::Playground(PathBuf::from("test.rs"), vec![]),
link_text: "{{#playpen test.rs }}", link_text: "{{#playground test.rs }}",
}, },
] ]
); );
@ -454,7 +462,7 @@ mod tests {
#[test] #[test]
fn test_find_links_with_special_characters() { fn test_find_links_with_special_characters() {
let s = "Some random text with {{#playpen foo-bar\\baz/_c++.rs}}..."; let s = "Some random text with {{#playground foo-bar\\baz/_c++.rs}}...";
let res = find_links(s).collect::<Vec<_>>(); let res = find_links(s).collect::<Vec<_>>();
println!("\nOUTPUT: {:?}\n", res); println!("\nOUTPUT: {:?}\n", res);
@ -463,9 +471,9 @@ mod tests {
res, res,
vec![Link { vec![Link {
start_index: 22, start_index: 22,
end_index: 54, end_index: 57,
link_type: LinkType::Playpen(PathBuf::from("foo-bar\\baz/_c++.rs"), vec![]), link_type: LinkType::Playground(PathBuf::from("foo-bar\\baz/_c++.rs"), vec![]),
link_text: "{{#playpen foo-bar\\baz/_c++.rs}}", link_text: "{{#playground foo-bar\\baz/_c++.rs}}",
},] },]
); );
} }
@ -605,7 +613,7 @@ mod tests {
#[test] #[test]
fn test_find_links_escaped_link() { fn test_find_links_escaped_link() {
let s = "Some random text with escaped playpen \\{{#playpen file.rs editable}} ..."; let s = "Some random text with escaped playground \\{{#playground file.rs editable}} ...";
let res = find_links(s).collect::<Vec<_>>(); let res = find_links(s).collect::<Vec<_>>();
println!("\nOUTPUT: {:?}\n", res); println!("\nOUTPUT: {:?}\n", res);
@ -613,18 +621,19 @@ mod tests {
assert_eq!( assert_eq!(
res, res,
vec![Link { vec![Link {
start_index: 38, start_index: 41,
end_index: 68, end_index: 74,
link_type: LinkType::Escaped, link_type: LinkType::Escaped,
link_text: "\\{{#playpen file.rs editable}}", link_text: "\\{{#playground file.rs editable}}",
}] }]
); );
} }
#[test] #[test]
fn test_find_playpens_with_properties() { fn test_find_playgrounds_with_properties() {
let s = "Some random text with escaped playpen {{#playpen file.rs editable }} and some \ let s =
more\n text {{#playpen my.rs editable no_run should_panic}} ..."; "Some random text with escaped playground {{#playground file.rs editable }} and some \
more\n text {{#playground my.rs editable no_run should_panic}} ...";
let res = find_links(s).collect::<Vec<_>>(); let res = find_links(s).collect::<Vec<_>>();
println!("\nOUTPUT: {:?}\n", res); println!("\nOUTPUT: {:?}\n", res);
@ -632,19 +641,19 @@ mod tests {
res, res,
vec![ vec![
Link { Link {
start_index: 38, start_index: 41,
end_index: 68, end_index: 74,
link_type: LinkType::Playpen(PathBuf::from("file.rs"), vec!["editable"]), link_type: LinkType::Playground(PathBuf::from("file.rs"), vec!["editable"]),
link_text: "{{#playpen file.rs editable }}", link_text: "{{#playground file.rs editable }}",
}, },
Link { Link {
start_index: 89, start_index: 95,
end_index: 136, end_index: 145,
link_type: LinkType::Playpen( link_type: LinkType::Playground(
PathBuf::from("my.rs"), PathBuf::from("my.rs"),
vec!["editable", "no_run", "should_panic"], vec!["editable", "no_run", "should_panic"],
), ),
link_text: "{{#playpen my.rs editable no_run should_panic}}", link_text: "{{#playground my.rs editable no_run should_panic}}",
}, },
] ]
); );
@ -652,8 +661,9 @@ mod tests {
#[test] #[test]
fn test_find_all_link_types() { fn test_find_all_link_types() {
let s = "Some random text with escaped playpen {{#include file.rs}} and \\{{#contents are \ let s =
insignifficant in escaped link}} some more\n text {{#playpen my.rs editable \ "Some random text with escaped playground {{#include file.rs}} and \\{{#contents are \
insignifficant in escaped link}} some more\n text {{#playground my.rs editable \
no_run should_panic}} ..."; no_run should_panic}} ...";
let res = find_links(s).collect::<Vec<_>>(); let res = find_links(s).collect::<Vec<_>>();
@ -662,8 +672,8 @@ mod tests {
assert_eq!( assert_eq!(
res[0], res[0],
Link { Link {
start_index: 38, start_index: 41,
end_index: 58, end_index: 61,
link_type: LinkType::Include( link_type: LinkType::Include(
PathBuf::from("file.rs"), PathBuf::from("file.rs"),
RangeOrAnchor::Range(LineRange::from(..)) RangeOrAnchor::Range(LineRange::from(..))
@ -674,8 +684,8 @@ mod tests {
assert_eq!( assert_eq!(
res[1], res[1],
Link { Link {
start_index: 63, start_index: 66,
end_index: 112, end_index: 115,
link_type: LinkType::Escaped, link_type: LinkType::Escaped,
link_text: "\\{{#contents are insignifficant in escaped link}}", link_text: "\\{{#contents are insignifficant in escaped link}}",
} }
@ -683,13 +693,13 @@ mod tests {
assert_eq!( assert_eq!(
res[2], res[2],
Link { Link {
start_index: 130, start_index: 133,
end_index: 177, end_index: 183,
link_type: LinkType::Playpen( link_type: LinkType::Playground(
PathBuf::from("my.rs"), PathBuf::from("my.rs"),
vec!["editable", "no_run", "should_panic"] vec!["editable", "no_run", "should_panic"]
), ),
link_text: "{{#playpen my.rs editable no_run should_panic}}", link_text: "{{#playground my.rs editable no_run should_panic}}",
} }
); );
} }

View File

@ -1,9 +1,9 @@
use crate::book::{Book, BookItem}; use crate::book::{Book, BookItem};
use crate::config::{Config, HtmlConfig, Playpen, RustEdition}; use crate::config::{Config, HtmlConfig, Playground, RustEdition};
use crate::errors::*; use crate::errors::*;
use crate::renderer::html_handlebars::helpers; use crate::renderer::html_handlebars::helpers;
use crate::renderer::{RenderContext, Renderer}; use crate::renderer::{RenderContext, Renderer};
use crate::theme::{self, playpen_editor, Theme}; use crate::theme::{self, playground_editor, Theme};
use crate::utils; use crate::utils;
use std::borrow::Cow; use std::borrow::Cow;
@ -85,7 +85,7 @@ impl HtmlHandlebars {
debug!("Render template"); debug!("Render template");
let rendered = ctx.handlebars.render("index", &ctx.data)?; let rendered = ctx.handlebars.render("index", &ctx.data)?;
let rendered = self.post_process(rendered, &ctx.html_config.playpen, ctx.edition); let rendered = self.post_process(rendered, &ctx.html_config.playground, ctx.edition);
// Write to file // Write to file
debug!("Creating {}", filepath.display()); debug!("Creating {}", filepath.display());
@ -97,7 +97,7 @@ impl HtmlHandlebars {
ctx.data.insert("is_index".to_owned(), json!("true")); ctx.data.insert("is_index".to_owned(), json!("true"));
let rendered_index = ctx.handlebars.render("index", &ctx.data)?; let rendered_index = ctx.handlebars.render("index", &ctx.data)?;
let rendered_index = let rendered_index =
self.post_process(rendered_index, &ctx.html_config.playpen, ctx.edition); self.post_process(rendered_index, &ctx.html_config.playground, ctx.edition);
debug!("Creating index.html from {}", ctx_path); debug!("Creating index.html from {}", ctx_path);
utils::fs::write_file(&ctx.destination, "index.html", rendered_index.as_bytes())?; utils::fs::write_file(&ctx.destination, "index.html", rendered_index.as_bytes())?;
} }
@ -109,12 +109,12 @@ impl HtmlHandlebars {
fn post_process( fn post_process(
&self, &self,
rendered: String, rendered: String,
playpen_config: &Playpen, playground_config: &Playground,
edition: Option<RustEdition>, edition: Option<RustEdition>,
) -> String { ) -> String {
let rendered = build_header_links(&rendered); let rendered = build_header_links(&rendered);
let rendered = fix_code_blocks(&rendered); let rendered = fix_code_blocks(&rendered);
let rendered = add_playpen_pre(&rendered, playpen_config, edition); let rendered = add_playground_pre(&rendered, playground_config, edition);
rendered rendered
} }
@ -194,19 +194,23 @@ impl HtmlHandlebars {
)?; )?;
} }
let playpen_config = &html_config.playpen; let playground_config = &html_config.playground;
// Ace is a very large dependency, so only load it when requested // Ace is a very large dependency, so only load it when requested
if playpen_config.editable && playpen_config.copy_js { if playground_config.editable && playground_config.copy_js {
// Load the editor // Load the editor
write_file(destination, "editor.js", playpen_editor::JS)?; write_file(destination, "editor.js", playground_editor::JS)?;
write_file(destination, "ace.js", playpen_editor::ACE_JS)?; write_file(destination, "ace.js", playground_editor::ACE_JS)?;
write_file(destination, "mode-rust.js", playpen_editor::MODE_RUST_JS)?; write_file(destination, "mode-rust.js", playground_editor::MODE_RUST_JS)?;
write_file(destination, "theme-dawn.js", playpen_editor::THEME_DAWN_JS)?; write_file(
destination,
"theme-dawn.js",
playground_editor::THEME_DAWN_JS,
)?;
write_file( write_file(
destination, destination,
"theme-tomorrow_night.js", "theme-tomorrow_night.js",
playpen_editor::THEME_TOMORROW_NIGHT_JS, playground_editor::THEME_TOMORROW_NIGHT_JS,
)?; )?;
} }
@ -447,7 +451,8 @@ impl Renderer for HtmlHandlebars {
debug!("Render template"); debug!("Render template");
let rendered = handlebars.render("index", &data)?; let rendered = handlebars.render("index", &data)?;
let rendered = self.post_process(rendered, &html_config.playpen, ctx.config.rust.edition); let rendered =
self.post_process(rendered, &html_config.playground, ctx.config.rust.edition);
utils::fs::write_file(&destination, "print.html", rendered.as_bytes())?; utils::fs::write_file(&destination, "print.html", rendered.as_bytes())?;
debug!("Creating print.html ✓"); debug!("Creating print.html ✓");
@ -555,14 +560,14 @@ fn make_data(
data.insert("additional_js".to_owned(), json!(js)); data.insert("additional_js".to_owned(), json!(js));
} }
if html_config.playpen.editable && html_config.playpen.copy_js { if html_config.playground.editable && html_config.playground.copy_js {
data.insert("playpen_js".to_owned(), json!(true)); data.insert("playground_js".to_owned(), json!(true));
if html_config.playpen.line_numbers { if html_config.playground.line_numbers {
data.insert("playpen_line_numbers".to_owned(), json!(true)); data.insert("playground_line_numbers".to_owned(), json!(true));
} }
} }
if html_config.playpen.copyable { if html_config.playground.copyable {
data.insert("playpen_copyable".to_owned(), json!(true)); data.insert("playground_copyable".to_owned(), json!(true));
} }
data.insert("fold_enable".to_owned(), json!((html_config.fold.enable))); data.insert("fold_enable".to_owned(), json!((html_config.fold.enable)));
@ -705,7 +710,11 @@ fn fix_code_blocks(html: &str) -> String {
.into_owned() .into_owned()
} }
fn add_playpen_pre(html: &str, playpen_config: &Playpen, edition: Option<RustEdition>) -> String { fn add_playground_pre(
html: &str,
playground_config: &Playground,
edition: Option<RustEdition>,
) -> String {
let regex = Regex::new(r##"((?s)<code[^>]?class="([^"]+)".*?>(.*?)</code>)"##).unwrap(); let regex = Regex::new(r##"((?s)<code[^>]?class="([^"]+)".*?>(.*?)</code>)"##).unwrap();
regex regex
.replace_all(html, |caps: &Captures<'_>| { .replace_all(html, |caps: &Captures<'_>| {
@ -714,7 +723,9 @@ fn add_playpen_pre(html: &str, playpen_config: &Playpen, edition: Option<RustEdi
let code = &caps[3]; let code = &caps[3];
if classes.contains("language-rust") { if classes.contains("language-rust") {
if (!classes.contains("ignore") && !classes.contains("noplaypen")) if (!classes.contains("ignore")
&& !classes.contains("noplayground")
&& !classes.contains("noplaypen"))
|| classes.contains("mdbook-runnable") || classes.contains("mdbook-runnable")
{ {
let contains_e2015 = classes.contains("edition2015"); let contains_e2015 = classes.contains("edition2015");
@ -732,11 +743,11 @@ fn add_playpen_pre(html: &str, playpen_config: &Playpen, edition: Option<RustEdi
// wrap the contents in an external pre block // wrap the contents in an external pre block
format!( format!(
"<pre class=\"playpen\"><code class=\"{}{}\">{}</code></pre>", "<pre class=\"playground\"><code class=\"{}{}\">{}</code></pre>",
classes, classes,
edition_class, edition_class,
{ {
let content: Cow<'_, str> = if playpen_config.editable let content: Cow<'_, str> = if playground_config.editable
&& classes.contains("editable") && classes.contains("editable")
|| text.contains("fn main") || text.contains("fn main")
|| text.contains("quick_main!") || text.contains("quick_main!")
@ -868,29 +879,29 @@ mod tests {
} }
#[test] #[test]
fn add_playpen() { fn add_playground() {
let inputs = [ let inputs = [
("<code class=\"language-rust\">x()</code>", ("<code class=\"language-rust\">x()</code>",
"<pre class=\"playpen\"><code class=\"language-rust\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}\n</span></code></pre>"), "<pre class=\"playground\"><code class=\"language-rust\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}\n</span></code></pre>"),
("<code class=\"language-rust\">fn main() {}</code>", ("<code class=\"language-rust\">fn main() {}</code>",
"<pre class=\"playpen\"><code class=\"language-rust\">fn main() {}\n</code></pre>"), "<pre class=\"playground\"><code class=\"language-rust\">fn main() {}\n</code></pre>"),
("<code class=\"language-rust editable\">let s = \"foo\n # bar\n\";</code>", ("<code class=\"language-rust editable\">let s = \"foo\n # bar\n\";</code>",
"<pre class=\"playpen\"><code class=\"language-rust editable\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";\n</code></pre>"), "<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";\n</code></pre>"),
("<code class=\"language-rust editable\">let s = \"foo\n ## bar\n\";</code>", ("<code class=\"language-rust editable\">let s = \"foo\n ## bar\n\";</code>",
"<pre class=\"playpen\"><code class=\"language-rust editable\">let s = \"foo\n # bar\n\";\n</code></pre>"), "<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n # bar\n\";\n</code></pre>"),
("<code class=\"language-rust editable\">let s = \"foo\n # bar\n#\n\";</code>", ("<code class=\"language-rust editable\">let s = \"foo\n # bar\n#\n\";</code>",
"<pre class=\"playpen\"><code class=\"language-rust editable\">let s = \"foo\n<span class=\"boring\"> bar\n</span><span class=\"boring\">\n</span>\";\n</code></pre>"), "<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n<span class=\"boring\"> bar\n</span><span class=\"boring\">\n</span>\";\n</code></pre>"),
("<code class=\"language-rust ignore\">let s = \"foo\n # bar\n\";</code>", ("<code class=\"language-rust ignore\">let s = \"foo\n # bar\n\";</code>",
"<code class=\"language-rust ignore\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";\n</code>"), "<code class=\"language-rust ignore\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";\n</code>"),
("<code class=\"language-rust editable\">#![no_std]\nlet s = \"foo\";\n #[some_attr]</code>", ("<code class=\"language-rust editable\">#![no_std]\nlet s = \"foo\";\n #[some_attr]</code>",
"<pre class=\"playpen\"><code class=\"language-rust editable\">#![no_std]\nlet s = \"foo\";\n #[some_attr]\n</code></pre>"), "<pre class=\"playground\"><code class=\"language-rust editable\">#![no_std]\nlet s = \"foo\";\n #[some_attr]\n</code></pre>"),
]; ];
for (src, should_be) in &inputs { for (src, should_be) in &inputs {
let got = add_playpen_pre( let got = add_playground_pre(
src, src,
&Playpen { &Playground {
editable: true, editable: true,
..Playpen::default() ..Playground::default()
}, },
None, None,
); );
@ -898,23 +909,23 @@ mod tests {
} }
} }
#[test] #[test]
fn add_playpen_edition2015() { fn add_playground_edition2015() {
let inputs = [ let inputs = [
("<code class=\"language-rust\">x()</code>", ("<code class=\"language-rust\">x()</code>",
"<pre class=\"playpen\"><code class=\"language-rust edition2015\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}\n</span></code></pre>"), "<pre class=\"playground\"><code class=\"language-rust edition2015\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}\n</span></code></pre>"),
("<code class=\"language-rust\">fn main() {}</code>", ("<code class=\"language-rust\">fn main() {}</code>",
"<pre class=\"playpen\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"), "<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
("<code class=\"language-rust edition2015\">fn main() {}</code>", ("<code class=\"language-rust edition2015\">fn main() {}</code>",
"<pre class=\"playpen\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"), "<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
("<code class=\"language-rust edition2018\">fn main() {}</code>", ("<code class=\"language-rust edition2018\">fn main() {}</code>",
"<pre class=\"playpen\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"), "<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
]; ];
for (src, should_be) in &inputs { for (src, should_be) in &inputs {
let got = add_playpen_pre( let got = add_playground_pre(
src, src,
&Playpen { &Playground {
editable: true, editable: true,
..Playpen::default() ..Playground::default()
}, },
Some(RustEdition::E2015), Some(RustEdition::E2015),
); );
@ -922,23 +933,23 @@ mod tests {
} }
} }
#[test] #[test]
fn add_playpen_edition2018() { fn add_playground_edition2018() {
let inputs = [ let inputs = [
("<code class=\"language-rust\">x()</code>", ("<code class=\"language-rust\">x()</code>",
"<pre class=\"playpen\"><code class=\"language-rust edition2018\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}\n</span></code></pre>"), "<pre class=\"playground\"><code class=\"language-rust edition2018\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}\n</span></code></pre>"),
("<code class=\"language-rust\">fn main() {}</code>", ("<code class=\"language-rust\">fn main() {}</code>",
"<pre class=\"playpen\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"), "<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
("<code class=\"language-rust edition2015\">fn main() {}</code>", ("<code class=\"language-rust edition2015\">fn main() {}</code>",
"<pre class=\"playpen\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"), "<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
("<code class=\"language-rust edition2018\">fn main() {}</code>", ("<code class=\"language-rust edition2018\">fn main() {}</code>",
"<pre class=\"playpen\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"), "<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
]; ];
for (src, should_be) in &inputs { for (src, should_be) in &inputs {
let got = add_playpen_pre( let got = add_playground_pre(
src, src,
&Playpen { &Playground {
editable: true, editable: true,
..Playpen::default() ..Playground::default()
}, },
Some(RustEdition::E2018), Some(RustEdition::E2018),
); );

View File

@ -4,8 +4,8 @@
window.onunload = function () { }; window.onunload = function () { };
// Global variable, shared between modules // Global variable, shared between modules
function playpen_text(playpen) { function playground_text(playground) {
let code_block = playpen.querySelector("code"); let code_block = playground.querySelector("code");
if (window.ace && code_block.classList.contains("editable")) { if (window.ace && code_block.classList.contains("editable")) {
let editor = window.ace.edit(code_block); let editor = window.ace.edit(code_block);
@ -23,8 +23,8 @@ function playpen_text(playpen) {
]); ]);
} }
var playpens = Array.from(document.querySelectorAll(".playpen")); var playgrounds = Array.from(document.querySelectorAll(".playground"));
if (playpens.length > 0) { if (playgrounds.length > 0) {
fetch_with_timeout("https://play.rust-lang.org/meta/crates", { fetch_with_timeout("https://play.rust-lang.org/meta/crates", {
headers: { headers: {
'Content-Type': "application/json", 'Content-Type': "application/json",
@ -36,21 +36,21 @@ function playpen_text(playpen) {
.then(response => { .then(response => {
// get list of crates available in the rust playground // get list of crates available in the rust playground
let playground_crates = response.crates.map(item => item["id"]); let playground_crates = response.crates.map(item => item["id"]);
playpens.forEach(block => handle_crate_list_update(block, playground_crates)); playgrounds.forEach(block => handle_crate_list_update(block, playground_crates));
}); });
} }
function handle_crate_list_update(playpen_block, playground_crates) { function handle_crate_list_update(playground_block, playground_crates) {
// update the play buttons after receiving the response // update the play buttons after receiving the response
update_play_button(playpen_block, playground_crates); update_play_button(playground_block, playground_crates);
// and install on change listener to dynamically update ACE editors // and install on change listener to dynamically update ACE editors
if (window.ace) { if (window.ace) {
let code_block = playpen_block.querySelector("code"); let code_block = playground_block.querySelector("code");
if (code_block.classList.contains("editable")) { if (code_block.classList.contains("editable")) {
let editor = window.ace.edit(code_block); let editor = window.ace.edit(code_block);
editor.addEventListener("change", function (e) { editor.addEventListener("change", function (e) {
update_play_button(playpen_block, playground_crates); update_play_button(playground_block, playground_crates);
}); });
// add Ctrl-Enter command to execute rust code // add Ctrl-Enter command to execute rust code
editor.commands.addCommand({ editor.commands.addCommand({
@ -59,7 +59,7 @@ function playpen_text(playpen) {
win: "Ctrl-Enter", win: "Ctrl-Enter",
mac: "Ctrl-Enter" mac: "Ctrl-Enter"
}, },
exec: _editor => run_rust_code(playpen_block) exec: _editor => run_rust_code(playground_block)
}); });
} }
} }
@ -77,7 +77,7 @@ function playpen_text(playpen) {
} }
// get list of `extern crate`'s from snippet // get list of `extern crate`'s from snippet
var txt = playpen_text(pre_block); var txt = playground_text(pre_block);
var re = /extern\s+crate\s+([a-zA-Z_0-9]+)\s*;/g; var re = /extern\s+crate\s+([a-zA-Z_0-9]+)\s*;/g;
var snippet_crates = []; var snippet_crates = [];
var item; var item;
@ -106,7 +106,7 @@ function playpen_text(playpen) {
code_block.append(result_block); code_block.append(result_block);
} }
let text = playpen_text(code_block); let text = playground_text(code_block);
let classes = code_block.querySelector('code').classList; let classes = code_block.querySelector('code').classList;
let has_2018 = classes.contains("edition2018"); let has_2018 = classes.contains("edition2018");
let edition = has_2018 ? "2018" : "2015"; let edition = has_2018 ? "2018" : "2015";
@ -200,10 +200,10 @@ function playpen_text(playpen) {
}); });
}); });
if (window.playpen_copyable) { if (window.playground_copyable) {
Array.from(document.querySelectorAll('pre code')).forEach(function (block) { Array.from(document.querySelectorAll('pre code')).forEach(function (block) {
var pre_block = block.parentNode; var pre_block = block.parentNode;
if (!pre_block.classList.contains('playpen')) { if (!pre_block.classList.contains('playground')) {
var buttons = pre_block.querySelector(".buttons"); var buttons = pre_block.querySelector(".buttons");
if (!buttons) { if (!buttons) {
buttons = document.createElement('div'); buttons = document.createElement('div');
@ -222,8 +222,8 @@ function playpen_text(playpen) {
}); });
} }
// Process playpen code blocks // Process playground code blocks
Array.from(document.querySelectorAll(".playpen")).forEach(function (pre_block) { Array.from(document.querySelectorAll(".playground")).forEach(function (pre_block) {
// Add play button // Add play button
var buttons = pre_block.querySelector(".buttons"); var buttons = pre_block.querySelector(".buttons");
if (!buttons) { if (!buttons) {
@ -243,7 +243,7 @@ function playpen_text(playpen) {
run_rust_code(pre_block); run_rust_code(pre_block);
}); });
if (window.playpen_copyable) { if (window.playground_copyable) {
var copyCodeClipboardButton = document.createElement('button'); var copyCodeClipboardButton = document.createElement('button');
copyCodeClipboardButton.className = 'fa fa-copy clip-button'; copyCodeClipboardButton.className = 'fa fa-copy clip-button';
copyCodeClipboardButton.innerHTML = '<i class="tooltiptext"></i>'; copyCodeClipboardButton.innerHTML = '<i class="tooltiptext"></i>';
@ -572,8 +572,8 @@ function playpen_text(playpen) {
var clipboardSnippets = new ClipboardJS('.clip-button', { var clipboardSnippets = new ClipboardJS('.clip-button', {
text: function (trigger) { text: function (trigger) {
hideTooltip(trigger); hideTooltip(trigger);
let playpen = trigger.closest("pre"); let playground = trigger.closest("pre");
return playpen_text(playpen); return playground_text(playground);
} }
}); });

View File

@ -236,19 +236,19 @@
</script> </script>
{{/if}} {{/if}}
{{#if playpen_line_numbers}} {{#if playground_line_numbers}}
<script type="text/javascript"> <script type="text/javascript">
window.playpen_line_numbers = true; window.playground_line_numbers = true;
</script> </script>
{{/if}} {{/if}}
{{#if playpen_copyable}} {{#if playground_copyable}}
<script type="text/javascript"> <script type="text/javascript">
window.playpen_copyable = true; window.playground_copyable = true;
</script> </script>
{{/if}} {{/if}}
{{#if playpen_js}} {{#if playground_js}}
<script src="{{ path_to_root }}ace.js" type="text/javascript" charset="utf-8"></script> <script src="{{ path_to_root }}ace.js" type="text/javascript" charset="utf-8"></script>
<script src="{{ path_to_root }}editor.js" type="text/javascript" charset="utf-8"></script> <script src="{{ path_to_root }}editor.js" type="text/javascript" charset="utf-8"></script>
<script src="{{ path_to_root }}mode-rust.js" type="text/javascript" charset="utf-8"></script> <script src="{{ path_to_root }}mode-rust.js" type="text/javascript" charset="utf-8"></script>

View File

@ -1,6 +1,6 @@
#![allow(missing_docs)] #![allow(missing_docs)]
pub mod playpen_editor; pub mod playground_editor;
pub mod fonts; pub mod fonts;

View File

@ -6,7 +6,7 @@ window.editors = [];
} }
Array.from(document.querySelectorAll('.editable')).forEach(function(editable) { Array.from(document.querySelectorAll('.editable')).forEach(function(editable) {
let display_line_numbers = window.playpen_line_numbers || false; let display_line_numbers = window.playground_line_numbers || false;
let editor = ace.edit(editable); let editor = ace.edit(editable);
editor.setOptions({ editor.setOptions({

View File

@ -1,4 +1,4 @@
//! Theme dependencies for the playpen editor. //! Theme dependencies for the playground editor.
pub static JS: &[u8] = include_bytes!("editor.js"); pub static JS: &[u8] = include_bytes!("editor.js");
pub static ACE_JS: &[u8] = include_bytes!("ace.js"); pub static ACE_JS: &[u8] = include_bytes!("ace.js");

View File

@ -2,4 +2,4 @@
This makes sure you can insert runnable Rust files. This makes sure you can insert runnable Rust files.
{{#playpen example.rs}} {{#playground example.rs}}

View File

@ -135,18 +135,18 @@ fn check_correct_relative_links_in_print_page() {
} }
#[test] #[test]
fn rendered_code_has_playpen_stuff() { fn rendered_code_has_playground_stuff() {
let temp = DummyBook::new().build().unwrap(); let temp = DummyBook::new().build().unwrap();
let md = MDBook::load(temp.path()).unwrap(); let md = MDBook::load(temp.path()).unwrap();
md.build().unwrap(); md.build().unwrap();
let nested = temp.path().join("book/first/nested.html"); let nested = temp.path().join("book/first/nested.html");
let playpen_class = vec![r#"class="playpen""#]; let playground_class = vec![r#"class="playground""#];
assert_contains_strings(nested, &playpen_class); assert_contains_strings(nested, &playground_class);
let book_js = temp.path().join("book/book.js"); let book_js = temp.path().join("book/book.js");
assert_contains_strings(book_js, &[".playpen"]); assert_contains_strings(book_js, &[".playground"]);
} }
#[test] #[test]
@ -344,23 +344,23 @@ fn create_missing_file_with_config() {
assert!(temp.path().join("src").join("intro.md").exists()); assert!(temp.path().join("src").join("intro.md").exists());
} }
/// This makes sure you can include a Rust file with `{{#playpen example.rs}}`. /// This makes sure you can include a Rust file with `{{#playground example.rs}}`.
/// Specification is in `book-example/src/format/rust.md` /// Specification is in `book-example/src/format/rust.md`
#[test] #[test]
fn able_to_include_playpen_files_in_chapters() { fn able_to_include_playground_files_in_chapters() {
let temp = DummyBook::new().build().unwrap(); let temp = DummyBook::new().build().unwrap();
let md = MDBook::load(temp.path()).unwrap(); let md = MDBook::load(temp.path()).unwrap();
md.build().unwrap(); md.build().unwrap();
let second = temp.path().join("book/second.html"); let second = temp.path().join("book/second.html");
let playpen_strings = &[ let playground_strings = &[
r#"class="playpen""#, r#"class="playground""#,
r#"println!(&quot;Hello World!&quot;);"#, r#"println!(&quot;Hello World!&quot;);"#,
]; ];
assert_contains_strings(&second, playpen_strings); assert_contains_strings(&second, playground_strings);
assert_doesnt_contain_strings(&second, &["{{#playpen example.rs}}"]); assert_doesnt_contain_strings(&second, &["{{#playground example.rs}}"]);
} }
/// This makes sure you can include a Rust file with `{{#include ../SUMMARY.md}}`. /// This makes sure you can include a Rust file with `{{#include ../SUMMARY.md}}`.