Merge pull request #1088 from benediktwerner/master

Fix hiding of empty boring lines
This commit is contained in:
Eric Huss 2019-11-07 07:44:47 -08:00 committed by GitHub
commit a9160acd64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 67 additions and 53 deletions

View File

@ -601,7 +601,6 @@ fn fix_code_blocks(html: &str) -> String {
} }
fn add_playpen_pre(html: &str, playpen_config: &Playpen) -> String { fn add_playpen_pre(html: &str, playpen_config: &Playpen) -> String {
let boring_line_regex = Regex::new(r"^(\s*)#(#|.)(.*)$").unwrap();
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<'_>| {
@ -609,57 +608,37 @@ fn add_playpen_pre(html: &str, playpen_config: &Playpen) -> String {
let classes = &caps[2]; let classes = &caps[2];
let code = &caps[3]; let code = &caps[3];
if (classes.contains("language-rust") if classes.contains("language-rust") {
&& !classes.contains("ignore") if (!classes.contains("ignore") && !classes.contains("noplaypen"))
&& !classes.contains("noplaypen")) || classes.contains("mdbook-runnable")
|| classes.contains("mdbook-runnable") {
{ // 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=\"playpen\"><code class=\"{}\">{}</code></pre>", classes,
classes,
{
let content: Cow<'_, str> = if playpen_config.editable
&& classes.contains("editable")
|| text.contains("fn main")
|| text.contains("quick_main!")
{ {
code.into() let content: Cow<'_, str> = if playpen_config.editable
} else { && classes.contains("editable")
// we need to inject our own main || text.contains("fn main")
let (attrs, code) = partition_source(code); || text.contains("quick_main!")
{
format!( code.into()
"\n# #![allow(unused_variables)]\n{}#fn main() {{\n{}#}}",
attrs, code
)
.into()
};
let mut prev_line_hidden = false;
let mut result = String::with_capacity(content.len());
for line in content.lines() {
if let Some(caps) = boring_line_regex.captures(line) {
if !prev_line_hidden && &caps[2] != "#" {
result += "<span class=\"boring\">";
prev_line_hidden = true;
}
result += &caps[1];
if &caps[2] != " " {
result += &caps[2];
}
result += &caps[3];
} else { } else {
if prev_line_hidden { // we need to inject our own main
result += "</span>"; let (attrs, code) = partition_source(code);
prev_line_hidden = false;
} format!(
result += line; "\n# #![allow(unused_variables)]\n{}#fn main() {{\n{}#}}",
} attrs, code
result += "\n"; )
.into()
};
hide_lines(&content)
} }
result )
} } else {
) format!("<code class=\"{}\">{}</code>", classes, hide_lines(code))
}
} else { } else {
// not language-rust, so no-op // not language-rust, so no-op
text.to_owned() text.to_owned()
@ -668,6 +647,38 @@ fn add_playpen_pre(html: &str, playpen_config: &Playpen) -> String {
.into_owned() .into_owned()
} }
lazy_static! {
static ref BORING_LINES_REGEX: Regex = Regex::new(r"^(\s*)#(.?)(.*)$").unwrap();
}
fn hide_lines(content: &str) -> String {
let mut result = String::with_capacity(content.len());
for line in content.lines() {
if let Some(caps) = BORING_LINES_REGEX.captures(line) {
if &caps[2] == "#" {
result += &caps[1];
result += &caps[2];
result += &caps[3];
result += "\n";
continue;
} else if &caps[2] != "!" && &caps[2] != "[" {
result += "<span class=\"boring\">";
result += &caps[1];
if &caps[2] != " " {
result += &caps[2];
}
result += &caps[3];
result += "\n";
result += "</span>";
continue;
}
}
result += line;
result += "\n";
}
result
}
fn partition_source(s: &str) -> (String, String) { fn partition_source(s: &str) -> (String, String) {
let mut after_header = false; let mut after_header = false;
let mut before = String::new(); let mut before = String::new();
@ -740,13 +751,19 @@ mod tests {
fn add_playpen() { fn add_playpen() {
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_variables)]\nfn main() {\n</span>x()\n<span class=\"boring\">}\n</code></pre>"), "<pre class=\"playpen\"><code class=\"language-rust\">\n<span class=\"boring\">#![allow(unused_variables)]\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=\"playpen\"><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=\"playpen\"><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=\"playpen\"><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>",
"<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>"),
("<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 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>"),
]; ];
for (src, should_be) in &inputs { for (src, should_be) in &inputs {
let got = add_playpen_pre( let got = add_playpen_pre(

View File

@ -16,9 +16,6 @@ function playpen_text(playpen) {
} }
(function codeSnippets() { (function codeSnippets() {
// Hide Rust code lines prepended with a specific character
var hiding_character = "#";
function fetch_with_timeout(url, options, timeout = 6000) { function fetch_with_timeout(url, options, timeout = 6000) {
return Promise.race([ return Promise.race([
fetch(url, options), fetch(url, options),