From 8a273d139b74124b11c4b1ba81db3cc0866d9102 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Wed, 25 Feb 2015 15:51:47 +0100 Subject: [PATCH] Fix generating emphasis nodes without semantic reason Roles ``ref``, ``term`` and ``menusel`` now don't generate :durole:`emphasis` nodes anymore. If you want to keep italic style, adapt your stylesheet. --- CHANGES | 10 +++++++ sphinx/domains/std.py | 6 ++--- sphinx/roles.py | 2 +- sphinx/writers/latex.py | 17 +++++++----- sphinx/writers/text.py | 6 +++-- tests/test_build_html.py | 58 ++++++++++++++++++++-------------------- tests/test_markup.py | 6 ++--- 7 files changed, 61 insertions(+), 44 deletions(-) diff --git a/CHANGES b/CHANGES index 665453eac..261da9e3c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,13 @@ +Release 1.3 (in development) +============================ + +Incompatible changes +-------------------- + +* Roles ``ref``, ``term`` and ``menusel`` now don't generate :durole:`emphasis` + nodes anymore. If you want to keep italic style, adapt your stylesheet. + + Release 1.3b3 (released Feb 24, 2015) ===================================== diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py index ffe6d8bdb..40dfe4a24 100644 --- a/sphinx/domains/std.py +++ b/sphinx/domains/std.py @@ -462,10 +462,10 @@ class StandardDomain(Domain): # links to tokens in grammar productions 'token': XRefRole(), # links to terms in glossary - 'term': XRefRole(lowercase=True, innernodeclass=nodes.emphasis, + 'term': XRefRole(lowercase=True, innernodeclass=nodes.inline, warn_dangling=True), # links to headings or arbitrary labels - 'ref': XRefRole(lowercase=True, innernodeclass=nodes.emphasis, + 'ref': XRefRole(lowercase=True, innernodeclass=nodes.inline, warn_dangling=True), # links to labels of numbered figures, tables and code-blocks 'numref': XRefRole(lowercase=True, @@ -584,7 +584,7 @@ class StandardDomain(Domain): **options): nodeclass = options.pop('nodeclass', nodes.reference) newnode = nodeclass('', '', internal=True, **options) - innernode = nodes.emphasis(sectname, sectname) + innernode = nodes.inline(sectname, sectname) if docname == fromdocname: newnode['refid'] = labelid else: diff --git a/sphinx/roles.py b/sphinx/roles.py index 9af52da82..d3a73f0dd 100644 --- a/sphinx/roles.py +++ b/sphinx/roles.py @@ -243,7 +243,7 @@ def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): text = text.replace('-->', u'\N{TRIANGULAR BULLET}') spans = _amp_re.split(text) - node = nodes.emphasis(rawtext=rawtext) + node = nodes.inline(rawtext=rawtext) for i, span in enumerate(spans): span = span.replace('&&', '&') if i == 0: diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 37811a948..15eb4fc41 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -1249,11 +1249,12 @@ class LaTeXTranslator(nodes.NodeVisitor): # references to labels in the same document id = self.curfilestack[-1] + ':' + uri[1:] self.body.append(self.hyperlink(id)) + self.body.append(r'\emph{') if self.builder.config.latex_show_pagerefs and not \ self.in_production_list: - self.context.append('}} (%s)' % self.hyperpageref(id)) + self.context.append('}}} (%s)' % self.hyperpageref(id)) else: - self.context.append('}}') + self.context.append('}}}') elif uri.startswith('%'): # references to documents or labels inside documents hashindex = uri.find('#') @@ -1264,16 +1265,17 @@ class LaTeXTranslator(nodes.NodeVisitor): # reference to a label id = uri[1:].replace('#', ':') self.body.append(self.hyperlink(id)) + self.body.append(r'\emph{') if len(node) and hasattr(node[0], 'attributes') and \ 'std-term' in node[0].get('classes', []): # don't add a pageref for glossary terms - self.context.append('}}') + self.context.append('}}}') else: if self.builder.config.latex_show_pagerefs and not \ self.in_production_list: - self.context.append('}} (%s)' % self.hyperpageref(id)) + self.context.append('}}} (%s)' % self.hyperpageref(id)) else: - self.context.append('}}') + self.context.append('}}}') else: self.builder.warn('unusable reference target found: %s' % uri, (self.curfilestack[-1], node.line)) @@ -1545,7 +1547,10 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_inline(self, node): classes = node.get('classes', []) - self.body.append(r'\DUspan{%s}{' % ','.join(classes)) + if classes in [['menuselection'], ['guilabel']]: + self.body.append(r'\emph{') + else: + self.body.append(r'\DUspan{%s}{' % ','.join(classes)) def depart_inline(self, node): self.body.append('}') diff --git a/sphinx/writers/text.py b/sphinx/writers/text.py index e2e9db6f6..b9167fc66 100644 --- a/sphinx/writers/text.py +++ b/sphinx/writers/text.py @@ -823,9 +823,11 @@ class TextTranslator(nodes.NodeVisitor): pass def visit_inline(self, node): - pass + if 'xref' in node['classes'] or 'term' in node['classes']: + self.add_text('*') def depart_inline(self, node): - pass + if 'xref' in node['classes'] or 'term' in node['classes']: + self.add_text('*') def visit_container(self, node): pass diff --git a/tests/test_build_html.py b/tests/test_build_html.py index 978bee8ed..78a4eed4e 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -134,7 +134,7 @@ HTML_XPATH = { (".//li/strong", r'^program\\n$'), (".//li/em", r'^dfn\\n$'), (".//li/code/span[@class='pre']", r'^kbd\\n$'), - (".//li/em", u'File \N{TRIANGULAR BULLET} Close'), + (".//li/span", u'File \N{TRIANGULAR BULLET} Close'), (".//li/code/span[@class='pre']", '^a/$'), (".//li/code/em/span[@class='pre']", '^varpart$'), (".//li/code/em/span[@class='pre']", '^i$'), @@ -188,7 +188,7 @@ HTML_XPATH = { (".//p", 'In both.'), (".//p", 'Always present'), # tests for ``any`` role - (".//a[@href='#with']/em", 'headings'), + (".//a[@href='#with']/span", 'headings'), (".//a[@href='objects.html#func_without_body']/code/span", 'objects'), ], 'objects.html': [ @@ -247,9 +247,9 @@ HTML_XPATH = { (".//div[@class='footer']", 'Georg Brandl & Team'), (".//a[@href='http://python.org/']" "[@class='reference external']", ''), - (".//li/a[@href='genindex.html']/em", 'Index'), - (".//li/a[@href='py-modindex.html']/em", 'Module Index'), - (".//li/a[@href='search.html']/em", 'Search Page'), + (".//li/a[@href='genindex.html']/span", 'Index'), + (".//li/a[@href='py-modindex.html']/span", 'Module Index'), + (".//li/a[@href='search.html']/span", 'Search Page'), # custom sidebar only for contents (".//h4", 'Contents sidebar'), # custom JavaScript @@ -554,12 +554,12 @@ def test_numfig_without_numbered_toctree(app, status, warning): "span[@class='caption-number']", '^Listing 9 $', True), (".//div[@class='code-block-caption']/" "span[@class='caption-number']", '^Listing 10 $', True), - (".//li/a/em", '^Fig. 9$', True), - (".//li/a/em", '^Figure6$', True), - (".//li/a/em", '^Table 9$', True), - (".//li/a/em", '^Table:6$', True), - (".//li/a/em", '^Listing 9$', True), - (".//li/a/em", '^Code-6$', True), + (".//li/a/span", '^Fig. 9$', True), + (".//li/a/span", '^Figure6$', True), + (".//li/a/span", '^Table 9$', True), + (".//li/a/span", '^Table:6$', True), + (".//li/a/span", '^Listing 9$', True), + (".//li/a/span", '^Code-6$', True), ], 'foo.html': [ (".//div[@class='figure']/p[@class='caption']/" @@ -649,12 +649,12 @@ def test_numfig_with_numbered_toctree(app, status, warning): "span[@class='caption-number']", '^Listing 1 $', True), (".//div[@class='code-block-caption']/" "span[@class='caption-number']", '^Listing 2 $', True), - (".//li/a/em", '^Fig. 1$', True), - (".//li/a/em", '^Figure2.2$', True), - (".//li/a/em", '^Table 1$', True), - (".//li/a/em", '^Table:2.2$', True), - (".//li/a/em", '^Listing 1$', True), - (".//li/a/em", '^Code-2.2$', True), + (".//li/a/span", '^Fig. 1$', True), + (".//li/a/span", '^Figure2.2$', True), + (".//li/a/span", '^Table 1$', True), + (".//li/a/span", '^Table:2.2$', True), + (".//li/a/span", '^Listing 1$', True), + (".//li/a/span", '^Code-2.2$', True), ], 'foo.html': [ (".//div[@class='figure']/p[@class='caption']/" @@ -747,12 +747,12 @@ def test_numfig_with_prefix(app, status, warning): "span[@class='caption-number']", '^Code-1 $', True), (".//div[@class='code-block-caption']/" "span[@class='caption-number']", '^Code-2 $', True), - (".//li/a/em", '^Figure:1$', True), - (".//li/a/em", '^Figure2.2$', True), - (".//li/a/em", '^Tab_1$', True), - (".//li/a/em", '^Table:2.2$', True), - (".//li/a/em", '^Code-1$', True), - (".//li/a/em", '^Code-2.2$', True), + (".//li/a/span", '^Figure:1$', True), + (".//li/a/span", '^Figure2.2$', True), + (".//li/a/span", '^Tab_1$', True), + (".//li/a/span", '^Table:2.2$', True), + (".//li/a/span", '^Code-1$', True), + (".//li/a/span", '^Code-2.2$', True), ], 'foo.html': [ (".//div[@class='figure']/p[@class='caption']/" @@ -842,12 +842,12 @@ def test_numfig_with_secnum_depth(app, status, warning): "span[@class='caption-number']", '^Listing 1 $', True), (".//div[@class='code-block-caption']/" "span[@class='caption-number']", '^Listing 2 $', True), - (".//li/a/em", '^Fig. 1$', True), - (".//li/a/em", '^Figure2.1.2$', True), - (".//li/a/em", '^Table 1$', True), - (".//li/a/em", '^Table:2.1.2$', True), - (".//li/a/em", '^Listing 1$', True), - (".//li/a/em", '^Code-2.1.2$', True), + (".//li/a/span", '^Fig. 1$', True), + (".//li/a/span", '^Figure2.1.2$', True), + (".//li/a/span", '^Table 1$', True), + (".//li/a/span", '^Table:2.1.2$', True), + (".//li/a/span", '^Listing 1$', True), + (".//li/a/span", '^Code-2.1.2$', True), ], 'foo.html': [ (".//div[@class='figure']/p[@class='caption']/" diff --git a/tests/test_markup.py b/tests/test_markup.py index d282d236d..e741571fb 100644 --- a/tests/test_markup.py +++ b/tests/test_markup.py @@ -102,13 +102,13 @@ def test_inline(): # interpolation of arrows in menuselection yield (verify, ':menuselection:`a --> b`', - u'

a \N{TRIANGULAR BULLET} b

', + u'

a \N{TRIANGULAR BULLET} b

', '\\emph{a \\(\\rightarrow\\) b}') # interpolation of ampersands in guilabel/menuselection yield (verify, ':guilabel:`&Foo -&&- &Bar`', - u'

Foo ' - '-&- Bar

', + u'

Foo ' + '-&- Bar

', r'\emph{\DUspan{accelerator}{F}oo -\&- \DUspan{accelerator}{B}ar}') # non-interpolation of dashes in option role