Skip to content
Merged
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
18 changes: 15 additions & 3 deletions docs/change_log/release-3.4.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ title: Release Notes for v3.4

# Python-Markdown 3.4 Release Notes

Python-Markdown version 3.4 supports Python versions 3.6, 3.7, 3.8, 3.9 and PyPy3.
Python-Markdown version 3.4 supports Python versions 3.6, 3.7, 3.8, 3.9, 3.10 and
PyPy3.

## Backwards-incompatible changes

Expand Down Expand Up @@ -37,8 +38,19 @@ The following new features have been included in the 3.3 release:
inter-operation. The old behavior is available by setting `use_align_attribute=True` when
adding the extension.

## Bug fixes
* Some new configuration options have been added to the [footnotes](../extensions/footnotes.md)
extension (#1218):

The following bug fixes are included in the 3.4 release:
* Small refactor of the `BACKLINK_TITLE` option; The use of `format()` instead
of "old" `%d` formatter allows to specify text without the need to have the
number of the footnote in it (like footnotes on Wikipedia for example).
The modification is backward compatible so no configuration change is required.

* Addition of a new option `SUPERSCRIPT_TEXT` that allows to specify a custom
placeholder for the footnote itself in the text.
Ex: `[{}]` will give <sup>[1]</sup>, `({})` will give <sup>(1)</sup>,
or just by default, the current behavior: <sup>1</sup>.

## Bug fixes

The following bug fixes are included in the 3.4 release:
8 changes: 6 additions & 2 deletions docs/extensions/footnotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,14 @@ The following options are provided to configure the output:
The text string that links from the footnote definition back to the position
in the document. Defaults to `&#8617;`.

* **`SUPERSCRIPT_TEXT`**:
The text string that links from the position in the document to the footnote
definition. Defaults to `{}`, i.e. only the footnote's number.

* **`BACKLINK_TITLE`**:
The text string for the `title` HTML attribute of the footnote definition link.
`%d` will be replaced by the footnote number. Defaults to `Jump back to
footnote %d in the text`
The placeholder `{}` will be replaced by the footnote number. Defaults to
`Jump back to footnote {} in the text`.

* **`SEPARATOR`**:
The text string used to set the footnote separator. Defaults to `:`.
Expand Down
13 changes: 11 additions & 2 deletions markdown/extensions/footnotes.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ def __init__(self, **kwargs):
["&#8617;",
"The text string that links from the footnote "
"to the reader's place."],
"SUPERSCRIPT_TEXT":
["{}",
"The text string that links from the reader's place "
"to the footnote."],
"BACKLINK_TITLE":
["Jump back to footnote %d in the text",
"The text string used for the title HTML attribute "
Expand Down Expand Up @@ -170,6 +174,9 @@ def makeFootnotesDiv(self, root):
ol = etree.SubElement(div, "ol")
surrogate_parent = etree.Element("div")

# Backward compatibility with old '%d' placeholder
backlink_title = self.getConfig("BACKLINK_TITLE").replace("%d", "{}")

for index, id in enumerate(self.footnotes.keys(), start=1):
li = etree.SubElement(ol, "li")
li.set("id", self.makeFootnoteId(id))
Expand All @@ -185,7 +192,7 @@ def makeFootnotesDiv(self, root):
backlink.set("class", "footnote-backref")
backlink.set(
"title",
self.getConfig("BACKLINK_TITLE") % (index)
backlink_title.format(index)
)
backlink.text = FN_BACKLINK_TEXT

Expand Down Expand Up @@ -303,7 +310,9 @@ def handleMatch(self, m, data):
sup.set('id', self.footnotes.makeFootnoteRefId(id, found=True))
a.set('href', '#' + self.footnotes.makeFootnoteId(id))
a.set('class', 'footnote-ref')
a.text = str(list(self.footnotes.footnotes.keys()).index(id) + 1)
a.text = self.footnotes.getConfig("SUPERSCRIPT_TEXT").format(
list(self.footnotes.footnotes.keys()).index(id) + 1
)
return sup, m.start(0), m.end(0)
else:
return None, None, None
Expand Down
36 changes: 36 additions & 0 deletions tests/test_syntax/extensions/test_footnotes.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,3 +300,39 @@ def test_footnote_separator(self):
'</div>',
extension_configs={'footnotes': {'SEPARATOR': '-'}}
)

def test_backlink_title(self):
"""Test backlink title configuration without placeholder."""

self.assertMarkdownRenders(
'paragraph[^1]\n\n[^1]: A Footnote',
'<p>paragraph<sup id="fnref:1"><a class="footnote-ref" href="#fn:1">1</a></sup></p>\n'
'<div class="footnote">\n'
'<hr />\n'
'<ol>\n'
'<li id="fn:1">\n'
'<p>A Footnote&#160;<a class="footnote-backref" href="#fnref:1"'
' title="Jump back to footnote">&#8617;</a></p>\n'
'</li>\n'
'</ol>\n'
'</div>',
extension_configs={'footnotes': {'BACKLINK_TITLE': 'Jump back to footnote'}}
)

def test_superscript_text(self):
"""Test superscript text configuration."""

self.assertMarkdownRenders(
'paragraph[^1]\n\n[^1]: A Footnote',
'<p>paragraph<sup id="fnref:1"><a class="footnote-ref" href="#fn:1">[1]</a></sup></p>\n'
'<div class="footnote">\n'
'<hr />\n'
'<ol>\n'
'<li id="fn:1">\n'
'<p>A Footnote&#160;<a class="footnote-backref" href="#fnref:1"'
' title="Jump back to footnote 1 in the text">&#8617;</a></p>\n'
'</li>\n'
'</ol>\n'
'</div>',
extension_configs={'footnotes': {'SUPERSCRIPT_TEXT': '[{}]'}}
)