Skip to content

Commit 217546c

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 217546c

File tree

1 file changed

+26
-23
lines changed

1 file changed

+26
-23
lines changed

src/renderer/html_handlebars/hbs_renderer.rs

+26-23
Original file line numberDiff line numberDiff line change
@@ -903,13 +903,16 @@ 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" };
907910
if let Some(caps) = BORING_LINES_REGEX.captures(line) {
908911
if &caps[2] == "#" {
909912
result += &caps[1];
910913
result += &caps[2];
911914
result += &caps[3];
912-
result += "\n";
915+
result += newline;
913916
continue;
914917
} else if &caps[2] != "!" && &caps[2] != "[" {
915918
result += "<span class=\"boring\">";
@@ -918,13 +921,13 @@ fn hide_lines(content: &str) -> String {
918921
result += &caps[2];
919922
}
920923
result += &caps[3];
921-
result += "\n";
924+
result += newline;
922925
result += "</span>";
923926
continue;
924927
}
925928
}
926929
result += line;
927-
result += "\n";
930+
result += newline;
928931
}
929932
result
930933
}
@@ -1004,19 +1007,19 @@ mod tests {
10041007
fn add_playground() {
10051008
let inputs = [
10061009
("<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>"),
1010+
"<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>"),
10081011
("<code class=\"language-rust\">fn main() {}</code>",
1009-
"<pre class=\"playground\"><code class=\"language-rust\">fn main() {}\n</code></pre>"),
1012+
"<pre class=\"playground\"><code class=\"language-rust\">fn main() {}</code></pre>"),
10101013
("<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>"),
1014+
"<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";</code></pre>"),
10121015
("<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>"),
1016+
"<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n # bar\n\";</code></pre>"),
10141017
("<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>"),
1018+
"<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>"),
10161019
("<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>"),
1020+
"<code class=\"language-rust ignore\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";</code>"),
10181021
("<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>"),
1022+
"<pre class=\"playground\"><code class=\"language-rust editable\">#![no_std]\nlet s = \"foo\";\n #[some_attr]</code></pre>"),
10201023
];
10211024
for (src, should_be) in &inputs {
10221025
let got = add_playground_pre(
@@ -1034,13 +1037,13 @@ mod tests {
10341037
fn add_playground_edition2015() {
10351038
let inputs = [
10361039
("<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>"),
1040+
"<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>"),
10381041
("<code class=\"language-rust\">fn main() {}</code>",
1039-
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
1042+
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
10401043
("<code class=\"language-rust edition2015\">fn main() {}</code>",
1041-
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
1044+
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
10421045
("<code class=\"language-rust edition2018\">fn main() {}</code>",
1043-
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
1046+
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
10441047
];
10451048
for (src, should_be) in &inputs {
10461049
let got = add_playground_pre(
@@ -1058,13 +1061,13 @@ mod tests {
10581061
fn add_playground_edition2018() {
10591062
let inputs = [
10601063
("<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>"),
1064+
"<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>"),
10621065
("<code class=\"language-rust\">fn main() {}</code>",
1063-
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
1066+
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
10641067
("<code class=\"language-rust edition2015\">fn main() {}</code>",
1065-
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
1068+
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
10661069
("<code class=\"language-rust edition2018\">fn main() {}</code>",
1067-
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
1070+
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
10681071
];
10691072
for (src, should_be) in &inputs {
10701073
let got = add_playground_pre(
@@ -1082,13 +1085,13 @@ mod tests {
10821085
fn add_playground_edition2021() {
10831086
let inputs = [
10841087
("<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>"),
1088+
"<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>"),
10861089
("<code class=\"language-rust\">fn main() {}</code>",
1087-
"<pre class=\"playground\"><code class=\"language-rust edition2021\">fn main() {}\n</code></pre>"),
1090+
"<pre class=\"playground\"><code class=\"language-rust edition2021\">fn main() {}</code></pre>"),
10881091
("<code class=\"language-rust edition2015\">fn main() {}</code>",
1089-
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
1092+
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
10901093
("<code class=\"language-rust edition2018\">fn main() {}</code>",
1091-
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
1094+
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
10921095
];
10931096
for (src, should_be) in &inputs {
10941097
let got = add_playground_pre(

0 commit comments

Comments
 (0)