From 1fff774a0421e0c4d6fa56340c2cda07f8e6d3c1 Mon Sep 17 00:00:00 2001 From: Arnaud Desmier Date: Thu, 14 Nov 2024 11:18:31 +0100 Subject: [PATCH] Closes #13022: fix _toctree_copy with multi level 'only' nodes. When copying toc tree, 'only' nodes should not be copied, but previous implementation always considered 'only' node children as duplicable nodes which is wrong when 'only' nodes is parent of other 'only' nodes. --- sphinx/environment/adapters/toctree.py | 30 ++++++++++++-------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/sphinx/environment/adapters/toctree.py b/sphinx/environment/adapters/toctree.py index 3079c7dc543..d4ab0ac2c0f 100644 --- a/sphinx/environment/adapters/toctree.py +++ b/sphinx/environment/adapters/toctree.py @@ -465,15 +465,13 @@ def _toctree_add_classes(node: Element, depth: int, docname: str) -> None: ET = TypeVar('ET', bound=Element) -def _toctree_copy( - node: ET, depth: int, maxdepth: int, collapse: bool, tags: Tags -) -> ET: +def _toctree_copy_children( + copy: ET, node: ET, depth: int, maxdepth: int, collapse: bool, tags: Tags +) -> None: """Utility: Cut and deep-copy a TOC at a specified depth.""" keep_bullet_list_sub_nodes = depth <= 1 or ( (depth <= maxdepth or maxdepth <= 0) and (not collapse or 'iscurrent' in node) ) - - copy = node.copy() for subnode in node.children: if isinstance(subnode, addnodes.compact_paragraph | nodes.list_item): # for

and

  • , just recurse @@ -489,18 +487,11 @@ def _toctree_copy( # copy sub toctree nodes for later processing copy.append(subnode.copy()) elif isinstance(subnode, addnodes.only): - # only keep children if the only node matches the tags + # Only keep its children if the 'only' node matches the tags. When + # matching, call recursively the current function without + # incrementing the depth as 'only' nodes are not toctree nodes. if _only_node_keep_children(subnode, tags): - for child in subnode.children: - copy.append( - _toctree_copy( - child, - depth, - maxdepth, - collapse, - tags, # type: ignore[type-var] - ) - ) + _toctree_copy_children(copy, subnode, depth, maxdepth, collapse, tags) elif isinstance(subnode, nodes.reference | nodes.title): # deep copy references and captions sub_node_copy = subnode.copy() @@ -511,6 +502,13 @@ def _toctree_copy( else: msg = f'Unexpected node type {subnode.__class__.__name__!r}!' raise ValueError(msg) + + +def _toctree_copy( + node: ET, depth: int, maxdepth: int, collapse: bool, tags: Tags +) -> ET: + copy = node.copy() + _toctree_copy_children(copy, node, depth, maxdepth, collapse, tags) return copy