mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Support `.jinja
` for theme static templates (#11916)
Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
This commit is contained in:
parent
5a55856dd1
commit
0806a00f05
@ -13,6 +13,12 @@ Deprecated
|
||||
Features added
|
||||
--------------
|
||||
|
||||
* #11165: Support the `officially recommended`_ ``.jinja`` suffix for template
|
||||
files.
|
||||
Patch by James Addison and Adam Turner
|
||||
|
||||
.. _officially recommended: https://jinja.palletsprojects.com/en/latest/templates/#template-file-extension
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
|
@ -247,12 +247,28 @@ template static files as well as HTML files. Therefore, Sphinx supports
|
||||
so-called "static templates", like this:
|
||||
|
||||
If the name of a file in the ``static/`` directory of a theme (or in the user's
|
||||
static path, for that matter) ends with ``_t``, it will be processed by the
|
||||
template engine. The ``_t`` will be left from the final file name. For
|
||||
example, the *classic* theme has a file ``static/classic.css_t`` which uses
|
||||
templating to put the color options into the stylesheet. When a documentation
|
||||
project is built with the classic theme, the output directory will contain a
|
||||
``_static/classic.css`` file where all template tags have been processed.
|
||||
static path) ends with ``.jinja`` or ``_t``, it will be processed by the
|
||||
template engine. The suffix will be removed from the final file name.
|
||||
|
||||
For example, a theme with a ``static/theme_styles.css.jinja`` file could use
|
||||
templating to put options into the stylesheet.
|
||||
When a documentation project is built with that theme,
|
||||
the output directory will contain a ``_static/theme_styles.css`` file
|
||||
where all template tags have been processed.
|
||||
|
||||
.. versionchanged:: 7.4
|
||||
|
||||
The preferred suffix for static templates is now ``.jinja``, in line with
|
||||
the Jinja project's `recommended file extension`_.
|
||||
|
||||
The ``_t`` file suffix for static templates is now considered 'legacy', and
|
||||
support may eventually be removed.
|
||||
|
||||
If a static template with either a ``_t`` suffix or a ``.jinja`` suffix is
|
||||
detected, it will be processed by the template engine, with the suffix
|
||||
removed from the final file name.
|
||||
|
||||
.. _recommended file extension: https://jinja.palletsprojects.com/en/latest/templates/#template-file-extension
|
||||
|
||||
|
||||
Use custom page metadata in HTML templates
|
||||
|
@ -1826,16 +1826,21 @@ Miscellany
|
||||
.. hint::
|
||||
|
||||
As an experimental feature, Sphinx can use user-defined template file for
|
||||
LaTeX source if you have a file named ``_templates/latex.tex_t`` in your
|
||||
LaTeX source if you have a file named ``_templates/latex.tex.jinja`` in your
|
||||
project.
|
||||
|
||||
Additional files ``longtable.tex_t``, ``tabulary.tex_t`` and
|
||||
``tabular.tex_t`` can be added to ``_templates/`` to configure some aspects
|
||||
of table rendering (such as the caption position).
|
||||
Additional files ``longtable.tex.jinja``, ``tabulary.tex.jinja`` and
|
||||
``tabular.tex.jinja`` can be added to ``_templates/`` to configure some
|
||||
aspects of table rendering (such as the caption position).
|
||||
|
||||
.. versionadded:: 1.6
|
||||
currently all template variables are unstable and undocumented.
|
||||
|
||||
.. versionchanged:: 7.4
|
||||
Added support for the ``.jinja`` file extension, which is preferred.
|
||||
The old file names remain supported.
|
||||
(``latex.tex_t``, ``longtable.tex_t``, ``tabulary.tex_t``, and ``tabular.tex_t``)
|
||||
|
||||
.. raw:: latex
|
||||
|
||||
\endgroup
|
||||
|
@ -15,6 +15,19 @@ if TYPE_CHECKING:
|
||||
from sphinx.util.typing import PathMatcher
|
||||
|
||||
|
||||
def _template_basename(filename: str | os.PathLike[str]) -> str | None:
|
||||
"""Given an input filename:
|
||||
If the input looks like a template, then return the filename output should
|
||||
be written to. Otherwise, return no result (None).
|
||||
"""
|
||||
basename = os.path.basename(filename)
|
||||
if basename.lower().endswith('_t'):
|
||||
return str(filename)[:-2]
|
||||
elif basename.lower().endswith('.jinja'):
|
||||
return str(filename)[:-6]
|
||||
return None
|
||||
|
||||
|
||||
def copy_asset_file(source: str | os.PathLike[str], destination: str | os.PathLike[str],
|
||||
context: dict[str, Any] | None = None,
|
||||
renderer: BaseRenderer | None = None) -> None:
|
||||
@ -37,14 +50,13 @@ def copy_asset_file(source: str | os.PathLike[str], destination: str | os.PathLi
|
||||
else:
|
||||
destination = str(destination)
|
||||
|
||||
if os.path.basename(source).endswith(('_t', '_T')) and context is not None:
|
||||
if _template_basename(source) and context is not None:
|
||||
if renderer is None:
|
||||
from sphinx.util.template import SphinxRenderer
|
||||
renderer = SphinxRenderer()
|
||||
|
||||
with open(source, encoding='utf-8') as fsrc:
|
||||
if destination.endswith(('_t', '_T')):
|
||||
destination = destination[:-2]
|
||||
destination = _template_basename(destination) or destination
|
||||
with open(destination, 'w', encoding='utf-8') as fdst:
|
||||
fdst.write(renderer.render_string(fsrc.read(), context))
|
||||
else:
|
||||
|
@ -0,0 +1 @@
|
||||
AU REVOIR, KANIGGETS
|
@ -0,0 +1,2 @@
|
||||
<!-- testing legacy _t static templates -->
|
||||
<html><project>{{ project | lower | escape }}</project></html>
|
@ -1391,6 +1391,7 @@ def test_latex_table_custom_template_caseA(app, status, warning):
|
||||
app.build(force_all=True)
|
||||
result = (app.outdir / 'python.tex').read_text(encoding='utf8')
|
||||
assert 'SALUT LES COPAINS' in result
|
||||
assert 'AU REVOIR, KANIGGETS' in result
|
||||
|
||||
|
||||
@pytest.mark.sphinx('latex', testroot='latex-table',
|
||||
|
@ -109,6 +109,11 @@ def test_nested_zipped_theme(app, status, warning):
|
||||
@pytest.mark.sphinx(testroot='theming', confoverrides={'html_theme': 'staticfiles'})
|
||||
def test_staticfiles(app, status, warning):
|
||||
app.build()
|
||||
assert (app.outdir / '_static' / 'legacytmpl.html').exists()
|
||||
assert (app.outdir / '_static' / 'legacytmpl.html').read_text(encoding='utf8') == (
|
||||
'<!-- testing legacy _t static templates -->\n'
|
||||
'<html><project>python</project></html>'
|
||||
)
|
||||
assert (app.outdir / '_static' / 'staticimg.png').exists()
|
||||
assert (app.outdir / '_static' / 'statictmpl.html').exists()
|
||||
assert (app.outdir / '_static' / 'statictmpl.html').read_text(encoding='utf8') == (
|
||||
|
@ -3,7 +3,7 @@
|
||||
from unittest import mock
|
||||
|
||||
from sphinx.jinja2glue import BuiltinTemplateLoader
|
||||
from sphinx.util.fileutil import copy_asset, copy_asset_file
|
||||
from sphinx.util.fileutil import _template_basename, copy_asset, copy_asset_file
|
||||
|
||||
|
||||
class DummyTemplateLoader(BuiltinTemplateLoader):
|
||||
@ -101,3 +101,13 @@ def test_copy_asset(tmp_path):
|
||||
assert not (destdir / '_static' / 'basic.css').exists()
|
||||
assert (destdir / '_templates' / 'layout.html').exists()
|
||||
assert not (destdir / '_templates' / 'sidebar.html').exists()
|
||||
|
||||
|
||||
def test_template_basename():
|
||||
assert _template_basename('asset.txt') is None
|
||||
assert _template_basename('asset.txt.jinja') == 'asset.txt'
|
||||
assert _template_basename('sidebar.html.jinja') == 'sidebar.html'
|
||||
|
||||
|
||||
def test_legacy_template_basename():
|
||||
assert _template_basename('asset.txt_t') == 'asset.txt'
|
||||
|
@ -42,7 +42,9 @@ METHOD_MAP = [
|
||||
# Extraction from Python source files
|
||||
('**.py', extract_python),
|
||||
# Extraction from Jinja2 template files
|
||||
('**/templates/latex/**.tex.jinja', extract_jinja2),
|
||||
('**/templates/latex/**.tex_t', extract_jinja2),
|
||||
('**/templates/latex/**.sty.jinja', extract_jinja2),
|
||||
('**/templates/latex/**.sty_t', extract_jinja2),
|
||||
# Extraction from Jinja2 HTML templates
|
||||
('**/themes/**.html', extract_jinja2),
|
||||
@ -50,6 +52,7 @@ METHOD_MAP = [
|
||||
('**/themes/**.xml', extract_jinja2),
|
||||
# Extraction from JavaScript files
|
||||
('**.js', extract_javascript),
|
||||
('**.js.jinja', extract_javascript),
|
||||
('**.js_t', extract_javascript),
|
||||
]
|
||||
OPTIONS_MAP = {
|
||||
@ -58,7 +61,9 @@ OPTIONS_MAP = {
|
||||
'encoding': 'utf-8',
|
||||
},
|
||||
# Extraction from Jinja2 template files
|
||||
'**/templates/latex/**.tex.jinja': TEX_DELIMITERS.copy(),
|
||||
'**/templates/latex/**.tex_t': TEX_DELIMITERS.copy(),
|
||||
'**/templates/latex/**.sty.jinja': TEX_DELIMITERS.copy(),
|
||||
'**/templates/latex/**.sty_t': TEX_DELIMITERS.copy(),
|
||||
# Extraction from Jinja2 HTML templates
|
||||
'**/themes/**.html': {
|
||||
|
Loading…
Reference in New Issue
Block a user