Add support for playground language choice

We add a config option under the `Playground` type to allow setting
which language should work with playground.

Any language outside of rust doesn't get any preferential treatment in
terms of code hiding, but atleast we get support at all.
Looks like other languages being able to *use* the playground comes
down to creating their own code in `book.js` after that
This commit is contained in:
Vance Palacio 2022-02-26 20:59:57 +00:00
parent 5921f59817
commit e2b06cb6e7
2 changed files with 68 additions and 48 deletions

View File

@ -630,6 +630,9 @@ pub struct Playground {
pub copy_js: bool,
/// Display line numbers on playground snippets. Default: `false`.
pub line_numbers: bool,
/// Set's the language the playground will work with
/// TODO: Turn this into an array when there's support for multiple languages
pub language: String,
}
impl Default for Playground {
@ -639,6 +642,7 @@ impl Default for Playground {
copyable: true,
copy_js: true,
line_numbers: false,
language: "rust".to_string(),
}
}
}
@ -748,6 +752,7 @@ mod tests {
[output.html.playground]
editable = true
editor = "ace"
language = "rust"
[output.html.redirect]
"index.html" = "overview.html"
@ -781,6 +786,7 @@ mod tests {
copyable: true,
copy_js: true,
line_numbers: false,
language: "rust".to_string(),
};
let html_should_be = HtmlConfig {
curly_quotes: true,

View File

@ -824,64 +824,78 @@ fn add_playground_pre(
let text = &caps[1];
let classes = &caps[2];
let code = &caps[3];
let lang_class = format!("language-{}", playground_config.language);
if classes.contains("language-rust") {
if (!classes.contains("ignore")
&& !classes.contains("noplayground")
&& !classes.contains("noplaypen"))
|| classes.contains("mdbook-runnable")
{
let contains_e2015 = classes.contains("edition2015");
let contains_e2018 = classes.contains("edition2018");
let contains_e2021 = classes.contains("edition2021");
let edition_class = if contains_e2015 || contains_e2018 || contains_e2021 {
// the user forced edition, we should not overwrite it
""
} else {
match edition {
Some(RustEdition::E2015) => " edition2015",
Some(RustEdition::E2018) => " edition2018",
Some(RustEdition::E2021) => " edition2021",
None => "",
}
};
// wrap the contents in an external pre block
format!(
"<pre class=\"playground\"><code class=\"{}{}\">{}</code></pre>",
classes,
edition_class,
{
let content: Cow<'_, str> = if playground_config.editable
&& classes.contains("editable")
|| text.contains("fn main")
|| text.contains("quick_main!")
{
code.into()
} else {
// we need to inject our own main
let (attrs, code) = partition_source(code);
format!(
"\n# #![allow(unused)]\n{}#fn main() {{\n{}#}}",
attrs, code
)
.into()
};
hide_lines(&content)
}
)
if classes.contains(lang_class.as_str()) {
if playground_config.language == "rust" {
add_playground_pre_rust(playground_config, edition, classes, text, code)
} else {
format!("<code class=\"{}\">{}</code>", classes, hide_lines(code))
format!(
"<pre class=\"playground\"><code class=\"{}\">{}</code></pre>",
classes, code
)
}
} else {
// not language-rust, so no-op
// Language doens't match playground config, so no-op
text.to_owned()
}
})
.into_owned()
}
fn add_playground_pre_rust(
playground_config: &Playground,
edition: Option<RustEdition>,
classes: &str,
text: &str,
code: &str,
) -> String {
if (!classes.contains("ignore")
&& !classes.contains("noplayground")
&& !classes.contains("noplaypen"))
|| classes.contains("mdbook-runnable")
{
let contains_e2015 = classes.contains("edition2015");
let contains_e2018 = classes.contains("edition2018");
let contains_e2021 = classes.contains("edition2021");
let edition_class = if contains_e2015 || contains_e2018 || contains_e2021 {
// the user forced edition, we should not overwrite it
""
} else {
match edition {
Some(RustEdition::E2015) => " edition2015",
Some(RustEdition::E2018) => " edition2018",
Some(RustEdition::E2021) => " edition2021",
None => "",
}
};
let all_classes = format!("{}{}", classes, edition_class);
// wrap the contents in an external pre block
format!(
"<pre class=\"playground\"><code class=\"{}\">{}</code></pre>",
all_classes,
{
let content: Cow<'_, str> = if playground_config.editable
&& classes.contains("editable")
|| text.contains("fn main")
|| text.contains("quick_main!")
{
code.into()
} else {
// we need to inject our own main
let (attrs, code) = partition_source(code);
format!("\n# #![allow(unused)]\n{}#fn main() {{\n{}#}}", attrs, code).into()
};
hide_lines(&content)
}
)
} else {
format!("<code class=\"{}\">{}</code>", classes, hide_lines(code))
}
}
lazy_static! {
static ref BORING_LINES_REGEX: Regex = Regex::new(r"^(\s*)#(.?)(.*)$").unwrap();
}