diff options
author | Klaus Mueller <earth@klml.de> | 2019-02-23 03:04:40 +0100 |
---|---|---|
committer | Waylan Limberg <waylan.limberg@icloud.com> | 2019-02-22 21:04:40 -0500 |
commit | 90833a19eae63f6e787d7718180bd48ca906575a (patch) | |
tree | b459b3766dfb65efa1f107c8a19011d8c225d6cd | |
parent | 12864d276855231c1d72f0da8efd8dace20a9062 (diff) | |
download | python-markdown-90833a19eae63f6e787d7718180bd48ca906575a.tar.gz |
Add support for a range to toc_depth.
Closes #786.
-rw-r--r-- | docs/change_log/release-3.1.md | 6 | ||||
-rw-r--r-- | docs/extensions/toc.md | 18 | ||||
-rw-r--r-- | markdown/extensions/toc.py | 16 | ||||
-rw-r--r-- | tests/test_extensions.py | 55 |
4 files changed, 85 insertions, 10 deletions
diff --git a/docs/change_log/release-3.1.md b/docs/change_log/release-3.1.md index 55dde79..b95eb16 100644 --- a/docs/change_log/release-3.1.md +++ b/docs/change_log/release-3.1.md @@ -27,6 +27,12 @@ The following new features have been included in the release: not valid in HTML5. The `refs` and `backrefs` classes already exist and serve the same purpose (#723). +* A new option for `toc_depth` to set not only the bottom section level, + but also the top section level. A string consisting of two digits + separated by a hyphen in between ("2-5"), defines the top (t) and the + bottom (b) (<ht>..<hb>). A single integer still defines the bottom + section level (<h1>..<hb>) only. (#787). + ## Bug fixes The following bug fixes are included in the 3.1 release: diff --git a/docs/extensions/toc.md b/docs/extensions/toc.md index f6111b2..ae54cba 100644 --- a/docs/extensions/toc.md +++ b/docs/extensions/toc.md @@ -197,9 +197,15 @@ The following options are provided to configure the output: Word separator. Character which replaces white space in id. Defaults to "`-`". * **`toc_depth`** - Define up to which section level "n" (`<h1>` to `<hn>`, where `1 <= n <= 6`) - to include in the Table of Contents. Defaults to `6`. - - When used with conjunction with `baselevel` this parameter will limit the - resulting (adjusted) heading. That is, if both `toc_depth` and `baselevel` - are 3, then only the highest level will be present in the table. + Define the range of section levels to include in the Table of Contents. + A single integer (b) defines the bottom section level (<h1>..<hb>) only. + A string consisting of two digits separated by a hyphen in between ("2-5"), + define the top (t) and the bottom (b) (<ht>..<hb>). Defaults to `6` (bottom). + + When used with conjunction with `baselevel`, this parameter will not + take the fitted hierarchy from `baselevel` into account. That is, if + both `toc_depth` and `baselevel` are 3, then only the highest level + will be present in the table. If you set `baselevel` to 3 and + `toc_depth` to '2-6', the *first* headline will be `<h3>` and so still + included in the Table of Contents. To exclude this first level, you + have to set `toc_depth` to '4-6'.
\ No newline at end of file diff --git a/markdown/extensions/toc.py b/markdown/extensions/toc.py index f6121c2..0985e0f 100644 --- a/markdown/extensions/toc.py +++ b/markdown/extensions/toc.py @@ -135,7 +135,11 @@ class TocTreeprocessor(Treeprocessor): if self.use_permalinks is None: self.use_permalinks = config["permalink"] self.header_rgx = re.compile("[Hh][123456]") - self.toc_depth = config["toc_depth"] + if isinstance(config["toc_depth"], string_type) and '-' in config["toc_depth"]: + self.toc_top, self.toc_bottom = [int(x) for x in config["toc_depth"].split('-')] + else: + self.toc_top = 1 + self.toc_bottom = int(config["toc_depth"]) def iterparent(self, node): ''' Iterator wrapper to get allowed parent and child all at once. ''' @@ -235,7 +239,7 @@ class TocTreeprocessor(Treeprocessor): for el in doc.iter(): if isinstance(el.tag, string_type) and self.header_rgx.match(el.tag): self.set_level(el) - if int(el.tag[-1]) > int(self.toc_depth): + if int(el.tag[-1]) < self.toc_top or int(el.tag[-1]) > self.toc_bottom: continue text = ''.join(el.itertext()).strip() @@ -296,8 +300,12 @@ class TocExtension(Extension): "Defaults to the headerid ext's slugify function."], 'separator': ['-', 'Word separator. Defaults to "-".'], "toc_depth": [6, - "Define up to which section level n (<h1>..<hn>) to " - "include in the TOC"] + 'Define the range of section levels to include in' + 'the Table of Contents. A single integer (b) defines' + 'the bottom section level (<h1>..<hb>) only.' + 'A string consisting of two digits separated by a hyphen' + 'in between ("2-5"), define the top (t) and the' + 'bottom (b) (<ht>..<hb>). Defaults to `6` (bottom).'], } super(TocExtension, self).__init__(**kwargs) diff --git a/tests/test_extensions.py b/tests/test_extensions.py index 2203a78..b4c0779 100644 --- a/tests/test_extensions.py +++ b/tests/test_extensions.py @@ -1021,6 +1021,34 @@ class TestTOC(TestCaseWithAssertStartsWith): '<h1 id="toc"><em>[TOC]</em></h1>' # noqa ) + def testMinMaxLevel(self): + """ Test toc_height setting """ + md = markdown.Markdown( + extensions=[markdown.extensions.toc.TocExtension(toc_depth='3-4')] + ) + text = '# Header 1 not in TOC\n\n## Header 2 not in TOC\n\n### Header 3\n\n####Header 4' + self.assertEqual( + md.convert(text), + '<h1>Header 1 not in TOC</h1>\n' + '<h2>Header 2 not in TOC</h2>\n' + '<h3 id="header-3">Header 3</h3>\n' + '<h4 id="header-4">Header 4</h4>' + ) + self.assertEqual( + md.toc, + '<div class="toc">\n' + '<ul>\n' # noqa + '<li><a href="#header-3">Header 3</a>' # noqa + '<ul>\n' # noqa + '<li><a href="#header-4">Header 4</a></li>\n' # noqa + '</ul>\n' # noqa + '</li>\n' # noqa + '</ul>\n' # noqa + '</div>\n' + ) + + self.assertNotIn("Header 1", md.toc) + def testMaxLevel(self): """ Test toc_depth setting """ md = markdown.Markdown( @@ -1048,6 +1076,33 @@ class TestTOC(TestCaseWithAssertStartsWith): self.assertNotIn("Header 3", md.toc) + def testMinMaxLevelwithBaseLevel(self): + """ Test toc_height setting together with baselevel """ + md = markdown.Markdown( + extensions=[markdown.extensions.toc.TocExtension(toc_depth='4-6', + baselevel=3)] + ) + text = '# First Header\n\n## Second Level\n\n### Third Level' + self.assertEqual( + md.convert(text), + '<h3>First Header</h3>\n' + '<h4 id="second-level">Second Level</h4>\n' + '<h5 id="third-level">Third Level</h5>' + ) + self.assertEqual( + md.toc, + '<div class="toc">\n' + '<ul>\n' # noqa + '<li><a href="#second-level">Second Level</a>' # noqa + '<ul>\n' # noqa + '<li><a href="#third-level">Third Level</a></li>\n' # noqa + '</ul>\n' # noqa + '</li>\n' # noqa + '</ul>\n' # noqa + '</div>\n' + ) + self.assertNotIn("First Header", md.toc) + def testMaxLevelwithBaseLevel(self): """ Test toc_depth setting together with baselevel """ md = markdown.Markdown( |