Source code for mdfy.elements.toc

from typing import Union, Optional

from mdfy.types import MdWritableItem
from mdfy.utils import generate_anchor
from mdfy.elements._base import MdControlElement
from mdfy.elements.header import MdHeader


[docs] class MdTableOfContents(MdControlElement): """Represents a table of contents in Markdown. This element can generate a table of contents from a list of markdown elements. If contents are provided during initialization, it will generate the table of contents when stringified. Otherwise, it will return just the title. Attributes: title (str): The title of the table of contents. level (int): The heading level for the table of contents title. contents (Optional[ContentType]): The markdown contents to generate TOC from. """ def __init__( self, contents: Union[list[MdWritableItem], None] = None, render_all: bool = False, ) -> None: """Initializes a table of contents element. Args: title (str): The title of the table of contents. level (int): The heading level for the table of contents title. """ super().__init__() self._contents = contents self._render_all = render_all
[docs] def render( self, contents: Union[list[MdWritableItem], None] = None, index: Optional[int] = None, ) -> str: """Generates a table of contents from a list of elements. Args: elements (list[ContentElementType]): The list of elements to generate TOC from. toc (MdTableOfContents): The table of contents element with configuration. Returns: str: The generated table of contents. """ contents_to_render = self._contents or contents if contents_to_render is None: raise ValueError( "No contents provided. " "Either contents argument or _contents attribute must be provided." ) if len(contents_to_render) == 0: return "" if index is not None: if index >= len(contents_to_render): return "" contents_to_render = contents_to_render[index:] headers = [elem for elem in contents_to_render if isinstance(elem, MdHeader)] lines = [] for header in headers: indent = " " * (header.level - 1) anchor = generate_anchor(header.content) lines.append(f"{indent}- [{header.content}](#{anchor})") return "\n".join(lines) + "\n"