aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/change_log/release-3.0.md12
-rw-r--r--docs/extensions/toc.md63
-rw-r--r--markdown/extensions/toc.py11
-rw-r--r--tests/test_extensions.py34
4 files changed, 108 insertions, 12 deletions
diff --git a/docs/change_log/release-3.0.md b/docs/change_log/release-3.0.md
index 85a5d27..ab6b83e 100644
--- a/docs/change_log/release-3.0.md
+++ b/docs/change_log/release-3.0.md
@@ -202,5 +202,17 @@ The following new features have been included in the release:
* A new `toc_depth` parameter has been added to the
[Table of Contents Extension](../extensions/toc.md).
+* A new `toc_tokens` attribute has been added to the Markdown class by the
+ [Table of Contents Extension](../extensions/toc.md), which contains the raw
+ tokens used to build the Table of Contents. Users can use this to build their
+ own custom Table of Contents rather than needing to parse the HTML available
+ on the `toc` attribute of the Markdown class.
+
+* When the [Table of Contents Extension](../extensions/toc.md) is used in
+ conjunction with the [Attribute Lists Extension](../extensions/attr_list.md)
+ and a `data-toc-label` attribute is defined on a header, the content of the
+ `data-toc-label` attribute is now used as the content of the Table of Contents
+ item for that header.
+
* Additional CSS class names can be appended to
[Admonitions](../extensions/admonition.md).
diff --git a/docs/extensions/toc.md b/docs/extensions/toc.md
index 5038428..f6111b2 100644
--- a/docs/extensions/toc.md
+++ b/docs/extensions/toc.md
@@ -56,7 +56,7 @@ would generate the following output:
</ul>
</div>
<h1 id="header-1">Header 1</h1>
-<h1 id="header-2">Header 2</h1>
+<h2 id="header-2">Header 2</h2>
```
Regardless of whether a `marker` is found in the document (or disabled), the
@@ -70,6 +70,67 @@ template. For example:
>>> page = render_some_template(context={'body': html, 'toc': md.toc})
```
+The `toc_tokens` attribute is also available on the Markdown class and contains
+a nested list of dict objects. For example, the above document would result in
+the following object at `md.toc_tokens`:
+
+```python
+[
+ {
+ 'level': 1,
+ 'id': 'header-1',
+ 'name': 'Header 1',
+ 'children': [
+ {'level': 2, 'id': 'header-2', 'name': 'Header 2', 'children':[]}
+ ]
+ }
+]
+```
+
+Note that the `level` refers to the `hn` level. In other words, `<h1>` is level
+`1` and `<h2>` is level `2`, etc. Be aware that improperly nested levels in the
+input may result in odd nesting of the output.
+
+### Custom Labels
+
+In most cases, the text label in the Table of Contents should match the text of
+the header. However, occasionally that is not desirable. In that case, if this
+extension is used in conjunction with the [Attribute Lists Extension] and a
+`data-toc-label` attribute is defined on the header, then the contents of that
+attribute will be used as the text label for the item in the Table of Contents.
+For example, the following Markdown:
+
+[Attribute Lists Extension]: attr_list.md
+
+```md
+[TOC]
+
+# Functions
+
+## `markdown.markdown(text [, **kwargs])` { #markdown data-toc-label='markdown.markdown' }
+```
+would generate the following output:
+
+```html
+<div class="toc">
+ <ul>
+ <li><a href="#functions">Functions</a></li>
+ <ul>
+ <li><a href="#markdown">markdown.markdown</a></li>
+ </ul>
+ </ul>
+</div>
+<h1 id="functions">Functions</h1>
+<h2 id="markdown"><code>markdown.markdown(text [, **kwargs])</code></h2>
+```
+
+Notice that the text in the Table of Contents is much cleaner and easier to read
+in the context of a Table of Contents. The `data-toc-label` is not included in
+the HTML header element. Also note that the ID was manually defined in the
+attribute list to provide a cleaner URL when linking to the header. If the ID is
+not manually defined, it is always derived from the text of the header, never
+from the `data-toc-label` attribute.
+
Usage
-----
diff --git a/markdown/extensions/toc.py b/markdown/extensions/toc.py
index 2741037..f6121c2 100644
--- a/markdown/extensions/toc.py
+++ b/markdown/extensions/toc.py
@@ -247,15 +247,20 @@ class TocTreeprocessor(Treeprocessor):
toc_tokens.append({
'level': int(el.tag[-1]),
'id': el.attrib["id"],
- 'name': text
+ 'name': el.attrib.get('data-toc-label', text)
})
+ # Remove the data-toc-label attribute as it is no longer needed
+ if 'data-toc-label' in el.attrib:
+ del el.attrib['data-toc-label']
+
if self.use_anchors:
self.add_anchor(el, el.attrib["id"])
if self.use_permalinks:
self.add_permalink(el, el.attrib["id"])
- div = self.build_toc_div(nest_toc_tokens(toc_tokens))
+ toc_tokens = nest_toc_tokens(toc_tokens)
+ div = self.build_toc_div(toc_tokens)
if self.marker:
self.replace_marker(doc, div)
@@ -263,6 +268,7 @@ class TocTreeprocessor(Treeprocessor):
toc = self.md.serializer(div)
for pp in self.md.postprocessors:
toc = pp.run(toc)
+ self.md.toc_tokens = toc_tokens
self.md.toc = toc
@@ -310,6 +316,7 @@ class TocExtension(Extension):
def reset(self):
self.md.toc = ''
+ self.md.toc_tokens = []
def makeExtension(**kwargs): # pragma: no cover
diff --git a/tests/test_extensions.py b/tests/test_extensions.py
index 532ed6f..5489887 100644
--- a/tests/test_extensions.py
+++ b/tests/test_extensions.py
@@ -852,24 +852,40 @@ class TestTOC(TestCaseWithAssertStartsWith):
def testWithAttrList(self):
""" Test TOC with attr_list Extension. """
md = markdown.Markdown(extensions=['toc', 'attr_list'])
- text = '# Header 1\n\n## Header 2 { #foo }'
+ text = '# Header 1\n\n## Header 2 { #foo }\n\n## Header 3 { data-toc-label="Foo Bar"}'
self.assertEqual(
md.convert(text),
'<h1 id="header-1">Header 1</h1>\n'
- '<h2 id="foo">Header 2</h2>'
+ '<h2 id="foo">Header 2</h2>\n'
+ '<h2 id="header-3">Header 3</h2>'
)
self.assertEqual(
md.toc,
'<div class="toc">\n'
- '<ul>\n' # noqa
- '<li><a href="#header-1">Header 1</a>' # noqa
- '<ul>\n' # noqa
- '<li><a href="#foo">Header 2</a></li>\n' # noqa
- '</ul>\n' # noqa
- '</li>\n' # noqa
- '</ul>\n' # noqa
+ '<ul>\n' # noqa
+ '<li><a href="#header-1">Header 1</a>' # noqa
+ '<ul>\n' # noqa
+ '<li><a href="#foo">Header 2</a></li>\n' # noqa
+ '<li><a href="#header-3">Foo Bar</a></li>\n' # noqa
+ '</ul>\n' # noqa
+ '</li>\n' # noqa
+ '</ul>\n' # noqa
'</div>\n'
)
+ self.assertEqual(
+ md.toc_tokens,
+ [
+ {
+ 'level': 1,
+ 'id': 'header-1',
+ 'name': 'Header 1',
+ 'children': [
+ {'level': 2, 'id': 'foo', 'name': 'Header 2', 'children': []},
+ {'level': 2, 'id': 'header-3', 'name': 'Foo Bar', 'children': []}
+ ]
+ }
+ ]
+ )
def testUniqueFunc(self):
""" Test 'unique' function. """