Skip to content

Commit 4ead4eb

Browse files
committed
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 ajaxorg/ace#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.
1 parent 4cf005d commit 4ead4eb

File tree

1 file changed

+32
-24
lines changed

1 file changed

+32
-24
lines changed

src/renderer/html_handlebars/hbs_renderer.rs

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -903,29 +903,37 @@ fn hide_lines(content: &str) -> String {
903903
}
904904

905905
let mut result = String::with_capacity(content.len());
906-
for line in content.lines() {
906+
let mut lines = content.lines().peekable();
907+
while let Some(line) = lines.next() {
908+
// Don't include newline on the last line.
909+
let newline = if lines.peek().is_none() { "" } else { "\n" };
910+
907911
if let Some(caps) = BORING_LINES_REGEX.captures(line) {
908912
if &caps[2] == "#" {
909913
result += &caps[1];
910914
result += &caps[2];
911915
result += &caps[3];
912-
result += "\n";
916+
result += newline;
913917
continue;
914-
} else if &caps[2] != "!" && &caps[2] != "[" {
918+
}
919+
920+
if &caps[2] != "!" && &caps[2] != "[" {
915921
result += "<span class=\"boring\">";
916922
result += &caps[1];
917923
if &caps[2] != " " {
918924
result += &caps[2];
919925
}
920926
result += &caps[3];
921-
result += "\n";
927+
result += newline;
922928
result += "</span>";
923929
continue;
924930
}
925931
}
932+
926933
result += line;
927-
result += "\n";
934+
result += newline;
928935
}
936+
929937
result
930938
}
931939

@@ -1004,19 +1012,19 @@ mod tests {
10041012
fn add_playground() {
10051013
let inputs = [
10061014
("<code class=\"language-rust\">x()</code>",
1007-
"<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>"),
1015+
"<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>"),
10081016
("<code class=\"language-rust\">fn main() {}</code>",
1009-
"<pre class=\"playground\"><code class=\"language-rust\">fn main() {}\n</code></pre>"),
1017+
"<pre class=\"playground\"><code class=\"language-rust\">fn main() {}</code></pre>"),
10101018
("<code class=\"language-rust editable\">let s = \"foo\n # bar\n\";</code>",
1011-
"<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";\n</code></pre>"),
1019+
"<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";</code></pre>"),
10121020
("<code class=\"language-rust editable\">let s = \"foo\n ## bar\n\";</code>",
1013-
"<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n # bar\n\";\n</code></pre>"),
1021+
"<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n # bar\n\";</code></pre>"),
10141022
("<code class=\"language-rust editable\">let s = \"foo\n # bar\n#\n\";</code>",
1015-
"<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>"),
1023+
"<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>"),
10161024
("<code class=\"language-rust ignore\">let s = \"foo\n # bar\n\";</code>",
1017-
"<code class=\"language-rust ignore\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";\n</code>"),
1025+
"<code class=\"language-rust ignore\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";</code>"),
10181026
("<code class=\"language-rust editable\">#![no_std]\nlet s = \"foo\";\n #[some_attr]</code>",
1019-
"<pre class=\"playground\"><code class=\"language-rust editable\">#![no_std]\nlet s = \"foo\";\n #[some_attr]\n</code></pre>"),
1027+
"<pre class=\"playground\"><code class=\"language-rust editable\">#![no_std]\nlet s = \"foo\";\n #[some_attr]</code></pre>"),
10201028
];
10211029
for (src, should_be) in &inputs {
10221030
let got = add_playground_pre(
@@ -1034,13 +1042,13 @@ mod tests {
10341042
fn add_playground_edition2015() {
10351043
let inputs = [
10361044
("<code class=\"language-rust\">x()</code>",
1037-
"<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>"),
1045+
"<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>"),
10381046
("<code class=\"language-rust\">fn main() {}</code>",
1039-
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
1047+
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
10401048
("<code class=\"language-rust edition2015\">fn main() {}</code>",
1041-
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
1049+
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
10421050
("<code class=\"language-rust edition2018\">fn main() {}</code>",
1043-
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
1051+
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
10441052
];
10451053
for (src, should_be) in &inputs {
10461054
let got = add_playground_pre(
@@ -1058,13 +1066,13 @@ mod tests {
10581066
fn add_playground_edition2018() {
10591067
let inputs = [
10601068
("<code class=\"language-rust\">x()</code>",
1061-
"<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>"),
1069+
"<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>"),
10621070
("<code class=\"language-rust\">fn main() {}</code>",
1063-
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
1071+
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
10641072
("<code class=\"language-rust edition2015\">fn main() {}</code>",
1065-
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
1073+
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
10661074
("<code class=\"language-rust edition2018\">fn main() {}</code>",
1067-
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
1075+
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
10681076
];
10691077
for (src, should_be) in &inputs {
10701078
let got = add_playground_pre(
@@ -1082,13 +1090,13 @@ mod tests {
10821090
fn add_playground_edition2021() {
10831091
let inputs = [
10841092
("<code class=\"language-rust\">x()</code>",
1085-
"<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>"),
1093+
"<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>"),
10861094
("<code class=\"language-rust\">fn main() {}</code>",
1087-
"<pre class=\"playground\"><code class=\"language-rust edition2021\">fn main() {}\n</code></pre>"),
1095+
"<pre class=\"playground\"><code class=\"language-rust edition2021\">fn main() {}</code></pre>"),
10881096
("<code class=\"language-rust edition2015\">fn main() {}</code>",
1089-
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
1097+
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
10901098
("<code class=\"language-rust edition2018\">fn main() {}</code>",
1091-
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
1099+
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
10921100
];
10931101
for (src, should_be) in &inputs {
10941102
let got = add_playground_pre(

0 commit comments

Comments
 (0)