mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Refactor: Add captioned_literal_block node to simplify LaTeX writer
This commit is contained in:
parent
51962c715c
commit
489d86d470
6
CHANGES
6
CHANGES
@ -64,9 +64,13 @@ Deprecated
|
|||||||
* ``sphinx.writers.latex.Table.caption_footnotetexts`` is deprecated
|
* ``sphinx.writers.latex.Table.caption_footnotetexts`` is deprecated
|
||||||
* ``sphinx.writers.latex.Table.header_footnotetexts`` is deprecated
|
* ``sphinx.writers.latex.Table.header_footnotetexts`` is deprecated
|
||||||
* ``sphinx.writers.latex.LaTeXWriter.footnotestack`` is deprecated
|
* ``sphinx.writers.latex.LaTeXWriter.footnotestack`` is deprecated
|
||||||
|
* ``sphinx.writers.latex.LaTeXWriter.in_container_literal_block`` is deprecated
|
||||||
|
* ``sphinx.writers.latex.LaTeXWriter.next_hyperlink_ids`` is deprecated
|
||||||
* ``sphinx.writers.latex.LaTeXWriter.restrict_footnote()`` is deprecated
|
* ``sphinx.writers.latex.LaTeXWriter.restrict_footnote()`` is deprecated
|
||||||
* ``sphinx.writers.latex.LaTeXWriter.unrestrict_footnote()`` is deprecated
|
* ``sphinx.writers.latex.LaTeXWriter.unrestrict_footnote()`` is deprecated
|
||||||
* ``LaTeXWriter.bibitems`` is deprecated
|
* ``sphinx.writers.latex.LaTeXWriter.push_hyperlink_ids()`` is deprecated
|
||||||
|
* ``sphinx.writers.latex.LaTeXWriter.pop_hyperlink_ids()`` is deprecated
|
||||||
|
* ``sphinx.writers.latex.LaTeXWriter.bibitems`` is deprecated
|
||||||
* ``BuildEnvironment.load()`` is deprecated
|
* ``BuildEnvironment.load()`` is deprecated
|
||||||
* ``BuildEnvironment.loads()`` is deprecated
|
* ``BuildEnvironment.loads()`` is deprecated
|
||||||
* ``BuildEnvironment.frompickle()`` is deprecated
|
* ``BuildEnvironment.frompickle()`` is deprecated
|
||||||
|
@ -171,6 +171,16 @@ The following is a list of deprecated interface.
|
|||||||
- 3.0
|
- 3.0
|
||||||
- N/A
|
- N/A
|
||||||
|
|
||||||
|
* - ``sphinx.writers.latex.LaTeXWriter.in_container_literal_block``
|
||||||
|
- 1.8
|
||||||
|
- 3.0
|
||||||
|
- N/A
|
||||||
|
|
||||||
|
* - ``sphinx.writers.latex.LaTeXWriter.next_hyperlink_ids``
|
||||||
|
- 1.8
|
||||||
|
- 3.0
|
||||||
|
- N/A
|
||||||
|
|
||||||
* - ``sphinx.writers.latex.LaTeXWriter.restrict_footnote()``
|
* - ``sphinx.writers.latex.LaTeXWriter.restrict_footnote()``
|
||||||
- 1.8
|
- 1.8
|
||||||
- 3.0
|
- 3.0
|
||||||
@ -181,6 +191,16 @@ The following is a list of deprecated interface.
|
|||||||
- 3.0
|
- 3.0
|
||||||
- N/A
|
- N/A
|
||||||
|
|
||||||
|
* - ``sphinx.writers.latex.LaTeXWriter.push_hyperlink_ids()``
|
||||||
|
- 1.8
|
||||||
|
- 3.0
|
||||||
|
- N/A
|
||||||
|
|
||||||
|
* - ``sphinx.writers.latex.LaTeXWriter.pop_hyperlink_ids()``
|
||||||
|
- 1.8
|
||||||
|
- 3.0
|
||||||
|
- N/A
|
||||||
|
|
||||||
* - ``sphinx.writers.latex.LaTeXWriter.bibitems``
|
* - ``sphinx.writers.latex.LaTeXWriter.bibitems``
|
||||||
- 1.8
|
- 1.8
|
||||||
- 3.0
|
- 3.0
|
||||||
|
@ -20,7 +20,8 @@ from sphinx import package_dir, addnodes, highlighting
|
|||||||
from sphinx.builders import Builder
|
from sphinx.builders import Builder
|
||||||
from sphinx.builders.latex.transforms import (
|
from sphinx.builders.latex.transforms import (
|
||||||
BibliographyTransform, CitationReferenceTransform, MathReferenceTransform,
|
BibliographyTransform, CitationReferenceTransform, MathReferenceTransform,
|
||||||
FootnoteDocnameUpdater, LaTeXFootnoteTransform, ShowUrlsTransform
|
FootnoteDocnameUpdater, LaTeXFootnoteTransform, LiteralBlockTransform,
|
||||||
|
ShowUrlsTransform,
|
||||||
)
|
)
|
||||||
from sphinx.config import string_classes, ENUM
|
from sphinx.config import string_classes, ENUM
|
||||||
from sphinx.environment import NoUri
|
from sphinx.environment import NoUri
|
||||||
@ -223,7 +224,8 @@ class LaTeXBuilder(Builder):
|
|||||||
transformer.set_environment(self.env)
|
transformer.set_environment(self.env)
|
||||||
transformer.add_transforms([BibliographyTransform,
|
transformer.add_transforms([BibliographyTransform,
|
||||||
ShowUrlsTransform,
|
ShowUrlsTransform,
|
||||||
LaTeXFootnoteTransform])
|
LaTeXFootnoteTransform,
|
||||||
|
LiteralBlockTransform])
|
||||||
transformer.apply_transforms()
|
transformer.apply_transforms()
|
||||||
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
|
@ -12,6 +12,11 @@
|
|||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
|
|
||||||
|
|
||||||
|
class captioned_literal_block(nodes.container):
|
||||||
|
"""A node for a container of literal_block having a caption."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class footnotemark(nodes.Inline, nodes.Referential, nodes.TextElement):
|
class footnotemark(nodes.Inline, nodes.Referential, nodes.TextElement):
|
||||||
"""A node represents ``\footnotemark``."""
|
"""A node represents ``\footnotemark``."""
|
||||||
pass
|
pass
|
||||||
|
@ -13,7 +13,7 @@ from docutils import nodes
|
|||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx.builders.latex.nodes import (
|
from sphinx.builders.latex.nodes import (
|
||||||
footnotemark, footnotetext, math_reference, thebibliography
|
captioned_literal_block, footnotemark, footnotetext, math_reference, thebibliography
|
||||||
)
|
)
|
||||||
from sphinx.transforms import SphinxTransform
|
from sphinx.transforms import SphinxTransform
|
||||||
|
|
||||||
@ -566,3 +566,18 @@ class MathReferenceTransform(SphinxTransform):
|
|||||||
if docname:
|
if docname:
|
||||||
refnode = math_reference('', docname=docname, target=node['reftarget'])
|
refnode = math_reference('', docname=docname, target=node['reftarget'])
|
||||||
node.replace_self(refnode)
|
node.replace_self(refnode)
|
||||||
|
|
||||||
|
|
||||||
|
class LiteralBlockTransform(SphinxTransform):
|
||||||
|
"""Replace container nodes for literal_block by captioned_literal_block."""
|
||||||
|
default_priority = 400
|
||||||
|
|
||||||
|
def apply(self):
|
||||||
|
# type: () -> None
|
||||||
|
if self.app.builder.name != 'latex':
|
||||||
|
return
|
||||||
|
|
||||||
|
for node in self.document.traverse(nodes.container):
|
||||||
|
if node['literal_block'] is True:
|
||||||
|
newnode = captioned_literal_block('', *node.children, **node.attributes)
|
||||||
|
node.replace_self(newnode)
|
||||||
|
@ -25,7 +25,7 @@ from six import itervalues, text_type
|
|||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx import highlighting
|
from sphinx import highlighting
|
||||||
from sphinx.builders.latex.nodes import footnotetext
|
from sphinx.builders.latex.nodes import captioned_literal_block, footnotetext
|
||||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||||
from sphinx.errors import SphinxError
|
from sphinx.errors import SphinxError
|
||||||
from sphinx.locale import admonitionlabels, _, __
|
from sphinx.locale import admonitionlabels, _, __
|
||||||
@ -58,6 +58,7 @@ HYPERLINK_SUPPORT_NODES = (
|
|||||||
nodes.literal_block,
|
nodes.literal_block,
|
||||||
nodes.table,
|
nodes.table,
|
||||||
nodes.section,
|
nodes.section,
|
||||||
|
captioned_literal_block,
|
||||||
)
|
)
|
||||||
|
|
||||||
DEFAULT_SETTINGS = {
|
DEFAULT_SETTINGS = {
|
||||||
@ -465,7 +466,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
self.in_production_list = 0
|
self.in_production_list = 0
|
||||||
self.in_footnote = 0
|
self.in_footnote = 0
|
||||||
self.in_caption = 0
|
self.in_caption = 0
|
||||||
self.in_container_literal_block = 0
|
|
||||||
self.in_term = 0
|
self.in_term = 0
|
||||||
self.needs_linetrimming = 0
|
self.needs_linetrimming = 0
|
||||||
self.in_minipage = 0
|
self.in_minipage = 0
|
||||||
@ -691,7 +691,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
self.pending_footnotes = [] # type: List[nodes.footnote_reference]
|
self.pending_footnotes = [] # type: List[nodes.footnote_reference]
|
||||||
self.curfilestack = [] # type: List[unicode]
|
self.curfilestack = [] # type: List[unicode]
|
||||||
self.handled_abbrs = set() # type: Set[unicode]
|
self.handled_abbrs = set() # type: Set[unicode]
|
||||||
self.next_hyperlink_ids = {} # type: Dict[unicode, Set[unicode]]
|
|
||||||
self.next_section_ids = set() # type: Set[unicode]
|
self.next_section_ids = set() # type: Set[unicode]
|
||||||
|
|
||||||
def pushbody(self, newbody):
|
def pushbody(self, newbody):
|
||||||
@ -705,15 +704,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
self.body = self.bodystack.pop()
|
self.body = self.bodystack.pop()
|
||||||
return body
|
return body
|
||||||
|
|
||||||
def push_hyperlink_ids(self, figtype, ids):
|
|
||||||
# type: (unicode, Set[unicode]) -> None
|
|
||||||
hyperlink_ids = self.next_hyperlink_ids.setdefault(figtype, set())
|
|
||||||
hyperlink_ids.update(ids)
|
|
||||||
|
|
||||||
def pop_hyperlink_ids(self, figtype):
|
|
||||||
# type: (unicode) -> Set[unicode]
|
|
||||||
return self.next_hyperlink_ids.pop(figtype, set())
|
|
||||||
|
|
||||||
def check_latex_elements(self):
|
def check_latex_elements(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
for key in self.builder.config.latex_elements:
|
for key in self.builder.config.latex_elements:
|
||||||
@ -1790,7 +1780,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
def visit_caption(self, node):
|
def visit_caption(self, node):
|
||||||
# type: (nodes.Node) -> None
|
# type: (nodes.Node) -> None
|
||||||
self.in_caption += 1
|
self.in_caption += 1
|
||||||
if self.in_container_literal_block:
|
if isinstance(node.parent, captioned_literal_block):
|
||||||
self.body.append('\\sphinxSetupCaptionForVerbatim{')
|
self.body.append('\\sphinxSetupCaptionForVerbatim{')
|
||||||
elif self.in_minipage and isinstance(node.parent, nodes.figure):
|
elif self.in_minipage and isinstance(node.parent, nodes.figure):
|
||||||
self.body.append('\\captionof{figure}{')
|
self.body.append('\\captionof{figure}{')
|
||||||
@ -1883,35 +1873,13 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
self.body.append(self.hypertarget(id, anchor=anchor))
|
self.body.append(self.hypertarget(id, anchor=anchor))
|
||||||
|
|
||||||
# skip if visitor for next node supports hyperlink
|
# skip if visitor for next node supports hyperlink
|
||||||
|
domain = self.builder.env.get_domain('std')
|
||||||
next_node = node.next_node(ascend=True)
|
next_node = node.next_node(ascend=True)
|
||||||
if isinstance(next_node, HYPERLINK_SUPPORT_NODES):
|
if isinstance(next_node, HYPERLINK_SUPPORT_NODES):
|
||||||
return
|
return
|
||||||
|
elif domain.get_enumerable_node_type(next_node) and domain.get_numfig_title(next_node):
|
||||||
|
return
|
||||||
|
|
||||||
# postpone the labels until after the sectioning command
|
|
||||||
parindex = node.parent.index(node)
|
|
||||||
try:
|
|
||||||
try:
|
|
||||||
next = node.parent[parindex + 1]
|
|
||||||
except IndexError:
|
|
||||||
# last node in parent, look at next after parent
|
|
||||||
# (for section of equal level) if it exists
|
|
||||||
if node.parent.parent is not None:
|
|
||||||
next = node.parent.parent[
|
|
||||||
node.parent.parent.index(node.parent)]
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
domain = self.builder.env.get_domain('std')
|
|
||||||
figtype = domain.get_enumerable_node_type(next)
|
|
||||||
if figtype and domain.get_numfig_title(next):
|
|
||||||
ids = set()
|
|
||||||
# labels for figures go in the figure body, not before
|
|
||||||
if node.get('refid'):
|
|
||||||
ids.add(node['refid'])
|
|
||||||
ids.update(node['ids'])
|
|
||||||
self.push_hyperlink_ids(figtype, ids)
|
|
||||||
return
|
|
||||||
except IndexError:
|
|
||||||
pass
|
|
||||||
if 'refuri' in node:
|
if 'refuri' in node:
|
||||||
return
|
return
|
||||||
if node.get('refid'):
|
if node.get('refid'):
|
||||||
@ -2221,6 +2189,14 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
# the \ignorespaces in particular for after table header use
|
# the \ignorespaces in particular for after table header use
|
||||||
self.body.append('%\n\\end{footnotetext}\\ignorespaces ')
|
self.body.append('%\n\\end{footnotetext}\\ignorespaces ')
|
||||||
|
|
||||||
|
def visit_captioned_literal_block(self, node):
|
||||||
|
# type: (nodes.Node) -> None
|
||||||
|
pass
|
||||||
|
|
||||||
|
def depart_captioned_literal_block(self, node):
|
||||||
|
# type: (nodes.Node) -> None
|
||||||
|
pass
|
||||||
|
|
||||||
def visit_literal_block(self, node):
|
def visit_literal_block(self, node):
|
||||||
# type: (nodes.Node) -> None
|
# type: (nodes.Node) -> None
|
||||||
if node.rawsource != node.astext():
|
if node.rawsource != node.astext():
|
||||||
@ -2229,9 +2205,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
self.body.append('\\begin{sphinxalltt}\n')
|
self.body.append('\\begin{sphinxalltt}\n')
|
||||||
else:
|
else:
|
||||||
labels = self.hypertarget_to(node)
|
labels = self.hypertarget_to(node)
|
||||||
# LaTeX code will insert \phantomsection prior to \label
|
if isinstance(node.parent, captioned_literal_block):
|
||||||
|
labels += self.hypertarget_to(node.parent)
|
||||||
if labels and not self.in_footnote:
|
if labels and not self.in_footnote:
|
||||||
self.body.append('\n\\def\\sphinxLiteralBlockLabel{' + labels + '}')
|
self.body.append('\n\\def\\sphinxLiteralBlockLabel{' + labels + '}')
|
||||||
|
|
||||||
code = node.astext()
|
code = node.astext()
|
||||||
lang = self.hlsettingstack[-1][0]
|
lang = self.hlsettingstack[-1][0]
|
||||||
linenos = code.count('\n') >= self.hlsettingstack[-1][1] - 1
|
linenos = code.count('\n') >= self.hlsettingstack[-1][1] - 1
|
||||||
@ -2458,22 +2436,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
|
|
||||||
def visit_container(self, node):
|
def visit_container(self, node):
|
||||||
# type: (nodes.Node) -> None
|
# type: (nodes.Node) -> None
|
||||||
if node.get('literal_block'):
|
pass
|
||||||
self.in_container_literal_block += 1
|
|
||||||
ids = '' # type: unicode
|
|
||||||
for id in self.pop_hyperlink_ids('code-block'):
|
|
||||||
ids += self.hypertarget(id, anchor=False)
|
|
||||||
if node['ids']:
|
|
||||||
# suppress with anchor=False \phantomsection insertion
|
|
||||||
ids += self.hypertarget(node['ids'][0], anchor=False)
|
|
||||||
# define label for use in caption.
|
|
||||||
if ids:
|
|
||||||
self.body.append('\n\\def\\sphinxLiteralBlockLabel{' + ids + '}\n')
|
|
||||||
|
|
||||||
def depart_container(self, node):
|
def depart_container(self, node):
|
||||||
# type: (nodes.Node) -> None
|
# type: (nodes.Node) -> None
|
||||||
if node.get('literal_block'):
|
pass
|
||||||
self.in_container_literal_block -= 1
|
|
||||||
|
|
||||||
def visit_decoration(self, node):
|
def visit_decoration(self, node):
|
||||||
# type: (nodes.Node) -> None
|
# type: (nodes.Node) -> None
|
||||||
@ -2603,6 +2570,32 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
RemovedInSphinx30Warning)
|
RemovedInSphinx30Warning)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def in_container_literal_block(self):
|
||||||
|
# type: () -> int
|
||||||
|
warnings.warn('LaTeXTranslator.in_container_literal_block is deprecated.',
|
||||||
|
RemovedInSphinx30Warning)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def next_hyperlink_ids(self):
|
||||||
|
# type: () -> Dict
|
||||||
|
warnings.warn('LaTeXTranslator.next_hyperlink_ids is deprecated.',
|
||||||
|
RemovedInSphinx30Warning)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def push_hyperlink_ids(self, figtype, ids):
|
||||||
|
# type: (unicode, Set[unicode]) -> None
|
||||||
|
warnings.warn('LaTeXTranslator.push_hyperlink_ids() is deprecated.',
|
||||||
|
RemovedInSphinx30Warning)
|
||||||
|
pass
|
||||||
|
|
||||||
|
def pop_hyperlink_ids(self, figtype):
|
||||||
|
# type: (unicode) -> Set[unicode]
|
||||||
|
warnings.warn('LaTeXTranslator.pop_hyperlink_ids() is deprecated.',
|
||||||
|
RemovedInSphinx30Warning)
|
||||||
|
return set()
|
||||||
|
|
||||||
|
|
||||||
# Import old modules here for compatibility
|
# Import old modules here for compatibility
|
||||||
# They should be imported after `LaTeXTranslator` to avoid recursive import.
|
# They should be imported after `LaTeXTranslator` to avoid recursive import.
|
||||||
|
Loading…
Reference in New Issue
Block a user