mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Support user defined LaTeX themes
This commit is contained in:
parent
a13ec4f41c
commit
cdbefb600f
@ -1904,7 +1904,7 @@ These options influence LaTeX output.
|
||||
|
||||
This value determines how to group the document tree into LaTeX source files.
|
||||
It must be a list of tuples ``(startdocname, targetname, title, author,
|
||||
documentclass, toctree_only)``, where the items are:
|
||||
theme, toctree_only)``, where the items are:
|
||||
|
||||
*startdocname*
|
||||
String that specifies the :term:`document name` of the LaTeX file's master
|
||||
@ -1926,13 +1926,8 @@ These options influence LaTeX output.
|
||||
applies. Use ``\\and`` to separate multiple authors, as in:
|
||||
``'John \\and Sarah'`` (backslashes must be Python-escaped to reach LaTeX).
|
||||
|
||||
*documentclass*
|
||||
Normally, one of ``'manual'`` or ``'howto'`` (provided by Sphinx and based
|
||||
on ``'report'``, resp. ``'article'``; Japanese documents use ``'jsbook'``,
|
||||
resp. ``'jreport'``.) "howto" (non-Japanese) documents will not get
|
||||
appendices. Also they have a simpler title page. Other document classes
|
||||
can be given. Independently of the document class, the "sphinx" package is
|
||||
always loaded in order to define Sphinx's custom LaTeX commands.
|
||||
*theme*
|
||||
LaTeX theme. See :confval:`latex_theme`.
|
||||
|
||||
*toctree_only*
|
||||
Must be ``True`` or ``False``. If true, the *startdoc* document itself is
|
||||
@ -2087,6 +2082,33 @@ These options influence LaTeX output.
|
||||
This overrides the files which is provided from Sphinx such as
|
||||
``sphinx.sty``.
|
||||
|
||||
.. confval:: latex_theme
|
||||
|
||||
The "theme" that the LaTeX output should use. It is a collection of settings
|
||||
for LaTeX output (ex. document class, top level sectioning unit and so on).
|
||||
|
||||
As a built-in LaTeX themes, ``manual`` and ``howto`` are bundled.
|
||||
|
||||
``manual``
|
||||
A LaTeX theme for writing a manual. It imports the ``report`` document
|
||||
class (Japanese documents use ``jsbook``).
|
||||
|
||||
``howto``
|
||||
A LaTeX theme for writing an article. It imports the ``article`` document
|
||||
class (Japanese documents use ``jreport`` rather). :confval:`latex_appendices`
|
||||
is available only for this theme.
|
||||
|
||||
It defaults to ``'manual'``.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
|
||||
.. confval:: latex_theme_path
|
||||
|
||||
A list of paths that contain custom LaTeX themes as subdirectories. Relative
|
||||
paths are taken as relative to the configuration directory.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
|
||||
|
||||
.. _text-options:
|
||||
|
||||
|
@ -493,7 +493,7 @@ def default_latex_documents(config: Config) -> List[Tuple[str, str, str, str, st
|
||||
make_filename_from_project(config.project) + '.tex',
|
||||
texescape.escape_abbr(project),
|
||||
texescape.escape_abbr(author),
|
||||
'manual')]
|
||||
config.latex_theme)]
|
||||
|
||||
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
@ -516,6 +516,8 @@ def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
app.add_config_value('latex_show_pagerefs', False, None)
|
||||
app.add_config_value('latex_elements', {}, None)
|
||||
app.add_config_value('latex_additional_files', [], None)
|
||||
app.add_config_value('latex_theme', 'manual', None, [str])
|
||||
app.add_config_value('latex_theme_path', [], None, [list])
|
||||
|
||||
app.add_config_value('latex_docclass', default_latex_docclass, None)
|
||||
|
||||
|
@ -8,10 +8,17 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import configparser
|
||||
from os import path
|
||||
from typing import Dict
|
||||
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.config import Config
|
||||
from sphinx.errors import ThemeError
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Theme:
|
||||
@ -56,11 +63,30 @@ class BuiltInTheme(Theme):
|
||||
return 'chapter'
|
||||
|
||||
|
||||
class UserTheme(Theme):
|
||||
"""A user defined LaTeX theme."""
|
||||
|
||||
def __init__(self, name: str, filename: str) -> None:
|
||||
self.name = name
|
||||
self.config = configparser.RawConfigParser()
|
||||
self.config.read(path.join(filename))
|
||||
|
||||
try:
|
||||
self.docclass = self.config.get('theme', 'docclass')
|
||||
self.wrapperclass = self.config.get('theme', 'wrapperclass')
|
||||
self.toplevel_sectioning = self.config.get('theme', 'toplevel_sectioning')
|
||||
except configparser.NoSectionError:
|
||||
raise ThemeError(__('%r doesn\'t have "theme" setting') % filename)
|
||||
except configparser.NoOptionError as exc:
|
||||
raise ThemeError(__('%r doesn\'t have "%s" setting') % (filename, exc.args[0]))
|
||||
|
||||
|
||||
class ThemeFactory:
|
||||
"""A factory class for LaTeX Themes."""
|
||||
|
||||
def __init__(self, app: Sphinx) -> None:
|
||||
self.themes = {} # type: Dict[str, Theme]
|
||||
self.theme_paths = [path.join(app.srcdir, p) for p in app.config.latex_theme_path]
|
||||
self.load_builtin_themes(app.config)
|
||||
|
||||
def load_builtin_themes(self, config: Config) -> None:
|
||||
@ -70,7 +96,23 @@ class ThemeFactory:
|
||||
|
||||
def get(self, name: str) -> Theme:
|
||||
"""Get a theme for given *name*."""
|
||||
if name not in self.themes:
|
||||
return Theme(name)
|
||||
else:
|
||||
if name in self.themes:
|
||||
return self.themes[name]
|
||||
else:
|
||||
theme = self.find_user_theme(name)
|
||||
if theme:
|
||||
return theme
|
||||
else:
|
||||
return Theme(name)
|
||||
|
||||
def find_user_theme(self, name: str) -> Theme:
|
||||
"""Find a theme named as *name* from latex_theme_path."""
|
||||
for theme_path in self.theme_paths:
|
||||
config_path = path.join(theme_path, name, 'theme.conf')
|
||||
if path.isfile(config_path):
|
||||
try:
|
||||
return UserTheme(name, config_path)
|
||||
except ThemeError as exc:
|
||||
logger.warning(exc)
|
||||
|
||||
return None
|
||||
|
2
tests/roots/test-latex-theme/conf.py
Normal file
2
tests/roots/test-latex-theme/conf.py
Normal file
@ -0,0 +1,2 @@
|
||||
latex_theme = 'custom'
|
||||
latex_theme_path = ['theme']
|
2
tests/roots/test-latex-theme/index.rst
Normal file
2
tests/roots/test-latex-theme/index.rst
Normal file
@ -0,0 +1,2 @@
|
||||
latex_theme
|
||||
===========
|
4
tests/roots/test-latex-theme/theme/custom/theme.conf
Normal file
4
tests/roots/test-latex-theme/theme/custom/theme.conf
Normal file
@ -0,0 +1,4 @@
|
||||
[theme]
|
||||
docclass = book
|
||||
wrapperclass = sphinxbook
|
||||
toplevel_sectioning = chapter
|
@ -20,7 +20,7 @@ from test_build_html import ENV_WARNINGS
|
||||
|
||||
from sphinx.builders.latex import default_latex_documents
|
||||
from sphinx.config import Config
|
||||
from sphinx.errors import SphinxError
|
||||
from sphinx.errors import SphinxError, ThemeError
|
||||
from sphinx.testing.util import strip_escseq
|
||||
from sphinx.util import docutils
|
||||
from sphinx.util.osutil import cd, ensuredir
|
||||
@ -215,6 +215,15 @@ def test_latex_basic_howto_ja(app, status, warning):
|
||||
assert r'\documentclass[letterpaper,10pt,dvipdfmx]{sphinxhowto}' in result
|
||||
|
||||
|
||||
@pytest.mark.sphinx('latex', testroot='latex-theme')
|
||||
def test_latex_theme(app, status, warning):
|
||||
app.builder.build_all()
|
||||
result = (app.outdir / 'python.tex').read_text(encoding='utf8')
|
||||
print(result)
|
||||
assert r'\def\sphinxdocclass{book}' in result
|
||||
assert r'\documentclass[letterpaper,10pt,english]{sphinxbook}' in result
|
||||
|
||||
|
||||
@pytest.mark.sphinx('latex', testroot='basic', confoverrides={'language': 'zh'})
|
||||
def test_latex_additional_settings_for_language_code(app, status, warning):
|
||||
app.builder.build_all()
|
||||
@ -1465,6 +1474,7 @@ def test_default_latex_documents():
|
||||
'author': "Wolfgang Schäuble & G'Beckstein."})
|
||||
config.init_values()
|
||||
config.add('latex_engine', None, True, None)
|
||||
config.add('latex_theme', 'manual', True, None)
|
||||
expected = [('index', 'stasi.tex', 'STASI™ Documentation',
|
||||
r"Wolfgang Schäuble \& G\textquotesingle{}Beckstein.\@{}", 'manual')]
|
||||
assert default_latex_documents(config) == expected
|
||||
|
Loading…
Reference in New Issue
Block a user