From e8f995b1a39979adead5d8fc76a56be88032396c Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Sat, 5 Jul 2025 17:56:12 +0200 Subject: [PATCH 1/6] [singlehtml] toctree no filename with anchor On #11970, same-document links dropped the uri (filename part). On #12551, fixes to do not include the filename on hyperlinks was added. So an anchor for a: * doc reference: #document-my-page * ref reference: #my-anchor. On #13037, fix_refuris was removed, which would blindly rmatch #.* . However, #12551 missed the toctree constructor, which was still generating: * #document-my-page#my-anchor. Modify _resolve_toctree() to do not include rel_uri if the is an anchorname. --- sphinx/environment/adapters/toctree.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sphinx/environment/adapters/toctree.py b/sphinx/environment/adapters/toctree.py index 670ac786629..bb3828b4d03 100644 --- a/sphinx/environment/adapters/toctree.py +++ b/sphinx/environment/adapters/toctree.py @@ -216,7 +216,10 @@ def _resolve_toctree( for refnode in newnode.findall(nodes.reference): if url_re.match(refnode['refuri']) is None: rel_uri = builder.get_relative_uri(docname, refnode['refuri']) - refnode['refuri'] = rel_uri + refnode['anchorname'] + if len(refnode['anchorname']): + refnode['refuri'] = refnode['anchorname'] + else: + refnode['refuri'] = rel_uri return newnode From c822bb7d8793e9a7400becc2dbe6c76a5720b3ed Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Sat, 5 Jul 2025 18:47:03 +0200 Subject: [PATCH 2/6] EPUB: Assert against anchor and not uri + anchor The toctree for anchors do not contain the uri (filename) anymore. --- tests/test_builders/test_build_epub.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/test_builders/test_build_epub.py b/tests/test_builders/test_build_epub.py index b8c7395c22c..f0f2202703e 100644 --- a/tests/test_builders/test_build_epub.py +++ b/tests/test_builders/test_build_epub.py @@ -257,13 +257,13 @@ def toc_navpoint_navinfo( assert toc_navpoint_navinfo(navchildren[2]) == ( 'navPoint5', '4', - 'foo.xhtml#foo-1', + '#foo-1', 'foo.1', ) assert toc_navpoint_navinfo(navchildren[3]) == ( 'navPoint8', '6', - 'foo.xhtml#foo-2', + '#foo-2', 'foo.2', ) @@ -286,12 +286,12 @@ def nav_nav_navinfo(elem: EPUBElementTree) -> tuple[str | None, str | None]: tocchildren = tocs[1].findall('./xhtml:ol/xhtml:li') assert len(tocchildren) == 3 assert nav_nav_navinfo(tocchildren[0]) == ('quux.xhtml', 'quux') - assert nav_nav_navinfo(tocchildren[1]) == ('foo.xhtml#foo-1', 'foo.1') - assert nav_nav_navinfo(tocchildren[2]) == ('foo.xhtml#foo-2', 'foo.2') + assert nav_nav_navinfo(tocchildren[1]) == ('#foo-1', 'foo.1') + assert nav_nav_navinfo(tocchildren[2]) == ('#foo-2', 'foo.2') grandchild = tocchildren[1].findall('./xhtml:ol/xhtml:li') assert len(grandchild) == 1 - assert nav_nav_navinfo(grandchild[0]) == ('foo.xhtml#foo-1-1', 'foo.1-1') + assert nav_nav_navinfo(grandchild[0]) == ('#foo-1-1', 'foo.1-1') @pytest.mark.sphinx('epub', testroot='need-escaped') @@ -330,13 +330,13 @@ def navpoint_navinfo( assert navpoint_navinfo(navchildren[2]) == ( 'navPoint5', '4', - 'foo.xhtml#foo-1', + '#foo-1', 'foo “1”', ) assert navpoint_navinfo(navchildren[3]) == ( 'navPoint8', '6', - 'foo.xhtml#foo-2', + '#foo-2', 'foo.2', ) @@ -359,12 +359,12 @@ def nav_navinfo(elem: EPUBElementTree) -> tuple[str | None, str | None]: tocchildren = tocs[1].findall('./xhtml:ol/xhtml:li') assert len(tocchildren) == 3 assert nav_navinfo(tocchildren[0]) == ('quux.xhtml', 'quux') - assert nav_navinfo(tocchildren[1]) == ('foo.xhtml#foo-1', 'foo “1”') - assert nav_navinfo(tocchildren[2]) == ('foo.xhtml#foo-2', 'foo.2') + assert nav_navinfo(tocchildren[1]) == ('#foo-1', 'foo “1”') + assert nav_navinfo(tocchildren[2]) == ('#foo-2', 'foo.2') grandchild = tocchildren[1].findall('./xhtml:ol/xhtml:li') assert len(grandchild) == 1 - assert nav_navinfo(grandchild[0]) == ('foo.xhtml#foo-1-1', 'foo.1-1') + assert nav_navinfo(grandchild[0]) == ('#foo-1-1', 'foo.1-1') @pytest.mark.sphinx('epub', testroot='basic') From 3ae15cfde1d4246f6094c84b1ae5e3cc9706d0a2 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Sun, 6 Jul 2025 21:51:55 +0200 Subject: [PATCH 3/6] Test enviroment: Assert anchor, not uri + anchor The toctree for anchors do not contain the uri (filename) anymore. --- tests/test_environment/test_environment_toctree.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/test_environment/test_environment_toctree.py b/tests/test_environment/test_environment_toctree.py index dcf5f8954da..e3a91904849 100644 --- a/tests/test_environment/test_environment_toctree.py +++ b/tests/test_environment/test_environment_toctree.py @@ -657,10 +657,10 @@ def test_global_toctree_for_doc(app): assert_node(toctree[1][0][0][0], reference, refuri='foo', secnumber=[1]) assert_node(toctree[1][0][1][0][0][0], reference, refuri='quux', secnumber=[1, 1]) assert_node( - toctree[1][0][1][1][0][0], reference, refuri='foo#foo-1', secnumber=[1, 2] + toctree[1][0][1][1][0][0], reference, refuri='#foo-1', secnumber=[1, 2] ) assert_node( - toctree[1][0][1][2][0][0], reference, refuri='foo#foo-2', secnumber=[1, 3] + toctree[1][0][1][2][0][0], reference, refuri='#foo-2', secnumber=[1, 3] ) assert_node(toctree[1][1][0][0], reference, refuri='bar', secnumber=[2]) assert_node(toctree[1][2][0][0], reference, refuri='https://sphinx-doc.org/') @@ -790,16 +790,16 @@ def test_global_toctree_for_doc_maxdepth(app): assert_node(toctree[1][0][0][0], reference, refuri='foo', secnumber=[1]) assert_node(toctree[1][0][1][0][0][0], reference, refuri='quux', secnumber=[1, 1]) assert_node( - toctree[1][0][1][1][0][0], reference, refuri='foo#foo-1', secnumber=[1, 2] + toctree[1][0][1][1][0][0], reference, refuri='#foo-1', secnumber=[1, 2] ) assert_node( toctree[1][0][1][1][1][0][0][0], reference, - refuri='foo#foo-1-1', + refuri='#foo-1-1', secnumber=[1, 2, 1], ) assert_node( - toctree[1][0][1][2][0][0], reference, refuri='foo#foo-2', secnumber=[1, 3] + toctree[1][0][1][2][0][0], reference, refuri='#foo-2', secnumber=[1, 3] ) assert_node(toctree[1][1][0][0], reference, refuri='bar', secnumber=[2]) assert_node(toctree[1][2][0][0], reference, refuri='https://sphinx-doc.org/') @@ -875,10 +875,10 @@ def test_global_toctree_for_doc_includehidden(app): assert_node(toctree[1][0][0][0], reference, refuri='foo', secnumber=[1]) assert_node(toctree[1][0][1][0][0][0], reference, refuri='quux', secnumber=[1, 1]) assert_node( - toctree[1][0][1][1][0][0], reference, refuri='foo#foo-1', secnumber=[1, 2] + toctree[1][0][1][1][0][0], reference, refuri='#foo-1', secnumber=[1, 2] ) assert_node( - toctree[1][0][1][2][0][0], reference, refuri='foo#foo-2', secnumber=[1, 3] + toctree[1][0][1][2][0][0], reference, refuri='#foo-2', secnumber=[1, 3] ) assert_node(toctree[1][1][0][0], reference, refuri='bar', secnumber=[2]) assert_node(toctree[1][2][0][0], reference, refuri='https://sphinx-doc.org/') From 618b1ec93283b443a9b31f7243010a4460e5ee48 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Mon, 7 Jul 2025 11:11:09 +0200 Subject: [PATCH 4/6] [singlehtml] toctree no filename with anchor --- sphinx/environment/adapters/toctree.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sphinx/environment/adapters/toctree.py b/sphinx/environment/adapters/toctree.py index bb3828b4d03..7d7e37612d6 100644 --- a/sphinx/environment/adapters/toctree.py +++ b/sphinx/environment/adapters/toctree.py @@ -216,10 +216,13 @@ def _resolve_toctree( for refnode in newnode.findall(nodes.reference): if url_re.match(refnode['refuri']) is None: rel_uri = builder.get_relative_uri(docname, refnode['refuri']) - if len(refnode['anchorname']): - refnode['refuri'] = refnode['anchorname'] + if builder.name == 'singlehtml': + if len(refnode['anchorname']): + refnode['refuri'] = refnode['anchorname'] + else: + refnode['refuri'] = rel_uri else: - refnode['refuri'] = rel_uri + refnode['refuri'] = rel_uri + refnode['anchorname'] return newnode From f0d39507490974bf22e732716956d6e5bfd226de Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Mon, 7 Jul 2025 11:04:21 +0200 Subject: [PATCH 5/6] Revert "EPUB: Assert against anchor and not uri + anchor" This reverts commit c822bb7d8793e9a7400becc2dbe6c76a5720b3ed. --- tests/test_builders/test_build_epub.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/test_builders/test_build_epub.py b/tests/test_builders/test_build_epub.py index f0f2202703e..b8c7395c22c 100644 --- a/tests/test_builders/test_build_epub.py +++ b/tests/test_builders/test_build_epub.py @@ -257,13 +257,13 @@ def toc_navpoint_navinfo( assert toc_navpoint_navinfo(navchildren[2]) == ( 'navPoint5', '4', - '#foo-1', + 'foo.xhtml#foo-1', 'foo.1', ) assert toc_navpoint_navinfo(navchildren[3]) == ( 'navPoint8', '6', - '#foo-2', + 'foo.xhtml#foo-2', 'foo.2', ) @@ -286,12 +286,12 @@ def nav_nav_navinfo(elem: EPUBElementTree) -> tuple[str | None, str | None]: tocchildren = tocs[1].findall('./xhtml:ol/xhtml:li') assert len(tocchildren) == 3 assert nav_nav_navinfo(tocchildren[0]) == ('quux.xhtml', 'quux') - assert nav_nav_navinfo(tocchildren[1]) == ('#foo-1', 'foo.1') - assert nav_nav_navinfo(tocchildren[2]) == ('#foo-2', 'foo.2') + assert nav_nav_navinfo(tocchildren[1]) == ('foo.xhtml#foo-1', 'foo.1') + assert nav_nav_navinfo(tocchildren[2]) == ('foo.xhtml#foo-2', 'foo.2') grandchild = tocchildren[1].findall('./xhtml:ol/xhtml:li') assert len(grandchild) == 1 - assert nav_nav_navinfo(grandchild[0]) == ('#foo-1-1', 'foo.1-1') + assert nav_nav_navinfo(grandchild[0]) == ('foo.xhtml#foo-1-1', 'foo.1-1') @pytest.mark.sphinx('epub', testroot='need-escaped') @@ -330,13 +330,13 @@ def navpoint_navinfo( assert navpoint_navinfo(navchildren[2]) == ( 'navPoint5', '4', - '#foo-1', + 'foo.xhtml#foo-1', 'foo “1”', ) assert navpoint_navinfo(navchildren[3]) == ( 'navPoint8', '6', - '#foo-2', + 'foo.xhtml#foo-2', 'foo.2', ) @@ -359,12 +359,12 @@ def nav_navinfo(elem: EPUBElementTree) -> tuple[str | None, str | None]: tocchildren = tocs[1].findall('./xhtml:ol/xhtml:li') assert len(tocchildren) == 3 assert nav_navinfo(tocchildren[0]) == ('quux.xhtml', 'quux') - assert nav_navinfo(tocchildren[1]) == ('#foo-1', 'foo “1”') - assert nav_navinfo(tocchildren[2]) == ('#foo-2', 'foo.2') + assert nav_navinfo(tocchildren[1]) == ('foo.xhtml#foo-1', 'foo “1”') + assert nav_navinfo(tocchildren[2]) == ('foo.xhtml#foo-2', 'foo.2') grandchild = tocchildren[1].findall('./xhtml:ol/xhtml:li') assert len(grandchild) == 1 - assert nav_navinfo(grandchild[0]) == ('#foo-1-1', 'foo.1-1') + assert nav_navinfo(grandchild[0]) == ('foo.xhtml#foo-1-1', 'foo.1-1') @pytest.mark.sphinx('epub', testroot='basic') From 2d8a9554243e8fe2e378dc4f3ffd8c973599c72e Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Mon, 7 Jul 2025 11:06:27 +0200 Subject: [PATCH 6/6] Revert "Test enviroment: Assert anchor, not uri + anchor" This reverts commit 3ae15cfde1d4246f6094c84b1ae5e3cc9706d0a2. --- tests/test_environment/test_environment_toctree.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/test_environment/test_environment_toctree.py b/tests/test_environment/test_environment_toctree.py index e3a91904849..dcf5f8954da 100644 --- a/tests/test_environment/test_environment_toctree.py +++ b/tests/test_environment/test_environment_toctree.py @@ -657,10 +657,10 @@ def test_global_toctree_for_doc(app): assert_node(toctree[1][0][0][0], reference, refuri='foo', secnumber=[1]) assert_node(toctree[1][0][1][0][0][0], reference, refuri='quux', secnumber=[1, 1]) assert_node( - toctree[1][0][1][1][0][0], reference, refuri='#foo-1', secnumber=[1, 2] + toctree[1][0][1][1][0][0], reference, refuri='foo#foo-1', secnumber=[1, 2] ) assert_node( - toctree[1][0][1][2][0][0], reference, refuri='#foo-2', secnumber=[1, 3] + toctree[1][0][1][2][0][0], reference, refuri='foo#foo-2', secnumber=[1, 3] ) assert_node(toctree[1][1][0][0], reference, refuri='bar', secnumber=[2]) assert_node(toctree[1][2][0][0], reference, refuri='https://sphinx-doc.org/') @@ -790,16 +790,16 @@ def test_global_toctree_for_doc_maxdepth(app): assert_node(toctree[1][0][0][0], reference, refuri='foo', secnumber=[1]) assert_node(toctree[1][0][1][0][0][0], reference, refuri='quux', secnumber=[1, 1]) assert_node( - toctree[1][0][1][1][0][0], reference, refuri='#foo-1', secnumber=[1, 2] + toctree[1][0][1][1][0][0], reference, refuri='foo#foo-1', secnumber=[1, 2] ) assert_node( toctree[1][0][1][1][1][0][0][0], reference, - refuri='#foo-1-1', + refuri='foo#foo-1-1', secnumber=[1, 2, 1], ) assert_node( - toctree[1][0][1][2][0][0], reference, refuri='#foo-2', secnumber=[1, 3] + toctree[1][0][1][2][0][0], reference, refuri='foo#foo-2', secnumber=[1, 3] ) assert_node(toctree[1][1][0][0], reference, refuri='bar', secnumber=[2]) assert_node(toctree[1][2][0][0], reference, refuri='https://sphinx-doc.org/') @@ -875,10 +875,10 @@ def test_global_toctree_for_doc_includehidden(app): assert_node(toctree[1][0][0][0], reference, refuri='foo', secnumber=[1]) assert_node(toctree[1][0][1][0][0][0], reference, refuri='quux', secnumber=[1, 1]) assert_node( - toctree[1][0][1][1][0][0], reference, refuri='#foo-1', secnumber=[1, 2] + toctree[1][0][1][1][0][0], reference, refuri='foo#foo-1', secnumber=[1, 2] ) assert_node( - toctree[1][0][1][2][0][0], reference, refuri='#foo-2', secnumber=[1, 3] + toctree[1][0][1][2][0][0], reference, refuri='foo#foo-2', secnumber=[1, 3] ) assert_node(toctree[1][1][0][0], reference, refuri='bar', secnumber=[2]) assert_node(toctree[1][2][0][0], reference, refuri='https://sphinx-doc.org/')