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 = ('foo
+
+
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