Skip to main content
`Ctrl`+`K`

#

# Source code for doxysphinx.toc

    # =====================================================================================
    #  C O P Y R I G H T
    # -------------------------------------------------------------------------------------
    #  Copyright (c) 2023 by Robert Bosch GmbH. All rights reserved.
    #
    #  Author(s):
    #  - Markus Braun, :em engineering methods AG (contracted by Robert Bosch GmbH)
    # =====================================================================================
    """The toc module contains classes related to the toctree generation for doxygen htmls/rsts."""

    import re
    import unicodedata
    from dataclasses import dataclass, field, replace
    from pathlib import Path
    from typing import Any, Dict, Iterable, Iterator, List, Protocol, Tuple

    from doxysphinx.doxygen import read_js_data_file
    from doxysphinx.utils.files import write_file
    from doxysphinx.utils.iterators import apply

    @dataclass
    class _MenuEntry:
        title: str
        docname: str
        url: str
        children: List["_MenuEntry"]
        is_structural_dummy: bool = (
            False  # indicated whether a menu entry references a children's file as a structural dummy
        )
        is_leaf: bool = field(init=False)

        def __post_init__(self):
            if not self.children:
                self.is_leaf = True
            else:
                self.is_leaf = False

        @staticmethod
        def from_json_node(json_node: Dict[str, Any]) -> "_MenuEntry":
            """Create a _MenuEntry from a json node (in doxygen's menudata.js).

            Note that this method will build up a _MenuEntry-tree automatically/recursively

            :param json_node: The json node to generate a _MenuEntry from
            :return: A _MenuEntry representation of the json_node and its' children
            """
            title = json_node["text"]
            url = json_node["url"]
            file = _MenuEntry._docname_from_url(url)
            children = _MenuEntry._get_sphinx_toc_compatible_children(json_node)
            is_structural_dummy = "is_structural_dummy" in json_node and json_node["is_structural_dummy"]
            return _MenuEntry(title, file, url, children, is_structural_dummy)

        @staticmethod
        def _docname_from_url(url: str) -> str:
            return url.split("#")[0].replace(".html", "")

        @staticmethod
        def _get_sphinx_toc_compatible_children(json_node: Dict[str, Any]) -> List["_MenuEntry"]:
            """Get a "sphinx compatible" view of the children.

            We therefore need a special handling for index anchors
            with doxygen we sometimes have urls in menu entries like:
            # - title: url
              - a: globals_enum.html#index_a
              - c: globals_enum.html#index_c
              - e: globals_enum.html#index_e
              - f: globals_enum.html#index_f
                ...
            The problem here is that the sphinx toctree simple cannot handle anchors... so we cannot add these
            links for entries in the parent's toctree. We therefore need to
            - eliminate all childrens with the same name/file down to one last child
            - then check if the parent has the same name/file and in that case get rid of the child completely
            """
            # get all children
            children = [_MenuEntry.from_json_node(c) for c in json_node["children"]] if "children" in json_node else []
            if not children:
                return []

            # get unique (considering .file value) children
            unique_children = []
            current_docname = _MenuEntry._docname_from_url(json_node["url"])
            unique_files = set()

            for child in children:
                if child.docname in unique_files and child.is_leaf:
                    continue

                if child.docname == current_docname:
                    json_node["is_structural_dummy"] = True

                unique_children.append(child)
                unique_files.add(child.docname)

            # if there is only one child item left and if that's the same as the current item - get rid of it
            current_docname = _MenuEntry._docname_from_url(json_node["url"])
            if len(unique_children) == 1 and unique_children[0].docname == current_docname and unique_children[0].is_leaf:
                json_node["is_structural_dummy"] = False
                return []

            return unique_children