Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TOC extension: Add new boolean option permalink_prepend #1339

Merged
merged 8 commits into from Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/change_log/index.md
Expand Up @@ -3,6 +3,8 @@ title: Change Log
Python-Markdown Change Log
=========================

*under development*: version 3.5 ([Notes](release-3.5.md))

March 23, 2023: version 3.4.3 (a bug-fix release).

* Restore console script (#1327).
Expand Down
20 changes: 20 additions & 0 deletions docs/change_log/release-3.5.md
ferdnyc marked this conversation as resolved.
Show resolved Hide resolved
@@ -0,0 +1,20 @@
title: Release Notes for v3.5

# Python-Markdown 3.5 Release Notes

Python-Markdown version 3.5 supports Python versions 3.7, 3.8, 3.9, 3.10,
3.11 and PyPy3.

## New features

The following new features have been included in the 3.5 release:

* A new configuration option has been added to the
[toc](../extensions/toc.md) extension (#1339):

* A new boolean option `permalink_leading` controls the position of
the permanent link anchors generated with `permalink`. Setting
`permalink_leading` to `True` will cause the links to be inserted
at the start of the header, before any other header content. The
default behavior for `permalink` is to append permanent links to
the header, placing them after all other header content.
9 changes: 9 additions & 0 deletions docs/extensions/toc.md
Expand Up @@ -174,6 +174,15 @@ The following options are provided to configure the output:
* **`permalink_title`**:
Title attribute of the permanent link. Defaults to `Permanent link`.

* **`permalink_leading`**:
Set to `True` if the extension should generate leading permanent links.
Default is `False`.

Leading permanent links are placed at the start of the header tag,
before any header content. The default `permalink` behavior (when
`permalink_leading` is unset or set to `False`) creates trailing
permanent links, which are placed at the end of the header content.

* **`baselevel`**:
Base level for headers. Defaults to `1`.

Expand Down
12 changes: 11 additions & 1 deletion markdown/extensions/toc.py
Expand Up @@ -168,6 +168,7 @@ def __init__(self, md, config):
self.use_permalinks = config["permalink"]
self.permalink_class = config["permalink_class"]
self.permalink_title = config["permalink_title"]
self.permalink_leading = parseBoolValue(config["permalink_leading"], False)
self.header_rgx = re.compile("[Hh][123456]")
if isinstance(config["toc_depth"], str) and '-' in config["toc_depth"]:
self.toc_top, self.toc_bottom = [int(x) for x in config["toc_depth"].split('-')]
Expand Down Expand Up @@ -235,7 +236,12 @@ def add_permalink(self, c, elem_id):
permalink.attrib["class"] = self.permalink_class
if self.permalink_title:
permalink.attrib["title"] = self.permalink_title
c.append(permalink)
if self.permalink_leading:
permalink.tail = c.text
c.text = ""
c.insert(0, permalink)
else:
c.append(permalink)

def build_toc_div(self, toc_list):
""" Return a string div given a toc list. """
Expand Down Expand Up @@ -347,6 +353,10 @@ def __init__(self, **kwargs):
"permalink_title": ["Permanent link",
"Title attribute of the permalink - "
"Defaults to 'Permanent link'"],
"permalink_leading": [False,
"True if permalinks should be placed at "
"the start of the header, rather than the "
"end - Defaults to False."],
"baselevel": ['1', 'Base level for headers.'],
"slugify": [slugify,
"Function to generate anchors based on header text - "
Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Expand Up @@ -41,6 +41,7 @@ nav:
- Test Tools: test_tools.md
- Contributing to Python-Markdown: contributing.md
- Change Log: change_log/index.md
- Release Notes for v.3.5: change_log/release-3.5.md
- Release Notes for v.3.4: change_log/release-3.4.md
- Release Notes for v.3.3: change_log/release-3.3.md
- Release Notes for v.3.2: change_log/release-3.2.md
Expand Down
80 changes: 80 additions & 0 deletions tests/test_extensions.py
Expand Up @@ -630,6 +630,86 @@ def testTocInHeaders(self):
'<h1 id="toc"><em>[TOC]</em></h1>' # noqa
)

def testPermalink(self):
""" Test TOC `permalink` feature. """
text = '# Hd 1\n\n## Hd 2'
md = markdown.Markdown(
extensions=[markdown.extensions.toc.TocExtension(
permalink=True, permalink_title="PL")]
)
self.assertEqual(
md.convert(text),
'<h1 id="hd-1">'
'Hd 1' # noqa
'<a class="headerlink" href="#hd-1" title="PL">' # noqa
'&para;' # noqa
'</a>' # noqa
'</h1>\n'
'<h2 id="hd-2">'
'Hd 2' # noqa
'<a class="headerlink" href="#hd-2" title="PL">' # noqa
'&para;' # noqa
'</a>' # noqa
'</h2>'
)

def testPermalinkLeading(self):
""" Test TOC `permalink` with `permalink_leading` option. """
text = '# Hd 1\n\n## Hd 2'
md = markdown.Markdown(extensions=[
markdown.extensions.toc.TocExtension(
permalink=True, permalink_title="PL", permalink_leading=True)]
)
self.assertEqual(
md.convert(text),
'<h1 id="hd-1">'
'<a class="headerlink" href="#hd-1" title="PL">' # noqa
'&para;' # noqa
'</a>' # noqa
'Hd 1' # noqa
'</h1>\n'
'<h2 id="hd-2">'
'<a class="headerlink" href="#hd-2" title="PL">' # noqa
'&para;' # noqa
'</a>' # noqa
'Hd 2' # noqa
'</h2>'
)

def testInlineMarkupPermalink(self):
""" Test TOC `permalink` with headers containing markup. """
text = '# Code `in` hd'
md = markdown.Markdown(
extensions=[markdown.extensions.toc.TocExtension(
permalink=True, permalink_title="PL")]
)
self.assertEqual(
md.convert(text),
'<h1 id="code-in-hd">'
'Code <code>in</code> hd' # noqa
'<a class="headerlink" href="#code-in-hd" title="PL">' # noqa
'&para;' # noqa
'</a>' # noqa
'</h1>'
)

def testInlineMarkupPermalinkLeading(self):
""" Test TOC `permalink_leading` with headers containing markup. """
text = '# Code `in` hd'
md = markdown.Markdown(extensions=[
markdown.extensions.toc.TocExtension(
permalink=True, permalink_title="PL", permalink_leading=True)]
)
self.assertEqual(
md.convert(text),
'<h1 id="code-in-hd">'
'<a class="headerlink" href="#code-in-hd" title="PL">' # noqa
'&para;' # noqa
'</a>' # noqa
'Code <code>in</code> hd' # noqa
'</h1>'
)


class TestSmarty(unittest.TestCase):
def setUp(self):
Expand Down