Add BibliographyTransform to restruct doctree for LaTeX

This commit is contained in:
Takeshi KOMIYA 2018-04-26 01:13:55 +09:00
parent 82a123f1d4
commit 304c208d32
7 changed files with 84 additions and 31 deletions

View File

@ -60,6 +60,7 @@ Deprecated
* ``sphinx.writers.latex.LaTeXWriter.footnotestack`` is deprecated
* ``sphinx.writers.latex.LaTeXWriter.restrict_footnote()`` is deprecated
* ``sphinx.writers.latex.LaTeXWriter.unrestrict_footnote()`` is deprecated
* ``LaTeXWriter.bibitems`` is deprecated
For more details, see `deprecation APIs list
<http://www.sphinx-doc.org/en/master/extdev/index.html#deprecated-apis>`_

View File

@ -151,6 +151,11 @@ The following is a list of deprecated interface.
- 3.0
- -
* - ``sphinx.writers.latex.LaTeXWriter.bibitems``
- 1.8
- 3.0
- Nothing
* - ``sphinx.application.CONFIG_FILENAME``
- 1.8
- 3.0

View File

@ -20,7 +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 (
FootnoteDocnameUpdater, LaTeXFootnoteTransform, ShowUrlsTransform
BibliographyTransform, FootnoteDocnameUpdater, LaTeXFootnoteTransform,
ShowUrlsTransform
)
from sphinx.config import string_classes, ENUM
from sphinx.environment import NoUri
@ -219,7 +220,8 @@ class LaTeXBuilder(Builder):
# type: (nodes.document) -> None
transformer = SphinxTransformer(doctree)
transformer.set_environment(self.env)
transformer.add_transforms([ShowUrlsTransform,
transformer.add_transforms([BibliographyTransform,
ShowUrlsTransform,
LaTeXFootnoteTransform])
transformer.apply_transforms()

View File

@ -3,7 +3,7 @@
sphinx.builders.latex.nodes
~~~~~~~~~~~~~~~~~~~~~~~~~~~
docutils nodes for LaTeX builder.
Additional nodes for LaTeX writer.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
@ -20,4 +20,8 @@ class footnotemark(nodes.Inline, nodes.Referential, nodes.TextElement):
class footnotetext(nodes.General, nodes.BackLinkable, nodes.Element,
nodes.Labeled, nodes.Targetable):
"""A node represents ``\footnotetext``."""
class thebibliography(nodes.container):
"""A node for wrapping bibliographies."""
pass

View File

@ -12,7 +12,7 @@
from docutils import nodes
from sphinx import addnodes
from sphinx.builders.latex.nodes import footnotemark, footnotetext
from sphinx.builders.latex.nodes import footnotemark, footnotetext, thebibliography
from sphinx.transforms import SphinxTransform
if False:
@ -476,3 +476,46 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
return footnote
return None
class BibliographyTransform(SphinxTransform):
"""Gather bibliography entries to tail of document.
Before::
<document>
<paragraph>
blah blah blah
<citation>
...
<paragraph>
blah blah blah
<citation>
...
...
After::
<document>
<paragraph>
blah blah blah
<paragraph>
blah blah blah
...
<thebibliography>
<citation>
...
<citation>
...
"""
default_priority = 750
def apply(self):
# type: () -> None
citations = thebibliography()
for node in self.document.traverse(nodes.citation):
node.parent.remove(node)
citations += node
if len(citations) > 0:
self.document += citations

View File

@ -590,6 +590,7 @@ class StandardDomain(Domain):
def note_citations(self, env, docname, document):
# type: (BuildEnvironment, unicode, nodes.Node) -> None
for node in document.traverse(nodes.citation):
node['docname'] = docname
label = node[0].astext()
if label in self.data['citations']:
path = env.doc2path(self.data['citations'][label][0])

View File

@ -660,7 +660,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
builder.config.pygments_style, builder.config.trim_doctest_flags)
self.context = [] # type: List[Any]
self.descstack = [] # type: List[unicode]
self.bibitems = [] # type: List[List[unicode]]
self.table = None # type: Table
self.next_table_colspec = None # type: unicode
# stack of [language, linenothreshold] settings per file
@ -902,20 +901,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
def depart_document(self, node):
# type: (nodes.Node) -> None
if self.bibitems:
widest_label = "" # type: unicode
for bi in self.bibitems:
if len(widest_label) < len(bi[0]):
widest_label = bi[0]
self.body.append(u'\n\\begin{sphinxthebibliography}{%s}\n' % widest_label)
for bi in self.bibitems:
target = self.hypertarget(bi[2] + ':' + bi[3],
withdoc=False)
self.body.append(u'\\bibitem[%s]{%s}{%s %s}\n' %
(self.encode(bi[0]), self.idescape(bi[0]),
target, bi[1]))
self.body.append(u'\\end{sphinxthebibliography}\n')
self.bibitems = []
pass
def visit_start_of_file(self, node):
# type: (nodes.Node) -> None
@ -1282,10 +1268,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_label(self, node):
# type: (nodes.Node) -> None
if isinstance(node.parent, nodes.citation):
self.bibitems[-1][0] = node.astext()
self.bibitems[-1][2] = self.curfilestack[-1]
self.bibitems[-1][3] = node.parent['ids'][0]
raise nodes.SkipNode
def visit_tabular_col_spec(self, node):
@ -2149,19 +2131,25 @@ class LaTeXTranslator(nodes.NodeVisitor):
# type: (nodes.Node) -> None
self.body.append('}')
def visit_thebibliography(self, node):
# type: (nodes.Node) -> None
longest_label = max((subnode[0].astext() for subnode in node), key=len)
self.body.append(u'\n\\begin{sphinxthebibliography}{%s}\n' % longest_label)
def depart_thebibliography(self, node):
# type: (nodes.Node) -> None
self.body.append(u'\\end{sphinxthebibliography}\n')
def visit_citation(self, node):
# type: (nodes.Node) -> None
# TODO maybe use cite bibitems
# bibitem: [citelabel, citetext, docname, citeid]
self.bibitems.append(['', '', '', ''])
self.context.append(len(self.body))
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))
def depart_citation(self, node):
# type: (nodes.Node) -> None
size = self.context.pop()
text = ''.join(self.body[size:])
del self.body[size:]
self.bibitems[-1][1] = text
self.body.append('}\n')
def visit_citation_reference(self, node):
# type: (nodes.Node) -> None
@ -2546,6 +2534,15 @@ class LaTeXTranslator(nodes.NodeVisitor):
# type: (nodes.Node) -> None
raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
# --------- METHODS FOR COMPATIBILITY --------------------------------------
@property
def bibitems(self):
# type: () -> List[List[unicode]]
warnings.warn('LaTeXTranslator.bibitems() is deprecated.',
RemovedInSphinx30Warning)
return []
# Import old modules here for compatibility
# They should be imported after `LaTeXTranslator` to avoid recursive import.