From fcfc02c27269986ebabf00131ba6a97773b01cb5 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Sun, 28 Jun 2026 12:27:07 +0200 Subject: [PATCH] Remove custom Sphinx index monkeypatch Drops the builder-inited hook that patched `IndexEntries.create_index` and removes the related TOC/anchor ordering helpers and unused imports. This restores default Sphinx index entry ordering behavior and simplifies the extension setup. --- src/sphinx_indexed_definitions/__init__.py | 150 +-------------------- 1 file changed, 1 insertion(+), 149 deletions(-) diff --git a/src/sphinx_indexed_definitions/__init__.py b/src/sphinx_indexed_definitions/__init__.py index 8c75e94..2a8f3a9 100644 --- a/src/sphinx_indexed_definitions/__init__.py +++ b/src/sphinx_indexed_definitions/__init__.py @@ -1,11 +1,7 @@ from sphinx.application import Sphinx from sphinx_proof.proof_type import DefinitionDirective, TheoremDirective, LemmaDirective, ConjectureDirective, CorollaryDirective, PropositionDirective, NotationDirective -from pathlib import PurePosixPath -import os import re from docutils import nodes -from sphinx.environment.adapters.indexentries import IndexEntries -import yaml SUPPORTED_NODES = ['strong','emphasis','literal'] DEFAULT_NODES = ['strong','emphasis'] @@ -172,9 +168,6 @@ def setup(app: Sphinx): app.add_directive_to_domain('prf','proposition',IndexedPropositionDirective,override=True) app.add_directive_to_domain('prf','notation',IndexedNotationDirective,override=True) - - app.connect("builder-inited", lambda app: patch_index(app)) - return {} def parse_config(app:Sphinx): @@ -558,145 +551,4 @@ def parse_title_and_terms(self,def_nodes): parsed_indexes = [] node_list = start_node + parsed_indexes + end_node + def_nodes - return node_list - - -def patch_index(app): - env = app.env - - # ----------------------------- - # Build TOC document order - # ----------------------------- - doc_order = build_doc_order(env) - - # ----------------------------- - # Build anchor positions per doc - # ----------------------------- - anchor_positions = build_anchor_positions(env) - - # ----------------------------- - # Monkeypatch - # ----------------------------- - original = IndexEntries.create_index - - def custom_create_index(self, builder, group_entries=True): - content = original(self, builder, group_entries) - - for _, entries in content: - for i, (term, (links, subitems, key)) in enumerate(entries): - - def sort_key(link): - # Current Sphinx index targets are (main, uri) pairs. - _, uri = link - - if not uri: - return (10**9, 10**9) - - target = uri.split("#", 1)[0] - anchor = uri.split("#", 1)[1] if "#" in uri else "" - docname = target[:-5] if target.endswith(".html") else target - - # 1. TOC order - doc_pos = doc_order.get(docname, 10**9) - - # 2. Prefer numeric index anchors when available so same-document - # entries follow their source order in the generated index. - index_match = re.search(r"index-(\d+)$", anchor) - if index_match: - anchor_pos = (0, int(index_match.group(1))) - else: - anchor_map = anchor_positions.get(docname, {}) - anchor_pos = (1, anchor_map.get(anchor, 10**9)) - - return (doc_pos, anchor_pos) - - links.sort(key=sort_key) - - entries[i] = (term, (links, subitems, key)) - - return content - - IndexEntries.create_index = custom_create_index - - -# -------------------------------------------------- -# Helpers -# -------------------------------------------------- - -def build_doc_order(env): - """ - Build document order based on the external TOC file order. - """ - order = {} - counter = [0] - - def normalize_docname(path): - if not path: - return None - normalized = path.replace("\\", "/") - return str(PurePosixPath(normalized).with_suffix("")) - - def add_doc(path): - docname = normalize_docname(path) - if docname and docname not in order: - order[docname] = counter[0] - counter[0] += 1 - - def walk_item(item): - if not isinstance(item, dict): - return - - add_doc(item.get("file")) - - for key in ("parts", "chapters", "sections"): - for child in item.get(key, []) or []: - walk_item(child) - - toc_name = getattr(env.config, "external_toc_path", "_toc.yml") - toc_path = toc_name if os.path.isabs(toc_name) else os.path.join(env.app.srcdir, toc_name) - - if os.path.exists(toc_path): - try: - with open(toc_path, "r", encoding="utf-8") as toc_file: - toc_data = yaml.safe_load(toc_file) or {} - except Exception as exc: - pass - else: - add_doc(toc_data.get("root")) - for part in toc_data.get("parts", []) or []: - walk_item(part) - - # fallback: include any missing docs - for doc in env.found_docs: - if doc not in order: - order[doc] = counter[0] - counter[0] += 1 - - return order - - -def build_anchor_positions(env): - """ - Build approximate top-to-bottom order of anchors per document - """ - positions = {} - - for docname in env.found_docs: - try: - doctree = env.get_doctree(docname) - except FileNotFoundError: - continue - pos = {} - counter = 0 - - for node in doctree.traverse(): - if not isinstance(node, nodes.Element): - continue - ids = node.get("ids", []) - for anchor in ids: - pos[anchor] = counter - counter += 1 - - positions[docname] = pos - - return positions + return node_list \ No newline at end of file