summaryrefslogtreecommitdiffstats
path: root/sphinx/builders/latex
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-05 16:20:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-05 16:20:58 +0000
commit5bb0bb4be543fd5eca41673696a62ed80d493591 (patch)
treead2c464f140e86c7f178a6276d7ea4a93e3e6c92 /sphinx/builders/latex
parentAdding upstream version 7.2.6. (diff)
downloadsphinx-upstream.tar.xz
sphinx-upstream.zip
Adding upstream version 7.3.7.upstream/7.3.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sphinx/builders/latex')
-rw-r--r--sphinx/builders/latex/__init__.py73
-rw-r--r--sphinx/builders/latex/nodes.py8
-rw-r--r--sphinx/builders/latex/transforms.py25
-rw-r--r--sphinx/builders/latex/util.py2
4 files changed, 64 insertions, 44 deletions
diff --git a/sphinx/builders/latex/__init__.py b/sphinx/builders/latex/__init__.py
index 3ece571..2b176f9 100644
--- a/sphinx/builders/latex/__init__.py
+++ b/sphinx/builders/latex/__init__.py
@@ -9,7 +9,7 @@ from typing import TYPE_CHECKING, Any
from docutils.frontend import OptionParser
-import sphinx.builders.latex.nodes # noqa: F401,E501 # Workaround: import this before writer to avoid ImportError
+import sphinx.builders.latex.nodes # NoQA: F401,E501 # Workaround: import this before writer to avoid ImportError
from sphinx import addnodes, highlighting, package_dir
from sphinx.builders import Builder
from sphinx.builders.latex.constants import ADDITIONAL_SETTINGS, DEFAULT_SETTINGS, SHORTHANDOFF
@@ -20,7 +20,7 @@ from sphinx.environment.adapters.asset import ImageAdapter
from sphinx.errors import NoUri, SphinxError
from sphinx.locale import _, __
from sphinx.util import logging, texescape
-from sphinx.util.console import bold, darkgreen # type: ignore[attr-defined]
+from sphinx.util.console import bold, darkgreen
from sphinx.util.display import progress_message, status_iterator
from sphinx.util.docutils import SphinxFileOutput, new_document
from sphinx.util.fileutil import copy_asset_file
@@ -39,6 +39,7 @@ if TYPE_CHECKING:
from docutils.nodes import Node
from sphinx.application import Sphinx
+ from sphinx.util.typing import ExtensionMetadata
XINDY_LANG_OPTIONS = {
# language codes from docutils.writers.latex2e.Babel
@@ -108,6 +109,7 @@ class LaTeXBuilder(Builder):
"""
Builds LaTeX output to create PDF.
"""
+
name = 'latex'
format = 'latex'
epilog = __('The LaTeX files are in %(outdir)s.')
@@ -215,15 +217,18 @@ class LaTeXBuilder(Builder):
if self.context['latex_engine'] == 'pdflatex':
if not self.babel.uses_cyrillic():
if 'X2' in self.context['fontenc']:
- self.context['substitutefont'] = '\\usepackage{substitutefont}'
+ self.context['substitutefont'] = ('\\usepackage'
+ '{sphinxpackagesubstitutefont}')
self.context['textcyrillic'] = ('\\usepackage[Xtwo]'
'{sphinxpackagecyrillic}')
elif 'T2A' in self.context['fontenc']:
- self.context['substitutefont'] = '\\usepackage{substitutefont}'
+ self.context['substitutefont'] = ('\\usepackage'
+ '{sphinxpackagesubstitutefont}')
self.context['textcyrillic'] = ('\\usepackage[TtwoA]'
'{sphinxpackagecyrillic}')
if 'LGR' in self.context['fontenc']:
- self.context['substitutefont'] = '\\usepackage{substitutefont}'
+ self.context['substitutefont'] = ('\\usepackage'
+ '{sphinxpackagesubstitutefont}')
else:
self.context['textgreek'] = ''
if self.context['substitutefont'] == '':
@@ -338,7 +343,7 @@ class LaTeXBuilder(Builder):
def assemble_doctree(
self, indexfile: str, toctree_only: bool, appendices: list[str],
) -> nodes.document:
- self.docnames = set([indexfile] + appendices)
+ self.docnames = {indexfile, *appendices}
logger.info(darkgreen(indexfile) + " ", nonl=True)
tree = self.env.get_doctree(indexfile)
tree['docname'] = indexfile
@@ -371,9 +376,11 @@ class LaTeXBuilder(Builder):
newnodes: list[Node] = [nodes.emphasis(sectname, sectname)]
for subdir, title in self.titles:
if docname.startswith(subdir):
- newnodes.append(nodes.Text(_(' (in ')))
- newnodes.append(nodes.emphasis(title, title))
- newnodes.append(nodes.Text(')'))
+ newnodes.extend((
+ nodes.Text(_(' (in ')),
+ nodes.emphasis(title, title),
+ nodes.Text(')'),
+ ))
break
else:
pass
@@ -386,7 +393,7 @@ class LaTeXBuilder(Builder):
@progress_message(__('copying TeX support files'))
def copy_support_files(self) -> None:
- """copy TeX support files from texinputs."""
+ """Copy TeX support files from texinputs."""
# configure usage of xindy (impacts Makefile and latexmkrc)
# FIXME: convert this rather to a confval with suitable default
# according to language ? but would require extra documentation
@@ -476,7 +483,7 @@ def install_packages_for_ja(app: Sphinx) -> None:
def default_latex_engine(config: Config) -> str:
- """ Better default latex_engine settings for specific languages. """
+ """Better default latex_engine settings for specific languages."""
if config.language == 'ja':
return 'uplatex'
if config.language.startswith('zh'):
@@ -487,7 +494,7 @@ def default_latex_engine(config: Config) -> str:
def default_latex_docclass(config: Config) -> dict[str, str]:
- """ Better default latex_docclass settings for specific languages. """
+ """Better default latex_docclass settings for specific languages."""
if config.language == 'ja':
if config.latex_engine == 'uplatex':
return {'manual': 'ujbook',
@@ -500,12 +507,12 @@ def default_latex_docclass(config: Config) -> dict[str, str]:
def default_latex_use_xindy(config: Config) -> bool:
- """ Better default latex_use_xindy settings for specific engines. """
+ """Better default latex_use_xindy settings for specific engines."""
return config.latex_engine in {'xelatex', 'lualatex'}
def default_latex_documents(config: Config) -> list[tuple[str, str, str, str, str]]:
- """ Better default latex_documents settings. """
+ """Better default latex_documents settings."""
project = texescape.escape(config.project, config.latex_engine)
author = texescape.escape(config.author, config.latex_engine)
return [(config.root_doc,
@@ -515,7 +522,7 @@ def default_latex_documents(config: Config) -> list[tuple[str, str, str, str, st
config.latex_theme)]
-def setup(app: Sphinx) -> dict[str, Any]:
+def setup(app: Sphinx) -> ExtensionMetadata:
app.setup_extension('sphinx.builders.latex.transforms')
app.add_builder(LaTeXBuilder)
@@ -523,26 +530,26 @@ def setup(app: Sphinx) -> dict[str, Any]:
app.connect('config-inited', validate_latex_theme_options, priority=800)
app.connect('builder-inited', install_packages_for_ja)
- app.add_config_value('latex_engine', default_latex_engine, False,
+ app.add_config_value('latex_engine', default_latex_engine, '',
ENUM('pdflatex', 'xelatex', 'lualatex', 'platex', 'uplatex'))
- app.add_config_value('latex_documents', default_latex_documents, False)
- app.add_config_value('latex_logo', None, False, [str])
- app.add_config_value('latex_appendices', [], False)
- app.add_config_value('latex_use_latex_multicolumn', False, False)
- app.add_config_value('latex_use_xindy', default_latex_use_xindy, False, [bool])
- app.add_config_value('latex_toplevel_sectioning', None, False,
+ app.add_config_value('latex_documents', default_latex_documents, '')
+ app.add_config_value('latex_logo', None, '', str)
+ app.add_config_value('latex_appendices', [], '')
+ app.add_config_value('latex_use_latex_multicolumn', False, '')
+ app.add_config_value('latex_use_xindy', default_latex_use_xindy, '', bool)
+ app.add_config_value('latex_toplevel_sectioning', None, '',
ENUM(None, 'part', 'chapter', 'section'))
- app.add_config_value('latex_domain_indices', True, False, [list])
- app.add_config_value('latex_show_urls', 'no', False)
- app.add_config_value('latex_show_pagerefs', False, False)
- app.add_config_value('latex_elements', {}, False)
- app.add_config_value('latex_additional_files', [], False)
- app.add_config_value('latex_table_style', ['booktabs', 'colorrows'], False, [list])
- app.add_config_value('latex_theme', 'manual', False, [str])
- app.add_config_value('latex_theme_options', {}, False)
- app.add_config_value('latex_theme_path', [], False, [list])
-
- app.add_config_value('latex_docclass', default_latex_docclass, False)
+ app.add_config_value('latex_domain_indices', True, '', list)
+ app.add_config_value('latex_show_urls', 'no', '')
+ app.add_config_value('latex_show_pagerefs', False, '')
+ app.add_config_value('latex_elements', {}, '')
+ app.add_config_value('latex_additional_files', [], '')
+ app.add_config_value('latex_table_style', ['booktabs', 'colorrows'], '', list)
+ app.add_config_value('latex_theme', 'manual', '', str)
+ app.add_config_value('latex_theme_options', {}, '')
+ app.add_config_value('latex_theme_path', [], '', list)
+
+ app.add_config_value('latex_docclass', default_latex_docclass, '')
return {
'version': 'builtin',
diff --git a/sphinx/builders/latex/nodes.py b/sphinx/builders/latex/nodes.py
index 2c008b9..68b743d 100644
--- a/sphinx/builders/latex/nodes.py
+++ b/sphinx/builders/latex/nodes.py
@@ -5,26 +5,30 @@ 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):
- """A node represents ``\footnotemark``."""
+ r"""A node represents ``\footnotemark``."""
+
pass
class footnotetext(nodes.General, nodes.BackLinkable, nodes.Element,
nodes.Labeled, nodes.Targetable):
- """A node represents ``\footnotetext``."""
+ r"""A node represents ``\footnotetext``."""
class math_reference(nodes.Inline, nodes.Referential, nodes.TextElement):
"""A node for a reference for equation."""
+
pass
class thebibliography(nodes.container):
"""A node for wrapping bibliographies."""
+
pass
diff --git a/sphinx/builders/latex/transforms.py b/sphinx/builders/latex/transforms.py
index ca1e4f3..83599d8 100644
--- a/sphinx/builders/latex/transforms.py
+++ b/sphinx/builders/latex/transforms.py
@@ -25,18 +25,20 @@ if TYPE_CHECKING:
from docutils.nodes import Element, Node
from sphinx.application import Sphinx
+ from sphinx.util.typing import ExtensionMetadata
URI_SCHEMES = ('mailto:', 'http:', 'https:', 'ftp:')
class FootnoteDocnameUpdater(SphinxTransform):
"""Add docname to footnote and footnote_reference nodes."""
+
default_priority = 700
TARGET_NODES = (nodes.footnote, nodes.footnote_reference)
def apply(self, **kwargs: Any) -> None:
matcher = NodeMatcher(*self.TARGET_NODES)
- for node in self.document.findall(matcher): # type: Element
+ for node in matcher.findall(self.document):
node['docname'] = self.env.docname
@@ -59,6 +61,7 @@ class ShowUrlsTransform(SphinxPostTransform):
.. note:: This transform is used for integrated doctree
"""
+
default_priority = 400
formats = ('latex',)
@@ -112,7 +115,7 @@ class ShowUrlsTransform(SphinxPostTransform):
node = node.parent
try:
- source = node['source'] # type: ignore[index]
+ source = node['source']
except TypeError:
raise ValueError(__('Failed to get a docname!')) from None
raise ValueError(__('Failed to get a docname '
@@ -509,6 +512,7 @@ class BibliographyTransform(SphinxPostTransform):
<citation>
...
"""
+
default_priority = 750
formats = ('latex',)
@@ -519,7 +523,7 @@ class BibliographyTransform(SphinxPostTransform):
citations += node
if len(citations) > 0:
- self.document += citations
+ self.document += citations # type: ignore[attr-defined]
class CitationReferenceTransform(SphinxPostTransform):
@@ -528,13 +532,14 @@ class CitationReferenceTransform(SphinxPostTransform):
To handle citation reference easily on LaTeX writer, this converts
pending_xref nodes to citation_reference.
"""
+
default_priority = 5 # before ReferencesResolver
formats = ('latex',)
def run(self, **kwargs: Any) -> None:
domain = cast(CitationDomain, self.env.get_domain('citation'))
matcher = NodeMatcher(addnodes.pending_xref, refdomain='citation', reftype='ref')
- for node in self.document.findall(matcher): # type: addnodes.pending_xref
+ for node in matcher.findall(self.document):
docname, labelid, _ = domain.citations.get(node['reftarget'], ('', '', 0))
if docname:
citation_ref = nodes.citation_reference('', '', *node.children,
@@ -548,6 +553,7 @@ class MathReferenceTransform(SphinxPostTransform):
To handle math reference easily on LaTeX writer, this converts pending_xref
nodes to math_reference.
"""
+
default_priority = 5 # before ReferencesResolver
formats = ('latex',)
@@ -563,18 +569,20 @@ class MathReferenceTransform(SphinxPostTransform):
class LiteralBlockTransform(SphinxPostTransform):
"""Replace container nodes for literal_block by captioned_literal_block."""
+
default_priority = 400
formats = ('latex',)
def run(self, **kwargs: Any) -> None:
matcher = NodeMatcher(nodes.container, literal_block=True)
- for node in self.document.findall(matcher): # type: nodes.container
+ for node in matcher.findall(self.document):
newnode = captioned_literal_block('', *node.children, **node.attributes)
node.replace_self(newnode)
class DocumentTargetTransform(SphinxPostTransform):
"""Add :doc label to the first section of each document."""
+
default_priority = 400
formats = ('latex',)
@@ -586,10 +594,10 @@ class DocumentTargetTransform(SphinxPostTransform):
class IndexInSectionTitleTransform(SphinxPostTransform):
- """Move index nodes in section title to outside of the title.
+ r"""Move index nodes in section title to outside of the title.
LaTeX index macro is not compatible with some handling of section titles
- such as uppercasing done on LaTeX side (cf. fncychap handling of ``\\chapter``).
+ such as uppercasing done on LaTeX side (cf. fncychap handling of ``\chapter``).
Moving the index node to after the title node fixes that.
Before::
@@ -611,6 +619,7 @@ class IndexInSectionTitleTransform(SphinxPostTransform):
blah blah blah
...
"""
+
default_priority = 400
formats = ('latex',)
@@ -623,7 +632,7 @@ class IndexInSectionTitleTransform(SphinxPostTransform):
node.parent.insert(i + 1, index)
-def setup(app: Sphinx) -> dict[str, Any]:
+def setup(app: Sphinx) -> ExtensionMetadata:
app.add_transform(FootnoteDocnameUpdater)
app.add_post_transform(SubstitutionDefinitionsRemover)
app.add_post_transform(BibliographyTransform)
diff --git a/sphinx/builders/latex/util.py b/sphinx/builders/latex/util.py
index 01597f9..aeef260 100644
--- a/sphinx/builders/latex/util.py
+++ b/sphinx/builders/latex/util.py
@@ -35,7 +35,7 @@ class ExtBabel(Babel):
return 'english' # fallback to english
def get_mainlanguage_options(self) -> str | None:
- """Return options for polyglossia's ``\\setmainlanguage``."""
+ r"""Return options for polyglossia's ``\setmainlanguage``."""
if self.use_polyglossia is False:
return None
elif self.language == 'german':