latex: Use `\cite for citation references instead \hyperref`

This commit is contained in:
Takeshi KOMIYA
2018-04-26 01:13:55 +09:00
parent 304c208d32
commit 92d8935df0
5 changed files with 47 additions and 35 deletions

View File

@@ -28,6 +28,7 @@ Incompatible changes
* #789: ``:samp:`` role supports to escape curly braces with backslash
* #4811: The files under :confval:`html_static_path` are excluded from source
files.
* latex: Use ``\cite`` for citation references instead ``\hyperref``
Deprecated
----------

View File

@@ -20,8 +20,8 @@ from six import text_type
from sphinx import package_dir, addnodes, highlighting
from sphinx.builders import Builder
from sphinx.builders.latex.transforms import (
BibliographyTransform, FootnoteDocnameUpdater, LaTeXFootnoteTransform,
ShowUrlsTransform
BibliographyTransform, CitationReferenceTransform,
FootnoteDocnameUpdater, LaTeXFootnoteTransform, ShowUrlsTransform
)
from sphinx.config import string_classes, ENUM
from sphinx.environment import NoUri
@@ -318,6 +318,7 @@ def default_latex_docclass(config):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.add_builder(LaTeXBuilder)
app.add_post_transform(CitationReferenceTransform)
app.connect('config-inited', validate_config_values)
app.add_transform(FootnoteDocnameUpdater)

View File

@@ -519,3 +519,26 @@ class BibliographyTransform(SphinxTransform):
if len(citations) > 0:
self.document += citations
class CitationReferenceTransform(SphinxTransform):
"""Replace pending_xref nodes for citation by citation_reference.
To handle citation reference easily on LaTeX writer, this converts
pending_xref nodes to citation_reference.
"""
default_priority = 5 # before ReferencesResolver
def apply(self):
# type: () -> None
if self.app.builder.name != 'latex':
return
citations = self.env.get_domain('std').data['citations']
for node in self.document.traverse(addnodes.pending_xref):
if node['refdomain'] == 'std' and node['reftype'] == 'citation':
docname, labelid, _ = citations.get(node['reftarget'], ('', '', 0))
if docname:
citation_ref = nodes.citation_reference('', *node.children,
docname=docname, refname=labelid)
node.replace_self(citation_ref)

View File

@@ -2143,9 +2143,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_citation(self, node):
# type: (nodes.Node) -> None
label = node[0].astext()
target = self.hypertarget(node['docname'] + ':' + node['ids'][0], withdoc=False)
self.body.append(u'\\bibitem[%s]{%s}{%s ' %
(self.encode(label), self.idescape(label), target))
self.body.append(u'\\bibitem[%s]{%s:%s}{' %
(self.encode(label), node['docname'], node['ids'][0]))
def depart_citation(self, node):
# type: (nodes.Node) -> None
@@ -2153,10 +2152,15 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_citation_reference(self, node):
# type: (nodes.Node) -> None
# This is currently never encountered, since citation_reference nodes
# are already replaced by pending_xref nodes in the environment.
self.body.append('\\cite{%s}' % self.idescape(node.astext()))
raise nodes.SkipNode
if self.in_title:
pass
else:
self.body.append('\\cite{%s:%s}' % (node['docname'], node['refname']))
raise nodes.SkipNode
def depart_citation_reference(self, node):
# type: (nodes.Node) -> None
pass
def visit_literal(self, node):
# type: (nodes.Node) -> None

View File

@@ -590,15 +590,9 @@ def test_footnote(app, status, warning):
assert ('\\begin{footnote}[2]\\sphinxAtStartFootnote\nauto numbered\n%\n'
'\\end{footnote}') in result
assert '\\begin{footnote}[3]\\sphinxAtStartFootnote\nnamed\n%\n\\end{footnote}' in result
assert '{\\hyperref[\\detokenize{footnote:bar}]{\\sphinxcrossref{{[}bar{]}}}}' in result
assert ('\\bibitem[bar]{\\detokenize{bar}}'
'{\\phantomsection\\label{\\detokenize{footnote:bar}} ') in result
assert ('\\bibitem[bar]{\\detokenize{bar}}'
'{\\phantomsection\\label{\\detokenize{footnote:bar}} '
'\ncite') in result
assert ('\\bibitem[bar]{\\detokenize{bar}}'
'{\\phantomsection\\label{\\detokenize{footnote:bar}} '
'\ncite\n}') in result
assert '\\cite{footnote:bar}' in result
assert ('\\bibitem[bar]{footnote:bar}'
'{\ncite\n}\n') in result
assert '\\sphinxcaption{Table caption \\sphinxfootnotemark[4]' in result
assert ('\\hline%\n\\begin{footnotetext}[4]\\sphinxAtStartFootnote\n'
'footnote in table caption\n%\n\\end{footnotetext}\\ignorespaces %\n'
@@ -620,9 +614,7 @@ def test_reference_in_caption_and_codeblock_in_footnote(app, status, warning):
print(status.getvalue())
print(warning.getvalue())
assert ('\\caption{This is the figure caption with a reference to '
'\\label{\\detokenize{index:id2}}'
'{\\hyperref[\\detokenize{index:authoryear}]'
'{\\sphinxcrossref{{[}AuthorYear{]}}}}.}' in result)
'\\cite{index:authoryear}.}' in result)
assert '\\chapter{The section with a reference to {[}AuthorYear{]}}' in result
assert ('\\sphinxcaption{The table title with a reference'
' to {[}AuthorYear{]}}' in result)
@@ -670,9 +662,7 @@ def test_latex_show_urls_is_inline(app, status, warning):
'{\\hyperref[\\detokenize{index:the-section'
'-with-a-reference-to-authoryear}]'
'{\\sphinxcrossref{The section with a reference to '
'\\phantomsection\\label{\\detokenize{index:id1}}'
'{\\hyperref[\\detokenize{index:authoryear}]'
'{\\sphinxcrossref{{[}AuthorYear{]}}}}}}}') in result
'\\cite{index:authoryear}}}}') in result
assert ('\\phantomsection\\label{\\detokenize{index:id33}}'
'{\\hyperref[\\detokenize{index:the-section-with-a-reference-to}]'
'{\\sphinxcrossref{The section with a reference to }}}' in result)
@@ -716,9 +706,7 @@ def test_latex_show_urls_is_footnote(app, status, warning):
assert ('\\phantomsection\\label{\\detokenize{index:id32}}'
'{\\hyperref[\\detokenize{index:the-section-with-a-reference-to-authoryear}]'
'{\\sphinxcrossref{The section with a reference '
'to \\phantomsection\\label{\\detokenize{index:id1}}'
'{\\hyperref[\\detokenize{index:authoryear}]'
'{\\sphinxcrossref{{[}AuthorYear{]}}}}}}}') in result
'to \\cite{index:authoryear}}}}') in result
assert ('\\phantomsection\\label{\\detokenize{index:id33}}'
'{\\hyperref[\\detokenize{index:the-section-with-a-reference-to}]'
'{\\sphinxcrossref{The section with a reference to }}}') in result
@@ -772,9 +760,7 @@ def test_latex_show_urls_is_no(app, status, warning):
assert ('\\phantomsection\\label{\\detokenize{index:id32}}'
'{\\hyperref[\\detokenize{index:the-section-with-a-reference-to-authoryear}]'
'{\\sphinxcrossref{The section with a reference '
'to \\phantomsection\\label{\\detokenize{index:id1}}'
'{\\hyperref[\\detokenize{index:authoryear}]'
'{\\sphinxcrossref{{[}AuthorYear{]}}}}}}}') in result
'to \\cite{index:authoryear}}}}') in result
assert ('\\phantomsection\\label{\\detokenize{index:id33}}'
'{\\hyperref[\\detokenize{index:the-section-with-a-reference-to}]'
'{\\sphinxcrossref{The section with a reference to }}}' in result)
@@ -1256,11 +1242,8 @@ def test_latex_thebibliography(app, status, warning):
result = (app.outdir / 'Python.tex').text(encoding='utf8')
print(result)
assert ('\\begin{sphinxthebibliography}{AuthorYear}\n'
'\\bibitem[AuthorYear]{\\detokenize{AuthorYear}}'
'{\\phantomsection\\label{\\detokenize{index:authoryear}} \n'
'\\bibitem[AuthorYear]{index:authoryear}{\n'
'Author, Title, Year\n'
'}\n'
'\\end{sphinxthebibliography}\n' in result)
assert ('{\\hyperref[\\detokenize{index:authoryear}]'
'{\\sphinxcrossref{{[}AuthorYear{]}}}}.}'
in result)
assert '\\cite{index:authoryear}' in result