Skip to content

Commit 962ea3f

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 962ea3f

File tree

1 file changed

+39
-25
lines changed

1 file changed

+39
-25
lines changed

src/renderer/html_handlebars/hbs_renderer.rs

+39-25
Original file line numberDiff line numberDiff line change
@@ -903,28 +903,42 @@ 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();
907+
let last_line = lines.next_back();
908+
let mut handle_line = |line: &str, newline: &str| {
907909
if let Some(caps) = BORING_LINES_REGEX.captures(line) {
908910
if &caps[2] == "#" {
909911
result += &caps[1];
910912
result += &caps[2];
911913
result += &caps[3];
912914
result += "\n";
913-
continue;
914-
} else if &caps[2] != "!" && &caps[2] != "[" {
915+
return;
916+
}
917+
918+
if &caps[2] != "!" && &caps[2] != "[" {
915919
result += "<span class=\"boring\">";
916920
result += &caps[1];
917921
if &caps[2] != " " {
918922
result += &caps[2];
919923
}
920924
result += &caps[3];
921-
result += "\n";
925+
result += newline;
922926
result += "</span>";
923-
continue;
927+
return;
924928
}
925929
}
930+
926931
result += line;
927-
result += "\n";
932+
result += newline;
933+
};
934+
935+
// Iterate over all lines except the last:
936+
for line in lines {
937+
handle_line(line, "\n");
938+
}
939+
// Handle the last line, if any:
940+
if let Some(line) = last_line {
941+
handle_line(line, "");
928942
}
929943
result
930944
}
@@ -1004,19 +1018,19 @@ mod tests {
10041018
fn add_playground() {
10051019
let inputs = [
10061020
("<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>"),
1021+
"<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>"),
10081022
("<code class=\"language-rust\">fn main() {}</code>",
1009-
"<pre class=\"playground\"><code class=\"language-rust\">fn main() {}\n</code></pre>"),
1023+
"<pre class=\"playground\"><code class=\"language-rust\">fn main() {}</code></pre>"),
10101024
("<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>"),
1025+
"<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";</code></pre>"),
10121026
("<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>"),
1027+
"<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n # bar\n\";</code></pre>"),
10141028
("<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>"),
1029+
"<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>"),
10161030
("<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>"),
1031+
"<code class=\"language-rust ignore\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";</code>"),
10181032
("<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>"),
1033+
"<pre class=\"playground\"><code class=\"language-rust editable\">#![no_std]\nlet s = \"foo\";\n #[some_attr]</code></pre>"),
10201034
];
10211035
for (src, should_be) in &inputs {
10221036
let got = add_playground_pre(
@@ -1034,13 +1048,13 @@ mod tests {
10341048
fn add_playground_edition2015() {
10351049
let inputs = [
10361050
("<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>"),
1051+
"<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>"),
10381052
("<code class=\"language-rust\">fn main() {}</code>",
1039-
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
1053+
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
10401054
("<code class=\"language-rust edition2015\">fn main() {}</code>",
1041-
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
1055+
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
10421056
("<code class=\"language-rust edition2018\">fn main() {}</code>",
1043-
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
1057+
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
10441058
];
10451059
for (src, should_be) in &inputs {
10461060
let got = add_playground_pre(
@@ -1058,13 +1072,13 @@ mod tests {
10581072
fn add_playground_edition2018() {
10591073
let inputs = [
10601074
("<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>"),
1075+
"<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>"),
10621076
("<code class=\"language-rust\">fn main() {}</code>",
1063-
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
1077+
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
10641078
("<code class=\"language-rust edition2015\">fn main() {}</code>",
1065-
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
1079+
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
10661080
("<code class=\"language-rust edition2018\">fn main() {}</code>",
1067-
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
1081+
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
10681082
];
10691083
for (src, should_be) in &inputs {
10701084
let got = add_playground_pre(
@@ -1082,13 +1096,13 @@ mod tests {
10821096
fn add_playground_edition2021() {
10831097
let inputs = [
10841098
("<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>"),
1099+
"<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>"),
10861100
("<code class=\"language-rust\">fn main() {}</code>",
1087-
"<pre class=\"playground\"><code class=\"language-rust edition2021\">fn main() {}\n</code></pre>"),
1101+
"<pre class=\"playground\"><code class=\"language-rust edition2021\">fn main() {}</code></pre>"),
10881102
("<code class=\"language-rust edition2015\">fn main() {}</code>",
1089-
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
1103+
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
10901104
("<code class=\"language-rust edition2018\">fn main() {}</code>",
1091-
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
1105+
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
10921106
];
10931107
for (src, should_be) in &inputs {
10941108
let got = add_playground_pre(

0 commit comments

Comments
 (0)