diff --git a/README.md b/README.md index c8d84430..2c3a988c 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,9 @@ as a script: >>> markdown2.markdown("*boo!*", extras=["footnotes"]) '

boo!

\n' ``` +The `footnotes` extra keeps the same number when a footnote is referenced more +than once. + There are a number of currently implemented extras for tables, footnotes, syntax coloring of `
`-blocks, auto-linking patterns, table of contents,
 Smarty Pants (for fancy quotes, dashes, etc.) and more. See the [Extras
diff --git a/lib/markdown2.py b/lib/markdown2.py
index 99e38ac0..c912e635 100755
--- a/lib/markdown2.py
+++ b/lib/markdown2.py
@@ -422,6 +422,7 @@ def _setup_extras(self):
             # https://docs.python.org/3/whatsnew/3.7.html#summary-release-highlights
             self.footnotes = OrderedDict()
             self.footnote_ids = []
+            self._footnote_numbers = {}
             self._footnote_marker = _hash_text('<>')
         if "header-ids" in self.extras:
             if not hasattr(self, '_count_from_header_id') or self.extras['header-ids'].get('reset-count', False):
@@ -586,9 +587,12 @@ def toc_sort(entry):
     def _do_footnote_marker(self, text):
         def footnote_sub(match):
             normed_id = match.group(1)
-            if normed_id not in self.footnote_ids:
+            if normed_id not in self._footnote_numbers:
                 self.footnote_ids.append(normed_id)
-            return str(len(self.footnote_ids))
+                self._footnote_numbers[normed_id] = (
+                    len(self._footnote_numbers) + 1
+                )
+            return str(self._footnote_numbers[normed_id])
 
         return re.sub(r'%s-(.*?)(?=)' % self._footnote_marker, footnote_sub, text)
 
diff --git a/test/test_markdown2.py b/test/test_markdown2.py
index 656c7a51..21a66aa3 100755
--- a/test/test_markdown2.py
+++ b/test/test_markdown2.py
@@ -230,6 +230,14 @@ def test_header_ids_from_file_vars(self):
             self.assertIn('

Heading

'.format(heading_id), html) self.assertEqual(md.convert("# Heading\n"), "

Heading

\n") + def test_footnote_numbers_reset_between_conversions(self): + md = markdown2.Markdown(extras=["footnotes"]) + md.convert("First[^first], second[^second].\n\n" + "[^first]: First note.\n[^second]: Second note.") + html = md.convert("Second[^second].\n\n[^second]: Second note.") + self.assertIn('1', html) + self.assertIn('
  • ', html) + def test_many_distinct_code_spans(self): source = '\n\n'.join('`value_%s`' % i for i in range(1000)) expected = '\n\n'.join('

    value_%s

    ' % i for i in range(1000)) + '\n' diff --git a/test/tm-cases/repeated_footnote_labels.html b/test/tm-cases/repeated_footnote_labels.html new file mode 100644 index 00000000..201708f0 --- /dev/null +++ b/test/tm-cases/repeated_footnote_labels.html @@ -0,0 +1,24 @@ +

    First1, second2, and first again1.

    + +
      +
    • Second again2.
    • +
    • Third3.
    • +
    • First again1.
    • +
    + +
    +
    +
      +
    1. +

      Second note referencing first1. ↩

      +
    2. + +
    3. +

      First note. ↩

      +
    4. + +
    5. +

      Third note referencing second2. ↩

      +
    6. +
    +
    diff --git a/test/tm-cases/repeated_footnote_labels.opts b/test/tm-cases/repeated_footnote_labels.opts new file mode 100644 index 00000000..9dfee9e2 --- /dev/null +++ b/test/tm-cases/repeated_footnote_labels.opts @@ -0,0 +1 @@ +{"extras": ["footnotes"]} diff --git a/test/tm-cases/repeated_footnote_labels.text b/test/tm-cases/repeated_footnote_labels.text new file mode 100644 index 00000000..59f5b12f --- /dev/null +++ b/test/tm-cases/repeated_footnote_labels.text @@ -0,0 +1,9 @@ +First[^first], second[^second], and first again[^first]. + +- Second again[^second]. +- Third[^third]. +- First again[^first]. + +[^second]: Second note referencing first[^first]. +[^first]: First note. +[^third]: Third note referencing second[^second].