Trim trailing whitespace in Rust code blocks
Before, a code block would always end with a final newline. The newline was added unconditionally by `hide_lines`. When the code block is syntax highlighted by highlight.js, this is not a problem, no empty line is added for a final trailing `\n` character. However, when the code block is editable and thus handled by the ACE editor, a trailing newline _is_ significant. I believe this issue is most closely described by https://github.com/ajaxorg/ace/issues/2083 in the upstream repository. The effect of the way ACE handles newlines is that a code block like <pre> Some code </pre> will create an editor with _two_ lines, not just one. By trimming trailing whitespace, we ensure that we don’t accidentally create more lines in the ACE editor than necessary.
This commit is contained in:
parent
4cf005d4bd
commit
217546c2a0
|
@ -903,13 +903,16 @@ fn hide_lines(content: &str) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = String::with_capacity(content.len());
|
let mut result = String::with_capacity(content.len());
|
||||||
for line in content.lines() {
|
let mut lines = content.lines().peekable();
|
||||||
|
while let Some(line) = lines.next() {
|
||||||
|
// Don't include newline on the last line.
|
||||||
|
let newline = if lines.peek().is_none() { "" } else { "\n" };
|
||||||
if let Some(caps) = BORING_LINES_REGEX.captures(line) {
|
if let Some(caps) = BORING_LINES_REGEX.captures(line) {
|
||||||
if &caps[2] == "#" {
|
if &caps[2] == "#" {
|
||||||
result += &caps[1];
|
result += &caps[1];
|
||||||
result += &caps[2];
|
result += &caps[2];
|
||||||
result += &caps[3];
|
result += &caps[3];
|
||||||
result += "\n";
|
result += newline;
|
||||||
continue;
|
continue;
|
||||||
} else if &caps[2] != "!" && &caps[2] != "[" {
|
} else if &caps[2] != "!" && &caps[2] != "[" {
|
||||||
result += "<span class=\"boring\">";
|
result += "<span class=\"boring\">";
|
||||||
|
@ -918,13 +921,13 @@ fn hide_lines(content: &str) -> String {
|
||||||
result += &caps[2];
|
result += &caps[2];
|
||||||
}
|
}
|
||||||
result += &caps[3];
|
result += &caps[3];
|
||||||
result += "\n";
|
result += newline;
|
||||||
result += "</span>";
|
result += "</span>";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result += line;
|
result += line;
|
||||||
result += "\n";
|
result += newline;
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -1004,19 +1007,19 @@ mod tests {
|
||||||
fn add_playground() {
|
fn add_playground() {
|
||||||
let inputs = [
|
let inputs = [
|
||||||
("<code class=\"language-rust\">x()</code>",
|
("<code class=\"language-rust\">x()</code>",
|
||||||
"<pre class=\"playground\"><code class=\"language-rust\"><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\"><span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}</span></code></pre>"),
|
||||||
("<code class=\"language-rust\">fn main() {}</code>",
|
("<code class=\"language-rust\">fn main() {}</code>",
|
||||||
"<pre class=\"playground\"><code class=\"language-rust\">fn main() {}\n</code></pre>"),
|
"<pre class=\"playground\"><code class=\"language-rust\">fn main() {}</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=\"playground\"><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>\";</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=\"playground\"><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\";</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=\"playground\"><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>\";</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>\";</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=\"playground\"><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]</code></pre>"),
|
||||||
];
|
];
|
||||||
for (src, should_be) in &inputs {
|
for (src, should_be) in &inputs {
|
||||||
let got = add_playground_pre(
|
let got = add_playground_pre(
|
||||||
|
@ -1034,13 +1037,13 @@ mod tests {
|
||||||
fn add_playground_edition2015() {
|
fn add_playground_edition2015() {
|
||||||
let inputs = [
|
let inputs = [
|
||||||
("<code class=\"language-rust\">x()</code>",
|
("<code class=\"language-rust\">x()</code>",
|
||||||
"<pre class=\"playground\"><code class=\"language-rust edition2015\"><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\"><span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}</span></code></pre>"),
|
||||||
("<code class=\"language-rust\">fn main() {}</code>",
|
("<code class=\"language-rust\">fn main() {}</code>",
|
||||||
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
|
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
|
||||||
("<code class=\"language-rust edition2015\">fn main() {}</code>",
|
("<code class=\"language-rust edition2015\">fn main() {}</code>",
|
||||||
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
|
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
|
||||||
("<code class=\"language-rust edition2018\">fn main() {}</code>",
|
("<code class=\"language-rust edition2018\">fn main() {}</code>",
|
||||||
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
|
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
|
||||||
];
|
];
|
||||||
for (src, should_be) in &inputs {
|
for (src, should_be) in &inputs {
|
||||||
let got = add_playground_pre(
|
let got = add_playground_pre(
|
||||||
|
@ -1058,13 +1061,13 @@ mod tests {
|
||||||
fn add_playground_edition2018() {
|
fn add_playground_edition2018() {
|
||||||
let inputs = [
|
let inputs = [
|
||||||
("<code class=\"language-rust\">x()</code>",
|
("<code class=\"language-rust\">x()</code>",
|
||||||
"<pre class=\"playground\"><code class=\"language-rust edition2018\"><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\"><span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}</span></code></pre>"),
|
||||||
("<code class=\"language-rust\">fn main() {}</code>",
|
("<code class=\"language-rust\">fn main() {}</code>",
|
||||||
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
|
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
|
||||||
("<code class=\"language-rust edition2015\">fn main() {}</code>",
|
("<code class=\"language-rust edition2015\">fn main() {}</code>",
|
||||||
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
|
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
|
||||||
("<code class=\"language-rust edition2018\">fn main() {}</code>",
|
("<code class=\"language-rust edition2018\">fn main() {}</code>",
|
||||||
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
|
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
|
||||||
];
|
];
|
||||||
for (src, should_be) in &inputs {
|
for (src, should_be) in &inputs {
|
||||||
let got = add_playground_pre(
|
let got = add_playground_pre(
|
||||||
|
@ -1082,13 +1085,13 @@ mod tests {
|
||||||
fn add_playground_edition2021() {
|
fn add_playground_edition2021() {
|
||||||
let inputs = [
|
let inputs = [
|
||||||
("<code class=\"language-rust\">x()</code>",
|
("<code class=\"language-rust\">x()</code>",
|
||||||
"<pre class=\"playground\"><code class=\"language-rust edition2021\"><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 edition2021\"><span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}</span></code></pre>"),
|
||||||
("<code class=\"language-rust\">fn main() {}</code>",
|
("<code class=\"language-rust\">fn main() {}</code>",
|
||||||
"<pre class=\"playground\"><code class=\"language-rust edition2021\">fn main() {}\n</code></pre>"),
|
"<pre class=\"playground\"><code class=\"language-rust edition2021\">fn main() {}</code></pre>"),
|
||||||
("<code class=\"language-rust edition2015\">fn main() {}</code>",
|
("<code class=\"language-rust edition2015\">fn main() {}</code>",
|
||||||
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
|
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
|
||||||
("<code class=\"language-rust edition2018\">fn main() {}</code>",
|
("<code class=\"language-rust edition2018\">fn main() {}</code>",
|
||||||
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
|
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
|
||||||
];
|
];
|
||||||
for (src, should_be) in &inputs {
|
for (src, should_be) in &inputs {
|
||||||
let got = add_playground_pre(
|
let got = add_playground_pre(
|
||||||
|
|
Loading…
Reference in New Issue