mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Add SphinxTranslator as an abstract class
This commit is contained in:
parent
e888e92ac4
commit
3863256cb6
@ -33,8 +33,9 @@ from sphinx.util.osutil import ensuredir, ENOENT, EPIPE, EINVAL
|
|||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
from docutils.parsers.rst import Directive # NOQA
|
from docutils.parsers.rst import Directive # NOQA
|
||||||
from typing import Any, Dict, List, Tuple, Union # NOQA
|
from typing import Any, Dict, List, Tuple # NOQA
|
||||||
from sphinx.application import Sphinx # NOQA
|
from sphinx.application import Sphinx # NOQA
|
||||||
|
from sphinx.util.docutils import SphinxTranslator # NOQA
|
||||||
from sphinx.util.typing import unicode # NOQA
|
from sphinx.util.typing import unicode # NOQA
|
||||||
from sphinx.writers.html import HTMLTranslator # NOQA
|
from sphinx.writers.html import HTMLTranslator # NOQA
|
||||||
from sphinx.writers.latex import LaTeXTranslator # NOQA
|
from sphinx.writers.latex import LaTeXTranslator # NOQA
|
||||||
@ -219,7 +220,7 @@ class GraphvizSimple(SphinxDirective):
|
|||||||
|
|
||||||
|
|
||||||
def render_dot(self, code, options, format, prefix='graphviz'):
|
def render_dot(self, code, options, format, prefix='graphviz'):
|
||||||
# type: (Union[HTMLTranslator, LaTeXTranslator, TexinfoTranslator], unicode, Dict, unicode, unicode) -> Tuple[unicode, unicode] # NOQA
|
# type: (SphinxTranslator, unicode, Dict, unicode, unicode) -> Tuple[unicode, unicode] # NOQA
|
||||||
"""Render graphviz code into a PNG or PDF output file."""
|
"""Render graphviz code into a PNG or PDF output file."""
|
||||||
graphviz_dot = options.get('graphviz_dot', self.builder.config.graphviz_dot)
|
graphviz_dot = options.get('graphviz_dot', self.builder.config.graphviz_dot)
|
||||||
hashkey = (code + str(options) + str(graphviz_dot) +
|
hashkey = (code + str(options) + str(graphviz_dot) +
|
||||||
|
@ -39,6 +39,7 @@ if False:
|
|||||||
from types import ModuleType # NOQA
|
from types import ModuleType # NOQA
|
||||||
from typing import Any, Callable, Generator, List, Set, Tuple, Type # NOQA
|
from typing import Any, Callable, Generator, List, Set, Tuple, Type # NOQA
|
||||||
from docutils.statemachine import State, ViewList # NOQA
|
from docutils.statemachine import State, ViewList # NOQA
|
||||||
|
from sphinx.builders import Builder # NOQA
|
||||||
from sphinx.config import Config # NOQA
|
from sphinx.config import Config # NOQA
|
||||||
from sphinx.environment import BuildEnvironment # NOQA
|
from sphinx.environment import BuildEnvironment # NOQA
|
||||||
from sphinx.io import SphinxFileInput # NOQA
|
from sphinx.io import SphinxFileInput # NOQA
|
||||||
@ -383,6 +384,32 @@ class SphinxDirective(Directive):
|
|||||||
return self.env.config
|
return self.env.config
|
||||||
|
|
||||||
|
|
||||||
|
class SphinxTranslator(nodes.NodeVisitor):
|
||||||
|
"""A base class for Sphinx translators.
|
||||||
|
|
||||||
|
This class provides helper methods for Sphinx translators.
|
||||||
|
|
||||||
|
.. note:: The subclasses of this class might not work with docutils.
|
||||||
|
This class is strongly coupled with Sphinx.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, builder, document):
|
||||||
|
# type: (Builder, nodes.document) -> None
|
||||||
|
super(SphinxTranslator, self).__init__(document)
|
||||||
|
self.builder = builder
|
||||||
|
self.config = builder.config
|
||||||
|
|
||||||
|
def get_settings(self):
|
||||||
|
# type: () -> Any
|
||||||
|
"""Get settings object with type safe.
|
||||||
|
|
||||||
|
.. note:: It is hard to check types for settings object because it's attributes
|
||||||
|
are added dynamically. This method avoids the type errors through
|
||||||
|
imitating it's type as Any.
|
||||||
|
"""
|
||||||
|
return self.document.settings
|
||||||
|
|
||||||
|
|
||||||
# cache a vanilla instance of nodes.document
|
# cache a vanilla instance of nodes.document
|
||||||
# Used in new_document() function
|
# Used in new_document() function
|
||||||
__document_cache__ = None # type: nodes.document
|
__document_cache__ = None # type: nodes.document
|
||||||
|
@ -23,6 +23,7 @@ from sphinx import addnodes
|
|||||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||||
from sphinx.locale import admonitionlabels, _, __
|
from sphinx.locale import admonitionlabels, _, __
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
|
from sphinx.util.docutils import SphinxTranslator
|
||||||
from sphinx.util.images import get_image_size
|
from sphinx.util.images import get_image_size
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
@ -67,25 +68,26 @@ class HTMLWriter(Writer):
|
|||||||
self.clean_meta = ''.join(self.visitor.meta[2:])
|
self.clean_meta = ''.join(self.visitor.meta[2:])
|
||||||
|
|
||||||
|
|
||||||
class HTMLTranslator(BaseTranslator):
|
class HTMLTranslator(SphinxTranslator, BaseTranslator):
|
||||||
"""
|
"""
|
||||||
Our custom HTML translator.
|
Our custom HTML translator.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, builder, *args, **kwds):
|
builder = None # type: StandaloneHTMLBuilder
|
||||||
# type: (StandaloneHTMLBuilder, Any, Any) -> None
|
|
||||||
super(HTMLTranslator, self).__init__(*args, **kwds)
|
def __init__(self, builder, document):
|
||||||
self.highlighter = builder.highlighter
|
# type: (StandaloneHTMLBuilder, nodes.document) -> None
|
||||||
self.builder = builder
|
super(HTMLTranslator, self).__init__(builder, document)
|
||||||
self.docnames = [builder.current_docname] # for singlehtml builder
|
self.highlighter = self.builder.highlighter
|
||||||
self.manpages_url = builder.config.manpages_url
|
self.docnames = [self.builder.current_docname] # for singlehtml builder
|
||||||
|
self.manpages_url = self.config.manpages_url
|
||||||
self.protect_literal_text = 0
|
self.protect_literal_text = 0
|
||||||
self.permalink_text = builder.config.html_add_permalinks
|
self.permalink_text = self.config.html_add_permalinks
|
||||||
# support backwards-compatible setting to a bool
|
# support backwards-compatible setting to a bool
|
||||||
if not isinstance(self.permalink_text, str):
|
if not isinstance(self.permalink_text, str):
|
||||||
self.permalink_text = self.permalink_text and u'\u00B6' or ''
|
self.permalink_text = self.permalink_text and u'\u00B6' or ''
|
||||||
self.permalink_text = self.encode(self.permalink_text)
|
self.permalink_text = self.encode(self.permalink_text)
|
||||||
self.secnumber_suffix = builder.config.html_secnumber_suffix
|
self.secnumber_suffix = self.config.html_secnumber_suffix
|
||||||
self.param_separator = ''
|
self.param_separator = ''
|
||||||
self.optional_param_level = 0
|
self.optional_param_level = 0
|
||||||
self._table_row_index = 0
|
self._table_row_index = 0
|
||||||
@ -250,8 +252,8 @@ class HTMLTranslator(BaseTranslator):
|
|||||||
atts['class'] += ' external'
|
atts['class'] += ' external'
|
||||||
if 'refuri' in node:
|
if 'refuri' in node:
|
||||||
atts['href'] = node['refuri'] or '#'
|
atts['href'] = node['refuri'] or '#'
|
||||||
if self.settings.cloak_email_addresses and \
|
if (self.get_settings().cloak_email_addresses and
|
||||||
atts['href'].startswith('mailto:'):
|
atts['href'].startswith('mailto:')):
|
||||||
atts['href'] = self.cloak_mailto(atts['href'])
|
atts['href'] = self.cloak_mailto(atts['href'])
|
||||||
self.in_mailto = True
|
self.in_mailto = True
|
||||||
else:
|
else:
|
||||||
@ -708,7 +710,7 @@ class HTMLTranslator(BaseTranslator):
|
|||||||
# protect runs of multiple spaces; the last one can wrap
|
# protect runs of multiple spaces; the last one can wrap
|
||||||
self.body.append(' ' * (len(token) - 1) + ' ')
|
self.body.append(' ' * (len(token) - 1) + ' ')
|
||||||
else:
|
else:
|
||||||
if self.in_mailto and self.settings.cloak_email_addresses:
|
if self.in_mailto and self.get_settings().cloak_email_addresses:
|
||||||
encoded = self.cloak_email(encoded)
|
encoded = self.cloak_email(encoded)
|
||||||
self.body.append(encoded)
|
self.body.append(encoded)
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ from sphinx import addnodes
|
|||||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||||
from sphinx.locale import admonitionlabels, _, __
|
from sphinx.locale import admonitionlabels, _, __
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
|
from sphinx.util.docutils import SphinxTranslator
|
||||||
from sphinx.util.images import get_image_size
|
from sphinx.util.images import get_image_size
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
@ -37,25 +38,26 @@ logger = logging.getLogger(__name__)
|
|||||||
# http://www.arnebrodowski.de/blog/write-your-own-restructuredtext-writer.html
|
# http://www.arnebrodowski.de/blog/write-your-own-restructuredtext-writer.html
|
||||||
|
|
||||||
|
|
||||||
class HTML5Translator(BaseTranslator):
|
class HTML5Translator(SphinxTranslator, BaseTranslator):
|
||||||
"""
|
"""
|
||||||
Our custom HTML translator.
|
Our custom HTML translator.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, builder, *args, **kwds):
|
builder = None # type: StandaloneHTMLBuilder
|
||||||
# type: (StandaloneHTMLBuilder, Any, Any) -> None
|
|
||||||
super(HTML5Translator, self).__init__(*args, **kwds)
|
def __init__(self, builder, document):
|
||||||
self.highlighter = builder.highlighter
|
# type: (StandaloneHTMLBuilder, nodes.document) -> None
|
||||||
self.builder = builder
|
super(HTML5Translator, self).__init__(builder, document)
|
||||||
self.docnames = [builder.current_docname] # for singlehtml builder
|
self.highlighter = self.builder.highlighter
|
||||||
self.manpages_url = builder.config.manpages_url
|
self.docnames = [self.builder.current_docname] # for singlehtml builder
|
||||||
|
self.manpages_url = self.config.manpages_url
|
||||||
self.protect_literal_text = 0
|
self.protect_literal_text = 0
|
||||||
self.permalink_text = builder.config.html_add_permalinks
|
self.permalink_text = self.config.html_add_permalinks
|
||||||
# support backwards-compatible setting to a bool
|
# support backwards-compatible setting to a bool
|
||||||
if not isinstance(self.permalink_text, str):
|
if not isinstance(self.permalink_text, str):
|
||||||
self.permalink_text = self.permalink_text and u'\u00B6' or ''
|
self.permalink_text = self.permalink_text and u'\u00B6' or ''
|
||||||
self.permalink_text = self.encode(self.permalink_text)
|
self.permalink_text = self.encode(self.permalink_text)
|
||||||
self.secnumber_suffix = builder.config.html_secnumber_suffix
|
self.secnumber_suffix = self.config.html_secnumber_suffix
|
||||||
self.param_separator = ''
|
self.param_separator = ''
|
||||||
self.optional_param_level = 0
|
self.optional_param_level = 0
|
||||||
self._table_row_index = 0
|
self._table_row_index = 0
|
||||||
@ -219,8 +221,8 @@ class HTML5Translator(BaseTranslator):
|
|||||||
atts['class'] += ' external'
|
atts['class'] += ' external'
|
||||||
if 'refuri' in node:
|
if 'refuri' in node:
|
||||||
atts['href'] = node['refuri'] or '#'
|
atts['href'] = node['refuri'] or '#'
|
||||||
if self.settings.cloak_email_addresses and \
|
if (self.get_settings().cloak_email_addresses and
|
||||||
atts['href'].startswith('mailto:'):
|
atts['href'].startswith('mailto:')):
|
||||||
atts['href'] = self.cloak_mailto(atts['href'])
|
atts['href'] = self.cloak_mailto(atts['href'])
|
||||||
self.in_mailto = True
|
self.in_mailto = True
|
||||||
else:
|
else:
|
||||||
@ -649,7 +651,7 @@ class HTML5Translator(BaseTranslator):
|
|||||||
# protect runs of multiple spaces; the last one can wrap
|
# protect runs of multiple spaces; the last one can wrap
|
||||||
self.body.append(' ' * (len(token) - 1) + ' ')
|
self.body.append(' ' * (len(token) - 1) + ' ')
|
||||||
else:
|
else:
|
||||||
if self.in_mailto and self.settings.cloak_email_addresses:
|
if self.in_mailto and self.get_settings().cloak_email_addresses:
|
||||||
encoded = self.cloak_email(encoded)
|
encoded = self.cloak_email(encoded)
|
||||||
self.body.append(encoded)
|
self.body.append(encoded)
|
||||||
|
|
||||||
@ -788,7 +790,7 @@ class HTML5Translator(BaseTranslator):
|
|||||||
self._table_row_index = 0
|
self._table_row_index = 0
|
||||||
|
|
||||||
classes = [cls.strip(u' \t\n')
|
classes = [cls.strip(u' \t\n')
|
||||||
for cls in self.settings.table_style.split(',')]
|
for cls in self.get_settings().table_style.split(',')]
|
||||||
classes.insert(0, "docutils") # compat
|
classes.insert(0, "docutils") # compat
|
||||||
if 'align' in node:
|
if 'align' in node:
|
||||||
classes.append('align-%s' % node['align'])
|
classes.append('align-%s' % node['align'])
|
||||||
|
@ -29,6 +29,7 @@ from sphinx.deprecation import RemovedInSphinx30Warning, RemovedInSphinx40Warnin
|
|||||||
from sphinx.errors import SphinxError
|
from sphinx.errors import SphinxError
|
||||||
from sphinx.locale import admonitionlabels, _, __
|
from sphinx.locale import admonitionlabels, _, __
|
||||||
from sphinx.util import split_into, logging
|
from sphinx.util import split_into, logging
|
||||||
|
from sphinx.util.docutils import SphinxTranslator
|
||||||
from sphinx.util.i18n import format_date
|
from sphinx.util.i18n import format_date
|
||||||
from sphinx.util.nodes import clean_astext
|
from sphinx.util.nodes import clean_astext
|
||||||
from sphinx.util.template import LaTeXRenderer
|
from sphinx.util.template import LaTeXRenderer
|
||||||
@ -497,7 +498,8 @@ def rstdim_to_latexdim(width_str):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
class LaTeXTranslator(nodes.NodeVisitor):
|
class LaTeXTranslator(SphinxTranslator):
|
||||||
|
builder = None # type: LaTeXBuilder
|
||||||
|
|
||||||
secnumdepth = 2 # legacy sphinxhowto.cls uses this, whereas article.cls
|
secnumdepth = 2 # legacy sphinxhowto.cls uses this, whereas article.cls
|
||||||
# default is originally 3. For book/report, 2 is already LaTeX default.
|
# default is originally 3. For book/report, 2 is already LaTeX default.
|
||||||
@ -508,8 +510,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
|
|
||||||
def __init__(self, document, builder):
|
def __init__(self, document, builder):
|
||||||
# type: (nodes.document, LaTeXBuilder) -> None
|
# type: (nodes.document, LaTeXBuilder) -> None
|
||||||
super(LaTeXTranslator, self).__init__(document)
|
super(LaTeXTranslator, self).__init__(builder, document)
|
||||||
self.builder = builder
|
|
||||||
self.body = [] # type: List[unicode]
|
self.body = [] # type: List[unicode]
|
||||||
|
|
||||||
# flags
|
# flags
|
||||||
@ -529,42 +530,42 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
self.first_param = 0
|
self.first_param = 0
|
||||||
|
|
||||||
# sort out some elements
|
# sort out some elements
|
||||||
self.elements = builder.context.copy()
|
self.elements = self.builder.context.copy()
|
||||||
|
|
||||||
# but some have other interface in config file
|
# but some have other interface in config file
|
||||||
self.elements['wrapperclass'] = self.format_docclass(document.settings.docclass)
|
self.elements['wrapperclass'] = self.format_docclass(self.get_settings().docclass)
|
||||||
|
|
||||||
# we assume LaTeX class provides \chapter command except in case
|
# we assume LaTeX class provides \chapter command except in case
|
||||||
# of non-Japanese 'howto' case
|
# of non-Japanese 'howto' case
|
||||||
self.sectionnames = LATEXSECTIONNAMES[:]
|
self.sectionnames = LATEXSECTIONNAMES[:]
|
||||||
if document.settings.docclass == 'howto':
|
if self.get_settings().docclass == 'howto':
|
||||||
docclass = builder.config.latex_docclass.get('howto', 'article')
|
docclass = self.config.latex_docclass.get('howto', 'article')
|
||||||
if docclass[0] == 'j': # Japanese class...
|
if docclass[0] == 'j': # Japanese class...
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
self.sectionnames.remove('chapter')
|
self.sectionnames.remove('chapter')
|
||||||
else:
|
else:
|
||||||
docclass = builder.config.latex_docclass.get('manual', 'report')
|
docclass = self.config.latex_docclass.get('manual', 'report')
|
||||||
self.elements['docclass'] = docclass
|
self.elements['docclass'] = docclass
|
||||||
|
|
||||||
# determine top section level
|
# determine top section level
|
||||||
self.top_sectionlevel = 1
|
self.top_sectionlevel = 1
|
||||||
if builder.config.latex_toplevel_sectioning:
|
if self.config.latex_toplevel_sectioning:
|
||||||
try:
|
try:
|
||||||
self.top_sectionlevel = \
|
self.top_sectionlevel = \
|
||||||
self.sectionnames.index(builder.config.latex_toplevel_sectioning)
|
self.sectionnames.index(self.config.latex_toplevel_sectioning)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logger.warning(__('unknown %r toplevel_sectioning for class %r') %
|
logger.warning(__('unknown %r toplevel_sectioning for class %r') %
|
||||||
(builder.config.latex_toplevel_sectioning, docclass))
|
(self.config.latex_toplevel_sectioning, docclass))
|
||||||
|
|
||||||
if builder.config.today:
|
if self.config.today:
|
||||||
self.elements['date'] = builder.config.today
|
self.elements['date'] = self.config.today
|
||||||
else:
|
else:
|
||||||
self.elements['date'] = format_date(builder.config.today_fmt or _('%b %d, %Y'),
|
self.elements['date'] = format_date(self.config.today_fmt or _('%b %d, %Y'),
|
||||||
language=builder.config.language)
|
language=self.config.language)
|
||||||
|
|
||||||
if builder.config.numfig:
|
if self.config.numfig:
|
||||||
self.numfig_secnum_depth = builder.config.numfig_secnum_depth
|
self.numfig_secnum_depth = self.config.numfig_secnum_depth
|
||||||
if self.numfig_secnum_depth > 0: # default is 1
|
if self.numfig_secnum_depth > 0: # default is 1
|
||||||
# numfig_secnum_depth as passed to sphinx.sty indices same names as in
|
# numfig_secnum_depth as passed to sphinx.sty indices same names as in
|
||||||
# LATEXSECTIONNAMES but with -1 for part, 0 for chapter, 1 for section...
|
# LATEXSECTIONNAMES but with -1 for part, 0 for chapter, 1 for section...
|
||||||
@ -582,31 +583,31 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
else:
|
else:
|
||||||
self.elements['sphinxpkgoptions'] += ',nonumfigreset'
|
self.elements['sphinxpkgoptions'] += ',nonumfigreset'
|
||||||
try:
|
try:
|
||||||
if builder.config.math_numfig:
|
if self.config.math_numfig:
|
||||||
self.elements['sphinxpkgoptions'] += ',mathnumfig'
|
self.elements['sphinxpkgoptions'] += ',mathnumfig'
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if builder.config.latex_logo:
|
if self.config.latex_logo:
|
||||||
# no need for \\noindent here, used in flushright
|
# no need for \\noindent here, used in flushright
|
||||||
self.elements['logo'] = '\\sphinxincludegraphics{%s}\\par' % \
|
self.elements['logo'] = '\\sphinxincludegraphics{%s}\\par' % \
|
||||||
path.basename(builder.config.latex_logo)
|
path.basename(self.config.latex_logo)
|
||||||
|
|
||||||
if (builder.config.language and builder.config.language != 'ja' and
|
if (self.config.language and self.config.language != 'ja' and
|
||||||
'fncychap' not in builder.config.latex_elements):
|
'fncychap' not in self.config.latex_elements):
|
||||||
# use Sonny style if any language specified
|
# use Sonny style if any language specified
|
||||||
self.elements['fncychap'] = ('\\usepackage[Sonny]{fncychap}\n'
|
self.elements['fncychap'] = ('\\usepackage[Sonny]{fncychap}\n'
|
||||||
'\\ChNameVar{\\Large\\normalfont'
|
'\\ChNameVar{\\Large\\normalfont'
|
||||||
'\\sffamily}\n\\ChTitleVar{\\Large'
|
'\\sffamily}\n\\ChTitleVar{\\Large'
|
||||||
'\\normalfont\\sffamily}')
|
'\\normalfont\\sffamily}')
|
||||||
|
|
||||||
self.babel = ExtBabel(builder.config.language,
|
self.babel = ExtBabel(self.config.language,
|
||||||
not self.elements['babel'])
|
not self.elements['babel'])
|
||||||
if builder.config.language and not self.babel.is_supported_language():
|
if self.config.language and not self.babel.is_supported_language():
|
||||||
# emit warning if specified language is invalid
|
# emit warning if specified language is invalid
|
||||||
# (only emitting, nothing changed to processing)
|
# (only emitting, nothing changed to processing)
|
||||||
logger.warning(__('no Babel option known for language %r'),
|
logger.warning(__('no Babel option known for language %r'),
|
||||||
builder.config.language)
|
self.config.language)
|
||||||
|
|
||||||
# set up multilingual module...
|
# set up multilingual module...
|
||||||
if self.elements['latex_engine'] == 'pdflatex':
|
if self.elements['latex_engine'] == 'pdflatex':
|
||||||
@ -628,12 +629,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
self.elements['classoptions'] += ',' + self.babel.get_language()
|
self.elements['classoptions'] += ',' + self.babel.get_language()
|
||||||
# this branch is not taken for xelatex/lualatex if default settings
|
# this branch is not taken for xelatex/lualatex if default settings
|
||||||
self.elements['multilingual'] = self.elements['babel']
|
self.elements['multilingual'] = self.elements['babel']
|
||||||
if builder.config.language:
|
if self.config.language:
|
||||||
self.elements['shorthandoff'] = SHORTHANDOFF
|
self.elements['shorthandoff'] = SHORTHANDOFF
|
||||||
|
|
||||||
# Times fonts don't work with Cyrillic languages
|
# Times fonts don't work with Cyrillic languages
|
||||||
if self.babel.uses_cyrillic() \
|
if self.babel.uses_cyrillic() and 'fontpkg' not in self.config.latex_elements:
|
||||||
and 'fontpkg' not in builder.config.latex_elements:
|
|
||||||
self.elements['fontpkg'] = ''
|
self.elements['fontpkg'] = ''
|
||||||
elif self.elements['polyglossia']:
|
elif self.elements['polyglossia']:
|
||||||
self.elements['classoptions'] += ',' + self.babel.get_language()
|
self.elements['classoptions'] += ',' + self.babel.get_language()
|
||||||
@ -647,25 +647,25 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
self.elements['multilingual'] = '%s\n%s' % (self.elements['polyglossia'],
|
self.elements['multilingual'] = '%s\n%s' % (self.elements['polyglossia'],
|
||||||
mainlanguage)
|
mainlanguage)
|
||||||
|
|
||||||
if getattr(builder, 'usepackages', None):
|
if getattr(self.builder, 'usepackages', None):
|
||||||
def declare_package(packagename, options=None):
|
def declare_package(packagename, options=None):
|
||||||
# type:(unicode, unicode) -> unicode
|
# type:(unicode, unicode) -> unicode
|
||||||
if options:
|
if options:
|
||||||
return '\\usepackage[%s]{%s}' % (options, packagename)
|
return '\\usepackage[%s]{%s}' % (options, packagename)
|
||||||
else:
|
else:
|
||||||
return '\\usepackage{%s}' % (packagename,)
|
return '\\usepackage{%s}' % (packagename,)
|
||||||
usepackages = (declare_package(*p) for p in builder.usepackages)
|
usepackages = (declare_package(*p) for p in self.builder.usepackages)
|
||||||
self.elements['usepackages'] += "\n".join(usepackages)
|
self.elements['usepackages'] += "\n".join(usepackages)
|
||||||
|
|
||||||
minsecnumdepth = self.secnumdepth # 2 from legacy sphinx manual/howto
|
minsecnumdepth = self.secnumdepth # 2 from legacy sphinx manual/howto
|
||||||
if document.get('tocdepth'):
|
if self.document.get('tocdepth'):
|
||||||
# reduce tocdepth if `part` or `chapter` is used for top_sectionlevel
|
# reduce tocdepth if `part` or `chapter` is used for top_sectionlevel
|
||||||
# tocdepth = -1: show only parts
|
# tocdepth = -1: show only parts
|
||||||
# tocdepth = 0: show parts and chapters
|
# tocdepth = 0: show parts and chapters
|
||||||
# tocdepth = 1: show parts, chapters and sections
|
# tocdepth = 1: show parts, chapters and sections
|
||||||
# tocdepth = 2: show parts, chapters, sections and subsections
|
# tocdepth = 2: show parts, chapters, sections and subsections
|
||||||
# ...
|
# ...
|
||||||
tocdepth = document['tocdepth'] + self.top_sectionlevel - 2
|
tocdepth = self.document['tocdepth'] + self.top_sectionlevel - 2
|
||||||
if len(self.sectionnames) < len(LATEXSECTIONNAMES) and \
|
if len(self.sectionnames) < len(LATEXSECTIONNAMES) and \
|
||||||
self.top_sectionlevel > 0:
|
self.top_sectionlevel > 0:
|
||||||
tocdepth += 1 # because top_sectionlevel is shifted by -1
|
tocdepth += 1 # because top_sectionlevel is shifted by -1
|
||||||
@ -676,16 +676,16 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
self.elements['tocdepth'] = '\\setcounter{tocdepth}{%d}' % tocdepth
|
self.elements['tocdepth'] = '\\setcounter{tocdepth}{%d}' % tocdepth
|
||||||
minsecnumdepth = max(minsecnumdepth, tocdepth)
|
minsecnumdepth = max(minsecnumdepth, tocdepth)
|
||||||
|
|
||||||
if builder.config.numfig and (builder.config.numfig_secnum_depth > 0):
|
if self.config.numfig and (self.config.numfig_secnum_depth > 0):
|
||||||
minsecnumdepth = max(minsecnumdepth, self.numfig_secnum_depth - 1)
|
minsecnumdepth = max(minsecnumdepth, self.numfig_secnum_depth - 1)
|
||||||
|
|
||||||
if minsecnumdepth > self.secnumdepth:
|
if minsecnumdepth > self.secnumdepth:
|
||||||
self.elements['secnumdepth'] = '\\setcounter{secnumdepth}{%d}' %\
|
self.elements['secnumdepth'] = '\\setcounter{secnumdepth}{%d}' %\
|
||||||
minsecnumdepth
|
minsecnumdepth
|
||||||
|
|
||||||
if getattr(document.settings, 'contentsname', None):
|
contentsname = self.get_settings().contentsname
|
||||||
self.elements['contentsname'] = \
|
self.elements['contentsname'] = self.babel_renewcommand('\\contentsname',
|
||||||
self.babel_renewcommand('\\contentsname', document.settings.contentsname)
|
contentsname)
|
||||||
|
|
||||||
if self.elements['maxlistdepth']:
|
if self.elements['maxlistdepth']:
|
||||||
self.elements['sphinxpkgoptions'] += (',maxlistdepth=%s' %
|
self.elements['sphinxpkgoptions'] += (',maxlistdepth=%s' %
|
||||||
@ -699,9 +699,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
if self.elements['extraclassoptions']:
|
if self.elements['extraclassoptions']:
|
||||||
self.elements['classoptions'] += ',' + \
|
self.elements['classoptions'] += ',' + \
|
||||||
self.elements['extraclassoptions']
|
self.elements['extraclassoptions']
|
||||||
self.elements['numfig_format'] = self.generate_numfig_format(builder)
|
self.elements['numfig_format'] = self.generate_numfig_format(self.builder)
|
||||||
|
|
||||||
self.highlighter = highlighting.PygmentsBridge('latex', builder.config.pygments_style)
|
self.highlighter = highlighting.PygmentsBridge('latex', self.config.pygments_style)
|
||||||
self.context = [] # type: List[Any]
|
self.context = [] # type: List[Any]
|
||||||
self.descstack = [] # type: List[unicode]
|
self.descstack = [] # type: List[unicode]
|
||||||
self.table = None # type: Table
|
self.table = None # type: Table
|
||||||
|
@ -20,6 +20,7 @@ from docutils.writers.manpage import (
|
|||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx.locale import admonitionlabels, _
|
from sphinx.locale import admonitionlabels, _
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
|
from sphinx.util.docutils import SphinxTranslator
|
||||||
from sphinx.util.i18n import format_date
|
from sphinx.util.i18n import format_date
|
||||||
from sphinx.util.nodes import NodeMatcher
|
from sphinx.util.nodes import NodeMatcher
|
||||||
|
|
||||||
@ -78,17 +79,16 @@ class NestedInlineTransform:
|
|||||||
node.parent.insert(pos + 1, newnode)
|
node.parent.insert(pos + 1, newnode)
|
||||||
|
|
||||||
|
|
||||||
class ManualPageTranslator(BaseTranslator):
|
class ManualPageTranslator(SphinxTranslator, BaseTranslator):
|
||||||
"""
|
"""
|
||||||
Custom translator.
|
Custom translator.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_docinfo = {} # type: Dict[unicode, Any]
|
_docinfo = {} # type: Dict[unicode, Any]
|
||||||
|
|
||||||
def __init__(self, builder, *args, **kwds):
|
def __init__(self, builder, document):
|
||||||
# type: (Builder, Any, Any) -> None
|
# type: (Builder, nodes.document) -> None
|
||||||
super(ManualPageTranslator, self).__init__(*args, **kwds)
|
super(ManualPageTranslator, self).__init__(builder, document)
|
||||||
self.builder = builder
|
|
||||||
|
|
||||||
self.in_productionlist = 0
|
self.in_productionlist = 0
|
||||||
|
|
||||||
@ -96,23 +96,24 @@ class ManualPageTranslator(BaseTranslator):
|
|||||||
self.section_level = -1
|
self.section_level = -1
|
||||||
|
|
||||||
# docinfo set by man_pages config value
|
# docinfo set by man_pages config value
|
||||||
self._docinfo['title'] = self.document.settings.title
|
settings = self.get_settings()
|
||||||
self._docinfo['subtitle'] = self.document.settings.subtitle
|
self._docinfo['title'] = settings.title
|
||||||
if self.document.settings.authors:
|
self._docinfo['subtitle'] = settings.subtitle
|
||||||
|
if settings.authors:
|
||||||
# don't set it if no author given
|
# don't set it if no author given
|
||||||
self._docinfo['author'] = self.document.settings.authors
|
self._docinfo['author'] = settings.authors
|
||||||
self._docinfo['manual_section'] = self.document.settings.section
|
self._docinfo['manual_section'] = settings.section
|
||||||
|
|
||||||
# docinfo set by other config values
|
# docinfo set by other config values
|
||||||
self._docinfo['title_upper'] = self._docinfo['title'].upper()
|
self._docinfo['title_upper'] = self._docinfo['title'].upper()
|
||||||
if builder.config.today:
|
if self.config.today:
|
||||||
self._docinfo['date'] = builder.config.today
|
self._docinfo['date'] = self.config.today
|
||||||
else:
|
else:
|
||||||
self._docinfo['date'] = format_date(builder.config.today_fmt or _('%b %d, %Y'),
|
self._docinfo['date'] = format_date(self.config.today_fmt or _('%b %d, %Y'),
|
||||||
language=builder.config.language)
|
language=self.config.language)
|
||||||
self._docinfo['copyright'] = builder.config.copyright
|
self._docinfo['copyright'] = self.config.copyright
|
||||||
self._docinfo['version'] = builder.config.version
|
self._docinfo['version'] = self.config.version
|
||||||
self._docinfo['manual_group'] = builder.config.project
|
self._docinfo['manual_group'] = self.config.project
|
||||||
|
|
||||||
# Overwrite admonition label translations with our own
|
# Overwrite admonition label translations with our own
|
||||||
for label, translation in admonitionlabels.items():
|
for label, translation in admonitionlabels.items():
|
||||||
|
@ -20,6 +20,7 @@ from sphinx import addnodes, __display_version__
|
|||||||
from sphinx.errors import ExtensionError
|
from sphinx.errors import ExtensionError
|
||||||
from sphinx.locale import admonitionlabels, _, __
|
from sphinx.locale import admonitionlabels, _, __
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
|
from sphinx.util.docutils import SphinxTranslator
|
||||||
from sphinx.util.i18n import format_date
|
from sphinx.util.i18n import format_date
|
||||||
from sphinx.writers.latex import collected_footnote
|
from sphinx.writers.latex import collected_footnote
|
||||||
|
|
||||||
@ -144,8 +145,9 @@ class TexinfoWriter(writers.Writer):
|
|||||||
setattr(self, attr, getattr(self.visitor, attr))
|
setattr(self, attr, getattr(self.visitor, attr))
|
||||||
|
|
||||||
|
|
||||||
class TexinfoTranslator(nodes.NodeVisitor):
|
class TexinfoTranslator(SphinxTranslator):
|
||||||
|
|
||||||
|
builder = None # type: TexinfoBuilder
|
||||||
ignore_missing_images = False
|
ignore_missing_images = False
|
||||||
|
|
||||||
default_elements = {
|
default_elements = {
|
||||||
@ -165,8 +167,7 @@ class TexinfoTranslator(nodes.NodeVisitor):
|
|||||||
|
|
||||||
def __init__(self, document, builder):
|
def __init__(self, document, builder):
|
||||||
# type: (nodes.document, TexinfoBuilder) -> None
|
# type: (nodes.document, TexinfoBuilder) -> None
|
||||||
super(TexinfoTranslator, self).__init__(document)
|
super(TexinfoTranslator, self).__init__(builder, document)
|
||||||
self.builder = builder
|
|
||||||
self.init_settings()
|
self.init_settings()
|
||||||
|
|
||||||
self.written_ids = set() # type: Set[unicode]
|
self.written_ids = set() # type: Set[unicode]
|
||||||
@ -227,7 +228,7 @@ class TexinfoTranslator(nodes.NodeVisitor):
|
|||||||
|
|
||||||
def init_settings(self):
|
def init_settings(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
settings = self.settings = self.document.settings
|
self.settings = settings = self.get_settings()
|
||||||
elements = self.elements = self.default_elements.copy()
|
elements = self.elements = self.default_elements.copy()
|
||||||
elements.update({
|
elements.update({
|
||||||
# if empty, the title is set to the first section title
|
# if empty, the title is set to the first section title
|
||||||
@ -243,11 +244,10 @@ class TexinfoTranslator(nodes.NodeVisitor):
|
|||||||
language=self.builder.config.language))
|
language=self.builder.config.language))
|
||||||
})
|
})
|
||||||
# title
|
# title
|
||||||
title = None # type: unicode
|
title = settings.title # type: unicode
|
||||||
title = elements['title'] # type: ignore
|
|
||||||
if not title:
|
if not title:
|
||||||
title = self.document.next_node(nodes.title)
|
title_node = self.document.next_node(nodes.title)
|
||||||
title = (title and title.astext()) or '<untitled>' # type: ignore
|
title = (title and title_node.astext()) or '<untitled>'
|
||||||
elements['title'] = self.escape_id(title) or '<untitled>'
|
elements['title'] = self.escape_id(title) or '<untitled>'
|
||||||
# filename
|
# filename
|
||||||
if not elements['filename']:
|
if not elements['filename']:
|
||||||
|
@ -20,6 +20,7 @@ from docutils.utils import column_width
|
|||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx.locale import admonitionlabels, _
|
from sphinx.locale import admonitionlabels, _
|
||||||
|
from sphinx.util.docutils import SphinxTranslator
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
@ -391,23 +392,23 @@ class TextWriter(writers.Writer):
|
|||||||
self.output = cast(TextTranslator, visitor).body
|
self.output = cast(TextTranslator, visitor).body
|
||||||
|
|
||||||
|
|
||||||
class TextTranslator(nodes.NodeVisitor):
|
class TextTranslator(SphinxTranslator):
|
||||||
|
builder = None # type: TextBuilder
|
||||||
|
|
||||||
def __init__(self, document, builder):
|
def __init__(self, document, builder):
|
||||||
# type: (nodes.document, TextBuilder) -> None
|
# type: (nodes.document, TextBuilder) -> None
|
||||||
super(TextTranslator, self).__init__(document)
|
super(TextTranslator, self).__init__(builder, document)
|
||||||
self.builder = builder
|
|
||||||
|
|
||||||
newlines = builder.config.text_newlines
|
newlines = self.config.text_newlines
|
||||||
if newlines == 'windows':
|
if newlines == 'windows':
|
||||||
self.nl = '\r\n'
|
self.nl = '\r\n'
|
||||||
elif newlines == 'native':
|
elif newlines == 'native':
|
||||||
self.nl = os.linesep
|
self.nl = os.linesep
|
||||||
else:
|
else:
|
||||||
self.nl = '\n'
|
self.nl = '\n'
|
||||||
self.sectionchars = builder.config.text_sectionchars
|
self.sectionchars = self.config.text_sectionchars
|
||||||
self.add_secnumbers = builder.config.text_add_secnumbers
|
self.add_secnumbers = self.config.text_add_secnumbers
|
||||||
self.secnumber_suffix = builder.config.text_secnumber_suffix
|
self.secnumber_suffix = self.config.text_secnumber_suffix
|
||||||
self.states = [[]] # type: List[List[Tuple[int, Union[unicode, List[unicode]]]]]
|
self.states = [[]] # type: List[List[Tuple[int, Union[unicode, List[unicode]]]]]
|
||||||
self.stateindent = [0]
|
self.stateindent = [0]
|
||||||
self.list_counter = [] # type: List[int]
|
self.list_counter = [] # type: List[int]
|
||||||
|
@ -35,6 +35,7 @@ def settings(app):
|
|||||||
settings.smart_quotes = True
|
settings.smart_quotes = True
|
||||||
settings.env = app.builder.env
|
settings.env = app.builder.env
|
||||||
settings.env.temp_data['docname'] = 'dummy'
|
settings.env.temp_data['docname'] = 'dummy'
|
||||||
|
settings.contentsname = 'dummy'
|
||||||
domain_context = sphinx_domains(settings.env)
|
domain_context = sphinx_domains(settings.env)
|
||||||
domain_context.enable()
|
domain_context.enable()
|
||||||
yield settings
|
yield settings
|
||||||
|
Loading…
Reference in New Issue
Block a user