Skip to content

Commit 0806a00

Browse files
Support .jinja for theme static templates (#11916)
Co-authored-by: Adam Turner <[email protected]>
1 parent 5a55856 commit 0806a00

File tree

11 files changed

+77
-14
lines changed

11 files changed

+77
-14
lines changed

CHANGES.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ Deprecated
1313
Features added
1414
--------------
1515

16+
* #11165: Support the `officially recommended`_ ``.jinja`` suffix for template
17+
files.
18+
Patch by James Addison and Adam Turner
19+
20+
.. _officially recommended: https://jinja.palletsprojects.com/en/latest/templates/#template-file-extension
21+
1622
Bugs fixed
1723
----------
1824

doc/development/theming.rst

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -247,12 +247,28 @@ template static files as well as HTML files. Therefore, Sphinx supports
247247
so-called "static templates", like this:
248248

249249
If the name of a file in the ``static/`` directory of a theme (or in the user's
250-
static path, for that matter) ends with ``_t``, it will be processed by the
251-
template engine. The ``_t`` will be left from the final file name. For
252-
example, the *classic* theme has a file ``static/classic.css_t`` which uses
253-
templating to put the color options into the stylesheet. When a documentation
254-
project is built with the classic theme, the output directory will contain a
255-
``_static/classic.css`` file where all template tags have been processed.
250+
static path) ends with ``.jinja`` or ``_t``, it will be processed by the
251+
template engine. The suffix will be removed from the final file name.
252+
253+
For example, a theme with a ``static/theme_styles.css.jinja`` file could use
254+
templating to put options into the stylesheet.
255+
When a documentation project is built with that theme,
256+
the output directory will contain a ``_static/theme_styles.css`` file
257+
where all template tags have been processed.
258+
259+
.. versionchanged:: 7.4
260+
261+
The preferred suffix for static templates is now ``.jinja``, in line with
262+
the Jinja project's `recommended file extension`_.
263+
264+
The ``_t`` file suffix for static templates is now considered 'legacy', and
265+
support may eventually be removed.
266+
267+
If a static template with either a ``_t`` suffix or a ``.jinja`` suffix is
268+
detected, it will be processed by the template engine, with the suffix
269+
removed from the final file name.
270+
271+
.. _recommended file extension: https://jinja.palletsprojects.com/en/latest/templates/#template-file-extension
256272

257273

258274
Use custom page metadata in HTML templates

doc/latex.rst

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1826,16 +1826,21 @@ Miscellany
18261826
.. hint::
18271827

18281828
As an experimental feature, Sphinx can use user-defined template file for
1829-
LaTeX source if you have a file named ``_templates/latex.tex_t`` in your
1829+
LaTeX source if you have a file named ``_templates/latex.tex.jinja`` in your
18301830
project.
18311831

1832-
Additional files ``longtable.tex_t``, ``tabulary.tex_t`` and
1833-
``tabular.tex_t`` can be added to ``_templates/`` to configure some aspects
1834-
of table rendering (such as the caption position).
1832+
Additional files ``longtable.tex.jinja``, ``tabulary.tex.jinja`` and
1833+
``tabular.tex.jinja`` can be added to ``_templates/`` to configure some
1834+
aspects of table rendering (such as the caption position).
18351835

18361836
.. versionadded:: 1.6
18371837
currently all template variables are unstable and undocumented.
18381838

1839+
.. versionchanged:: 7.4
1840+
Added support for the ``.jinja`` file extension, which is preferred.
1841+
The old file names remain supported.
1842+
(``latex.tex_t``, ``longtable.tex_t``, ``tabulary.tex_t``, and ``tabular.tex_t``)
1843+
18391844
.. raw:: latex
18401845

18411846
\endgroup

sphinx/util/fileutil.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@
1515
from sphinx.util.typing import PathMatcher
1616

1717

18+
def _template_basename(filename: str | os.PathLike[str]) -> str | None:
19+
"""Given an input filename:
20+
If the input looks like a template, then return the filename output should
21+
be written to. Otherwise, return no result (None).
22+
"""
23+
basename = os.path.basename(filename)
24+
if basename.lower().endswith('_t'):
25+
return str(filename)[:-2]
26+
elif basename.lower().endswith('.jinja'):
27+
return str(filename)[:-6]
28+
return None
29+
30+
1831
def copy_asset_file(source: str | os.PathLike[str], destination: str | os.PathLike[str],
1932
context: dict[str, Any] | None = None,
2033
renderer: BaseRenderer | None = None) -> None:
@@ -37,14 +50,13 @@ def copy_asset_file(source: str | os.PathLike[str], destination: str | os.PathLi
3750
else:
3851
destination = str(destination)
3952

40-
if os.path.basename(source).endswith(('_t', '_T')) and context is not None:
53+
if _template_basename(source) and context is not None:
4154
if renderer is None:
4255
from sphinx.util.template import SphinxRenderer
4356
renderer = SphinxRenderer()
4457

4558
with open(source, encoding='utf-8') as fsrc:
46-
if destination.endswith(('_t', '_T')):
47-
destination = destination[:-2]
59+
destination = _template_basename(destination) or destination
4860
with open(destination, 'w', encoding='utf-8') as fdst:
4961
fdst.write(renderer.render_string(fsrc.read(), context))
5062
else:
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
AU REVOIR, KANIGGETS
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<!-- testing legacy _t static templates -->
2+
<html><project>{{ project | lower | escape }}</project></html>

tests/test_builders/test_build_latex.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,6 +1391,7 @@ def test_latex_table_custom_template_caseA(app, status, warning):
13911391
app.build(force_all=True)
13921392
result = (app.outdir / 'python.tex').read_text(encoding='utf8')
13931393
assert 'SALUT LES COPAINS' in result
1394+
assert 'AU REVOIR, KANIGGETS' in result
13941395

13951396

13961397
@pytest.mark.sphinx('latex', testroot='latex-table',

tests/test_theming/test_theming.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ def test_nested_zipped_theme(app, status, warning):
109109
@pytest.mark.sphinx(testroot='theming', confoverrides={'html_theme': 'staticfiles'})
110110
def test_staticfiles(app, status, warning):
111111
app.build()
112+
assert (app.outdir / '_static' / 'legacytmpl.html').exists()
113+
assert (app.outdir / '_static' / 'legacytmpl.html').read_text(encoding='utf8') == (
114+
'<!-- testing legacy _t static templates -->\n'
115+
'<html><project>python</project></html>'
116+
)
112117
assert (app.outdir / '_static' / 'staticimg.png').exists()
113118
assert (app.outdir / '_static' / 'statictmpl.html').exists()
114119
assert (app.outdir / '_static' / 'statictmpl.html').read_text(encoding='utf8') == (

tests/test_util/test_util_fileutil.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from unittest import mock
44

55
from sphinx.jinja2glue import BuiltinTemplateLoader
6-
from sphinx.util.fileutil import copy_asset, copy_asset_file
6+
from sphinx.util.fileutil import _template_basename, copy_asset, copy_asset_file
77

88

99
class DummyTemplateLoader(BuiltinTemplateLoader):
@@ -101,3 +101,13 @@ def excluded(path):
101101
assert not (destdir / '_static' / 'basic.css').exists()
102102
assert (destdir / '_templates' / 'layout.html').exists()
103103
assert not (destdir / '_templates' / 'sidebar.html').exists()
104+
105+
106+
def test_template_basename():
107+
assert _template_basename('asset.txt') is None
108+
assert _template_basename('asset.txt.jinja') == 'asset.txt'
109+
assert _template_basename('sidebar.html.jinja') == 'sidebar.html'
110+
111+
112+
def test_legacy_template_basename():
113+
assert _template_basename('asset.txt_t') == 'asset.txt'

0 commit comments

Comments
 (0)