Avoid backslashes before a new block.

This commit is contained in:
Joe Neeman 2024-04-05 19:29:10 -05:00
parent 26ad7543a5
commit 023ea309b2
3 changed files with 47 additions and 4 deletions

2
fuzz/Cargo.lock generated
View File

@ -128,7 +128,7 @@ checksum = "4f0807fb6f644c83f3e4ec014fec9858c1c8b26a7db8eb5f0bde5817df9c1df7"
[[package]]
name = "comrak"
version = "0.20.0"
version = "0.22.0"
dependencies = [
"arbitrary",
"clap",

View File

@ -326,6 +326,9 @@ impl<'a, 'o> CommonMarkFormatter<'a, 'o> {
)
&& self.get_in_tight_list_item(node);
}
let next_is_block = node
.next_sibling()
.map_or(true, |next| next.data.borrow().value.block());
match node.data.borrow().value {
NodeValue::Document => (),
@ -345,7 +348,7 @@ impl<'a, 'o> CommonMarkFormatter<'a, 'o> {
NodeValue::Text(ref literal) => {
self.format_text(literal.as_bytes(), allow_wrap, entering)
}
NodeValue::LineBreak => self.format_line_break(entering),
NodeValue::LineBreak => self.format_line_break(entering, next_is_block),
NodeValue::SoftBreak => self.format_soft_break(allow_wrap, entering),
NodeValue::Code(ref code) => {
self.format_code(code.literal.as_bytes(), allow_wrap, entering)
@ -571,10 +574,16 @@ impl<'a, 'o> CommonMarkFormatter<'a, 'o> {
}
}
fn format_line_break(&mut self, entering: bool) {
fn format_line_break(&mut self, entering: bool, next_is_block: bool) {
if entering {
if !self.options.render.hardbreaks {
write!(self, "\\").unwrap();
if !next_is_block {
// If the next element is a block, a backslash means a
// literal backslash instead of a line break. In this case
// we can just skip the line break since it's meaningless
// before a block.
write!(self, "\\").unwrap();
}
}
self.cr();
}

View File

@ -1,3 +1,7 @@
use std::cell::RefCell;
use self::nodes::{Ast, LineColumn};
use super::*;
use ntest::test_case;
@ -11,6 +15,36 @@ fn commonmark_removes_redundant_strong() {
commonmark(input, output, Some(&options));
}
#[test]
fn commonmark_avoids_spurious_backslash() {
let arena = Arena::new();
let options = Options::default();
let empty = LineColumn { line: 0, column: 0 };
let ast = |val: NodeValue| arena.alloc(AstNode::new(RefCell::new(Ast::new(val, empty))));
let root = ast(NodeValue::Document);
let p1 = ast(NodeValue::Paragraph);
p1.append(ast(NodeValue::Text("Line 1".to_owned())));
root.append(p1);
root.append(ast(NodeValue::LineBreak));
let p2 = ast(NodeValue::Paragraph);
p2.append(ast(NodeValue::Text("Line 2".to_owned())));
root.append(p2);
let mut output = vec![];
cm::format_document(root, &options, &mut output).unwrap();
compare_strs(
&String::from_utf8(output).unwrap(),
"Line 1\n\nLine 2\n",
"rendered",
"<synthetic>",
);
}
#[test_case("$$x^2$$ and $1 + 2$ and $`y^2`$", "$$x^2$$ and $1 + 2$ and $`y^2`$\n")]
#[test_case("$$\nx^2\n$$", "$$\nx^2\n$$\n")]
#[test_case("```math\nx^2\n```", "``` math\nx^2\n```\n")]