Skip to content

Commit ac3ca5e

Browse files
authored
Merge pull request #295 from liborjelinek/fix-theme-support-for-ablog
2 parents be88a0c + ba80b51 commit ac3ca5e

File tree

13 files changed

+209
-34
lines changed

13 files changed

+209
-34
lines changed

docs/conf.py

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"Ahmet": ("Ahmet Bakan", "https://ahmetbakan.com"),
5555
"Luc": ("Luc Saffre", "https://saffre-rumma.net/luc/"),
5656
"Mehmet": ("Mehmet Gerçeker", "https://github.com/mehmetg"),
57+
"Libor": ("Libor Jelínek", "https://liborjelinek.github.io/")
5758
}
5859
blog_feed_archives = True
5960
blog_feed_fulltext = True

docs/manual/ablog-configuration-options.rst

-33
Original file line numberDiff line numberDiff line change
@@ -265,39 +265,6 @@ Integration is provided by `sphinxnotes-isso`_ and the instructions there.
265265

266266
.. _sphinxnotes-isso: https://sphinx-notes.github.io/isso/
267267

268-
.. _sidebars:
269-
270-
Blog sidebars
271-
-------------
272-
273-
There are seven Ablog sidebars you can include in your HTML output using Sphinx_ :confval:`html_sidebars` configuration option (in addition to your theme sidebars).
274-
275-
- ``alog/postcard.html`` provides information regarding the current post (when on a post page)
276-
- ``alog/recentposts.html`` lists most recent five posts.
277-
- ``alog/tagcloud.html`` provides a links to a archive pages generated for each tag
278-
- ``alog/category.html``, ``alog/authors.html``, ``alog/languages.html``, and ``alog/locations.html`` sidebars generates list of link to respective archive pages with number of matching posts (e.g., "Manual 14)", "2023 (8)", "English (22")).
279-
280-
For example, sidebars that you see on this website on the left are:
281-
282-
.. code-block:: python
283-
284-
html_sidebars = {
285-
"**": [
286-
# Comes from Alabaster theme
287-
"about.html",
288-
"searchfield.html",
289-
# Ablog sidebards
290-
"ablog/postcard.html",
291-
"ablog/recentposts.html",
292-
"ablog/tagcloud.html",
293-
"ablog/categories.html",
294-
"ablog/archives.html",
295-
"ablog/authors.html",
296-
"ablog/languages.html",
297-
"ablog/locations.html",
298-
]
299-
}
300-
301268
Command Options
302269
---------------
303270

docs/manual/templates-themes.rst

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
Templating and Themes Support
2+
=============================
3+
4+
.. post:: Oct 26, 2024
5+
:tags: themes
6+
:category: Manual
7+
:author: Libor
8+
9+
Ablog, being a Sphinx extension, has highly customizable HTML output. The generated HTML files are based on `Sphinx templates`_. You, or Sphinx themes, can partially or completely override these templates to customize the resulting HTML.
10+
11+
.. _Sphinx templates: https://www.sphinx-doc.org/en/master/development/html_themes/templating.html
12+
13+
.. versionchanged:: 0.11
14+
The :doc:`Ablog 0.11 </release/ablog-v0.11-released>` has changed and improved the way you can customize templates and themes. Please note that this document describes the new way of customizing templates and themes support.
15+
16+
.. _sidebars:
17+
18+
Blog sidebars
19+
-------------
20+
21+
Sidebars are a common way to provide additional information to the reader. There are seven Ablog sidebars you can include in your HTML output using the Sphinx_ :confval:`html_sidebars` configuration option (in addition to your theme sidebars).
22+
23+
- ``alog/postcard.html`` provides information regarding the current post (when on a post page).
24+
- ``alog/recentposts.html`` lists the most recent five posts.
25+
- ``alog/tagcloud.html`` provides links to archive pages generated for each tag.
26+
- ``alog/category.html``, ``alog/authors.html``, ``alog/languages.html``, and ``alog/locations.html`` sidebars generate lists of links to respective archive pages with the number of matching posts (e.g., "Manual (14)", "2023 (8)", "English (22)").
27+
28+
For example, the sidebars that you see on this website on the left are:
29+
30+
.. code-block:: python
31+
32+
html_sidebars = {
33+
"**": [
34+
# Comes from Alabaster theme
35+
"about.html",
36+
"searchfield.html",
37+
# Ablog sidebars
38+
"ablog/postcard.html",
39+
"ablog/recentposts.html",
40+
"ablog/tagcloud.html",
41+
"ablog/categories.html",
42+
"ablog/archives.html",
43+
"ablog/authors.html",
44+
"ablog/languages.html",
45+
"ablog/locations.html",
46+
]
47+
}
48+
49+
Styling default Ablog sidebars
50+
------------------------------
51+
52+
Ablog standard sidebars are wrapped in ``<div>`` with CSS classes like :samp:`ablog-sidebar-item ablog__{<template_name>}`, making them easier to style.
53+
54+
For example, the ``recentposts.html`` template is wrapped in ``<div class="ablog-sidebar-item ablog__recentposts">``.
55+
56+
.. seealso::
57+
58+
Built-in sidebars can be found in the ``ablog/`` folder in the `Ablog source code <https://github.com/sunpy/ablog/tree/main/src/ablog/templates/ablog>`_.
59+
60+
If styling is not enough, you can override the Ablog templates in your Sphinx project or in the Sphinx theme.
61+
62+
Partial or complete override of Ablog templates
63+
-----------------------------------------------
64+
65+
To control whether Ablog injects its own templates into the Sphinx build, you can use the following ``conf.py`` configuration option:
66+
67+
.. confval:: skip_injecting_base_ablog_templates
68+
69+
If set to ``True``, Ablog will not inject its own templates into the Sphinx build. This is useful if you want to completely override Ablog templates in your Sphinx project or in the Sphinx theme. The default is ``False``.
70+
71+
Customizing templates in the project
72+
------------------------------------
73+
74+
All Ablog templates are under the ``ablog/`` folder space. For example, ``ablog/postcard.html``. You can override these templates by placing them in the ``ablog/`` folder in your project templates folder.
75+
76+
#. Add the :confval:`templates_path` option in your ``conf.py`` file:
77+
78+
.. code-block:: python
79+
80+
templates_path = ["_templates"]
81+
82+
#. Create a folder ``_templates/`` next to your ``conf.py`` file. It will hold your custom templates.
83+
#. Create a folder ``ablog/`` inside the ``_templates/`` folder.
84+
#. Create a file here with the same name as the template you want to override. For example, ``postcard.html``. This file will be used as a custom template for the sidebar. You can copy the content of the original template from the Ablog source code and modify it as you need.
85+
#. Optionally: if you want to completely override all Ablog templates, set the :confval:`skip_injecting_base_ablog_templates` option to ``True``, copy all Ablog templates here, and customize them as you need.
86+
87+
Customizing templates in the theme
88+
----------------------------------
89+
90+
If you are a Sphinx theme author, you can ship customized Ablog templates in your theme. You can override Ablog templates by placing them in the ``ablog/`` folder in your theme templates, e.g., ``ablog/postcard.html``.
91+
92+
#. In the theme root (where the ``theme.toml`` (or ``theme.ini`` in older Sphinx themes) file is), create a folder ``ablog/``.
93+
#. Create a file here with the same name as the template you want to override. For example, ``postcard.html``.
94+
#. This file will be used as a custom template for the sidebar. You can copy the content of the original template from the Ablog source code and modify it as you need.
95+
#. In your ``theme.toml`` file, add the following (under the ``[options]`` section):
96+
97+
.. code-block:: toml
98+
99+
ablog_inject_templates_after_theme = true
100+
101+
This will ensure that Ablog templates are injected *after* the theme templates, so you can override them while still using the Ablog templates as a fallback.

docs/release/ablog-v0.11-released.rst

+7
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ Pull Requests merged in:
2929

3030
`Add external links for posts <https://github.com/sunpy/ablog/pull/112>`__ from `Chris Holdgraf <https://github.com/choldgraf>`__.
3131

32+
Unreleased
33+
----------
34+
35+
Pull Requests merged in:
36+
37+
`Fix theme support for Ablog <https://github.com/sunpy/ablog/pull/295>`__ from `Libor Jelínek <https://github.com/liborjelinek/>`__.
38+
3239
ABlog v0.11.1 released
3340
----------------------
3441

Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
custom postcard.html
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
custom postcard.html from theme
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[theme]
2+
inherit = "basic"
3+
4+
[options]
5+
ablog_inject_templates_after_theme = true

roots/test-templates/conf.py

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
extensions = ["ablog"]
2+

roots/test-templates/index.rst

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
test-postlist
2+
===============
3+
4+
.. toctree::
5+
:maxdepth: 1
6+
7+
postlist

roots/test-templates/post.rst

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.. post:: 2020-12-01
2+
:author: Durden
3+
4+
post
5+
=======

roots/test-templates/postlist.rst

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
postlist
2+
==========
3+
4+
.. postlist::

src/ablog/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def builder_inited(app):
122122
try:
123123
# Modern Sphinx now errors instead of returning the default if there is not a value
124124
# in any of the config files.
125-
after_theme = theme.get_config("ablog", "inject_templates_after_theme", False)
125+
after_theme = theme.get_config("options", "ablog_inject_templates_after_theme", False)
126126
except ThemeError:
127127
after_theme = False
128128
if after_theme:

src/ablog/tests/test_templates.py

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
from pathlib import Path
2+
import pytest
3+
from sphinx.application import Sphinx
4+
from sphinx.errors import ThemeError
5+
6+
7+
@pytest.mark.sphinx("html", testroot="templates", confoverrides={"skip_injecting_base_ablog_templates": True})
8+
def test_skip_ablog_templates_but_missing_templates(app: Sphinx):
9+
"""Completely override the templates used by ablog, but not provide them."""
10+
with pytest.raises(
11+
ThemeError,
12+
match=r"An error happened in rendering the page blog/author\.\nReason: TemplateNotFound\(\"'ablog/catalog.html' not found in *.",
13+
):
14+
app.build()
15+
16+
17+
@pytest.mark.sphinx(
18+
"html",
19+
testroot="templates",
20+
confoverrides={
21+
"templates_path": ["_templates"],
22+
"skip_injecting_base_ablog_templates": False, # default value
23+
"html_sidebars": {
24+
"**": [
25+
# overriden by user
26+
"ablog/postcard.html",
27+
# fallback to builtin
28+
"ablog/authors.html",
29+
]
30+
},
31+
},
32+
)
33+
def test_override_template_but_fallback_missing(app: Sphinx, rootdir: Path):
34+
"""Partically override the only some Ablog templates, but use the Ablog ones for missing as fallback."""
35+
app.build()
36+
37+
# is the customized template it in the output?
38+
customized = (rootdir / "test-templates" / "_templates" / "ablog" / "postcard.html").read_text()
39+
source = (app.outdir / "post.html").read_text()
40+
assert customized in source
41+
42+
# is builtin template in the output?
43+
builtin = '<div class="ablog-sidebar-item ablog__authors">'
44+
assert builtin in source
45+
46+
47+
@pytest.mark.sphinx(
48+
"html",
49+
testroot="templates",
50+
confoverrides={
51+
"html_sidebars": {
52+
"**": [
53+
# overriden by theme
54+
"ablog/postcard.html",
55+
# fallback to builtin
56+
"ablog/authors.html",
57+
]
58+
},
59+
"html_theme_path": "_themes",
60+
"html_theme": "test_theme",
61+
},
62+
)
63+
def test_themes_templates_come_first(app: Sphinx, rootdir: Path):
64+
"""Ensures that if theme supplies own Ablog template, it is used over the builtin one, but fallback to builtin for missing ones."""
65+
app.build()
66+
67+
# is the customized template it in the output?
68+
customized = (rootdir / "test-templates" / "_themes" / "test_theme" / "ablog" / "postcard.html").read_text()
69+
source = (app.outdir / "post.html").read_text()
70+
assert customized in source
71+
72+
# is builtin template in the output?
73+
builtin = '<div class="ablog-sidebar-item ablog__authors">'
74+
assert builtin in source

0 commit comments

Comments
 (0)