1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
|
"""
Table of contents support for mistletoe.
See `if __name__ == '__main__'` section for sample usage.
"""
import re
from mistletoe.html_renderer import HTMLRenderer
class TOCRenderer(HTMLRenderer):
"""
Extends HTMLRenderer class for table of contents support.
Args:
depth (int): the maximum level of heading to be included in TOC;
omit_title (bool): whether to ignore tokens where token.level == 1;
filter_conds (list): when any of these functions evaluate to true,
current heading will not be included;
extras (list): allows subclasses to add even more custom tokens.
"""
def __init__(self, depth=5, omit_title=True, filter_conds=[], *extras):
super().__init__(*extras)
self._headings = []
self.depth = depth
self.omit_title = omit_title
self.filter_conds = filter_conds
@property
def toc(self):
"""
Returns table of contents as a block_token.List instance.
"""
from mistletoe.block_token import List
def get_indent(level):
if self.omit_title:
level -= 1
return ' ' * 4 * (level - 1)
def build_list_item(heading):
level, content = heading
template = '{indent}- {content}\n'
return template.format(indent=get_indent(level), content=content)
return List([build_list_item(heading) for heading in self._headings])
def render_heading(self, token):
"""
Overrides super().render_heading; stores rendered heading first,
then returns it.
"""
rendered = super().render_heading(token)
content = self.parse_rendered_heading(rendered)
if not (self.omit_title and token.level == 1
or token.level > self.depth
or any(cond(content) for cond in self.filter_conds)):
self._headings.append((token.level, content))
return rendered
@staticmethod
def parse_rendered_heading(rendered):
"""
Helper method; converts rendered heading to plain text.
"""
return re.sub(r'<.+?>', '', rendered)
|