From 3ad110edbf92b39e98d19e082e5de3e06e2adec6 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Tue, 14 Oct 2025 21:48:56 +0200 Subject: [PATCH 01/73] Add logging to extension initialization Introduced a logger and added a warning message when initializing the sphinx_external_toc extension to indicate it is a forked version. This helps with debugging and tracking extension usage. --- sphinx_external_toc/__init__.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sphinx_external_toc/__init__.py b/sphinx_external_toc/__init__.py index 6bcffd4..ebe2057 100644 --- a/sphinx_external_toc/__init__.py +++ b/sphinx_external_toc/__init__.py @@ -5,6 +5,10 @@ from typing import TYPE_CHECKING +from sphinx.util import logging +logger = logging.getLogger(__name__) + + if TYPE_CHECKING: from sphinx.application import Sphinx @@ -19,6 +23,8 @@ def setup(app: "Sphinx") -> dict: parse_toc_to_env, ) + logger.warning("[FORKED] Initializing sphinx_external_toc extension") + # variables app.add_config_value("external_toc_path", "_toc.yml", "env") app.add_config_value("external_toc_exclude_missing", False, "env") From 81da090612fb724efaf2ac0adc5c5eadb1199791 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Tue, 14 Oct 2025 21:59:26 +0200 Subject: [PATCH 02/73] Add custom TocTreeCollector and disable built-in collector Introduces a new collectors.py module with a custom TocTreeCollectorWithAppendices and a function to disable the built-in TocTreeCollector. Updates the extension setup to use these changes, ensuring the custom collector is registered and the built-in one is disabled, with logging for both actions. --- sphinx_external_toc/__init__.py | 8 ++++++++ sphinx_external_toc/collectors.py | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 sphinx_external_toc/collectors.py diff --git a/sphinx_external_toc/__init__.py b/sphinx_external_toc/__init__.py index ebe2057..a7ecaad 100644 --- a/sphinx_external_toc/__init__.py +++ b/sphinx_external_toc/__init__.py @@ -22,9 +22,17 @@ def setup(app: "Sphinx") -> dict: ensure_index_file, parse_toc_to_env, ) + from .collectors import ( + disable_builtin_toctree_collector, + TocTreeCollectorWithAppendices + ) logger.warning("[FORKED] Initializing sphinx_external_toc extension") + # collectors + disable_builtin_toctree_collector(app) + app.add_env_collector(TocTreeCollectorWithAppendices) + # variables app.add_config_value("external_toc_path", "_toc.yml", "env") app.add_config_value("external_toc_exclude_missing", False, "env") diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py new file mode 100644 index 0000000..9a20a0a --- /dev/null +++ b/sphinx_external_toc/collectors.py @@ -0,0 +1,23 @@ +from sphinx.environment.collectors.toctree import TocTreeCollector +import gc +from sphinx.util import logging +logger = logging.getLogger(__name__) + +def disable_builtin_toctree_collector(app): + for obj in gc.get_objects(): + if not isinstance(obj, TocTreeCollector): + continue + # When running sphinx-autobuild, this function might be called multiple + # times. When the collector is already disabled `listener_ids` will be + # `None`, and thus we don't need to disable it again. + # + # Note that disabling an already disabled collector will fail. + if obj.listener_ids is None: + continue + obj.disable(app) + logger.warning("[FORKED] Disabled built-in TocTreeCollector") + +class TocTreeCollectorWithAppendices(TocTreeCollector): + def __init__(self, *args, **kwargs): + logger.warning("[FORKED] Enabling new TocTreeCollectorWithAppendices") + super().__init__(*args, **kwargs) \ No newline at end of file From 498ef7ac2e6b8f8d5cb8719c9c0d1542585ef9d2 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Tue, 14 Oct 2025 22:11:03 +0200 Subject: [PATCH 03/73] Add 'style' field to TocTree and propagate to nodes Introduces a 'style' attribute to the TocTree class for specifying toctree rendering style (e.g., numerical, roman, letter). The style is validated and passed through to the generated node in the insert_toctrees event. --- sphinx_external_toc/api.py | 12 ++++++++++++ sphinx_external_toc/events.py | 1 + 2 files changed, 13 insertions(+) diff --git a/sphinx_external_toc/api.py b/sphinx_external_toc/api.py index 3bd8155..098d096 100644 --- a/sphinx_external_toc/api.py +++ b/sphinx_external_toc/api.py @@ -61,6 +61,18 @@ class TocTree: ) reversed: bool = field(default=False, kw_only=True, validator=instance_of(bool)) titlesonly: bool = field(default=False, kw_only=True, validator=instance_of(bool)) + # Add extra field for style of toctree rendering + style: str = field( + default="numerical", + kw_only=True, + validator=[ + instance_of(str), + lambda s: s in {"numerical", "roman_upper", "roman_lower", "letter_upper", "letter_lower"} + or ValueError( + f"Invalid style '{s}'. Must be one of: numerical, roman_upper, roman_lower, letter_upper, letter_lower" + ), + ], + ) def __post_init__(self): validate_fields(self) diff --git a/sphinx_external_toc/events.py b/sphinx_external_toc/events.py index 8d468f4..7673aa7 100644 --- a/sphinx_external_toc/events.py +++ b/sphinx_external_toc/events.py @@ -240,6 +240,7 @@ def insert_toctrees(app: Sphinx, doctree: nodes.document) -> None: else (999 if toctree.numbered is True else int(toctree.numbered)) ) subnode["titlesonly"] = toctree.titlesonly + subnode["style"] = toctree.style wrappernode = nodes.compound(classes=["toctree-wrapper"]) wrappernode.append(subnode) From 97bb7c05179120732eb6765d92567f616a7b043f Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Tue, 14 Oct 2025 22:13:16 +0200 Subject: [PATCH 04/73] Update validator lambda signature in TocTree Modified the validator lambda for the 'style' attribute in the TocTree class to accept three arguments instead of one, aligning with expected usage. --- sphinx_external_toc/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx_external_toc/api.py b/sphinx_external_toc/api.py index 098d096..471e26e 100644 --- a/sphinx_external_toc/api.py +++ b/sphinx_external_toc/api.py @@ -67,7 +67,7 @@ class TocTree: kw_only=True, validator=[ instance_of(str), - lambda s: s in {"numerical", "roman_upper", "roman_lower", "letter_upper", "letter_lower"} + lambda s,f,g: s in {"numerical", "roman_upper", "roman_lower", "letter_upper", "letter_lower"} or ValueError( f"Invalid style '{s}'. Must be one of: numerical, roman_upper, roman_lower, letter_upper, letter_lower" ), From 7ada9d8d738f7ef61d90699aca37ecff284310ff Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Tue, 14 Oct 2025 22:49:41 +0200 Subject: [PATCH 05/73] Add and enforce 'style' option for toctree Introduces a 'style' option to TOCTREE_OPTIONS and adds a validator to ensure only allowed style values are accepted. Updates the TocTree dataclass to use the new validate_style function for style validation. --- sphinx_external_toc/_compat.py | 6 ++++++ sphinx_external_toc/api.py | 9 ++------- sphinx_external_toc/parsing.py | 1 + 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/sphinx_external_toc/_compat.py b/sphinx_external_toc/_compat.py index c87fb83..cdf5b6f 100644 --- a/sphinx_external_toc/_compat.py +++ b/sphinx_external_toc/_compat.py @@ -147,3 +147,9 @@ def findall(node: Element): # findall replaces traverse in docutils v0.18 # note a difference is that findall is an iterator return getattr(node, "findall", node.traverse) + + +def validate_style(instance, attribute, value): + allowed = ["numerical", "romanupper", "romanlower", "alphaupper", "alphalower"] + if value not in allowed: + raise ValueError(f"{attribute.name} must be one of {allowed}, not {value!r}") \ No newline at end of file diff --git a/sphinx_external_toc/api.py b/sphinx_external_toc/api.py index 471e26e..b8b6607 100644 --- a/sphinx_external_toc/api.py +++ b/sphinx_external_toc/api.py @@ -11,6 +11,7 @@ matches_re, optional, validate_fields, + validate_style, ) #: Pattern used to match URL items. @@ -65,13 +66,7 @@ class TocTree: style: str = field( default="numerical", kw_only=True, - validator=[ - instance_of(str), - lambda s,f,g: s in {"numerical", "roman_upper", "roman_lower", "letter_upper", "letter_lower"} - or ValueError( - f"Invalid style '{s}'. Must be one of: numerical, roman_upper, roman_lower, letter_upper, letter_lower" - ), - ], + validator=validate_style ) def __post_init__(self): diff --git a/sphinx_external_toc/parsing.py b/sphinx_external_toc/parsing.py index 717b9fa..723fd84 100644 --- a/sphinx_external_toc/parsing.py +++ b/sphinx_external_toc/parsing.py @@ -23,6 +23,7 @@ "numbered", "reversed", "titlesonly", + "style", ) From ffca3686a720214e7b8906bb2a3e0adda4993235 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 08:47:13 +0200 Subject: [PATCH 06/73] Replace TocTreeCollectorWithAppendices with TocTreeCollectorWithStyles Renames the custom collector class to TocTreeCollectorWithStyles and updates its usage in the extension setup. Adds a process_doc method stub for future style processing, with logging for debugging. --- sphinx_external_toc/__init__.py | 4 ++-- sphinx_external_toc/collectors.py | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/sphinx_external_toc/__init__.py b/sphinx_external_toc/__init__.py index a7ecaad..925ab23 100644 --- a/sphinx_external_toc/__init__.py +++ b/sphinx_external_toc/__init__.py @@ -24,14 +24,14 @@ def setup(app: "Sphinx") -> dict: ) from .collectors import ( disable_builtin_toctree_collector, - TocTreeCollectorWithAppendices + TocTreeCollectorWithStyles ) logger.warning("[FORKED] Initializing sphinx_external_toc extension") # collectors disable_builtin_toctree_collector(app) - app.add_env_collector(TocTreeCollectorWithAppendices) + app.add_env_collector(TocTreeCollectorWithStyles) # variables app.add_config_value("external_toc_path", "_toc.yml", "env") diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 9a20a0a..887251f 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -1,6 +1,8 @@ from sphinx.environment.collectors.toctree import TocTreeCollector +from docutils.nodes import toctree, Node import gc from sphinx.util import logging + logger = logging.getLogger(__name__) def disable_builtin_toctree_collector(app): @@ -17,7 +19,15 @@ def disable_builtin_toctree_collector(app): obj.disable(app) logger.warning("[FORKED] Disabled built-in TocTreeCollector") -class TocTreeCollectorWithAppendices(TocTreeCollector): +class TocTreeCollectorWithStyles(TocTreeCollector): def __init__(self, *args, **kwargs): - logger.warning("[FORKED] Enabling new TocTreeCollectorWithAppendices") - super().__init__(*args, **kwargs) \ No newline at end of file + logger.warning("[FORKED] Enabling new TocTreeCollectorWithStyles") + super().__init__(*args, **kwargs) + + def process_doc(self, app, doctree: Node): + # First, call the original process_doc to get the default behavior + logger.warning("[FORKED] Calling original TocTreeCollector.process_doc") + super().process_doc(app, doctree) + + # Then, add any additional processing for styles here + logger.warning("[FORKED] Processing styles") \ No newline at end of file From a49d589a96c56e5c1bcf719b7168a90486dac3f6 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 08:50:58 +0200 Subject: [PATCH 07/73] Remove unused toctree import from collectors.py The 'toctree' import from docutils.nodes was not used in the file and has been removed to clean up the imports. --- sphinx_external_toc/collectors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 887251f..0925fda 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -1,5 +1,5 @@ from sphinx.environment.collectors.toctree import TocTreeCollector -from docutils.nodes import toctree, Node +from docutils.nodes import Node import gc from sphinx.util import logging From 4408ceaa4bc3521a4c3c90cf08aacbd2121bf54e Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 09:09:41 +0200 Subject: [PATCH 08/73] Refactor to override assign_section_numbers method Replaces the process_doc override with assign_section_numbers in TocTreeCollectorWithStyles. This change ensures custom style processing occurs after section numbers are assigned, maintaining original behavior and logging. --- sphinx_external_toc/collectors.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 0925fda..f03809a 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -24,10 +24,12 @@ def __init__(self, *args, **kwargs): logger.warning("[FORKED] Enabling new TocTreeCollectorWithStyles") super().__init__(*args, **kwargs) - def process_doc(self, app, doctree: Node): - # First, call the original process_doc to get the default behavior - logger.warning("[FORKED] Calling original TocTreeCollector.process_doc") - super().process_doc(app, doctree) + def assign_section_numbers(self, env): + # First, call the original assign_section_numbers to get the default behavior + logger.warning("[FORKED] Calling original TocTreeCollector.assign_section_numbers") + result = super().assign_section_numbers(env) # Then, add any additional processing for styles here - logger.warning("[FORKED] Processing styles") \ No newline at end of file + logger.warning("[FORKED] Processing styles") + + return result \ No newline at end of file From 77eba840b40bfb603dbb2c11bd079475f336cb5b Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 09:13:11 +0200 Subject: [PATCH 09/73] Add logging for docnames in TocTreeCollectorWithStyles Added a loop to log each docname in env.numbered_toctrees and retrieve its doctree for additional processing. This enhances visibility into which documents are being processed during style handling. --- sphinx_external_toc/collectors.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index f03809a..5095081 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -1,5 +1,4 @@ from sphinx.environment.collectors.toctree import TocTreeCollector -from docutils.nodes import Node import gc from sphinx.util import logging @@ -31,5 +30,8 @@ def assign_section_numbers(self, env): # Then, add any additional processing for styles here logger.warning("[FORKED] Processing styles") + for docname in env.numbered_toctrees: + logger.warning(f"[FORKED] Processing docname: {docname}") + doctree = env.get_doctree(docname) return result \ No newline at end of file From 594ac62b9eafa5b15fd031099529cac2ffb3544c Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 09:18:24 +0200 Subject: [PATCH 10/73] Add logging for found toctree nodes in collector Enhanced TocTreeCollectorWithStyles to log each found toctree node within doctrees for debugging and analysis purposes. --- sphinx_external_toc/collectors.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 5095081..b7b1ee4 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -1,6 +1,7 @@ from sphinx.environment.collectors.toctree import TocTreeCollector import gc from sphinx.util import logging +from sphinx import addnodes as sphinxnodes logger = logging.getLogger(__name__) @@ -33,5 +34,7 @@ def assign_section_numbers(self, env): for docname in env.numbered_toctrees: logger.warning(f"[FORKED] Processing docname: {docname}") doctree = env.get_doctree(docname) + for toctree in doctree.findall(sphinxnodes.toctree): + logger.warning(f"[FORKED] Found toctree: {toctree}") return result \ No newline at end of file From fba99bd8d420274fc81dab430e1e99ecf4fe16dc Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 09:21:21 +0200 Subject: [PATCH 11/73] Log non-numerical toctree styles in collector Added a check to log a warning when a toctree with a style other than 'numerical' is found during document processing. This helps identify and debug custom toctree styles in the documentation. --- sphinx_external_toc/collectors.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index b7b1ee4..a0e6dab 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -35,6 +35,8 @@ def assign_section_numbers(self, env): logger.warning(f"[FORKED] Processing docname: {docname}") doctree = env.get_doctree(docname) for toctree in doctree.findall(sphinxnodes.toctree): - logger.warning(f"[FORKED] Found toctree: {toctree}") + style = toctree.get("style", "numerical") + if style != "numerical": + logger.warning(f"[FORKED] Found toctree with non-numerical style: {style}") return result \ No newline at end of file From e15a4f2e41d00e47c23eb5ecddfac28bdfa62dd6 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 09:23:10 +0200 Subject: [PATCH 12/73] Improve toctree style warning message The warning now includes the toctree caption (or 'NAMELESS' if missing) along with the non-numerical style, providing more context for debugging. --- sphinx_external_toc/collectors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index a0e6dab..69900c4 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -37,6 +37,6 @@ def assign_section_numbers(self, env): for toctree in doctree.findall(sphinxnodes.toctree): style = toctree.get("style", "numerical") if style != "numerical": - logger.warning(f"[FORKED] Found toctree with non-numerical style: {style}") + logger.warning(f"[FORKED] Found toctree {toctree.get('caption','NAMELESS')} with non-numerical style {style}") return result \ No newline at end of file From 50ae7c8d82e28f58d0bc670825bb2f4c8d2061d9 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 09:27:41 +0200 Subject: [PATCH 13/73] Update collectors.py --- sphinx_external_toc/collectors.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 69900c4..bc297da 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -28,6 +28,7 @@ def assign_section_numbers(self, env): # First, call the original assign_section_numbers to get the default behavior logger.warning("[FORKED] Calling original TocTreeCollector.assign_section_numbers") result = super().assign_section_numbers(env) + logger.warning(f"[FORKED] Original assign_section_numbers completed with result {result}") # Then, add any additional processing for styles here logger.warning("[FORKED] Processing styles") From c662e738bbb7f553d8772d4777ea09c4f6dd423b Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 09:46:58 +0200 Subject: [PATCH 14/73] Update collectors.py --- sphinx_external_toc/collectors.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index bc297da..46e4df9 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -27,10 +27,9 @@ def __init__(self, *args, **kwargs): def assign_section_numbers(self, env): # First, call the original assign_section_numbers to get the default behavior logger.warning("[FORKED] Calling original TocTreeCollector.assign_section_numbers") - result = super().assign_section_numbers(env) - logger.warning(f"[FORKED] Original assign_section_numbers completed with result {result}") + result = super().assign_section_numbers(env) # only needed to maintain functionality - # Then, add any additional processing for styles here + # Processing styles logger.warning("[FORKED] Processing styles") for docname in env.numbered_toctrees: logger.warning(f"[FORKED] Processing docname: {docname}") @@ -39,5 +38,8 @@ def assign_section_numbers(self, env): style = toctree.get("style", "numerical") if style != "numerical": logger.warning(f"[FORKED] Found toctree {toctree.get('caption','NAMELESS')} with non-numerical style {style}") + # convert the section numbers to the new style + for _, ref in toctree["entries"]: + logger.warning(f"[FORKED] Current section number: {env.titles[ref]['secnumber']}") return result \ No newline at end of file From d3c177eb9bcb984a98ba46fd9e72b7744c3a9ce8 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 10:02:45 +0200 Subject: [PATCH 15/73] Add __renumber method to TocTreeCollectorWithStyles Introduces a private __renumber method to handle section number style conversion in TocTreeCollectorWithStyles. Currently, the method returns the original number unless a specific style is provided. --- sphinx_external_toc/collectors.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 46e4df9..b25e1be 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -41,5 +41,13 @@ def assign_section_numbers(self, env): # convert the section numbers to the new style for _, ref in toctree["entries"]: logger.warning(f"[FORKED] Current section number: {env.titles[ref]['secnumber']}") + env.titles[ref]["secnumber"] = self.__renumber(env.titles[ref]["secnumber"]) + logger.warning(f"[FORKED] New section number: {env.titles[ref]['secnumber']}") - return result \ No newline at end of file + return result + + def __renumber(self, number,style): + if not number or not style or style == "numerical": + return number + + return number \ No newline at end of file From 07344a2adb0e6eff1b81ba9d3d9b78b2f9a41f31 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 10:03:14 +0200 Subject: [PATCH 16/73] Update collectors.py --- sphinx_external_toc/collectors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index b25e1be..19b2c20 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -41,7 +41,7 @@ def assign_section_numbers(self, env): # convert the section numbers to the new style for _, ref in toctree["entries"]: logger.warning(f"[FORKED] Current section number: {env.titles[ref]['secnumber']}") - env.titles[ref]["secnumber"] = self.__renumber(env.titles[ref]["secnumber"]) + env.titles[ref]["secnumber"] = self.__renumber(env.titles[ref]["secnumber"],style) logger.warning(f"[FORKED] New section number: {env.titles[ref]['secnumber']}") return result From 010398f9a3d9467776a75e3e15be9327ec66d208 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 10:08:34 +0200 Subject: [PATCH 17/73] Add Roman numeral support to TOC numbering styles Implemented conversion of TOC numbering to upper and lower case Roman numerals in TocTreeCollectorWithStyles. Added a helper method to convert integers to Roman numerals and updated renumbering logic to handle 'romanupper' and 'romanlower' styles. --- sphinx_external_toc/collectors.py | 36 ++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 19b2c20..6171701 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -49,5 +49,39 @@ def assign_section_numbers(self, env): def __renumber(self, number,style): if not number or not style or style == "numerical": return number + + if len(style) != 1: + style = style[0] # if multiple styles are given, use only the first one, the other are used in another method + # only convert the first number to the new style + first = number[0] + if style == "romanupper": + number[0] = self.__to_roman(first).upper() + elif style == "romanlower": + number[0] = self.__to_roman(first).lower() + else: + pass - return number \ No newline at end of file + return number + + def __to_roman(self, n): + """Convert an integer to a Roman numeral.""" + val = [ + 1000, 900, 500, 400, + 100, 90, 50, 40, + 10, 9, 5, 4, + 1 + ] + syms = [ + "M", "CM", "D", "CD", + "C", "XC", "L", "XL", + "X", "IX", "V", "IV", + "I" + ] + roman_num = '' + i = 0 + while n > 0: + for _ in range(n // val[i]): + roman_num += syms[i] + n -= val[i] + i += 1 + return roman_num \ No newline at end of file From b227b4d772b5f144be0c5f2c09085067b3ae16ed Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 10:10:55 +0200 Subject: [PATCH 18/73] Update collectors.py --- sphinx_external_toc/collectors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 6171701..84c4b33 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -50,7 +50,7 @@ def __renumber(self, number,style): if not number or not style or style == "numerical": return number - if len(style) != 1: + if not isinstance(style, str): style = style[0] # if multiple styles are given, use only the first one, the other are used in another method # only convert the first number to the new style first = number[0] From 1b60bd34dc084aab1b5820fb53be003321d2c173 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 10:16:51 +0200 Subject: [PATCH 19/73] Update collectors.py --- sphinx_external_toc/collectors.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 84c4b33..96d7a66 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -24,6 +24,9 @@ def __init__(self, *args, **kwargs): logger.warning("[FORKED] Enabling new TocTreeCollectorWithStyles") super().__init__(*args, **kwargs) + self.__romanupper_count = 0 + self.__romanlower_count = 0 + def assign_section_numbers(self, env): # First, call the original assign_section_numbers to get the default behavior logger.warning("[FORKED] Calling original TocTreeCollector.assign_section_numbers") @@ -53,11 +56,12 @@ def __renumber(self, number,style): if not isinstance(style, str): style = style[0] # if multiple styles are given, use only the first one, the other are used in another method # only convert the first number to the new style - first = number[0] if style == "romanupper": - number[0] = self.__to_roman(first).upper() + self.__romanupper_count += 1 + number[0] = self.__to_roman(self.__romanupper_count).upper() elif style == "romanlower": - number[0] = self.__to_roman(first).lower() + self.__romanlower_count += 1 + number[0] = self.__to_roman(self.__romanlower_count).lower() else: pass From 6a39651dde8681546187973f5e296cff030e563d Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 10:20:37 +0200 Subject: [PATCH 20/73] Add alpha section numbering to TocTreeCollectorWithStyles Introduces support for 'alphaupper' and 'alphalower' section numbering styles in TocTreeCollectorWithStyles by adding counters and a method to convert integers to alphabetical representations. --- sphinx_external_toc/collectors.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 96d7a66..edbef1f 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -26,6 +26,8 @@ def __init__(self, *args, **kwargs): self.__romanupper_count = 0 self.__romanlower_count = 0 + self.__alphaupper_count = 0 + self.__alphalower_count = 0 def assign_section_numbers(self, env): # First, call the original assign_section_numbers to get the default behavior @@ -62,6 +64,12 @@ def __renumber(self, number,style): elif style == "romanlower": self.__romanlower_count += 1 number[0] = self.__to_roman(self.__romanlower_count).lower() + elif style == "alphaupper": + self.__alphaupper_count += 1 + number[0] = self.__to_alpha(self.__alphaupper_count).upper() + elif style == "alphalower": + self.__alphalower_count += 1 + number[0] = self.__to_alpha(self.__alphalower_count).lower() else: pass @@ -88,4 +96,13 @@ def __to_roman(self, n): roman_num += syms[i] n -= val[i] i += 1 - return roman_num \ No newline at end of file + return roman_num + + def __to_alpha(self, n): + """Convert an integer to an alphabetical representation (A, B, ..., Z, AA, AB, ...).""" + result = "" + while n > 0: + n -= 1 + result = chr(n % 26 + ord('A')) + result + n //= 26 + return result \ No newline at end of file From 2211db864325127d1b17b6e2135b593cb9906c4d Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 10:32:18 +0200 Subject: [PATCH 21/73] Support numerical style renumbering in TocTreeCollectorWithStyles Added a counter for the 'numerical' style and updated the renumbering logic to handle all styles, including 'numerical', consistently. This ensures section numbers are properly converted based on the specified style in toctree entries. --- sphinx_external_toc/collectors.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index edbef1f..db7aeb4 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -24,6 +24,7 @@ def __init__(self, *args, **kwargs): logger.warning("[FORKED] Enabling new TocTreeCollectorWithStyles") super().__init__(*args, **kwargs) + self.__numerical_count = 0 self.__romanupper_count = 0 self.__romanlower_count = 0 self.__alphaupper_count = 0 @@ -41,23 +42,24 @@ def assign_section_numbers(self, env): doctree = env.get_doctree(docname) for toctree in doctree.findall(sphinxnodes.toctree): style = toctree.get("style", "numerical") - if style != "numerical": - logger.warning(f"[FORKED] Found toctree {toctree.get('caption','NAMELESS')} with non-numerical style {style}") - # convert the section numbers to the new style - for _, ref in toctree["entries"]: - logger.warning(f"[FORKED] Current section number: {env.titles[ref]['secnumber']}") - env.titles[ref]["secnumber"] = self.__renumber(env.titles[ref]["secnumber"],style) - logger.warning(f"[FORKED] New section number: {env.titles[ref]['secnumber']}") + # convert the section numbers to the new style + for _, ref in toctree["entries"]: + logger.warning(f"[FORKED] Current section number: {env.titles[ref]['secnumber']}") + env.titles[ref]["secnumber"] = self.__renumber(env.titles[ref]["secnumber"],style) + logger.warning(f"[FORKED] New section number: {env.titles[ref]['secnumber']}") return result def __renumber(self, number,style): - if not number or not style or style == "numerical": + if not number or not style: return number if not isinstance(style, str): style = style[0] # if multiple styles are given, use only the first one, the other are used in another method # only convert the first number to the new style + if style == "numerical": + self.__numerical_count += 1 + number[0] = self.__numerical_count if style == "romanupper": self.__romanupper_count += 1 number[0] = self.__to_roman(self.__romanupper_count).upper() From 9dfe08251ccfd442ec6ea089eac8b3542bb6904b Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 10:52:40 +0200 Subject: [PATCH 22/73] Add TOC section renumbering with style support Introduces a __replace_toc method to recursively update section numbers in the table of contents according to a specified style. This ensures that section numbers in the TOC reflect the desired numbering format, and raises an error if nested toctrees are encountered. --- sphinx_external_toc/collectors.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index db7aeb4..509ac0d 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -2,6 +2,7 @@ import gc from sphinx.util import logging from sphinx import addnodes as sphinxnodes +from docutils import nodes logger = logging.getLogger(__name__) @@ -47,6 +48,8 @@ def assign_section_numbers(self, env): logger.warning(f"[FORKED] Current section number: {env.titles[ref]['secnumber']}") env.titles[ref]["secnumber"] = self.__renumber(env.titles[ref]["secnumber"],style) logger.warning(f"[FORKED] New section number: {env.titles[ref]['secnumber']}") + if ref in env.tocs: + self.__replace_toc(env, ref, env.tocs[ref],style) return result @@ -107,4 +110,17 @@ def __to_alpha(self, n): n -= 1 result = chr(n % 26 + ord('A')) + result n //= 26 - return result \ No newline at end of file + return result + + def __replace_toc(self, env, ref, node,style): + if isinstance(node, nodes.reference): + fixed_number = self.__renumber(node["secnumber"],style) + node["secnumber"] = fixed_number + env.toc_secnumbers[ref][node["anchorname"]] = fixed_number + + elif isinstance(node, sphinxnodes.toctree): + raise RuntimeError("nested toctrees are not supported") + + else: + for child in node.children: + self.__replace_toc(env, ref, child,style) \ No newline at end of file From e9c5c97e3f5ba365fd0e99ee57a364984c7cf0ce Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 10:54:32 +0200 Subject: [PATCH 23/73] Comment out nested toctree RuntimeError The RuntimeError for nested toctrees has been commented out in TocTreeCollectorWithStyles. This may allow nested toctrees to be processed or ignored without raising an exception. --- sphinx_external_toc/collectors.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 509ac0d..da60427 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -118,8 +118,8 @@ def __replace_toc(self, env, ref, node,style): node["secnumber"] = fixed_number env.toc_secnumbers[ref][node["anchorname"]] = fixed_number - elif isinstance(node, sphinxnodes.toctree): - raise RuntimeError("nested toctrees are not supported") + # elif isinstance(node, sphinxnodes.toctree): + # raise RuntimeError("nested toctrees are not supported") else: for child in node.children: From baec699ba7ca7aa9e29e92787ad391ac58d58d65 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 10:56:27 +0200 Subject: [PATCH 24/73] Update collectors.py --- sphinx_external_toc/collectors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index da60427..7f62d62 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -123,4 +123,4 @@ def __replace_toc(self, env, ref, node,style): else: for child in node.children: - self.__replace_toc(env, ref, child,style) \ No newline at end of file + self.__replace_toc(env, ref, child,"numerical") # nested toctrees are not supported, so reset style to numerical \ No newline at end of file From f7889b888c393e3275223fd4e0760e7e195e363a Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 11:00:54 +0200 Subject: [PATCH 25/73] Update collectors.py --- sphinx_external_toc/collectors.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 7f62d62..9c90511 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -121,6 +121,6 @@ def __replace_toc(self, env, ref, node,style): # elif isinstance(node, sphinxnodes.toctree): # raise RuntimeError("nested toctrees are not supported") - else: - for child in node.children: - self.__replace_toc(env, ref, child,"numerical") # nested toctrees are not supported, so reset style to numerical \ No newline at end of file + # else: + # for child in node.children: + # self.__replace_toc(env, ref, child,"numerical") # nested toctrees are not supported, so reset style to numerical \ No newline at end of file From dab5bfcdae16c7486ef86e318832e5ce86764c9c Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 14:14:57 +0200 Subject: [PATCH 26/73] Refactor section number increment logic in collector Moves the increment of section number counters for different styles from __renumber to the main loop in TocTreeCollectorWithStyles. This avoids double-incrementing and ensures counters are updated only once per entry. --- sphinx_external_toc/collectors.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 9c90511..b9bd1c4 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -45,6 +45,18 @@ def assign_section_numbers(self, env): style = toctree.get("style", "numerical") # convert the section numbers to the new style for _, ref in toctree["entries"]: + if style == "numerical": + self.__numerical_count += 1 + if style == "romanupper": + self.__romanupper_count += 1 + elif style == "romanlower": + self.__romanlower_count += 1 + elif style == "alphaupper": + self.__alphaupper_count += 1 + elif style == "alphalower": + self.__alphalower_count += 1 + else: + pass logger.warning(f"[FORKED] Current section number: {env.titles[ref]['secnumber']}") env.titles[ref]["secnumber"] = self.__renumber(env.titles[ref]["secnumber"],style) logger.warning(f"[FORKED] New section number: {env.titles[ref]['secnumber']}") @@ -61,19 +73,14 @@ def __renumber(self, number,style): style = style[0] # if multiple styles are given, use only the first one, the other are used in another method # only convert the first number to the new style if style == "numerical": - self.__numerical_count += 1 number[0] = self.__numerical_count if style == "romanupper": - self.__romanupper_count += 1 number[0] = self.__to_roman(self.__romanupper_count).upper() elif style == "romanlower": - self.__romanlower_count += 1 number[0] = self.__to_roman(self.__romanlower_count).lower() elif style == "alphaupper": - self.__alphaupper_count += 1 number[0] = self.__to_alpha(self.__alphaupper_count).upper() elif style == "alphalower": - self.__alphalower_count += 1 number[0] = self.__to_alpha(self.__alphalower_count).lower() else: pass From 83bb1e20f459f2fa6cae35de0e6a3065974215dc Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 14:18:30 +0200 Subject: [PATCH 27/73] Update collectors.py --- sphinx_external_toc/collectors.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index b9bd1c4..58a115b 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -35,6 +35,7 @@ def assign_section_numbers(self, env): # First, call the original assign_section_numbers to get the default behavior logger.warning("[FORKED] Calling original TocTreeCollector.assign_section_numbers") result = super().assign_section_numbers(env) # only needed to maintain functionality + logger.warning("[FORKED] Original TocTreeCollector.assign_section_numbers done.\nResult:\n{result}\nSection numbers:\n{env.toc_secnumbers}") # Processing styles logger.warning("[FORKED] Processing styles") From 80592397117fa71116d6571485f17e7190b8c71f Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 14:19:24 +0200 Subject: [PATCH 28/73] Update collectors.py --- sphinx_external_toc/collectors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 58a115b..2613e2d 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -35,7 +35,7 @@ def assign_section_numbers(self, env): # First, call the original assign_section_numbers to get the default behavior logger.warning("[FORKED] Calling original TocTreeCollector.assign_section_numbers") result = super().assign_section_numbers(env) # only needed to maintain functionality - logger.warning("[FORKED] Original TocTreeCollector.assign_section_numbers done.\nResult:\n{result}\nSection numbers:\n{env.toc_secnumbers}") + logger.warning(f"[FORKED] Original TocTreeCollector.assign_section_numbers done.\nResult:\n{result}\nSection numbers:\n{env.toc_secnumbers}") # Processing styles logger.warning("[FORKED] Processing styles") From ae119ef624993a1d048157e0ba1cab53ebc548ea Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 14:29:58 +0200 Subject: [PATCH 29/73] Update collectors.py --- sphinx_external_toc/collectors.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 2613e2d..6f90dbc 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -58,11 +58,13 @@ def assign_section_numbers(self, env): self.__alphalower_count += 1 else: pass - logger.warning(f"[FORKED] Current section number: {env.titles[ref]['secnumber']}") + logger.warning(f"[FORKED] Current section name: {ref}") env.titles[ref]["secnumber"] = self.__renumber(env.titles[ref]["secnumber"],style) logger.warning(f"[FORKED] New section number: {env.titles[ref]['secnumber']}") - if ref in env.tocs: - self.__replace_toc(env, ref, env.tocs[ref],style) + # replace in toc_secnumbers as well + old_secnumbers = env.toc_secnumbers[ref] + logger.warning(f"[FORKED] Old toc_secnumbers: {old_secnumbers}") + return result From 44ec28e6a45f5dcd2de614207993a9f636893283 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 14:35:58 +0200 Subject: [PATCH 30/73] Update collectors.py --- sphinx_external_toc/collectors.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 6f90dbc..6844dc2 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -30,6 +30,7 @@ def __init__(self, *args, **kwargs): self.__romanlower_count = 0 self.__alphaupper_count = 0 self.__alphalower_count = 0 + self.__map_old_to_new = {} def assign_section_numbers(self, env): # First, call the original assign_section_numbers to get the default behavior @@ -58,13 +59,13 @@ def assign_section_numbers(self, env): self.__alphalower_count += 1 else: pass - logger.warning(f"[FORKED] Current section name: {ref}") - env.titles[ref]["secnumber"] = self.__renumber(env.titles[ref]["secnumber"],style) - logger.warning(f"[FORKED] New section number: {env.titles[ref]['secnumber']}") - # replace in toc_secnumbers as well - old_secnumbers = env.toc_secnumbers[ref] - logger.warning(f"[FORKED] Old toc_secnumbers: {old_secnumbers}") - + old_secnumber = env.titles[ref]["secnumber"] + logger.warning(f"[FORKED] Old section number of {ref}: {old_secnumber}") + new_secnumber = self.__renumber(env.titles[ref]["secnumber"],style) + logger.warning(f"[FORKED] New section number of {ref}: {new_secnumber}") + self.__map_old_to_new[str(old_secnumber)] = new_secnumber + env.titles[ref]["secnumber"] = new_secnumber + logger.warning(f"[FORKED] New section number: {env.titles[ref]['secnumber']}") return result From 0666bf538951e2dc8b221492abe4d7d87e02d735 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 14:38:50 +0200 Subject: [PATCH 31/73] Update collectors.py --- sphinx_external_toc/collectors.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 6844dc2..0061b68 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -65,7 +65,9 @@ def assign_section_numbers(self, env): logger.warning(f"[FORKED] New section number of {ref}: {new_secnumber}") self.__map_old_to_new[str(old_secnumber)] = new_secnumber env.titles[ref]["secnumber"] = new_secnumber - logger.warning(f"[FORKED] New section number: {env.titles[ref]['secnumber']}") + logger.warning(f"[FORKED] New section number: {env.titles[ref]['secnumber']}") + + logger.warning(f"[FORKED] Map of old to new section numbers: {self.__map_old_to_new}") return result From fd9a47dfdf75fe0f615df7428e3bd8c9c6740cd3 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 14:41:13 +0200 Subject: [PATCH 32/73] Update collectors.py --- sphinx_external_toc/collectors.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 0061b68..5298343 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -59,13 +59,12 @@ def assign_section_numbers(self, env): self.__alphalower_count += 1 else: pass - old_secnumber = env.titles[ref]["secnumber"] + old_secnumber = env.titles[ref]["secnumber"][0] logger.warning(f"[FORKED] Old section number of {ref}: {old_secnumber}") - new_secnumber = self.__renumber(env.titles[ref]["secnumber"],style) + new_secnumber = self.__renumber([old_secnumber][0],style) logger.warning(f"[FORKED] New section number of {ref}: {new_secnumber}") self.__map_old_to_new[str(old_secnumber)] = new_secnumber - env.titles[ref]["secnumber"] = new_secnumber - logger.warning(f"[FORKED] New section number: {env.titles[ref]['secnumber']}") + env.titles[ref]["secnumber"] = [new_secnumber] logger.warning(f"[FORKED] Map of old to new section numbers: {self.__map_old_to_new}") From 4c8b84e13fd577ebea7c8e8c3cb7576a625f0250 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 14:42:12 +0200 Subject: [PATCH 33/73] Update collectors.py --- sphinx_external_toc/collectors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 5298343..1320a46 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -61,7 +61,7 @@ def assign_section_numbers(self, env): pass old_secnumber = env.titles[ref]["secnumber"][0] logger.warning(f"[FORKED] Old section number of {ref}: {old_secnumber}") - new_secnumber = self.__renumber([old_secnumber][0],style) + new_secnumber = self.__renumber(old_secnumber,style) logger.warning(f"[FORKED] New section number of {ref}: {new_secnumber}") self.__map_old_to_new[str(old_secnumber)] = new_secnumber env.titles[ref]["secnumber"] = [new_secnumber] From 70fa36095046f6694fcbccf8af0c273a3d8e89f9 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 14:43:48 +0200 Subject: [PATCH 34/73] Update collectors.py --- sphinx_external_toc/collectors.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 1320a46..ad938cb 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -76,17 +76,19 @@ def __renumber(self, number,style): if not isinstance(style, str): style = style[0] # if multiple styles are given, use only the first one, the other are used in another method + if not isinstance(number, int): + number = number[0] # if multiple numbers are given, use only the first one, the other are used in another method # only convert the first number to the new style if style == "numerical": - number[0] = self.__numerical_count + number = self.__numerical_count if style == "romanupper": - number[0] = self.__to_roman(self.__romanupper_count).upper() + number = self.__to_roman(self.__romanupper_count).upper() elif style == "romanlower": - number[0] = self.__to_roman(self.__romanlower_count).lower() + number = self.__to_roman(self.__romanlower_count).lower() elif style == "alphaupper": - number[0] = self.__to_alpha(self.__alphaupper_count).upper() + number = self.__to_alpha(self.__alphaupper_count).upper() elif style == "alphalower": - number[0] = self.__to_alpha(self.__alphalower_count).lower() + number = self.__to_alpha(self.__alphalower_count).lower() else: pass From d9b60d0395fcec6c7e498f402e0edf4ba8ea7059 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 14:58:25 +0200 Subject: [PATCH 35/73] Update collectors.py --- sphinx_external_toc/collectors.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index ad938cb..05e9844 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -59,14 +59,19 @@ def assign_section_numbers(self, env): self.__alphalower_count += 1 else: pass - old_secnumber = env.titles[ref]["secnumber"][0] + old_secnumber = env.titles[ref]["secnumber"] logger.warning(f"[FORKED] Old section number of {ref}: {old_secnumber}") - new_secnumber = self.__renumber(old_secnumber,style) + new_secnumber = self.__renumber(env.titles[ref]["secnumber"],style) logger.warning(f"[FORKED] New section number of {ref}: {new_secnumber}") - self.__map_old_to_new[str(old_secnumber)] = new_secnumber - env.titles[ref]["secnumber"] = [new_secnumber] + env.titles[ref]["secnumber"] = self.__renumber(env.titles[ref]["secnumber"],style) + + # STORE THE MAP + if isinstance(old_secnumber, list): + old_secnumber = old_secnumber[0] + if isinstance(old_secnumber, list): + old_secnumber = old_secnumber[0] + self.__map_old_to_new[old_secnumber] = new_secnumber - logger.warning(f"[FORKED] Map of old to new section numbers: {self.__map_old_to_new}") return result @@ -76,19 +81,17 @@ def __renumber(self, number,style): if not isinstance(style, str): style = style[0] # if multiple styles are given, use only the first one, the other are used in another method - if not isinstance(number, int): - number = number[0] # if multiple numbers are given, use only the first one, the other are used in another method # only convert the first number to the new style if style == "numerical": - number = self.__numerical_count + number[0] = self.__numerical_count if style == "romanupper": - number = self.__to_roman(self.__romanupper_count).upper() + number[0] = self.__to_roman(self.__romanupper_count).upper() elif style == "romanlower": - number = self.__to_roman(self.__romanlower_count).lower() + number[0] = self.__to_roman(self.__romanlower_count).lower() elif style == "alphaupper": - number = self.__to_alpha(self.__alphaupper_count).upper() + number[0] = self.__to_alpha(self.__alphaupper_count).upper() elif style == "alphalower": - number = self.__to_alpha(self.__alphalower_count).lower() + number[0] = self.__to_alpha(self.__alphalower_count).lower() else: pass From 28a98edf31653baf7e9013409781c252cad172db Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 15:00:23 +0200 Subject: [PATCH 36/73] Update collectors.py --- sphinx_external_toc/collectors.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 05e9844..1ab8230 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -63,15 +63,16 @@ def assign_section_numbers(self, env): logger.warning(f"[FORKED] Old section number of {ref}: {old_secnumber}") new_secnumber = self.__renumber(env.titles[ref]["secnumber"],style) logger.warning(f"[FORKED] New section number of {ref}: {new_secnumber}") - env.titles[ref]["secnumber"] = self.__renumber(env.titles[ref]["secnumber"],style) + env.titles[ref]["secnumber"] = new_secnumber - # STORE THE MAP - if isinstance(old_secnumber, list): - old_secnumber = old_secnumber[0] + # STORE IN THE MAP if isinstance(old_secnumber, list): old_secnumber = old_secnumber[0] + if isinstance(new_secnumber, list): + new_secnumber = new_secnumber[0] self.__map_old_to_new[old_secnumber] = new_secnumber + logger.warning(f"[FORKED] Final map:\n{self.__map_old_to_new}") return result From 6f371fb0356da71b94d9a454177eb7e1677d47d6 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 15:02:02 +0200 Subject: [PATCH 37/73] Update collectors.py --- sphinx_external_toc/collectors.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 1ab8230..f700ca5 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -1,3 +1,4 @@ +from shutil import copy from sphinx.environment.collectors.toctree import TocTreeCollector import gc from sphinx.util import logging @@ -59,11 +60,11 @@ def assign_section_numbers(self, env): self.__alphalower_count += 1 else: pass - old_secnumber = env.titles[ref]["secnumber"] + old_secnumber = copy.deepcopy(env.titles[ref]["secnumber"]) logger.warning(f"[FORKED] Old section number of {ref}: {old_secnumber}") new_secnumber = self.__renumber(env.titles[ref]["secnumber"],style) logger.warning(f"[FORKED] New section number of {ref}: {new_secnumber}") - env.titles[ref]["secnumber"] = new_secnumber + env.titles[ref]["secnumber"] = copy.deepcopy(new_secnumber) # STORE IN THE MAP if isinstance(old_secnumber, list): From 354ae655c8c68985c3901d000e265bda34565279 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 15:04:24 +0200 Subject: [PATCH 38/73] Update collectors.py --- sphinx_external_toc/collectors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index f700ca5..d904f33 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -1,4 +1,4 @@ -from shutil import copy +import copy from sphinx.environment.collectors.toctree import TocTreeCollector import gc from sphinx.util import logging From 36ce81cdecb6d91d74d7251a22fac7bffe9f79ac Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 15:06:35 +0200 Subject: [PATCH 39/73] Update collectors.py --- sphinx_external_toc/collectors.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index d904f33..fbd40cd 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -74,6 +74,9 @@ def assign_section_numbers(self, env): self.__map_old_to_new[old_secnumber] = new_secnumber logger.warning(f"[FORKED] Final map:\n{self.__map_old_to_new}") + # Now, replace the section numbers in env.toc_secnumbers + for docname in env.toc_secnumbers: + logger.warning(f"[FORKED] Old section numbers in {docname}: {env.toc_secnumbers[docname]}") return result From ba0355be41f91c3fc3c44644b76bd07ad308a034 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 15:09:49 +0200 Subject: [PATCH 40/73] Update collectors.py --- sphinx_external_toc/collectors.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index fbd40cd..a998c51 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -77,6 +77,11 @@ def assign_section_numbers(self, env): # Now, replace the section numbers in env.toc_secnumbers for docname in env.toc_secnumbers: logger.warning(f"[FORKED] Old section numbers in {docname}: {env.toc_secnumbers[docname]}") + for _, secnumber in env.toc_secnumbers[docname].items(): + first_number = secnumber[0] + secnumber[0] = self.__map_old_to_new.get(first_number, first_number) + logger.warning(f"[FORKED] New section numbers in {docname}: {env.toc_secnumbers[docname]}") + return result From a0c43fc5dcc4b18d371364d569c51537ffece33a Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 15:11:18 +0200 Subject: [PATCH 41/73] Update collectors.py --- sphinx_external_toc/collectors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index a998c51..c50c9fa 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -79,7 +79,7 @@ def assign_section_numbers(self, env): logger.warning(f"[FORKED] Old section numbers in {docname}: {env.toc_secnumbers[docname]}") for _, secnumber in env.toc_secnumbers[docname].items(): first_number = secnumber[0] - secnumber[0] = self.__map_old_to_new.get(first_number, first_number) + secnumber = (self.__map_old_to_new.get(first_number, first_number), secnumber[1:]) logger.warning(f"[FORKED] New section numbers in {docname}: {env.toc_secnumbers[docname]}") From 924ccaa7d53c9929dc967f9cc16a6f23b21362c4 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 15:13:10 +0200 Subject: [PATCH 42/73] Update collectors.py --- sphinx_external_toc/collectors.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index c50c9fa..72f7158 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -78,6 +78,7 @@ def assign_section_numbers(self, env): for docname in env.toc_secnumbers: logger.warning(f"[FORKED] Old section numbers in {docname}: {env.toc_secnumbers[docname]}") for _, secnumber in env.toc_secnumbers[docname].items(): + logger.warning(f"[FORKED] Old secnumber: {secnumber}") first_number = secnumber[0] secnumber = (self.__map_old_to_new.get(first_number, first_number), secnumber[1:]) logger.warning(f"[FORKED] New section numbers in {docname}: {env.toc_secnumbers[docname]}") From 6c58b37df5b821d8962eb1af113dda3ed8c69f60 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 15:15:28 +0200 Subject: [PATCH 43/73] Update collectors.py --- sphinx_external_toc/collectors.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 72f7158..0268cad 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -77,10 +77,12 @@ def assign_section_numbers(self, env): # Now, replace the section numbers in env.toc_secnumbers for docname in env.toc_secnumbers: logger.warning(f"[FORKED] Old section numbers in {docname}: {env.toc_secnumbers[docname]}") - for _, secnumber in env.toc_secnumbers[docname].items(): + for anchorname, secnumber in env.toc_secnumbers[docname].items(): logger.warning(f"[FORKED] Old secnumber: {secnumber}") first_number = secnumber[0] secnumber = (self.__map_old_to_new.get(first_number, first_number), secnumber[1:]) + logger.warning(f"[FORKED] New secnumber: {secnumber}") + env.toc_secnumbers[docname][anchorname] = copy.deepcopy(secnumber) logger.warning(f"[FORKED] New section numbers in {docname}: {env.toc_secnumbers[docname]}") From e1c79ca46b15262f271572d27cc3394ecf5f14ca Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 15:19:33 +0200 Subject: [PATCH 44/73] Update collectors.py --- sphinx_external_toc/collectors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 0268cad..eefb2ce 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -80,7 +80,7 @@ def assign_section_numbers(self, env): for anchorname, secnumber in env.toc_secnumbers[docname].items(): logger.warning(f"[FORKED] Old secnumber: {secnumber}") first_number = secnumber[0] - secnumber = (self.__map_old_to_new.get(first_number, first_number), secnumber[1:]) + secnumber = (self.__map_old_to_new.get(first_number, first_number), *secnumber[1:]) logger.warning(f"[FORKED] New secnumber: {secnumber}") env.toc_secnumbers[docname][anchorname] = copy.deepcopy(secnumber) logger.warning(f"[FORKED] New section numbers in {docname}: {env.toc_secnumbers[docname]}") From 398677306f6bb36e2a3f32dfa9efc1d8b33c4fd2 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 15:22:20 +0200 Subject: [PATCH 45/73] Update collectors.py --- sphinx_external_toc/collectors.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index eefb2ce..9a3d8a2 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -65,6 +65,8 @@ def assign_section_numbers(self, env): new_secnumber = self.__renumber(env.titles[ref]["secnumber"],style) logger.warning(f"[FORKED] New section number of {ref}: {new_secnumber}") env.titles[ref]["secnumber"] = copy.deepcopy(new_secnumber) + if ref in env.tocs: + self.__replace_toc(env, ref, env.tocs[ref]) # STORE IN THE MAP if isinstance(old_secnumber, list): From b8fa42a6d8020c88baa8c71d76078d6fe96852d6 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 15:23:24 +0200 Subject: [PATCH 46/73] Update collectors.py --- sphinx_external_toc/collectors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 9a3d8a2..468e709 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -66,7 +66,7 @@ def assign_section_numbers(self, env): logger.warning(f"[FORKED] New section number of {ref}: {new_secnumber}") env.titles[ref]["secnumber"] = copy.deepcopy(new_secnumber) if ref in env.tocs: - self.__replace_toc(env, ref, env.tocs[ref]) + self.__replace_toc(env, ref, env.tocs[ref],style) # STORE IN THE MAP if isinstance(old_secnumber, list): From 39c29118b13aa680e68ff0f85679d222ba984027 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 15:26:30 +0200 Subject: [PATCH 47/73] Update collectors.py --- sphinx_external_toc/collectors.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 468e709..527fe5b 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -153,6 +153,6 @@ def __replace_toc(self, env, ref, node,style): # elif isinstance(node, sphinxnodes.toctree): # raise RuntimeError("nested toctrees are not supported") - # else: - # for child in node.children: - # self.__replace_toc(env, ref, child,"numerical") # nested toctrees are not supported, so reset style to numerical \ No newline at end of file + else: + for child in node.children: + self.__replace_toc(env, ref, child,style) \ No newline at end of file From 687a57aea9df3cc7d26e1ac32ee687e8e109c3a8 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 15:38:02 +0200 Subject: [PATCH 48/73] Update collectors.py --- sphinx_external_toc/collectors.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 527fe5b..19137c1 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -155,4 +155,5 @@ def __replace_toc(self, env, ref, node,style): else: for child in node.children: + logger.warning(f"[FORKED] Recursing into child of {type(node)}") self.__replace_toc(env, ref, child,style) \ No newline at end of file From 3d6d925d71fc60fe9349decafc1255ae7a7c9ffd Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 15:40:03 +0200 Subject: [PATCH 49/73] Update collectors.py --- sphinx_external_toc/collectors.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 19137c1..d96a10c 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -150,8 +150,8 @@ def __replace_toc(self, env, ref, node,style): node["secnumber"] = fixed_number env.toc_secnumbers[ref][node["anchorname"]] = fixed_number - # elif isinstance(node, sphinxnodes.toctree): - # raise RuntimeError("nested toctrees are not supported") + elif isinstance(node, sphinxnodes.toctree): + logger.warning(f"[FORKED] Found nested toctree in {ref}:\n{node.pformat()}") else: for child in node.children: From ccc639de82901448dd26d0258e8f0c236688e3cf Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 15:42:40 +0200 Subject: [PATCH 50/73] Update collectors.py --- sphinx_external_toc/collectors.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index d96a10c..237f097 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -152,6 +152,7 @@ def __replace_toc(self, env, ref, node,style): elif isinstance(node, sphinxnodes.toctree): logger.warning(f"[FORKED] Found nested toctree in {ref}:\n{node.pformat()}") + raise RuntimeError("[FORKED] Nested toctrees are not (yet) supported.") else: for child in node.children: From f38061504edd519b1c5fe5ba5ab93a6d3d476368 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 15:48:38 +0200 Subject: [PATCH 51/73] Handle nested toctrees in TocTreeCollectorWithStyles Introduces the __fix_nested_toc method to process nested toctrees instead of raising a RuntimeError. This change updates section numbers and recursively replaces tocs for nested entries, improving support for complex toctree structures. --- sphinx_external_toc/collectors.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 237f097..0af8483 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -152,9 +152,20 @@ def __replace_toc(self, env, ref, node,style): elif isinstance(node, sphinxnodes.toctree): logger.warning(f"[FORKED] Found nested toctree in {ref}:\n{node.pformat()}") - raise RuntimeError("[FORKED] Nested toctrees are not (yet) supported.") + self.__fix_nested_toc(env, node, style) + # raise RuntimeError("[FORKED] Nested toctrees are not (yet) supported.") else: for child in node.children: logger.warning(f"[FORKED] Recursing into child of {type(node)}") - self.__replace_toc(env, ref, child,style) \ No newline at end of file + self.__replace_toc(env, ref, child,style) + + def __fix_nested_toc(self, env, toctree, style): + for _, ref in toctree["entries"]: + old_secnumber = copy.deepcopy(env.titles[ref]["secnumber"]) + logger.warning(f"[FORKED-NESTED] Old section number of {ref}: {old_secnumber}") + new_secnumber = self.__renumber(env.titles[ref]["secnumber"],style) + logger.warning(f"[FORKED-NESTED] New section number of {ref}: {new_secnumber}") + env.titles[ref]["secnumber"] = copy.deepcopy(new_secnumber) + if ref in env.tocs: + self.__replace_toc(env, ref, env.tocs[ref],style) \ No newline at end of file From 30eb4471e8f8cedca0cf779930b8f0f8988c774d Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 16:21:41 +0200 Subject: [PATCH 52/73] Add restart_numbering option to TocTree and parsing Introduces a new 'restart_numbering' boolean field to the TocTree class and includes it in the list of recognized TOCTREE_OPTIONS. This allows users to specify whether numbering should restart for a given toctree style. --- sphinx_external_toc/api.py | 4 ++++ sphinx_external_toc/parsing.py | 1 + 2 files changed, 5 insertions(+) diff --git a/sphinx_external_toc/api.py b/sphinx_external_toc/api.py index b8b6607..e07d79b 100644 --- a/sphinx_external_toc/api.py +++ b/sphinx_external_toc/api.py @@ -68,6 +68,10 @@ class TocTree: kw_only=True, validator=validate_style ) + # add extra field for restarting numbering for the set style + restart_numbering: bool = field( + default=False, kw_only=True, validator=instance_of(bool) + ) def __post_init__(self): validate_fields(self) diff --git a/sphinx_external_toc/parsing.py b/sphinx_external_toc/parsing.py index 723fd84..6af3791 100644 --- a/sphinx_external_toc/parsing.py +++ b/sphinx_external_toc/parsing.py @@ -24,6 +24,7 @@ "reversed", "titlesonly", "style", + "restart_numbering", ) From ceb541f2df8acbda30fa9d508184de34d76102b1 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 16:25:12 +0200 Subject: [PATCH 53/73] Add support for restarting section numbering in toctree Introduces handling of a 'restart_numbering' attribute in toctree nodes. When set, the section numbering for the specified style is reset, and a warning is logged. This allows for more flexible control over section numbering in generated documentation. --- sphinx_external_toc/collectors.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 0af8483..f0c0344 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -46,6 +46,19 @@ def assign_section_numbers(self, env): doctree = env.get_doctree(docname) for toctree in doctree.findall(sphinxnodes.toctree): style = toctree.get("style", "numerical") + restart = toctree.get("restart_numbering", False) + if restart: + logger.warning(f"[FORKED] Restarting numbering for style {style}") + if style == "numerical": + self.__numerical_count = 0 + elif style == "romanupper": + self.__romanupper_count = 0 + elif style == "romanlower": + self.__romanlower_count = 0 + elif style == "alphaupper": + self.__alphaupper_count = 0 + elif style == "alphalower": + self.__alphalower_count = 0 # convert the section numbers to the new style for _, ref in toctree["entries"]: if style == "numerical": From 32bdcc4f6612dc29a853157c04737861eae34eb4 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 16:27:16 +0200 Subject: [PATCH 54/73] Update events.py --- sphinx_external_toc/events.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sphinx_external_toc/events.py b/sphinx_external_toc/events.py index 7673aa7..aad996d 100644 --- a/sphinx_external_toc/events.py +++ b/sphinx_external_toc/events.py @@ -241,6 +241,7 @@ def insert_toctrees(app: Sphinx, doctree: nodes.document) -> None: ) subnode["titlesonly"] = toctree.titlesonly subnode["style"] = toctree.style + subnode["restart_numbering"] = toctree.restart_numbering wrappernode = nodes.compound(classes=["toctree-wrapper"]) wrappernode.append(subnode) From 69f1ab34f2401b0bff4b6855eeb28f331407a01a Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 16:39:24 +0200 Subject: [PATCH 55/73] Support list values for toctree style attribute Updated the TocTree style attribute to accept both string and list values, adjusting validation and internal handling accordingly. This allows for more flexible style specifications in toctree rendering and ensures correct processing when multiple styles are provided. --- sphinx_external_toc/_compat.py | 6 +++- sphinx_external_toc/api.py | 2 +- sphinx_external_toc/collectors.py | 56 ++++++++++++++++--------------- 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/sphinx_external_toc/_compat.py b/sphinx_external_toc/_compat.py index cdf5b6f..f3ed887 100644 --- a/sphinx_external_toc/_compat.py +++ b/sphinx_external_toc/_compat.py @@ -151,5 +151,9 @@ def findall(node: Element): def validate_style(instance, attribute, value): allowed = ["numerical", "romanupper", "romanlower", "alphaupper", "alphalower"] - if value not in allowed: + if isinstance(value, list): + for v in value: + if v not in allowed: + raise ValueError(f"{attribute.name} must be one of {allowed}, not {v!r}") + elif value not in allowed: raise ValueError(f"{attribute.name} must be one of {allowed}, not {value!r}") \ No newline at end of file diff --git a/sphinx_external_toc/api.py b/sphinx_external_toc/api.py index e07d79b..f050417 100644 --- a/sphinx_external_toc/api.py +++ b/sphinx_external_toc/api.py @@ -63,7 +63,7 @@ class TocTree: reversed: bool = field(default=False, kw_only=True, validator=instance_of(bool)) titlesonly: bool = field(default=False, kw_only=True, validator=instance_of(bool)) # Add extra field for style of toctree rendering - style: str = field( + style: Union[List[str],str] = field( default="numerical", kw_only=True, validator=validate_style diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index f0c0344..f97b1a4 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -46,30 +46,32 @@ def assign_section_numbers(self, env): doctree = env.get_doctree(docname) for toctree in doctree.findall(sphinxnodes.toctree): style = toctree.get("style", "numerical") + if not isinstance(style, list): + style = [style] restart = toctree.get("restart_numbering", False) if restart: logger.warning(f"[FORKED] Restarting numbering for style {style}") - if style == "numerical": + if style[0] == "numerical": self.__numerical_count = 0 - elif style == "romanupper": + elif style[0] == "romanupper": self.__romanupper_count = 0 - elif style == "romanlower": + elif style[0] == "romanlower": self.__romanlower_count = 0 - elif style == "alphaupper": + elif style[0] == "alphaupper": self.__alphaupper_count = 0 - elif style == "alphalower": + elif style[0] == "alphalower": self.__alphalower_count = 0 # convert the section numbers to the new style for _, ref in toctree["entries"]: - if style == "numerical": + if style[0] == "numerical": self.__numerical_count += 1 - if style == "romanupper": + if style[0] == "romanupper": self.__romanupper_count += 1 - elif style == "romanlower": + elif style[0] == "romanlower": self.__romanlower_count += 1 - elif style == "alphaupper": + elif style[0] == "alphaupper": self.__alphaupper_count += 1 - elif style == "alphalower": + elif style[0] == "alphalower": self.__alphalower_count += 1 else: pass @@ -103,27 +105,27 @@ def assign_section_numbers(self, env): return result - def __renumber(self, number,style): - if not number or not style: - return number - - if not isinstance(style, str): - style = style[0] # if multiple styles are given, use only the first one, the other are used in another method + def __renumber(self, number_set,style_set): + if not number_set or not style_set: + return number_set + + if not isinstance(style_set, list): + style_set = [style_set] # if multiple styles are given, use only the first one, the other are used in another method # only convert the first number to the new style - if style == "numerical": - number[0] = self.__numerical_count - if style == "romanupper": - number[0] = self.__to_roman(self.__romanupper_count).upper() - elif style == "romanlower": - number[0] = self.__to_roman(self.__romanlower_count).lower() - elif style == "alphaupper": - number[0] = self.__to_alpha(self.__alphaupper_count).upper() - elif style == "alphalower": - number[0] = self.__to_alpha(self.__alphalower_count).lower() + if style_set[0] == "numerical": + number_set[0] = self.__numerical_count + if style_set[0] == "romanupper": + number_set[0] = self.__to_roman(self.__romanupper_count).upper() + elif style_set[0] == "romanlower": + number_set[0] = self.__to_roman(self.__romanlower_count).lower() + elif style_set[0] == "alphaupper": + number_set[0] = self.__to_alpha(self.__alphaupper_count).upper() + elif style_set[0] == "alphalower": + number_set[0] = self.__to_alpha(self.__alphalower_count).lower() else: pass - return number + return number_set def __to_roman(self, n): """Convert an integer to a Roman numeral.""" From 601f5a1630a8696b63ae6e817972366f279f5bea Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 16:43:41 +0200 Subject: [PATCH 56/73] Improve style conversion for numbered toctree items Enhanced the logic in TocTreeCollectorWithStyles to convert each number in number_set to its corresponding style in style_set, rather than only converting the first. This allows for more flexible and accurate handling of mixed numbering styles in toctrees. --- sphinx_external_toc/collectors.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index f97b1a4..cab3169 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -110,8 +110,10 @@ def __renumber(self, number_set,style_set): return number_set if not isinstance(style_set, list): - style_set = [style_set] # if multiple styles are given, use only the first one, the other are used in another method - # only convert the first number to the new style + style_set = [style_set] # if not multiple styles are given, convert to list + # for each style, convert the corresponding number, where only the first number + # is rebased, the rest are kept as is, but converted. + # convert the first number to the new style if style_set[0] == "numerical": number_set[0] = self.__numerical_count if style_set[0] == "romanupper": @@ -124,6 +126,20 @@ def __renumber(self, number_set,style_set): number_set[0] = self.__to_alpha(self.__alphalower_count).lower() else: pass + # convert the rest of the numbers to the corresponding styles + for i in range(1, min(len(number_set), len(style_set))): + if style_set[i] == "numerical": + continue # keep as is + if style_set[i] == "romanupper": + number_set[i] = self.__to_roman(number_set[i]).upper() + elif style_set[i] == "romanlower": + number_set[i] = self.__to_roman(number_set[i]).lower() + elif style_set[i] == "alphaupper": + number_set[i] = self.__to_alpha(number_set[i]).upper() + elif style_set[i] == "alphalower": + number_set[i] = self.__to_alpha(number_set[i]).lower() + else: + pass return number_set @@ -168,7 +184,6 @@ def __replace_toc(self, env, ref, node,style): elif isinstance(node, sphinxnodes.toctree): logger.warning(f"[FORKED] Found nested toctree in {ref}:\n{node.pformat()}") self.__fix_nested_toc(env, node, style) - # raise RuntimeError("[FORKED] Nested toctrees are not (yet) supported.") else: for child in node.children: From ee71be1c3effef0bccf4d554f86d7206ed0c021f Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 16:45:12 +0200 Subject: [PATCH 57/73] Update collectors.py --- sphinx_external_toc/collectors.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index cab3169..a17edb5 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -131,13 +131,13 @@ def __renumber(self, number_set,style_set): if style_set[i] == "numerical": continue # keep as is if style_set[i] == "romanupper": - number_set[i] = self.__to_roman(number_set[i]).upper() + number_set[i] = self.__to_roman(int(number_set[i])).upper() elif style_set[i] == "romanlower": - number_set[i] = self.__to_roman(number_set[i]).lower() + number_set[i] = self.__to_roman(int(number_set[i])).lower() elif style_set[i] == "alphaupper": - number_set[i] = self.__to_alpha(number_set[i]).upper() + number_set[i] = self.__to_alpha(int(number_set[i])).upper() elif style_set[i] == "alphalower": - number_set[i] = self.__to_alpha(number_set[i]).lower() + number_set[i] = self.__to_alpha(int(number_set[i])).lower() else: pass From 1c762dcff0a5bf6cb79bf9d68cd0ae27f3951c65 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 16:46:58 +0200 Subject: [PATCH 58/73] Update collectors.py --- sphinx_external_toc/collectors.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index a17edb5..b777aca 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -127,6 +127,8 @@ def __renumber(self, number_set,style_set): else: pass # convert the rest of the numbers to the corresponding styles + logger.warning(f"[FORKED] Renumbering {number_set} with styles {style_set}") + logger.warning(f"[FORKED] Renumbering {min(len(number_set), len(style_set))} levels") for i in range(1, min(len(number_set), len(style_set))): if style_set[i] == "numerical": continue # keep as is From 061a845ba015deb0b807c460e62b8d3e087dc001 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 16:49:43 +0200 Subject: [PATCH 59/73] Update collectors.py --- sphinx_external_toc/collectors.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index b777aca..0bc3de8 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -113,6 +113,7 @@ def __renumber(self, number_set,style_set): style_set = [style_set] # if not multiple styles are given, convert to list # for each style, convert the corresponding number, where only the first number # is rebased, the rest are kept as is, but converted. + logger.warning(f"[FORKED] Renumbering {number_set} with styles {style_set}") # convert the first number to the new style if style_set[0] == "numerical": number_set[0] = self.__numerical_count @@ -127,9 +128,9 @@ def __renumber(self, number_set,style_set): else: pass # convert the rest of the numbers to the corresponding styles - logger.warning(f"[FORKED] Renumbering {number_set} with styles {style_set}") - logger.warning(f"[FORKED] Renumbering {min(len(number_set), len(style_set))} levels") + logger.warning(f"[FORKED] Renumbering {min(len(number_set), len(style_set))-1} secondary levels") for i in range(1, min(len(number_set), len(style_set))): + logger.warning(f"[FORKED] Renumbering level {i}: {number_set[i]} with style {style_set[i]}") if style_set[i] == "numerical": continue # keep as is if style_set[i] == "romanupper": From 47ff9c66cd249858b0228378f8f8e2db188a869e Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 16:53:28 +0200 Subject: [PATCH 60/73] Improve type checks in renumbering logic Added explicit type checks for numerical and string values in the renumbering loop to prevent incorrect conversions and ensure only appropriate types are processed. --- sphinx_external_toc/collectors.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 0bc3de8..36ffc31 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -131,8 +131,10 @@ def __renumber(self, number_set,style_set): logger.warning(f"[FORKED] Renumbering {min(len(number_set), len(style_set))-1} secondary levels") for i in range(1, min(len(number_set), len(style_set))): logger.warning(f"[FORKED] Renumbering level {i}: {number_set[i]} with style {style_set[i]}") - if style_set[i] == "numerical": + if style_set[i] == "numerical" and isinstance(number_set[i], int): continue # keep as is + if isinstance(number_set[i], str): + continue # skip non-numeric values, assuming those are already converted if style_set[i] == "romanupper": number_set[i] = self.__to_roman(int(number_set[i])).upper() elif style_set[i] == "romanlower": From 5666533d8253682e5dca2de29f1c48ca74491a3c Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 17:00:01 +0200 Subject: [PATCH 61/73] Remove debug logging from TocTreeCollectorWithStyles Eliminated all logger.warning debug statements from the TocTreeCollectorWithStyles class and related functions to clean up the code and reduce unnecessary log output. --- sphinx_external_toc/collectors.py | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 36ffc31..12a5ba6 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -5,8 +5,6 @@ from sphinx import addnodes as sphinxnodes from docutils import nodes -logger = logging.getLogger(__name__) - def disable_builtin_toctree_collector(app): for obj in gc.get_objects(): if not isinstance(obj, TocTreeCollector): @@ -19,11 +17,9 @@ def disable_builtin_toctree_collector(app): if obj.listener_ids is None: continue obj.disable(app) - logger.warning("[FORKED] Disabled built-in TocTreeCollector") class TocTreeCollectorWithStyles(TocTreeCollector): def __init__(self, *args, **kwargs): - logger.warning("[FORKED] Enabling new TocTreeCollectorWithStyles") super().__init__(*args, **kwargs) self.__numerical_count = 0 @@ -35,14 +31,10 @@ def __init__(self, *args, **kwargs): def assign_section_numbers(self, env): # First, call the original assign_section_numbers to get the default behavior - logger.warning("[FORKED] Calling original TocTreeCollector.assign_section_numbers") result = super().assign_section_numbers(env) # only needed to maintain functionality - logger.warning(f"[FORKED] Original TocTreeCollector.assign_section_numbers done.\nResult:\n{result}\nSection numbers:\n{env.toc_secnumbers}") # Processing styles - logger.warning("[FORKED] Processing styles") for docname in env.numbered_toctrees: - logger.warning(f"[FORKED] Processing docname: {docname}") doctree = env.get_doctree(docname) for toctree in doctree.findall(sphinxnodes.toctree): style = toctree.get("style", "numerical") @@ -50,7 +42,6 @@ def assign_section_numbers(self, env): style = [style] restart = toctree.get("restart_numbering", False) if restart: - logger.warning(f"[FORKED] Restarting numbering for style {style}") if style[0] == "numerical": self.__numerical_count = 0 elif style[0] == "romanupper": @@ -76,9 +67,7 @@ def assign_section_numbers(self, env): else: pass old_secnumber = copy.deepcopy(env.titles[ref]["secnumber"]) - logger.warning(f"[FORKED] Old section number of {ref}: {old_secnumber}") new_secnumber = self.__renumber(env.titles[ref]["secnumber"],style) - logger.warning(f"[FORKED] New section number of {ref}: {new_secnumber}") env.titles[ref]["secnumber"] = copy.deepcopy(new_secnumber) if ref in env.tocs: self.__replace_toc(env, ref, env.tocs[ref],style) @@ -90,18 +79,12 @@ def assign_section_numbers(self, env): new_secnumber = new_secnumber[0] self.__map_old_to_new[old_secnumber] = new_secnumber - logger.warning(f"[FORKED] Final map:\n{self.__map_old_to_new}") # Now, replace the section numbers in env.toc_secnumbers for docname in env.toc_secnumbers: - logger.warning(f"[FORKED] Old section numbers in {docname}: {env.toc_secnumbers[docname]}") for anchorname, secnumber in env.toc_secnumbers[docname].items(): - logger.warning(f"[FORKED] Old secnumber: {secnumber}") first_number = secnumber[0] secnumber = (self.__map_old_to_new.get(first_number, first_number), *secnumber[1:]) - logger.warning(f"[FORKED] New secnumber: {secnumber}") env.toc_secnumbers[docname][anchorname] = copy.deepcopy(secnumber) - logger.warning(f"[FORKED] New section numbers in {docname}: {env.toc_secnumbers[docname]}") - return result @@ -113,7 +96,6 @@ def __renumber(self, number_set,style_set): style_set = [style_set] # if not multiple styles are given, convert to list # for each style, convert the corresponding number, where only the first number # is rebased, the rest are kept as is, but converted. - logger.warning(f"[FORKED] Renumbering {number_set} with styles {style_set}") # convert the first number to the new style if style_set[0] == "numerical": number_set[0] = self.__numerical_count @@ -128,9 +110,7 @@ def __renumber(self, number_set,style_set): else: pass # convert the rest of the numbers to the corresponding styles - logger.warning(f"[FORKED] Renumbering {min(len(number_set), len(style_set))-1} secondary levels") for i in range(1, min(len(number_set), len(style_set))): - logger.warning(f"[FORKED] Renumbering level {i}: {number_set[i]} with style {style_set[i]}") if style_set[i] == "numerical" and isinstance(number_set[i], int): continue # keep as is if isinstance(number_set[i], str): @@ -187,20 +167,16 @@ def __replace_toc(self, env, ref, node,style): env.toc_secnumbers[ref][node["anchorname"]] = fixed_number elif isinstance(node, sphinxnodes.toctree): - logger.warning(f"[FORKED] Found nested toctree in {ref}:\n{node.pformat()}") self.__fix_nested_toc(env, node, style) else: for child in node.children: - logger.warning(f"[FORKED] Recursing into child of {type(node)}") self.__replace_toc(env, ref, child,style) def __fix_nested_toc(self, env, toctree, style): for _, ref in toctree["entries"]: old_secnumber = copy.deepcopy(env.titles[ref]["secnumber"]) - logger.warning(f"[FORKED-NESTED] Old section number of {ref}: {old_secnumber}") new_secnumber = self.__renumber(env.titles[ref]["secnumber"],style) - logger.warning(f"[FORKED-NESTED] New section number of {ref}: {new_secnumber}") env.titles[ref]["secnumber"] = copy.deepcopy(new_secnumber) if ref in env.tocs: self.__replace_toc(env, ref, env.tocs[ref],style) \ No newline at end of file From 217a776a76d7478e09bac2550eb0b726a96f5caf Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 17:16:25 +0200 Subject: [PATCH 62/73] Update README with section numbering style options Documents new options for defining section numbering styles and restarting numbering per subtree in the Table of Contents. Adds details and examples for the 'style' and 'restart_numbering' options, and updates usage instructions accordingly. --- README.md | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 4e4e619..dcfea7b 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,12 @@ [![Code style: black][black-badge]][black-link] [![PyPI][pypi-badge]][pypi-link] +> [!NOTE] +> Currently, this is a *forked* version of `sphinx-external-toc` that implements: +> +> - Defining section numbering styles (e.g. numerical, roman (upper/lower), alphabetic (upper/lower)) per any level in the ToC. +> - Restarting the upper level section numbering for each subtree for the selected numbering style. + A sphinx extension that allows the documentation site-map (a.k.a Table of Contents) to be defined external to the documentation files. As used by [Jupyter Book](https://jupyterbook.org)! @@ -118,6 +124,20 @@ Each subtree can be configured with a number of options (see also [sphinx `toctr - `reversed` (boolean): If `True` then the entries in the subtree will be listed in reverse order (default `False`). This can be useful when using `glob` entries. - `titlesonly` (boolean): If `True` then only the first heading in the document will be shown in the ToC, not other headings of the same level (default `False`). +- `style` (string or list of strings): The section numbering style to use for this subtree (default `numerical`). + If a single string is given, this will be used for the top level of the subtree. + If a list of strings is given, then each entry will be used for the corresponding level of section numbering. + If styles are not given for all levels, then the remaining levels will be `numerical`. + If too many styles are given, the extra ones will be ignored. + The first time a style is used at the top level in a subtree, the numbering will start from 1, 'a', 'A', 'I' or 'i' depending on the style. + Subsequent times the same style is used at the top level in a subtree, the numbering will continue from the last number used for that style, unless `restart_numbering` is set to `True`. + Available styles: + - `numerical`: 1, 2, 3, ... + - `romanlower`: i, ii, iii, iv, v, ... + - `romanupper`: I, II, III, IV, V, ... + - `alphalower`: a, b, c, d, e, ..., aa, ab, ... + - `alphaupper`: A, B, C, D, E, ..., AA, AB, ... +- `restart_numbering` (boolean): If `True`, the section numbering for the top level of this subtree will restart from 1 (or 'a', 'A', 'I' or 'i' depending on the style) (default `False`). These options can be set at the level of the subtree: @@ -130,6 +150,8 @@ subtrees: numbered: True reversed: False titlesonly: True + style: [alphaupper, romanlower] + restart_numbering: True entries: - file: doc1 subtrees: @@ -149,6 +171,8 @@ options: numbered: True reversed: False titlesonly: True + style: [alphaupper, romanlower] + restart_numbering: True entries: - file: doc1 options: @@ -169,21 +193,14 @@ options: maxdepth: 1 numbered: True reversed: False + style: [alphaupper, romanlower] + restart_numbering: True entries: - file: doc1 entries: - file: doc2 ``` -:::{warning} -`numbered` should not generally be used as a default, since numbering cannot be changed by nested subtrees, and sphinx will log a warning. -::: - -:::{note} -By default, title numbering restarts for each subtree. -If you want want this numbering to be continuous, check-out the [sphinx-multitoc-numbering extension](https://github.com/executablebooks/sphinx-multitoc-numbering). -::: - ### Using different key-mappings For certain use-cases, it is helpful to map the `subtrees`/`entries` keys to mirror e.g. an output [LaTeX structure](https://www.overleaf.com/learn/latex/sections_and_chapters). From a5856722dfd03fccb2c8b2843196621b2ee09af2 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 17:49:11 +0200 Subject: [PATCH 63/73] Fix secnumber handling in TocTreeCollectorWithStyles Added a check to ensure 'secnumber' exists in env.titles[ref] before processing section numbers in TocTreeCollectorWithStyles. This prevents errors when entries do not have a 'secnumber' attribute. Also, setup now loads 'sphinx_multitoc_numbering' extension. --- sphinx_external_toc/__init__.py | 3 ++ sphinx_external_toc/collectors.py | 47 ++++++++++++++++--------------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/sphinx_external_toc/__init__.py b/sphinx_external_toc/__init__.py index 925ab23..d0c29b3 100644 --- a/sphinx_external_toc/__init__.py +++ b/sphinx_external_toc/__init__.py @@ -14,6 +14,9 @@ def setup(app: "Sphinx") -> dict: + + app.setup_extension("sphinx_multitoc_numbering") + """Initialize the Sphinx extension.""" from .events import ( InsertToctrees, diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 12a5ba6..671b6c5 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -54,30 +54,31 @@ def assign_section_numbers(self, env): self.__alphalower_count = 0 # convert the section numbers to the new style for _, ref in toctree["entries"]: - if style[0] == "numerical": - self.__numerical_count += 1 - if style[0] == "romanupper": - self.__romanupper_count += 1 - elif style[0] == "romanlower": - self.__romanlower_count += 1 - elif style[0] == "alphaupper": - self.__alphaupper_count += 1 - elif style[0] == "alphalower": - self.__alphalower_count += 1 - else: - pass - old_secnumber = copy.deepcopy(env.titles[ref]["secnumber"]) - new_secnumber = self.__renumber(env.titles[ref]["secnumber"],style) - env.titles[ref]["secnumber"] = copy.deepcopy(new_secnumber) - if ref in env.tocs: - self.__replace_toc(env, ref, env.tocs[ref],style) + if "secnumber" in env.titles[ref]: + if style[0] == "numerical": + self.__numerical_count += 1 + if style[0] == "romanupper": + self.__romanupper_count += 1 + elif style[0] == "romanlower": + self.__romanlower_count += 1 + elif style[0] == "alphaupper": + self.__alphaupper_count += 1 + elif style[0] == "alphalower": + self.__alphalower_count += 1 + else: + pass + old_secnumber = copy.deepcopy(env.titles[ref]["secnumber"]) + new_secnumber = self.__renumber(env.titles[ref]["secnumber"],style) + env.titles[ref]["secnumber"] = copy.deepcopy(new_secnumber) + if ref in env.tocs: + self.__replace_toc(env, ref, env.tocs[ref],style) - # STORE IN THE MAP - if isinstance(old_secnumber, list): - old_secnumber = old_secnumber[0] - if isinstance(new_secnumber, list): - new_secnumber = new_secnumber[0] - self.__map_old_to_new[old_secnumber] = new_secnumber + # STORE IN THE MAP + if isinstance(old_secnumber, list): + old_secnumber = old_secnumber[0] + if isinstance(new_secnumber, list): + new_secnumber = new_secnumber[0] + self.__map_old_to_new[old_secnumber] = new_secnumber # Now, replace the section numbers in env.toc_secnumbers for docname in env.toc_secnumbers: From eec33bf9cbc444cd500285ac62db69e97e6c76df Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 17:51:23 +0200 Subject: [PATCH 64/73] Update README with new features and clarifications Clarifies section numbering features, adds note about automatic inclusion of `sphinx-multitoc-numbering`, and explains that `use_multitoc_numbering: false` is ignored in JupyterBooks. --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dcfea7b..99b9646 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,9 @@ > [!NOTE] > Currently, this is a *forked* version of `sphinx-external-toc` that implements: > -> - Defining section numbering styles (e.g. numerical, roman (upper/lower), alphabetic (upper/lower)) per any level in the ToC. -> - Restarting the upper level section numbering for each subtree for the selected numbering style. +> - Section numbering styles (e.g. numerical, roman (upper/lower), alphabetic (upper/lower)) per any level in the ToC. +> - The option to restart the upper level section numbering for each subtree for the selected numbering style. +> - Automatic inclusion of `sphinx-multitoc-numbering` as the other features depend on continuous section numbering across multiple toctrees. This means that `use_multitoc_numbering: false` in `conf.py` will be ignored in JupyterBooks. A sphinx extension that allows the documentation site-map (a.k.a Table of Contents) to be defined external to the documentation files. As used by [Jupyter Book](https://jupyterbook.org)! From 0fc6222998874184b92c132f532a254cca58d68d Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Wed, 15 Oct 2025 17:58:24 +0200 Subject: [PATCH 65/73] Remove unused logger from __init__.py Eliminated the import and usage of the logger in sphinx_external_toc/__init__.py as it was not being used except for a warning message, which has also been removed. --- sphinx_external_toc/__init__.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sphinx_external_toc/__init__.py b/sphinx_external_toc/__init__.py index d0c29b3..7133b1a 100644 --- a/sphinx_external_toc/__init__.py +++ b/sphinx_external_toc/__init__.py @@ -5,10 +5,6 @@ from typing import TYPE_CHECKING -from sphinx.util import logging -logger = logging.getLogger(__name__) - - if TYPE_CHECKING: from sphinx.application import Sphinx @@ -30,8 +26,6 @@ def setup(app: "Sphinx") -> dict: TocTreeCollectorWithStyles ) - logger.warning("[FORKED] Initializing sphinx_external_toc extension") - # collectors disable_builtin_toctree_collector(app) app.add_env_collector(TocTreeCollectorWithStyles) From 39f4d364937aea1c1263629f8027a1cf352e1fab Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Thu, 16 Oct 2025 09:03:34 +0200 Subject: [PATCH 66/73] Update README and improve section numbering logic Clarifies documentation for section numbering options and subtree configuration in README. Removes unused __version__ variable from __init__.py. Adds checks in collectors.py to handle missing or empty section numbers, preventing potential errors during section renumbering. --- README.md | 14 +++++++------- sphinx_external_toc/__init__.py | 5 +---- sphinx_external_toc/collectors.py | 5 ++++- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 99b9646..3c3522e 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ > [!NOTE] > Currently, this is a *forked* version of `sphinx-external-toc` that implements: > -> - Section numbering styles (e.g. numerical, roman (upper/lower), alphabetic (upper/lower)) per any level in the ToC. -> - The option to restart the upper level section numbering for each subtree for the selected numbering style. +> - Section numbering styles (e.g. numerical, roman (upper/lower), alphabetic (upper/lower)) per any level in the ToC by providing a new option `style` per subtree. +> - The option to restart the upper level section numbering for each subtree for the selected numbering style by providing a new option `restart_numbering` per subtree. > - Automatic inclusion of `sphinx-multitoc-numbering` as the other features depend on continuous section numbering across multiple toctrees. This means that `use_multitoc_numbering: false` in `conf.py` will be ignored in JupyterBooks. A sphinx extension that allows the documentation site-map (a.k.a Table of Contents) to be defined external to the documentation files. @@ -120,8 +120,8 @@ Each subtree can be configured with a number of options (see also [sphinx `toctr By default it is appended to the end of the document, but see also the `tableofcontents` directive for positioning of the ToC. - `maxdepth` (integer): A maximum nesting depth to use when showing the ToC within the document (default -1, meaning infinite). - `numbered` (boolean or integer): Automatically add numbers to all documents within a subtree (default `False`). - If set to `True`, all sub-trees will also be numbered based on nesting (e.g. with `1.1` or `1.1.1`), - or if set to an integer then the numbering will only be applied to that depth. + If set to `True`, all subtrees will also be numbered based on nesting (e.g. with `1.1` or `1.1.1`), + or if set to an integer then the numbering will only be applied until that depth. Warning: This can lead to unexpected results if not carefully managed, for example references created using `numref` may fail. Internally this options is always converted to an integer, with `True` -> `999` (effectively unlimited depth) and `False` -> `0` (no numbering). - `reversed` (boolean): If `True` then the entries in the subtree will be listed in reverse order (default `False`). This can be useful when using `glob` entries. - `titlesonly` (boolean): If `True` then only the first heading in the document will be shown in the ToC, not other headings of the same level (default `False`). @@ -138,7 +138,7 @@ Each subtree can be configured with a number of options (see also [sphinx `toctr - `romanupper`: I, II, III, IV, V, ... - `alphalower`: a, b, c, d, e, ..., aa, ab, ... - `alphaupper`: A, B, C, D, E, ..., AA, AB, ... -- `restart_numbering` (boolean): If `True`, the section numbering for the top level of this subtree will restart from 1 (or 'a', 'A', 'I' or 'i' depending on the style) (default `False`). +- `restart_numbering` (boolean): If `True`, the numbering for the top level of this subtree will restart from 1 (or 'a', 'A', 'I' or 'i' depending on the style) (default `False`). These options can be set at the level of the subtree: @@ -442,13 +442,13 @@ meta: {} Questions / TODOs: -- Add additional top-level keys, e.g. `appendices` (see https://github.com/sphinx-doc/sphinx/issues/2502) and `bibliography` +- ~~Add additional top-level keys, e.g. `appendices` (see https://github.com/sphinx-doc/sphinx/issues/2502) and `bibliography`.~~ Can be replaced by setting the numbering style and (possibly) restarting the numbering. - Using `external_toc_exclude_missing` to exclude a certain file suffix: currently if you had files `doc.md` and `doc.rst`, and put `doc.md` in your ToC, it will add `doc.rst` to the excluded patterns but then, when looking for `doc.md`, will still select `doc.rst` (since it is first in `source_suffix`). Maybe open an issue on sphinx, that `doc2path` should respect exclude patterns. -- Integrate https://github.com/executablebooks/sphinx-multitoc-numbering into this extension? (or upstream PR) +- ~~Integrate https://github.com/executablebooks/sphinx-multitoc-numbering into this extension? (or upstream PR).~~ Included and enforced in this fork. - document suppressing warnings - test against orphan file - https://github.com/executablebooks/sphinx-book-theme/pull/304 diff --git a/sphinx_external_toc/__init__.py b/sphinx_external_toc/__init__.py index 7133b1a..c3701db 100644 --- a/sphinx_external_toc/__init__.py +++ b/sphinx_external_toc/__init__.py @@ -1,8 +1,5 @@ """A sphinx extension that allows the project toctree to be defined in a single file.""" -__version__ = "1.0.1" - - from typing import TYPE_CHECKING if TYPE_CHECKING: @@ -43,4 +40,4 @@ def setup(app: "Sphinx") -> dict: app.add_transform(InsertToctrees) app.connect("build-finished", ensure_index_file) - return {"version": __version__, "parallel_read_safe": True} + return {"parallel_read_safe": True} diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index 671b6c5..b2c6a51 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -83,6 +83,8 @@ def assign_section_numbers(self, env): # Now, replace the section numbers in env.toc_secnumbers for docname in env.toc_secnumbers: for anchorname, secnumber in env.toc_secnumbers[docname].items(): + if not secnumber: + continue first_number = secnumber[0] secnumber = (self.__map_old_to_new.get(first_number, first_number), *secnumber[1:]) env.toc_secnumbers[docname][anchorname] = copy.deepcopy(secnumber) @@ -176,7 +178,8 @@ def __replace_toc(self, env, ref, node,style): def __fix_nested_toc(self, env, toctree, style): for _, ref in toctree["entries"]: - old_secnumber = copy.deepcopy(env.titles[ref]["secnumber"]) + if "secnumber" not in env.titles[ref]: + continue new_secnumber = self.__renumber(env.titles[ref]["secnumber"],style) env.titles[ref]["secnumber"] = copy.deepcopy(new_secnumber) if ref in env.tocs: From a77ace359b9318318b8b133f7d2c0e04bac6494f Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Thu, 16 Oct 2025 10:58:59 +0200 Subject: [PATCH 67/73] Add sphinx-multitoc-numbering to dependencies Included 'sphinx-multitoc-numbering>=0.1.3' in the project dependencies to support multi-TOC numbering in Sphinx documentation builds. --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 6783f6f..b52f36a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,6 +29,7 @@ dependencies = [ "click>=7.1", "pyyaml", "sphinx>=5", + "sphinx-multitoc-numbering>=0.1.3" ] [project.urls] From f2d65353b5f95c01f1ad19845631c2bdd00e4532 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Thu, 16 Oct 2025 11:27:55 +0200 Subject: [PATCH 68/73] Add __version__ and include version in setup return Introduces a __version__ variable set to '1.1.0-dev' and updates the setup() function to return the extension version in its metadata dictionary. --- sphinx_external_toc/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sphinx_external_toc/__init__.py b/sphinx_external_toc/__init__.py index c3701db..1f9b460 100644 --- a/sphinx_external_toc/__init__.py +++ b/sphinx_external_toc/__init__.py @@ -5,6 +5,7 @@ if TYPE_CHECKING: from sphinx.application import Sphinx +__version__ = "1.1.0-dev" def setup(app: "Sphinx") -> dict: @@ -40,4 +41,5 @@ def setup(app: "Sphinx") -> dict: app.add_transform(InsertToctrees) app.connect("build-finished", ensure_index_file) - return {"parallel_read_safe": True} + return {"version": __version__, "parallel_read_safe": True} + From e58e7822f4d9923658389b56d36036af4701441b Mon Sep 17 00:00:00 2001 From: Tom van Woudenberg Date: Mon, 20 Oct 2025 15:26:39 +0200 Subject: [PATCH 69/73] Update README with Jupyter Book configuration info Clarified Jupyter Book extension usage and configuration details. --- README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c3522e..e1796c8 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ > - Automatic inclusion of `sphinx-multitoc-numbering` as the other features depend on continuous section numbering across multiple toctrees. This means that `use_multitoc_numbering: false` in `conf.py` will be ignored in JupyterBooks. A sphinx extension that allows the documentation site-map (a.k.a Table of Contents) to be defined external to the documentation files. -As used by [Jupyter Book](https://jupyterbook.org)! +As used by default [Jupyter Book](https://jupyterbook.org) (no need to manually add this extension to the extensions in `_config.yml` in a JupyterBook)! In normal Sphinx documentation, the documentation site-map is defined *via* a bottom-up approach - adding [`toctree` directives](https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#table-of-contents) within pages of the documentation. @@ -37,6 +37,17 @@ external_toc_exclude_missing = False # optional, default: False Note the `external_toc_path` is always read as a Unix path, and can either be specified relative to the source directory (recommended) or as an absolute path. +### Jupyterbook configuration + +This extension is included in your jupyterbook configuration by default, so there's need to add it to the list of extensions. The other options can still be added: + +```yaml +external_toc_path: "_toc.yml" # optional, default: _toc.yml +external_toc_exclude_missing: False # optional, default: False +``` + +Note the `external_toc_path` is always read as a Unix path, and can either be specified relative to the source directory (recommended) or as an absolute path. + ### Basic Structure A minimal ToC defines the top level `root` key, for a single root document file: From 06c77c432501b905a34d2a9b52d52b9f75ec0a4a Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst <49307154+douden@users.noreply.github.com> Date: Mon, 20 Oct 2025 15:29:19 +0200 Subject: [PATCH 70/73] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e1796c8..4fa68ce 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ > - Automatic inclusion of `sphinx-multitoc-numbering` as the other features depend on continuous section numbering across multiple toctrees. This means that `use_multitoc_numbering: false` in `conf.py` will be ignored in JupyterBooks. A sphinx extension that allows the documentation site-map (a.k.a Table of Contents) to be defined external to the documentation files. -As used by default [Jupyter Book](https://jupyterbook.org) (no need to manually add this extension to the extensions in `_config.yml` in a JupyterBook)! +As used by default by [Jupyter Book](https://jupyterbook.org) (no need to manually add this extension to the extensions in `_config.yml` in a JupyterBook)! In normal Sphinx documentation, the documentation site-map is defined *via* a bottom-up approach - adding [`toctree` directives](https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#table-of-contents) within pages of the documentation. From 1640204ef1339ab78e9a5a5a7606d33560257033 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Mon, 20 Oct 2025 20:20:22 +0200 Subject: [PATCH 71/73] Update numbering options and defaults for ToC subtrees Refines the behavior of the `restart_numbering` option for ToC subtrees, making its default value depend on the `use_multitoc_numbering` setting. Updates the README to clarify the new logic and usage, changes the API to allow `restart_numbering` to be None, and adjusts the collector logic to apply the correct default based on configuration. --- README.md | 7 +++++-- sphinx_external_toc/api.py | 5 +++-- sphinx_external_toc/collectors.py | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4fa68ce..847c7cb 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,6 @@ > > - Section numbering styles (e.g. numerical, roman (upper/lower), alphabetic (upper/lower)) per any level in the ToC by providing a new option `style` per subtree. > - The option to restart the upper level section numbering for each subtree for the selected numbering style by providing a new option `restart_numbering` per subtree. -> - Automatic inclusion of `sphinx-multitoc-numbering` as the other features depend on continuous section numbering across multiple toctrees. This means that `use_multitoc_numbering: false` in `conf.py` will be ignored in JupyterBooks. A sphinx extension that allows the documentation site-map (a.k.a Table of Contents) to be defined external to the documentation files. As used by default by [Jupyter Book](https://jupyterbook.org) (no need to manually add this extension to the extensions in `_config.yml` in a JupyterBook)! @@ -31,6 +30,7 @@ Add to your `conf.py`: ```python extensions = ["sphinx_external_toc"] +use_multitoc_numbering = True # optional, default: True external_toc_path = "_toc.yml" # optional, default: _toc.yml external_toc_exclude_missing = False # optional, default: False ``` @@ -42,6 +42,7 @@ Note the `external_toc_path` is always read as a Unix path, and can either be sp This extension is included in your jupyterbook configuration by default, so there's need to add it to the list of extensions. The other options can still be added: ```yaml +use_multitoc_numbering: true # optional, default: true external_toc_path: "_toc.yml" # optional, default: _toc.yml external_toc_exclude_missing: False # optional, default: False ``` @@ -149,7 +150,9 @@ Each subtree can be configured with a number of options (see also [sphinx `toctr - `romanupper`: I, II, III, IV, V, ... - `alphalower`: a, b, c, d, e, ..., aa, ab, ... - `alphaupper`: A, B, C, D, E, ..., AA, AB, ... -- `restart_numbering` (boolean): If `True`, the numbering for the top level of this subtree will restart from 1 (or 'a', 'A', 'I' or 'i' depending on the style) (default `False`). +- `restart_numbering` (boolean): If `True`, the numbering for the top level of this subtree will restart from 1 (or 'a', 'A', 'I' or 'i' depending on the style). If `False` the numbering for the top level of this subtree will continue from the last letter/number/symbol used in a previous subtree with the same style. The default value of this option is `not use_multitoc_numbering`. This means that: + - if `use_multitoc_numbering` is `True` (the default), the numbering for each part will continue from the last letter/number/symbol used in a previous part with the same style, unless `restart_numbering` is explicitly set to `True`. + - if `use_multitoc_numbering` is `False`, the numbering of each subtree will restart from 1 (or 'a', 'A', 'I' or 'i' depending on the style), unless `restart_numbering` is explicitly set to `False`. These options can be set at the level of the subtree: diff --git a/sphinx_external_toc/api.py b/sphinx_external_toc/api.py index f050417..cd71dc8 100644 --- a/sphinx_external_toc/api.py +++ b/sphinx_external_toc/api.py @@ -69,8 +69,9 @@ class TocTree: validator=validate_style ) # add extra field for restarting numbering for the set style - restart_numbering: bool = field( - default=False, kw_only=True, validator=instance_of(bool) + # Only allow True, False or None. None is the default value. + restart_numbering: Optional[bool] = field( + default=None, kw_only=True, validator=optional(instance_of(bool)) ) def __post_init__(self): diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index b2c6a51..d3f741e 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -1,7 +1,6 @@ import copy from sphinx.environment.collectors.toctree import TocTreeCollector import gc -from sphinx.util import logging from sphinx import addnodes as sphinxnodes from docutils import nodes @@ -40,7 +39,10 @@ def assign_section_numbers(self, env): style = toctree.get("style", "numerical") if not isinstance(style, list): style = [style] - restart = toctree.get("restart_numbering", False) + restart = toctree.get("restart_numbering", None) + continuous = env.app.config.get("use_multitoc_numbering", True) + if restart is None: + restart = not continuous # set default behavior if restart: if style[0] == "numerical": self.__numerical_count = 0 From 98b3408bce8893c519a8abe726a8fb479f88184a Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Mon, 20 Oct 2025 20:22:49 +0200 Subject: [PATCH 72/73] Remove warnings and notes about numbered option in Sphinx docs Deleted warning and note sections regarding the use of the 'numbered' option and title numbering behavior in the Sphinx user guide. This streamlines the documentation and removes potentially confusing or redundant information. --- docs/user_guide/sphinx.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/docs/user_guide/sphinx.md b/docs/user_guide/sphinx.md index 0235d7f..1c91ece 100644 --- a/docs/user_guide/sphinx.md +++ b/docs/user_guide/sphinx.md @@ -157,15 +157,6 @@ entries: - file: doc2 ``` -:::{warning} -`numbered` should not generally be used as a default, since numbering cannot be changed by nested subtrees, and sphinx will log a warning. -::: - -:::{note} -By default, title numbering restarts for each subtree. -If you want want this numbering to be continuous, check-out the [sphinx-multitoc-numbering extension](https://github.com/executablebooks/sphinx-multitoc-numbering). -::: - ## Using different key-mappings For certain use-cases, it is helpful to map the `subtrees`/`entries` keys to mirror e.g. an output [LaTeX structure](https://www.overleaf.com/learn/latex/sections_and_chapters). From 08d86aeedfd7a34a7003af281185102d8cc0e423 Mon Sep 17 00:00:00 2001 From: Dennis den Ouden-van der Horst Date: Mon, 20 Oct 2025 20:46:41 +0200 Subject: [PATCH 73/73] Fix config access for multitoc numbering option Replaces use of env.app.config.get with direct attribute access for 'use_multitoc_numbering'. This ensures correct retrieval of the configuration value and avoids defaulting to True if the option is missing. --- sphinx_external_toc/collectors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx_external_toc/collectors.py b/sphinx_external_toc/collectors.py index d3f741e..a56db94 100644 --- a/sphinx_external_toc/collectors.py +++ b/sphinx_external_toc/collectors.py @@ -40,7 +40,7 @@ def assign_section_numbers(self, env): if not isinstance(style, list): style = [style] restart = toctree.get("restart_numbering", None) - continuous = env.app.config.get("use_multitoc_numbering", True) + continuous = env.app.config.use_multitoc_numbering if restart is None: restart = not continuous # set default behavior if restart: