Skip to content

Commit 085c380

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 0547868 commit 085c380

File tree

1 file changed

+39
-25
lines changed

1 file changed

+39
-25
lines changed

src/renderer/html_handlebars/hbs_renderer.rs

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -906,28 +906,42 @@ fn hide_lines(content: &str) -> String {
906906
}
907907

908908
let mut result = String::with_capacity(content.len());
909-
for line in content.lines() {
909+
let mut lines = content.lines();
910+
let last_line = lines.next_back();
911+
let mut handle_line = |line: &str, newline: &str| {
910912
if let Some(caps) = BORING_LINES_REGEX.captures(line) {
911913
if &caps[2] == "#" {
912914
result += &caps[1];
913915
result += &caps[2];
914916
result += &caps[3];
915917
result += "\n";
916-
continue;
917-
} else if &caps[2] != "!" && &caps[2] != "[" {
918+
return;
919+
}
920+
921+
if &caps[2] != "!" && &caps[2] != "[" {
918922
result += "<span class=\"boring\">";
919923
result += &caps[1];
920924
if &caps[2] != " " {
921925
result += &caps[2];
922926
}
923927
result += &caps[3];
924-
result += "\n";
928+
result += newline;
925929
result += "</span>";
926-
continue;
930+
return;
927931
}
928932
}
933+
929934
result += line;
930-
result += "\n";
935+
result += newline;
936+
};
937+
938+
// Iterate over all lines except the last:
939+
for line in lines {
940+
handle_line(line, "\n");
941+
}
942+
// Handle the last line, if any:
943+
if let Some(line) = last_line {
944+
handle_line(line, "");
931945
}
932946
result
933947
}
@@ -1007,19 +1021,19 @@ mod tests {
10071021
fn add_playground() {
10081022
let inputs = [
10091023
("<code class=\"language-rust\">x()</code>",
1010-
"<pre class=\"playground\"><code class=\"language-rust\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}\n</span></code></pre>"),
1024+
"<pre class=\"playground\"><code class=\"language-rust\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}</span></code></pre>"),
10111025
("<code class=\"language-rust\">fn main() {}</code>",
1012-
"<pre class=\"playground\"><code class=\"language-rust\">fn main() {}\n</code></pre>"),
1026+
"<pre class=\"playground\"><code class=\"language-rust\">fn main() {}</code></pre>"),
10131027
("<code class=\"language-rust editable\">let s = \"foo\n # bar\n\";</code>",
1014-
"<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";\n</code></pre>"),
1028+
"<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";</code></pre>"),
10151029
("<code class=\"language-rust editable\">let s = \"foo\n ## bar\n\";</code>",
1016-
"<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n # bar\n\";\n</code></pre>"),
1030+
"<pre class=\"playground\"><code class=\"language-rust editable\">let s = \"foo\n # bar\n\";</code></pre>"),
10171031
("<code class=\"language-rust editable\">let s = \"foo\n # bar\n#\n\";</code>",
1018-
"<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>"),
1032+
"<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>"),
10191033
("<code class=\"language-rust ignore\">let s = \"foo\n # bar\n\";</code>",
1020-
"<code class=\"language-rust ignore\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";\n</code>"),
1034+
"<code class=\"language-rust ignore\">let s = \"foo\n<span class=\"boring\"> bar\n</span>\";</code>"),
10211035
("<code class=\"language-rust editable\">#![no_std]\nlet s = \"foo\";\n #[some_attr]</code>",
1022-
"<pre class=\"playground\"><code class=\"language-rust editable\">#![no_std]\nlet s = \"foo\";\n #[some_attr]\n</code></pre>"),
1036+
"<pre class=\"playground\"><code class=\"language-rust editable\">#![no_std]\nlet s = \"foo\";\n #[some_attr]</code></pre>"),
10231037
];
10241038
for (src, should_be) in &inputs {
10251039
let got = add_playground_pre(
@@ -1037,13 +1051,13 @@ mod tests {
10371051
fn add_playground_edition2015() {
10381052
let inputs = [
10391053
("<code class=\"language-rust\">x()</code>",
1040-
"<pre class=\"playground\"><code class=\"language-rust edition2015\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}\n</span></code></pre>"),
1054+
"<pre class=\"playground\"><code class=\"language-rust edition2015\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}</span></code></pre>"),
10411055
("<code class=\"language-rust\">fn main() {}</code>",
1042-
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
1056+
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
10431057
("<code class=\"language-rust edition2015\">fn main() {}</code>",
1044-
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
1058+
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
10451059
("<code class=\"language-rust edition2018\">fn main() {}</code>",
1046-
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
1060+
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
10471061
];
10481062
for (src, should_be) in &inputs {
10491063
let got = add_playground_pre(
@@ -1061,13 +1075,13 @@ mod tests {
10611075
fn add_playground_edition2018() {
10621076
let inputs = [
10631077
("<code class=\"language-rust\">x()</code>",
1064-
"<pre class=\"playground\"><code class=\"language-rust edition2018\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}\n</span></code></pre>"),
1078+
"<pre class=\"playground\"><code class=\"language-rust edition2018\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}</span></code></pre>"),
10651079
("<code class=\"language-rust\">fn main() {}</code>",
1066-
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
1080+
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
10671081
("<code class=\"language-rust edition2015\">fn main() {}</code>",
1068-
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
1082+
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
10691083
("<code class=\"language-rust edition2018\">fn main() {}</code>",
1070-
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
1084+
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
10711085
];
10721086
for (src, should_be) in &inputs {
10731087
let got = add_playground_pre(
@@ -1085,13 +1099,13 @@ mod tests {
10851099
fn add_playground_edition2021() {
10861100
let inputs = [
10871101
("<code class=\"language-rust\">x()</code>",
1088-
"<pre class=\"playground\"><code class=\"language-rust edition2021\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}\n</span></code></pre>"),
1102+
"<pre class=\"playground\"><code class=\"language-rust edition2021\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}</span></code></pre>"),
10891103
("<code class=\"language-rust\">fn main() {}</code>",
1090-
"<pre class=\"playground\"><code class=\"language-rust edition2021\">fn main() {}\n</code></pre>"),
1104+
"<pre class=\"playground\"><code class=\"language-rust edition2021\">fn main() {}</code></pre>"),
10911105
("<code class=\"language-rust edition2015\">fn main() {}</code>",
1092-
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
1106+
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}</code></pre>"),
10931107
("<code class=\"language-rust edition2018\">fn main() {}</code>",
1094-
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
1108+
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}</code></pre>"),
10951109
];
10961110
for (src, should_be) in &inputs {
10971111
let got = add_playground_pre(

0 commit comments

Comments
 (0)