mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
singlehtml: Use same-document hyperlinks for internal project references (#12551)
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> Co-authored-by: Adam Turner <9087854+aa-turner@users.noreply.github.com>
This commit is contained in:
parent
a3f138329b
commit
0bfaadf6c9
@ -54,6 +54,11 @@ Bugs fixed
|
||||
get passed to :program:`latexmk`. Let :option:`-Q <sphinx-build -Q>`
|
||||
(silent) apply as well to the PDF build phase.
|
||||
Patch by Jean-François B.
|
||||
* #11970, #12551: singlehtml builder: make target URIs to be same-document
|
||||
references in the sense of :rfc:`RFC 3986, §4.4 <3986#section-4.4>`,
|
||||
e.g., ``index.html#foo`` becomes ``#foo``.
|
||||
(note: continuation of a partial fix added in Sphinx 7.3.0)
|
||||
Patch by James Addison (with reference to prior work by Eric Norige)
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
@ -52,7 +52,6 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
||||
|
||||
def fix_refuris(self, tree: Node) -> None:
|
||||
# fix refuris with double anchor
|
||||
fname = self.config.root_doc + self.out_suffix
|
||||
for refnode in tree.findall(nodes.reference):
|
||||
if 'refuri' not in refnode:
|
||||
continue
|
||||
@ -62,7 +61,8 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
||||
continue
|
||||
hashindex = refuri.find('#', hashindex + 1)
|
||||
if hashindex >= 0:
|
||||
refnode['refuri'] = fname + refuri[hashindex:]
|
||||
# all references are on the same page...
|
||||
refnode['refuri'] = refuri[hashindex:]
|
||||
|
||||
def _get_local_toctree(self, docname: str, collapse: bool = True, **kwargs: Any) -> str:
|
||||
if isinstance(includehidden := kwargs.get('includehidden'), str):
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from tests.test_builders.xpath_html_util import _intradocument_hyperlink_check
|
||||
from tests.test_builders.xpath_util import check_xpath
|
||||
|
||||
|
||||
@ -78,6 +79,7 @@ def test_tocdepth(app, cached_etree_parse, fname, path, check, be_found):
|
||||
(".//li[@class='toctree-l3']/a", '1.2.1. Foo B1', True),
|
||||
(".//li[@class='toctree-l3']/a", '2.1.1. Bar A1', False),
|
||||
(".//li[@class='toctree-l3']/a", '2.2.1. Bar B1', False),
|
||||
(".//ul/li[@class='toctree-l1']/..//a", _intradocument_hyperlink_check),
|
||||
# index.rst
|
||||
('.//h1', 'test-tocdepth', True),
|
||||
# foo.rst
|
||||
|
@ -4,6 +4,9 @@ import re
|
||||
|
||||
import pytest
|
||||
|
||||
from tests.test_builders.xpath_html_util import _intradocument_hyperlink_check
|
||||
from tests.test_builders.xpath_util import check_xpath
|
||||
|
||||
|
||||
@pytest.mark.sphinx(testroot='toctree-glob')
|
||||
def test_relations(app):
|
||||
@ -45,3 +48,17 @@ def test_numbered_toctree(app):
|
||||
index = re.sub(':numbered:.*', ':numbered: 1', index)
|
||||
(app.srcdir / 'index.rst').write_text(index, encoding='utf8')
|
||||
app.build(force_all=True)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'expect',
|
||||
[
|
||||
# internal references should be same-document; external should not
|
||||
(".//a[@class='reference internal']", _intradocument_hyperlink_check),
|
||||
(".//a[@class='reference external']", r'https?://'),
|
||||
],
|
||||
)
|
||||
@pytest.mark.sphinx('singlehtml', testroot='toctree')
|
||||
def test_singlehtml_hyperlinks(app, cached_etree_parse, expect):
|
||||
app.build()
|
||||
check_xpath(cached_etree_parse(app.outdir / 'index.html'), 'index.html', *expect)
|
19
tests/test_builders/xpath_html_util.py
Normal file
19
tests/test_builders/xpath_html_util.py
Normal file
@ -0,0 +1,19 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Sequence
|
||||
from xml.etree.ElementTree import Element
|
||||
|
||||
|
||||
def _intradocument_hyperlink_check(nodes: Sequence[Element]) -> None:
|
||||
"""Confirm that a series of nodes are all HTML hyperlinks to the current page"""
|
||||
assert nodes, 'Expected at least one node to check'
|
||||
for node in nodes:
|
||||
assert node.tag == 'a', 'Attempted to check hyperlink on a non-anchor element'
|
||||
href = node.attrib.get('href')
|
||||
# Allow Sphinx index and table hyperlinks to be non-same-document, as exceptions.
|
||||
if href in {'genindex.html', 'py-modindex.html', 'search.html'}:
|
||||
continue
|
||||
assert not href or href.startswith('#'), 'Hyperlink failed same-document check'
|
Loading…
Reference in New Issue
Block a user