From 5bca26676019e5c3d2260a5312994985962a2af3 Mon Sep 17 00:00:00 2001 From: Crozzers Date: Mon, 29 Dec 2025 21:04:53 +0000 Subject: [PATCH 1/2] Fix nested footnote references --- lib/markdown2.py | 23 ++++++++++++++------ test/tm-cases/nested_footnotes_issue664.html | 14 ++++++++++++ test/tm-cases/nested_footnotes_issue664.opts | 1 + test/tm-cases/nested_footnotes_issue664.text | 4 ++++ 4 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 test/tm-cases/nested_footnotes_issue664.html create mode 100644 test/tm-cases/nested_footnotes_issue664.opts create mode 100644 test/tm-cases/nested_footnotes_issue664.text diff --git a/lib/markdown2.py b/lib/markdown2.py index 68dced73..9364550a 100755 --- a/lib/markdown2.py +++ b/lib/markdown2.py @@ -514,12 +514,7 @@ def convert(self, text: str) -> 'UnicodeWithAttrs': text = self._run_block_gamut(text) if "footnotes" in self.extras: - def footnote_sub(match): - normed_id = match.group(1) - self.footnote_ids.append(normed_id) - return str(len(self.footnote_ids)) - - text = re.sub(r'%s-(.*?)(?=)' % self._footnote_marker, footnote_sub, text) + text = self._do_footnote_marker(text) text = self._add_footnotes(text) text = self.postprocess(text) @@ -572,6 +567,15 @@ def toc_sort(entry): rv.metadata = self.metadata return rv + def _do_footnote_marker(self, text): + def footnote_sub(match): + normed_id = match.group(1) + if normed_id not in self.footnote_ids: + self.footnote_ids.append(normed_id) + return str(len(self.footnote_ids)) + + return re.sub(r'%s-(.*?)(?=)' % self._footnote_marker, footnote_sub, text) + @mark_stage(Stage.POSTPROCESS) def postprocess(self, text: str) -> str: """A hook for subclasses to do some postprocessing of the html, if @@ -2170,7 +2174,12 @@ def _add_footnotes(self, text: str) -> str: if i != 0: footer.append('') footer.append('
  • ' % id) - footer.append(self._run_block_gamut(self.footnotes[id])) + footer.append( + # handle any nested footnote markers + self._do_footnote_marker( + self._run_block_gamut(self.footnotes[id]) + ) + ) try: backlink = ('foo1

    + +
    +
    +
      +
    1. +

      Note 12 

      +
    2. + +
    3. +

      Note 2 

      +
    4. +
    +
    diff --git a/test/tm-cases/nested_footnotes_issue664.opts b/test/tm-cases/nested_footnotes_issue664.opts new file mode 100644 index 00000000..9c801570 --- /dev/null +++ b/test/tm-cases/nested_footnotes_issue664.opts @@ -0,0 +1 @@ +{"extras": ["footnotes"]} \ No newline at end of file diff --git a/test/tm-cases/nested_footnotes_issue664.text b/test/tm-cases/nested_footnotes_issue664.text new file mode 100644 index 00000000..b6b644a4 --- /dev/null +++ b/test/tm-cases/nested_footnotes_issue664.text @@ -0,0 +1,4 @@ +foo[^n1] + +[^n1]: Note 1[^n2] +[^n2]: Note 2 \ No newline at end of file From 5699d7b6a56262d8c48a83f7b07c9e3b3127c6e2 Mon Sep 17 00:00:00 2001 From: Crozzers Date: Mon, 29 Dec 2025 23:55:07 +0000 Subject: [PATCH 2/2] Update changelog --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index e1c9c958..0ebf4ea7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ - [pull #644] Fix a number of em/strong issues (#641, #642, #643) - [pull #659] Fix a number of safemode issues (#647) - [pull #665] Rewrite emphasis and strong processing to be more GFM compliant +- [pull #672] Fix nested footnote references (#664) ## python-markdown2 2.5.4