diff --git a/markdown/extensions/footnotes.py b/markdown/extensions/footnotes.py index 46bb93c3..4bfd827b 100644 --- a/markdown/extensions/footnotes.py +++ b/markdown/extensions/footnotes.py @@ -302,20 +302,22 @@ def detectTabbed(self, blocks: list[str]) -> list[str]: while blocks: if blocks[0].startswith(' '*4): block = blocks.pop(0) + detabbed_block = self.detab(block) # Check for new footnotes within this block and split at new footnote. - m = self.RE.search(block) + m = self.RE.search(detabbed_block) if m: # Another footnote exists in this block. # Any content before match is continuation of this footnote, which may be lazily indented. - before = block[:m.start()].rstrip('\n') - fn_blocks.append(self.detab(before)) + before = detabbed_block[:m.start()].rstrip('\n') + if before: + fn_blocks.append(before) # Add back to blocks everything from beginning of match forward for next iteration. - blocks.insert(0, block[m.start():]) + blocks.insert(0, detabbed_block[m.start():]) # End of this footnote. break else: # Entire block is part of this footnote. - fn_blocks.append(self.detab(block)) + fn_blocks.append(detabbed_block) else: # End of this footnote. break diff --git a/tests/test_syntax/extensions/test_footnotes.py b/tests/test_syntax/extensions/test_footnotes.py index 896e1fcd..6a8793f1 100644 --- a/tests/test_syntax/extensions/test_footnotes.py +++ b/tests/test_syntax/extensions/test_footnotes.py @@ -676,3 +676,99 @@ def test_footnote_id_with_special_chars(self): '\n' '' ) + + def test_footnote_indented_nested_definition(self): + """Test an indented footnote definition nested within another footnote. + + The nested definition used to be silently dropped from the output. + """ + + self.assertMarkdownRenders( + self.dedent( + """ + Main[^1]. + + [^1]: First + + [^2]: Second + """ + ), + '

Main1.

\n' + '
\n' + '
\n' + '
    \n' + '
  1. \n' + '

    First ↩

    \n' + '
  2. \n' + '
  3. \n' + '

    Second ↩

    \n' + '
  4. \n' + '
\n' + '
' + ) + + def test_footnote_indented_nested_definition_with_reference(self): + """Test an indented nested definition that is also referenced. + + The reference used to link to a `#fn:2` anchor that never existed. + """ + + self.assertMarkdownRenders( + self.dedent( + """ + Main[^1]. + + [^1]: First [^2] + + [^2]: Second + """ + ), + '

Main1.

\n' + '
\n' + '
\n' + '
    \n' + '
  1. \n' + '

    First 2' + ' ↩

    \n' + '
  2. \n' + '
  3. \n' + '

    Second ↩

    \n' + '
  4. \n' + '
\n' + '
' + ) + + def test_footnote_indented_nested_definition_after_content(self): + """Test an indented nested definition preceded by continuation content.""" + + self.assertMarkdownRenders( + self.dedent( + """ + Main[^1]. + + [^1]: First + + some continuation + [^2]: Second + """ + ), + '

Main1.

\n' + '
\n' + '
\n' + '
    \n' + '
  1. \n' + '

    First

    \n' + '

    some continuation ↩

    \n' + '
  2. \n' + '
  3. \n' + '

    Second ↩

    \n' + '
  4. \n' + '
\n' + '
' + )