Skip to content

Commit 8f8b0ac

Browse files
author
Arnaud Desmier
committed
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.
1 parent c93723b commit 8f8b0ac

File tree

1 file changed

+16
-16
lines changed

1 file changed

+16
-16
lines changed

sphinx/environment/adapters/toctree.py

+16-16
Original file line numberDiff line numberDiff line change
@@ -465,15 +465,13 @@ def _toctree_add_classes(node: Element, depth: int, docname: str) -> None:
465465
ET = TypeVar('ET', bound=Element)
466466

467467

468-
def _toctree_copy(
469-
node: ET, depth: int, maxdepth: int, collapse: bool, tags: Tags
470-
) -> ET:
468+
def _toctree_copy_children(
469+
copy: ET, node: ET, depth: int, maxdepth: int, collapse: bool, tags: Tags
470+
) -> None:
471471
"""Utility: Cut and deep-copy a TOC at a specified depth."""
472472
keep_bullet_list_sub_nodes = depth <= 1 or (
473473
(depth <= maxdepth or maxdepth <= 0) and (not collapse or 'iscurrent' in node)
474474
)
475-
476-
copy = node.copy()
477475
for subnode in node.children:
478476
if isinstance(subnode, addnodes.compact_paragraph | nodes.list_item):
479477
# for <p> and <li>, just recurse
@@ -489,18 +487,11 @@ def _toctree_copy(
489487
# copy sub toctree nodes for later processing
490488
copy.append(subnode.copy())
491489
elif isinstance(subnode, addnodes.only):
492-
# only keep children if the only node matches the tags
490+
# Only keep its children if the 'only' node matches the tags. When
491+
# matching, call recursively the current function without
492+
# incrementing the depth as 'only' nodes are not toctree nodes.
493493
if _only_node_keep_children(subnode, tags):
494-
for child in subnode.children:
495-
copy.append(
496-
_toctree_copy(
497-
child,
498-
depth,
499-
maxdepth,
500-
collapse,
501-
tags, # type: ignore[type-var]
502-
)
503-
)
494+
_toctree_copy_children(copy, subnode, depth, maxdepth, collapse, tags)
504495
elif isinstance(subnode, nodes.reference | nodes.title):
505496
# deep copy references and captions
506497
sub_node_copy = subnode.copy()
@@ -511,6 +502,15 @@ def _toctree_copy(
511502
else:
512503
msg = f'Unexpected node type {subnode.__class__.__name__!r}!'
513504
raise ValueError(msg)
505+
506+
return copy
507+
508+
509+
def _toctree_copy(
510+
node: ET, depth: int, maxdepth: int, collapse: bool, tags: Tags
511+
) -> ET:
512+
copy = node.copy()
513+
_toctree_copy_children(copy, node, depth, maxdepth, collapse, tags)
514514
return copy
515515

516516

0 commit comments

Comments
 (0)