Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## python-markdown2 2.5.6 (not yet released)

- [pull #777] Give each reference to a repeated footnote its own id instead of repeating `fnref-<id>`
- [pull #762] Speed up documents with many links by skipping the backslash-escape scan for text without a backslash
- [pull #748] Speed up `_unescape_special_chars` by skipping text with no hashes and dropping the full-text comparison per pass (#635)
- [pull #749] URL-encode destinations generated by the `link-patterns` extra (#55)
Expand Down
12 changes: 11 additions & 1 deletion lib/markdown2.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ def _setup_extras(self):
self.footnotes = OrderedDict()
self.footnote_ids = []
self._footnote_numbers = {}
self._footnote_ref_counts = {}
self._footnote_marker = _hash_text('<<footnote>>')
if "header-ids" in self.extras:
if not hasattr(self, '_count_from_header_id') or self.extras['header-ids'].get('reset-count', False):
Expand Down Expand Up @@ -598,6 +599,15 @@ def footnote_sub(match):
)
return str(self._footnote_numbers[normed_id])

def footnote_ref_id_sub(match):
# Every reference needs its own id. The first one in the document keeps `fnref-<id>`,
# which the footnote's back link points to, and later ones get `fnref2-<id>` and so on.
normed_id = match.group(1)
count = self._footnote_ref_counts.get(normed_id, 0) + 1
self._footnote_ref_counts[normed_id] = count
return 'fnref-%s' % normed_id if count == 1 else 'fnref%d-%s' % (count, normed_id)

text = re.sub(r'%s-ref-([^"]*)' % self._footnote_marker, footnote_ref_id_sub, text)
return re.sub(r'%s-(.*?)(?=</a></sup>)' % self._footnote_marker, footnote_sub, text)

@mark_stage(Stage.POSTPROCESS)
Expand Down Expand Up @@ -3373,7 +3383,7 @@ def run(self, text: str):
normed_id = re.sub(r'\W', '-', link_text[1:])
if normed_id in self.md.footnotes:
result = (
f'<sup class="footnote-ref" id="fnref-{normed_id}">'
f'<sup class="footnote-ref" id="{self.md._footnote_marker}-ref-{normed_id}">'
# insert special footnote marker that's easy to find and match against later
f'<a href="#fn-{normed_id}">{self.md._footnote_marker}-{normed_id}</a></sup>'
)
Expand Down
10 changes: 5 additions & 5 deletions test/tm-cases/repeated_footnote_labels.html
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
<p>First<sup class="footnote-ref" id="fnref-first"><a href="#fn-first">1</a></sup>, second<sup class="footnote-ref" id="fnref-second"><a href="#fn-second">2</a></sup>, and first again<sup class="footnote-ref" id="fnref-first"><a href="#fn-first">1</a></sup>.</p>
<p>First<sup class="footnote-ref" id="fnref-first"><a href="#fn-first">1</a></sup>, second<sup class="footnote-ref" id="fnref-second"><a href="#fn-second">2</a></sup>, and first again<sup class="footnote-ref" id="fnref2-first"><a href="#fn-first">1</a></sup>.</p>

<ul>
<li>Second again<sup class="footnote-ref" id="fnref-second"><a href="#fn-second">2</a></sup>.</li>
<li>Second again<sup class="footnote-ref" id="fnref2-second"><a href="#fn-second">2</a></sup>.</li>
<li>Third<sup class="footnote-ref" id="fnref-third"><a href="#fn-third">3</a></sup>.</li>
<li>First again<sup class="footnote-ref" id="fnref-first"><a href="#fn-first">1</a></sup>.</li>
<li>First again<sup class="footnote-ref" id="fnref3-first"><a href="#fn-first">1</a></sup>.</li>
</ul>

<div class="footnotes">
<hr />
<ol>
<li id="fn-second">
<p>Second note referencing first<sup class="footnote-ref" id="fnref-first"><a href="#fn-first">1</a></sup>.&#160;<a href="#fnref-second" class="footnoteBackLink" title="Jump back to footnote 1 in the text.">&#8617;</a></p>
<p>Second note referencing first<sup class="footnote-ref" id="fnref4-first"><a href="#fn-first">1</a></sup>.&#160;<a href="#fnref-second" class="footnoteBackLink" title="Jump back to footnote 1 in the text.">&#8617;</a></p>
</li>

<li id="fn-first">
<p>First note.&#160;<a href="#fnref-first" class="footnoteBackLink" title="Jump back to footnote 2 in the text.">&#8617;</a></p>
</li>

<li id="fn-third">
<p>Third note referencing second<sup class="footnote-ref" id="fnref-second"><a href="#fn-second">2</a></sup>.&#160;<a href="#fnref-third" class="footnoteBackLink" title="Jump back to footnote 3 in the text.">&#8617;</a></p>
<p>Third note referencing second<sup class="footnote-ref" id="fnref3-second"><a href="#fn-second">2</a></sup>.&#160;<a href="#fnref-third" class="footnoteBackLink" title="Jump back to footnote 3 in the text.">&#8617;</a></p>
</li>
</ol>
</div>
Loading