diff --git a/doc/usage/restructuredtext/directives.rst b/doc/usage/restructuredtext/directives.rst index d1877bca018..ad62274ac4a 100644 --- a/doc/usage/restructuredtext/directives.rst +++ b/doc/usage/restructuredtext/directives.rst @@ -150,7 +150,8 @@ tables of contents. The ``toctree`` directive is the central element. The special entry name ``self`` stands for the document containing the toctree directive. This is useful if you want to generate a "sitemap" from - the toctree. + the toctree. The special document names ``genindex``, ``modindex``, and + ``search`` can also be used. You can use the ``reversed`` flag option to reverse the order of the entries in the list. This can be useful when using the ``glob`` flag option to @@ -220,6 +221,9 @@ tables of contents. The ``toctree`` directive is the central element. .. versionchanged:: 1.3 Added "caption" and "name" option. + .. versionchanged:: 4.5 + Added support for "genindex", "modindex", and "search" references. + Special names ^^^^^^^^^^^^^ diff --git a/sphinx/directives/other.py b/sphinx/directives/other.py index a14b6e801e3..c2f694dbc1c 100644 --- a/sphinx/directives/other.py +++ b/sphinx/directives/other.py @@ -124,7 +124,7 @@ def parse_content(self, toctree: addnodes.toctree) -> List[Node]: break # absolutize filenames docname = docname_join(self.env.docname, docname) - if url_re.match(ref) or ref == 'self': + if url_re.match(ref) or ref in ('self', 'genindex', 'modindex', 'search'): toctree['entries'].append((title, ref)) elif docname not in self.env.found_docs: if excluded(self.env.doc2path(docname, None)): diff --git a/sphinx/environment/adapters/toctree.py b/sphinx/environment/adapters/toctree.py index 962e731435a..5c7ad37ab12 100644 --- a/sphinx/environment/adapters/toctree.py +++ b/sphinx/environment/adapters/toctree.py @@ -132,12 +132,16 @@ def _entries_from_toctree(toctreenode: addnodes.toctree, parents: List[str], para = addnodes.compact_paragraph('', '', reference) item = nodes.list_item('', para) toc = nodes.bullet_list('', item) - elif ref == 'self': + elif ref in ('self', 'genindex', 'modindex', 'search'): # 'self' refers to the document from which this # toctree originates - ref = toctreenode['parent'] - if not title: - title = clean_astext(self.env.titles[ref]) + if ref == 'self': + ref = toctreenode['parent'] + title = title or clean_astext(self.env.titles[ref]) + else: + reflabel = self.env.domains['std'].data['labels'][ref] + ref = reflabel[0] + title = title or reflabel[2] reference = nodes.reference('', '', internal=True, refuri=ref, anchorname='', diff --git a/sphinx/environment/collectors/toctree.py b/sphinx/environment/collectors/toctree.py index ddc7a0417b5..844493a6a7b 100644 --- a/sphinx/environment/collectors/toctree.py +++ b/sphinx/environment/collectors/toctree.py @@ -178,7 +178,7 @@ def _walk_toctree(toctreenode: addnodes.toctree, depth: int) -> None: if depth == 0: return for (_title, ref) in toctreenode['entries']: - if url_re.match(ref) or ref == 'self': + if url_re.match(ref) or ref in ('self', 'genindex', 'modindex', 'search'): # don't mess with those continue elif ref in assigned: @@ -262,7 +262,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.rst b/tests/roots/test-toctree/index.rst index adf1b84dda3..6a51bffa70f 100644 --- a/tests/roots/test-toctree/index.rst +++ b/tests/roots/test-toctree/index.rst @@ -17,6 +17,9 @@ Contents: bar http://sphinx-doc.org/ self + genindex + Modules + search .. only:: html diff --git a/tests/test_build_epub.py b/tests/test_build_epub.py index 851e8ac9dd4..a399e65f2c8 100644 --- a/tests/test_build_epub.py +++ b/tests/test_build_epub.py @@ -184,7 +184,7 @@ def navinfo(elem): content.get('src'), label.text) navpoints = toc.findall("./ncx:navMap/ncx:navPoint") - assert len(navpoints) == 4 + assert len(navpoints) == 7 assert navinfo(navpoints[0]) == ('navPoint1', '1', 'index.xhtml', "Welcome to Sphinx Tests’s documentation!") assert navpoints[0].findall("./ncx:navPoint") == [] @@ -205,7 +205,7 @@ def navinfo(elem): nav = EPUBElementTree.fromstring((app.outdir / 'nav.xhtml').read_bytes()) toc = nav.findall("./xhtml:body/xhtml:nav/xhtml:ol/xhtml:li") - assert len(toc) == 4 + assert len(toc) == 7 assert navinfo(toc[0]) == ('index.xhtml', "Welcome to Sphinx Tests’s documentation!") assert toc[0].findall("./xhtml:ol") == [] diff --git a/tests/test_environment_toctree.py b/tests/test_environment_toctree.py index dc5a184a4cf..41839e8490f 100644 --- a/tests/test_environment_toctree.py +++ b/tests/test_environment_toctree.py @@ -42,7 +42,8 @@ def test_process_doc(app): caption="Table of Contents", glob=False, hidden=False, titlesonly=False, maxdepth=2, numbered=999, entries=[(None, 'foo'), (None, 'bar'), (None, 'http://sphinx-doc.org/'), - (None, 'self')], + (None, 'self'), (None, 'genindex'), ('Modules', 'modindex'), + (None, 'search')], includefiles=['foo', 'bar']) # only branch @@ -222,7 +223,10 @@ def test_get_toctree_for(app): [list_item, compact_paragraph, reference, "bar"], [list_item, compact_paragraph, reference, "http://sphinx-doc.org/"], [list_item, compact_paragraph, reference, - "Welcome to Sphinx Tests’s documentation!"])) + "Welcome to Sphinx Tests’s documentation!"], + [list_item, compact_paragraph, reference, "Index"], + [list_item, compact_paragraph, reference, "Modules"], + [list_item, compact_paragraph, reference, "Search Page"])) assert_node(toctree[1][0][1], ([list_item, compact_paragraph, reference, "quux"], [list_item, compact_paragraph, reference, "foo.1"], @@ -261,7 +265,10 @@ def test_get_toctree_for_collapse(app): [list_item, compact_paragraph, reference, "bar"], [list_item, compact_paragraph, reference, "http://sphinx-doc.org/"], [list_item, compact_paragraph, reference, - "Welcome to Sphinx Tests’s documentation!"])) + "Welcome to Sphinx Tests’s documentation!"], + [list_item, compact_paragraph, reference, "Index"], + [list_item, compact_paragraph, reference, "Modules"], + [list_item, compact_paragraph, reference, "Search Page"])) assert_node(toctree[1][0][0][0], reference, refuri="foo", secnumber=[1]) assert_node(toctree[1][1][0][0], reference, refuri="bar", secnumber=[2]) assert_node(toctree[1][2][0][0], reference, refuri="http://sphinx-doc.org/") @@ -294,7 +301,10 @@ def test_get_toctree_for_maxdepth(app): [list_item, compact_paragraph, reference, "bar"], [list_item, compact_paragraph, reference, "http://sphinx-doc.org/"], [list_item, compact_paragraph, reference, - "Welcome to Sphinx Tests’s documentation!"])) + "Welcome to Sphinx Tests’s documentation!"], + [list_item, compact_paragraph, reference, "Index"], + [list_item, compact_paragraph, reference, "Modules"], + [list_item, compact_paragraph, reference, "Search Page"])) assert_node(toctree[1][0][1], ([list_item, compact_paragraph, reference, "quux"], [list_item, ([compact_paragraph, reference, "foo.1"], @@ -339,7 +349,10 @@ def test_get_toctree_for_includehidden(app): [list_item, compact_paragraph, reference, "bar"], [list_item, compact_paragraph, reference, "http://sphinx-doc.org/"], [list_item, compact_paragraph, reference, - "Welcome to Sphinx Tests’s documentation!"])) + "Welcome to Sphinx Tests’s documentation!"], + [list_item, compact_paragraph, reference, "Index"], + [list_item, compact_paragraph, reference, "Modules"], + [list_item, compact_paragraph, reference, "Search Page"])) assert_node(toctree[1][0][1], ([list_item, compact_paragraph, reference, "quux"], [list_item, compact_paragraph, reference, "foo.1"],