From fbfaf41e8309580b51ee0bb78e6f46ebcaf30633 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 29 Feb 2020 17:21:48 +0900 Subject: [PATCH 1/2] std domain: Generate node_id for generic objects in the right way --- sphinx/domains/std.py | 25 ++++++++++++++++++++----- tests/test_build_epub.py | 10 +++++++--- tests/test_build_html.py | 2 +- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py index abf3be71607..d7239f79d78 100644 --- a/sphinx/domains/std.py +++ b/sphinx/domains/std.py @@ -66,9 +66,17 @@ def handle_signature(self, sig: str, signode: desc_signature) -> str: return name def add_target_and_index(self, name: str, sig: str, signode: desc_signature) -> None: - targetname = '%s-%s' % (self.objtype, name) - signode['ids'].append(targetname) + node_id = make_id(self.env, self.state.document, self.objtype, name) + signode['ids'].append(node_id) + + # Assign old styled node_id not to break old hyperlinks (if possible) + # Note: Will be removed in Sphinx-5.0 (RemovedInSphinx50Warning) + old_node_id = self.make_old_id(name) + if old_node_id not in self.state.document.ids and old_node_id not in signode['ids']: + signode['ids'].append(old_node_id) + self.state.document.note_explicit_target(signode) + if self.indextemplate: colon = self.indextemplate.find(':') if colon != -1: @@ -77,11 +85,18 @@ def add_target_and_index(self, name: str, sig: str, signode: desc_signature) -> else: indextype = 'single' indexentry = self.indextemplate % (name,) - self.indexnode['entries'].append((indextype, indexentry, - targetname, '', None)) + self.indexnode['entries'].append((indextype, indexentry, node_id, '', None)) std = cast(StandardDomain, self.env.get_domain('std')) - std.note_object(self.objtype, name, targetname, location=signode) + std.note_object(self.objtype, name, node_id, location=signode) + + def make_old_id(self, name: str) -> str: + """Generate old styled node_id for generic objects. + + .. note:: Old Styled node_id was used until Sphinx-3.0. + This will be removed in Sphinx-5.0. + """ + return self.objtype + '-' + name class EnvVar(GenericObject): diff --git a/tests/test_build_epub.py b/tests/test_build_epub.py index a5780b04f9b..a61c3cbbb60 100644 --- a/tests/test_build_epub.py +++ b/tests/test_build_epub.py @@ -320,9 +320,13 @@ def test_epub_anchor_id(app): app.build() html = (app.outdir / 'index.xhtml').read_text() - assert '

blah blah blah

' in html - assert '

blah blah blah

' in html - assert 'see ' in html + assert ('

' + '' + 'blah blah blah

' in html) + assert ('' + '' + '

blah blah blah

' in html) + assert 'see
' in html @pytest.mark.sphinx('epub', testroot='html_assets') diff --git a/tests/test_build_html.py b/tests/test_build_html.py index c53d0b97d9b..4c2618af9a9 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -218,7 +218,7 @@ def test_html4_output(app, status, warning): "[@class='rfc reference external']/strong", 'RFC 1'), (".//a[@href='https://tools.ietf.org/html/rfc1.html']" "[@class='rfc reference external']/strong", 'Request for Comments #1'), - (".//a[@href='objects.html#envvar-HOME']" + (".//a[@href='objects.html#envvar-home']" "[@class='reference internal']/code/span[@class='pre']", 'HOME'), (".//a[@href='#with']" "[@class='reference internal']/code/span[@class='pre']", '^with$'), From dfb2d6407ecb720ee1fc07f5e37ef1f920972e69 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 29 Feb 2020 17:23:55 +0900 Subject: [PATCH 2/2] std domain: Generate node_id for targets in the right way --- sphinx/domains/std.py | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py index d7239f79d78..dcf72efe8f0 100644 --- a/sphinx/domains/std.py +++ b/sphinx/domains/std.py @@ -139,9 +139,16 @@ class Target(SphinxDirective): def run(self) -> List[Node]: # normalize whitespace in fullname like XRefRole does fullname = ws_re.sub(' ', self.arguments[0].strip()) - targetname = '%s-%s' % (self.name, fullname) - node = nodes.target('', '', ids=[targetname]) + node_id = make_id(self.env, self.state.document, self.name, fullname) + node = nodes.target('', '', ids=[node_id]) self.set_source_info(node) + + # Assign old styled node_id not to break old hyperlinks (if possible) + # Note: Will be removed in Sphinx-5.0 (RemovedInSphinx50Warning) + old_node_id = self.make_old_id(fullname) + if old_node_id not in self.state.document.ids and old_node_id not in node['ids']: + node['ids'].append(old_node_id) + self.state.document.note_explicit_target(node) ret = [node] # type: List[Node] if self.indextemplate: @@ -151,18 +158,25 @@ def run(self) -> List[Node]: if colon != -1: indextype = indexentry[:colon].strip() indexentry = indexentry[colon + 1:].strip() - inode = addnodes.index(entries=[(indextype, indexentry, - targetname, '', None)]) + inode = addnodes.index(entries=[(indextype, indexentry, node_id, '', None)]) ret.insert(0, inode) name = self.name if ':' in self.name: _, name = self.name.split(':', 1) std = cast(StandardDomain, self.env.get_domain('std')) - std.note_object(name, fullname, targetname, location=node) + std.note_object(name, fullname, node_id, location=node) return ret + def make_old_id(self, name: str) -> str: + """Generate old styled node_id for targets. + + .. note:: Old Styled node_id was used until Sphinx-3.0. + This will be removed in Sphinx-5.0. + """ + return self.name + '-' + name + class Cmdoption(ObjectDescription): """