diff --git a/CHANGES b/CHANGES index ba01f72a985..90ec78048fe 100644 --- a/CHANGES +++ b/CHANGES @@ -18,9 +18,10 @@ Features added * #10755: linkcheck: Check the source URL of raw directives that use the ``url`` option. * #10781: Allow :rst:role:`ref` role to be used with definitions and fields. -* #10717: HTML Search: Increase priority for full title and +* #10717: HTML Search: Increase priority for full title and subtitle matches in search results * #10718: HTML Search: Save search result score to the HTML element for debugging +* #10673: Make toctree accept 'genindex', 'modindex' and 'search' docnames Bugs fixed ---------- diff --git a/sphinx/directives/other.py b/sphinx/directives/other.py index 35e16e6230a..c27cc3d7824 100644 --- a/sphinx/directives/other.py +++ b/sphinx/directives/other.py @@ -77,6 +77,8 @@ def run(self) -> List[Node]: return ret def parse_content(self, toctree: addnodes.toctree) -> List[Node]: + generated_documents = {'genindex', 'modindex', 'search'} + referencable_docs = self.env.found_docs | generated_documents suffixes = self.config.source_suffix # glob target documents @@ -118,7 +120,7 @@ def parse_content(self, toctree: addnodes.toctree) -> List[Node]: docname = docname_join(self.env.docname, docname) if url_re.match(ref) or ref == 'self': toctree['entries'].append((title, ref)) - elif docname not in self.env.found_docs: + elif docname not in referencable_docs: if excluded(self.env.doc2path(docname, False)): message = __('toctree contains reference to excluded document %r') subtype = 'excluded' @@ -132,6 +134,8 @@ def parse_content(self, toctree: addnodes.toctree) -> List[Node]: else: if docname in all_docnames: all_docnames.remove(docname) + elif docname in generated_documents: + pass else: logger.warning(__('duplicated entry found in toctree: %s'), docname, location=toctree) diff --git a/sphinx/environment/adapters/toctree.py b/sphinx/environment/adapters/toctree.py index 9678e3c7c83..5db7a854a84 100644 --- a/sphinx/environment/adapters/toctree.py +++ b/sphinx/environment/adapters/toctree.py @@ -139,6 +139,16 @@ def _entries_from_toctree(toctreenode: addnodes.toctree, parents: List[str], item = nodes.list_item('', para) # don't show subitems toc = nodes.bullet_list('', item) + elif ref in {'genindex', 'modindex', 'search'}: + docname, _, sectionname = self.env.domains['std'].labels[ref] # type: ignore[attr-defined] + if not title: + title = sectionname + reference = nodes.reference('', title, internal=True, + refuri=docname, anchorname='') + para = addnodes.compact_paragraph('', '', reference) + item = nodes.list_item('', para) + # don't show subitems + toc = nodes.bullet_list('', item) else: if ref in parents: logger.warning(__('circular toctree references ' diff --git a/sphinx/environment/collectors/toctree.py b/sphinx/environment/collectors/toctree.py index 52a8fd8d12b..419f23e1bb6 100644 --- a/sphinx/environment/collectors/toctree.py +++ b/sphinx/environment/collectors/toctree.py @@ -256,7 +256,8 @@ def _walk_doctree(docname: str, doctree: Element, secnum: Tuple[int, ...]) -> No _walk_doctree(docname, subnode, secnum) elif isinstance(subnode, addnodes.toctree): for _title, subdocname in subnode['entries']: - if url_re.match(subdocname) or subdocname == 'self': + if (url_re.match(subdocname) + or subdocname in {'self', 'genindex', 'modindex', 'search'}): # don't mess with those continue diff --git a/tests/roots/test-toctree-index/conf.py b/tests/roots/test-toctree-index/conf.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/roots/test-toctree-index/foo.rst b/tests/roots/test-toctree-index/foo.rst new file mode 100644 index 00000000000..fc2c716ae81 --- /dev/null +++ b/tests/roots/test-toctree-index/foo.rst @@ -0,0 +1,8 @@ +foo +=== + +:index:`word` + +.. py:module:: pymodule + +.. py:function:: Timer.repeat(repeat=3, number=1000000) diff --git a/tests/roots/test-toctree-index/index.rst b/tests/roots/test-toctree-index/index.rst new file mode 100644 index 00000000000..eb211c53fee --- /dev/null +++ b/tests/roots/test-toctree-index/index.rst @@ -0,0 +1,15 @@ +test-toctree-index +================== + +.. toctree:: + + foo + + +.. toctree:: + :caption: Indices + + genindex + modindex + search + diff --git a/tests/test_environment_toctree.py b/tests/test_environment_toctree.py index 60a9826fda6..8d5cfc0b9fb 100644 --- a/tests/test_environment_toctree.py +++ b/tests/test_environment_toctree.py @@ -346,3 +346,17 @@ def test_get_toctree_for_includehidden(app): assert_node(toctree[2], [bullet_list, list_item, compact_paragraph, reference, "baz"]) + + +@pytest.mark.sphinx('xml', testroot='toctree-index') +def test_toctree_index(app): + app.build() + toctree = app.env.tocs['index'] + assert_node(toctree, + [bullet_list, ([list_item, (compact_paragraph, # [0][0] + [bullet_list, (addnodes.toctree, # [0][1][0] + addnodes.toctree)])])]) # [0][1][1] + assert_node(toctree[0][1][1], addnodes.toctree, + caption="Indices", glob=False, hidden=False, + titlesonly=False, maxdepth=-1, numbered=0, + entries=[(None, 'genindex'), (None, 'modindex'), (None, 'search')])