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
6 changes: 6 additions & 0 deletions docs/change_log/release-3.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
18 changes: 12 additions & 6 deletions docs/extensions/toc.md
Original file line number Diff line number Diff line change
Expand Up @@ -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'.
16 changes: 12 additions & 4 deletions markdown/extensions/toc.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,11 @@ def __init__(self, md, config):
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. '''
Expand Down Expand Up @@ -235,7 +239,7 @@ def run(self, doc):
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()

Expand Down Expand Up @@ -296,8 +300,12 @@ def __init__(self, **kwargs):
"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)
Expand Down
55 changes: 55 additions & 0 deletions tests/test_extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1021,6 +1021,34 @@ def testTocInHeaders(self):
'<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(
Expand Down Expand Up @@ -1048,6 +1076,33 @@ def testMaxLevel(self):

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(
Expand Down