Skip to content

Commit 90833a1

Browse files
Klaus Muellerwaylan
Klaus Mueller
authored andcommitted
Add support for a range to toc_depth.
Closes #786.
1 parent 12864d2 commit 90833a1

File tree

4 files changed

+85
-10
lines changed

4 files changed

+85
-10
lines changed

docs/change_log/release-3.1.md

+6
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ The following new features have been included in the release:
2727
not valid in HTML5. The `refs` and `backrefs` classes already exist and
2828
serve the same purpose (#723).
2929

30+
* A new option for `toc_depth` to set not only the bottom section level,
31+
but also the top section level. A string consisting of two digits
32+
separated by a hyphen in between ("2-5"), defines the top (t) and the
33+
bottom (b) (<ht>..<hb>). A single integer still defines the bottom
34+
section level (<h1>..<hb>) only. (#787).
35+
3036
## Bug fixes
3137

3238
The following bug fixes are included in the 3.1 release:

docs/extensions/toc.md

+12-6
Original file line numberDiff line numberDiff line change
@@ -197,9 +197,15 @@ The following options are provided to configure the output:
197197
Word separator. Character which replaces white space in id. Defaults to "`-`".
198198

199199
* **`toc_depth`**
200-
Define up to which section level "n" (`<h1>` to `<hn>`, where `1 <= n <= 6`)
201-
to include in the Table of Contents. Defaults to `6`.
202-
203-
When used with conjunction with `baselevel` this parameter will limit the
204-
resulting (adjusted) heading. That is, if both `toc_depth` and `baselevel`
205-
are 3, then only the highest level will be present in the table.
200+
Define the range of section levels to include in the Table of Contents.
201+
A single integer (b) defines the bottom section level (<h1>..<hb>) only.
202+
A string consisting of two digits separated by a hyphen in between ("2-5"),
203+
define the top (t) and the bottom (b) (<ht>..<hb>). Defaults to `6` (bottom).
204+
205+
When used with conjunction with `baselevel`, this parameter will not
206+
take the fitted hierarchy from `baselevel` into account. That is, if
207+
both `toc_depth` and `baselevel` are 3, then only the highest level
208+
will be present in the table. If you set `baselevel` to 3 and
209+
`toc_depth` to '2-6', the *first* headline will be `<h3>` and so still
210+
included in the Table of Contents. To exclude this first level, you
211+
have to set `toc_depth` to '4-6'.

markdown/extensions/toc.py

+12-4
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,11 @@ def __init__(self, md, config):
135135
if self.use_permalinks is None:
136136
self.use_permalinks = config["permalink"]
137137
self.header_rgx = re.compile("[Hh][123456]")
138-
self.toc_depth = config["toc_depth"]
138+
if isinstance(config["toc_depth"], string_type) and '-' in config["toc_depth"]:
139+
self.toc_top, self.toc_bottom = [int(x) for x in config["toc_depth"].split('-')]
140+
else:
141+
self.toc_top = 1
142+
self.toc_bottom = int(config["toc_depth"])
139143

140144
def iterparent(self, node):
141145
''' Iterator wrapper to get allowed parent and child all at once. '''
@@ -235,7 +239,7 @@ def run(self, doc):
235239
for el in doc.iter():
236240
if isinstance(el.tag, string_type) and self.header_rgx.match(el.tag):
237241
self.set_level(el)
238-
if int(el.tag[-1]) > int(self.toc_depth):
242+
if int(el.tag[-1]) < self.toc_top or int(el.tag[-1]) > self.toc_bottom:
239243
continue
240244
text = ''.join(el.itertext()).strip()
241245

@@ -296,8 +300,12 @@ def __init__(self, **kwargs):
296300
"Defaults to the headerid ext's slugify function."],
297301
'separator': ['-', 'Word separator. Defaults to "-".'],
298302
"toc_depth": [6,
299-
"Define up to which section level n (<h1>..<hn>) to "
300-
"include in the TOC"]
303+
'Define the range of section levels to include in'
304+
'the Table of Contents. A single integer (b) defines'
305+
'the bottom section level (<h1>..<hb>) only.'
306+
'A string consisting of two digits separated by a hyphen'
307+
'in between ("2-5"), define the top (t) and the'
308+
'bottom (b) (<ht>..<hb>). Defaults to `6` (bottom).'],
301309
}
302310

303311
super(TocExtension, self).__init__(**kwargs)

tests/test_extensions.py

+55
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,34 @@ def testTocInHeaders(self):
10211021
'<h1 id="toc"><em>[TOC]</em></h1>' # noqa
10221022
)
10231023

1024+
def testMinMaxLevel(self):
1025+
""" Test toc_height setting """
1026+
md = markdown.Markdown(
1027+
extensions=[markdown.extensions.toc.TocExtension(toc_depth='3-4')]
1028+
)
1029+
text = '# Header 1 not in TOC\n\n## Header 2 not in TOC\n\n### Header 3\n\n####Header 4'
1030+
self.assertEqual(
1031+
md.convert(text),
1032+
'<h1>Header 1 not in TOC</h1>\n'
1033+
'<h2>Header 2 not in TOC</h2>\n'
1034+
'<h3 id="header-3">Header 3</h3>\n'
1035+
'<h4 id="header-4">Header 4</h4>'
1036+
)
1037+
self.assertEqual(
1038+
md.toc,
1039+
'<div class="toc">\n'
1040+
'<ul>\n' # noqa
1041+
'<li><a href="#header-3">Header 3</a>' # noqa
1042+
'<ul>\n' # noqa
1043+
'<li><a href="#header-4">Header 4</a></li>\n' # noqa
1044+
'</ul>\n' # noqa
1045+
'</li>\n' # noqa
1046+
'</ul>\n' # noqa
1047+
'</div>\n'
1048+
)
1049+
1050+
self.assertNotIn("Header 1", md.toc)
1051+
10241052
def testMaxLevel(self):
10251053
""" Test toc_depth setting """
10261054
md = markdown.Markdown(
@@ -1048,6 +1076,33 @@ def testMaxLevel(self):
10481076

10491077
self.assertNotIn("Header 3", md.toc)
10501078

1079+
def testMinMaxLevelwithBaseLevel(self):
1080+
""" Test toc_height setting together with baselevel """
1081+
md = markdown.Markdown(
1082+
extensions=[markdown.extensions.toc.TocExtension(toc_depth='4-6',
1083+
baselevel=3)]
1084+
)
1085+
text = '# First Header\n\n## Second Level\n\n### Third Level'
1086+
self.assertEqual(
1087+
md.convert(text),
1088+
'<h3>First Header</h3>\n'
1089+
'<h4 id="second-level">Second Level</h4>\n'
1090+
'<h5 id="third-level">Third Level</h5>'
1091+
)
1092+
self.assertEqual(
1093+
md.toc,
1094+
'<div class="toc">\n'
1095+
'<ul>\n' # noqa
1096+
'<li><a href="#second-level">Second Level</a>' # noqa
1097+
'<ul>\n' # noqa
1098+
'<li><a href="#third-level">Third Level</a></li>\n' # noqa
1099+
'</ul>\n' # noqa
1100+
'</li>\n' # noqa
1101+
'</ul>\n' # noqa
1102+
'</div>\n'
1103+
)
1104+
self.assertNotIn("First Header", md.toc)
1105+
10511106
def testMaxLevelwithBaseLevel(self):
10521107
""" Test toc_depth setting together with baselevel """
10531108
md = markdown.Markdown(

0 commit comments

Comments
 (0)