Repository: raphlinus/pulldown-cmark (rust)

Issue:
HTML has higher priority than block quotes
Found with modified differential fuzzer (please mark as a fuzzing output): https://github.com/raphlinus/pulldown-cmark/pull/673

Events from pulldown-cmark:

```rust
"<G\n>\n" -> [
  Start(Paragraph)
    Html(Boxed("<G\n>"))
  End(Paragraph)
]
```

Events from pandoc:

```rust
"<G\n>\n" -> [
  Start(Paragraph)
    Text(Boxed("<G"))
  End(Paragraph)
  Start(BlockQuote)
  End(BlockQuote)
]
```

Events from commonmark.js:

```rust
"<G\n>\n" -> [
  Start(Paragraph)
    Text(Boxed("<G"))
  End(Paragraph)
  Start(BlockQuote)
  End(BlockQuote)
]
```

AST from [pandoc](https://pandoc.org/try/?params=%7B%22text%22%3A%22%3CG%5Cn%3E%5Cn%22%2C%22to%22%3A%22json%22%2C%22from%22%3A%22commonmark%22%7D):

```text
Pandoc {
    meta: {},
    blocks: [
        Para(
            [
                Str(
                    "<G",
                ),
            ],
        ),
        BlockQuote(
            [],
        ),
    ],
}
```

Pull request:
Block quotes interrupt paragraphs even with no space at start
Fixes #674

Patch:
diff --git a/specs/regression.txt b/specs/regression.txt
index f906385..3ac1fbf 100644
--- a/specs/regression.txt
+++ b/specs/regression.txt
@@ -1180,3 +1180,54 @@ a\
 <p>a\</p>
 </blockquote>
 ````````````````````````````````
+
+
+ISSUE 674
+
+```````````````````````````````` example
+<a
+>
+.
+<p>&lt;a</p>
+<blockquote></blockquote>
+````````````````````````````````
+
+```````````````````````````````` example
+<div
+>
+.
+<div
+>
+````````````````````````````````
+
+```````````````````````````````` example
+<a
+> quote
+.
+<p>&lt;a</p>
+<blockquote><p>quote</p></blockquote>
+````````````````````````````````
+
+```````````````````````````````` example
+<div
+> not quote
+.
+<div
+> not quote
+````````````````````````````````
+
+```````````````````````````````` example
+<a
+>quote
+.
+<p>&lt;a</p>
+<blockquote><p>quote</p></blockquote>
+````````````````````````````````
+
+```````````````````````````````` example
+<div
+>not quote
+.
+<div
+>not quote
+````````````````````````````````
diff --git a/src/scanners.rs b/src/scanners.rs
index 41f4ab1..b3357c2 100644
--- a/src/scanners.rs
+++ b/src/scanners.rs
@@ -699,8 +699,9 @@ pub(crate) fn scan_metadata_block(
 }
 
 pub(crate) fn scan_blockquote_start(data: &[u8]) -> Option<usize> {
-    if data.starts_with(b"> ") {
-        Some(2)
+    if data.get(0).copied() == Some(b'>') {
+        let space = if data.get(1).copied() == Some(b' ') { 1 } else { 0 };
+        Some(1 + space)
     } else {
         None
     }


Test patch:
diff --git a/tests/suite/regression.rs b/tests/suite/regression.rs
index 071cc03..342edce 100644
--- a/tests/suite/regression.rs
+++ b/tests/suite/regression.rs
@@ -1390,3 +1390,75 @@ fn regression_test_91() {
 
     test_markdown_html(original, expected, false, false, false);
 }
+
+#[test]
+fn regression_test_92() {
+    let original = r##"<a
+>
+"##;
+    let expected = r##"<p>&lt;a</p>
+<blockquote></blockquote>
+"##;
+
+    test_markdown_html(original, expected, false, false, false);
+}
+
+#[test]
+fn regression_test_93() {
+    let original = r##"<div
+>
+"##;
+    let expected = r##"<div
+>
+"##;
+
+    test_markdown_html(original, expected, false, false, false);
+}
+
+#[test]
+fn regression_test_94() {
+    let original = r##"<a
+> quote
+"##;
+    let expected = r##"<p>&lt;a</p>
+<blockquote><p>quote</p></blockquote>
+"##;
+
+    test_markdown_html(original, expected, false, false, false);
+}
+
+#[test]
+fn regression_test_95() {
+    let original = r##"<div
+> not quote
+"##;
+    let expected = r##"<div
+> not quote
+"##;
+
+    test_markdown_html(original, expected, false, false, false);
+}
+
+#[test]
+fn regression_test_96() {
+    let original = r##"<a
+>quote
+"##;
+    let expected = r##"<p>&lt;a</p>
+<blockquote><p>quote</p></blockquote>
+"##;
+
+    test_markdown_html(original, expected, false, false, false);
+}
+
+#[test]
+fn regression_test_97() {
+    let original = r##"<div
+>not quote
+"##;
+    let expected = r##"<div
+>not quote
+"##;
+
+    test_markdown_html(original, expected, false, false, false);
+}