Repository: raphlinus/pulldown-cmark (rust)

Issue:
[fuzz result] footnote definitions in blockquotes do not match on first line
This markdown:

```markdown
> [^5]: * test
>
> test [^5]
```

On GitHub, it looks like this:

> [^5]: * test
>
> test [^5]

(the block quote appears at the end of the document, but it still parses)

pulldown-cmark isn't recognizing it, parsing it as text

<details>

```rust
">>  [^^]:>,* 8[\n" -> [
  Start(BlockQuote)
    Start(BlockQuote)
      Start(Paragraph)
        Text(Boxed("[^^]:>,* 8["))
      End(Paragraph)
    End(BlockQuote)
  End(BlockQuote)
]
```

Events from pandoc:

```rust
">>  [^^]:>,* 8[\n" -> [
  Start(BlockQuote)
    Start(BlockQuote)
    End(BlockQuote)
  End(BlockQuote)
]
```

Events from commonmark.js:

```rust
">>  [^^]:>,* 8[\n" -> [
  Start(BlockQuote)
    Start(BlockQuote)
      Start(Paragraph)
        Text(Boxed("[^^]:>,* 8["))
      End(Paragraph)
    End(BlockQuote)
  End(BlockQuote)
]
```

</details>

Pull request:
Parse footnote definitions below the first line of nested blocks
Fixes #766

Patch:
diff --git a/specs/footnotes.txt b/specs/footnotes.txt
index 510ca6c..1343378 100644
--- a/specs/footnotes.txt
+++ b/specs/footnotes.txt
@@ -515,6 +515,8 @@ first      | second
 |------------|-----------|
 | first      | second    |
 | [^4]: test | test [^4] |
+
+> [^5]: * test [^5]
 .
 <ul>
 <li>First
@@ -541,6 +543,13 @@ Second <sup class="footnote-reference"><a href="#2">2</a></sup> test</p>
 <tr><td>first</td><td>second</td></tr>
 <tr><td>[^4]: test</td><td>test [^4]</td></tr>
 </tbody></table>
+<blockquote>
+<div class="footnote-definition" id="5"><sup class="footnote-definition-label">4</sup>
+<ul>
+<li>test <sup class="footnote-reference"><a href="#5">4</a></sup></li>
+</ul>
+</div>
+</blockquote>
 ````````````````````````````````
 
 Footnote labels cannot be empty.
diff --git a/src/firstpass.rs b/src/firstpass.rs
index 08661f0..07b6854 100644
--- a/src/firstpass.rs
+++ b/src/firstpass.rs
@@ -97,27 +97,28 @@ impl<'a, 'b> FirstPass<'a, 'b> {
                 start_ix += scan_blank_line(&bytes[start_ix..]).unwrap_or(0);
                 line_start = LineStart::new(&bytes[start_ix..]);
             }
-        } else if self.options.contains(Options::ENABLE_FOOTNOTES) {
-            // Footnote definitions of the form
-            // [^bar]:
-            //     * anything really
-            let save = line_start.clone();
-            let indent = line_start.scan_space_upto(4);
-            if indent < 4 {
-                let container_start = start_ix + line_start.bytes_scanned();
-                if let Some(bytecount) = self.parse_footnote(container_start) {
-                    start_ix = container_start + bytecount;
-                    line_start = LineStart::new(&bytes[start_ix..]);
-                } else {
-                    line_start = save;
-                }
-            } else {
-                line_start = save;
-            }
         }
 
         // Process new containers
         loop {
+            if self.options.has_gfm_footnotes() {
+                // Footnote definitions of the form
+                // [^bar]:
+                //     * anything really
+                let save = line_start.clone();
+                let indent = line_start.scan_space_upto(4);
+                if indent < 4 {
+                    let container_start = start_ix + line_start.bytes_scanned();
+                    if let Some(bytecount) = self.parse_footnote(container_start) {
+                        start_ix = container_start + bytecount;
+                        line_start = LineStart::new(&bytes[start_ix..]);
+                    } else {
+                        line_start = save;
+                    }
+                } else {
+                    line_start = save;
+                }
+            }
             let container_start = start_ix + line_start.bytes_scanned();
             if let Some((ch, index, indent)) = line_start.scan_list_marker() {
                 let after_marker_index = start_ix + line_start.bytes_scanned();


Test patch:
diff --git a/tests/suite/footnotes.rs b/tests/suite/footnotes.rs
index e00f9bb..87d712a 100644
--- a/tests/suite/footnotes.rs
+++ b/tests/suite/footnotes.rs
@@ -503,6 +503,8 @@ first      | second
 |------------|-----------|
 | first      | second    |
 | [^4]: test | test [^4] |
+
+> [^5]: * test [^5]
 "##;
     let expected = r##"<ul>
 <li>First
@@ -529,6 +531,13 @@ Second <sup class="footnote-reference"><a href="#2">2</a></sup> test</p>
 <tr><td>first</td><td>second</td></tr>
 <tr><td>[^4]: test</td><td>test [^4]</td></tr>
 </tbody></table>
+<blockquote>
+<div class="footnote-definition" id="5"><sup class="footnote-definition-label">4</sup>
+<ul>
+<li>test <sup class="footnote-reference"><a href="#5">4</a></sup></li>
+</ul>
+</div>
+</blockquote>
 "##;
 
     test_markdown_html(original, expected, false, false, false);