diff --git a/cli/src/tests/highlight_test.rs b/cli/src/tests/highlight_test.rs
index 57f61e16..accca617 100644
--- a/cli/src/tests/highlight_test.rs
+++ b/cli/src/tests/highlight_test.rs
@@ -122,6 +122,37 @@ fn test_highlighting_multiline_scopes_to_html() {
);
}
+#[test]
+fn test_highlighting_empty_lines() {
+ let source = vec![
+ "class A {",
+ "",
+ " b(c) {",
+ "",
+ " d(e)",
+ "",
+ " }",
+ "",
+ "}",
+ ]
+ .join("\n");
+
+ assert_eq!(
+ &to_html(&source, get_language("javascript"), &JS_SHEET,).unwrap(),
+ &[
+ "class A {\n".to_string(),
+ "\n".to_string(),
+ " b(c) {\n".to_string(),
+ "\n".to_string(),
+ " d(e)\n".to_string(),
+ "\n".to_string(),
+ " }\n".to_string(),
+ "\n".to_string(),
+ "}\n".to_string(),
+ ]
+ );
+}
+
fn test_language_for_injection_string<'a>(
string: &str,
) -> Option<(Language, &'a PropertySheet)> {
diff --git a/highlight/src/lib.rs b/highlight/src/lib.rs
index 7ec186d8..647064bb 100644
--- a/highlight/src/lib.rs
+++ b/highlight/src/lib.rs
@@ -781,17 +781,19 @@ where
renderer.end_scope();
}
HighlightEvent::Source(src) => {
- renderer.render_line(src, &scopes);
+ renderer.add_text(src, &scopes);
}
};
}
- renderer.flush();
+ if !renderer.current_line.is_empty() {
+ renderer.finish_line();
+ }
Ok(renderer.result)
}
struct HtmlRenderer<'a, F: Fn(Scope) -> &'a str> {
result: Vec,
- buffer: String,
+ current_line: String,
attribute_callback: F,
}
@@ -802,37 +804,40 @@ where
fn new(attribute_callback: F) -> Self {
HtmlRenderer {
result: Vec::new(),
- buffer: String::new(),
+ current_line: String::new(),
attribute_callback,
}
}
fn start_scope(&mut self, s: Scope) {
- write!(&mut self.buffer, "", (self.attribute_callback)(s),).unwrap();
+ write!(
+ &mut self.current_line,
+ "",
+ (self.attribute_callback)(s),
+ )
+ .unwrap();
}
fn end_scope(&mut self) {
- write!(&mut self.buffer, "").unwrap();
+ write!(&mut self.current_line, "").unwrap();
}
- fn flush(&mut self) {
- if !self.buffer.is_empty() {
- self.buffer.push('\n');
- self.result.push(self.buffer.clone());
- self.buffer.clear();
- }
+ fn finish_line(&mut self) {
+ self.current_line.push('\n');
+ self.result.push(self.current_line.clone());
+ self.current_line.clear();
}
- fn render_line(&mut self, src: &str, scopes: &Vec) {
+ fn add_text(&mut self, src: &str, scopes: &Vec) {
let mut multiline = false;
for line in src.split('\n') {
let line = line.trim_end_matches('\r');
if multiline {
scopes.iter().for_each(|_| self.end_scope());
- self.flush();
+ self.finish_line();
scopes.iter().for_each(|scope| self.start_scope(*scope));
}
- write!(&mut self.buffer, "{}", escape::Escape(line)).unwrap();
+ write!(&mut self.current_line, "{}", escape::Escape(line)).unwrap();
multiline = true;
}
}