Describe the feature
Hi ablog developers,
This issue is a bit long, so please feel free to read it when you have time ☕ .
Related: #310, #108
Goal
Discuss a generic approach for supporting Sphinx themes in ablog, instead of adding theme-specific support on a case-by-case basis.
Current situation and key points
- ablog provides its own
page.html template, but it does not coexist well with page.html provided by external themes.
- By default, ablog’s
page.html takes precedence over the theme’s template.
- When
skip_injecting_base_ablog_template is enabled in conf.py, ablog’s page.html is not used.
- When the theme option
ablog_inject_templates_after_theme is enabled, the theme’s templates take precedence.
- Using the theme’s templates usually resolves layout issues, but some features provided by ablog are no longer rendered as HTML (this is a trade-off):
- Links to RSS/Atom feeds
- Link to Font Awesome CSS
- Previous/next post navigation
- Disqus comment section
Possible approach
To avoid this trade-off, one possible approach is to extend the theme’s templates from ablog’s templates, and inject ablog-specific elements there.
This approach is already used in the Pull Request #310:
https://github.com/SilverRainZ/ablog-with-shibuya/blob/6f6adbc896faca10365a947348de681b523a49e6/src/ablog/templates/page.html#L1
Regarding the use of a theme name as a prefix:
Sphinx adds both the theme directory and its parent directory to the template search paths, which allows templates to be referenced with a theme-name prefix.
Although I have not fully traced the original motivation, this mechanism likely exists to avoid infinite loops when using extends "page.html" inside page.html itself.
Relevant code in Sphinx:
https://github.com/sphinx-doc/sphinx/blob/cc7c6f435ad37bb12264f8118c8461b230e6830c/sphinx/jinja2glue.py#L172-L198
One important caveat is that themes can have inheritance relationships.
Even if a_theme/page.html does not exist, parent_theme/page.html may exist and be used for rendering.
Therefore, when deciding which template ablog’s page.html should extend, it may be necessary to traverse the theme inheritance chain.
Another challenge: content blocks
Another challenge for generalization is that the Jinja2 block that contains the main content (the HTML converted from reST or Markdown, stored in the body variable) differs between themes.
For ablog’s previous/next post navigation and the Disqus comment section, these elements need to be placed after the article content. However, the appropriate block differs depending on the theme.
alabaster (basic)
https://github.com/sphinx-doc/sphinx/blob/cc7c6f435ad37bb12264f8118c8461b230e6830c/sphinx/themes/basic/page.html#L2-L5
{{ body }} is placed inside the {% block body %}
- The
{% block content %} wraps the {% block body %}
furo
https://github.com/pradyunsg/furo/blob/4e7a7e0308bfdfef84db3bb3759278c431ebd97f/src/furo/theme/furo/page.html#L111
{{ body }} is placed inside the {% block content %}
- The
{% block body %} wraps the {% block content %}
shibuya
https://github.com/lepture/shibuya/blob/a98526255a61675bbb97e85d7a5087ee4b878359/src/shibuya/theme/shibuya/layout/default.html#L49
{{ body }} is placed inside the {% block content %}
- The
{% block body %} wraps the {% block content %}
pydata-sphinx-theme
https://github.com/pydata/pydata-sphinx-theme/tree/main/src/pydata_sphinx_theme/theme/pydata_sphinx_theme
{{ body }} is placed inside the {% block body %}
- This theme does not provide
page.html, so basic/page.html is used via inheritance
- As with
basic, the {% block content %} wraps the {% block body %}
Proposed solution
Prototype implementation
At least for the themes listed above, it seems sufficient to control whether the comment section is inserted into the content block or the body block.
As a prototype, I implemented an approach that adds a theme-specific setting theme_content_block in conf.py to select one of the two.
The code diff is available here:
PR: #324
And the ablog documentation built with different themes can be found below:
Describe the feature
Hi ablog developers,
This issue is a bit long, so please feel free to read it when you have time ☕ .
Related: #310, #108
Goal
Discuss a generic approach for supporting Sphinx themes in ablog, instead of adding theme-specific support on a case-by-case basis.
Current situation and key points
page.htmltemplate, but it does not coexist well withpage.htmlprovided by external themes.page.htmltakes precedence over the theme’s template.skip_injecting_base_ablog_templateis enabled inconf.py, ablog’spage.htmlis not used.ablog_inject_templates_after_themeis enabled, the theme’s templates take precedence.Possible approach
To avoid this trade-off, one possible approach is to extend the theme’s templates from ablog’s templates, and inject ablog-specific elements there.
This approach is already used in the Pull Request #310:
https://github.com/SilverRainZ/ablog-with-shibuya/blob/6f6adbc896faca10365a947348de681b523a49e6/src/ablog/templates/page.html#L1
Regarding the use of a theme name as a prefix:
Sphinx adds both the theme directory and its parent directory to the template search paths, which allows templates to be referenced with a theme-name prefix.
Although I have not fully traced the original motivation, this mechanism likely exists to avoid infinite loops when using
extends "page.html"insidepage.htmlitself.Relevant code in Sphinx:
https://github.com/sphinx-doc/sphinx/blob/cc7c6f435ad37bb12264f8118c8461b230e6830c/sphinx/jinja2glue.py#L172-L198
One important caveat is that themes can have inheritance relationships.
Even if
a_theme/page.htmldoes not exist,parent_theme/page.htmlmay exist and be used for rendering.Therefore, when deciding which template ablog’s
page.htmlshould extend, it may be necessary to traverse the theme inheritance chain.Another challenge: content blocks
Another challenge for generalization is that the Jinja2 block that contains the main content (the HTML converted from reST or Markdown, stored in the body variable) differs between themes.
For ablog’s previous/next post navigation and the Disqus comment section, these elements need to be placed after the article content. However, the appropriate block differs depending on the theme.
alabaster (basic)
https://github.com/sphinx-doc/sphinx/blob/cc7c6f435ad37bb12264f8118c8461b230e6830c/sphinx/themes/basic/page.html#L2-L5
{{ body }}is placed inside the{% block body %}{% block content %}wraps the{% block body %}furo
https://github.com/pradyunsg/furo/blob/4e7a7e0308bfdfef84db3bb3759278c431ebd97f/src/furo/theme/furo/page.html#L111
{{ body }}is placed inside the{% block content %}{% block body %}wraps the{% block content %}shibuya
https://github.com/lepture/shibuya/blob/a98526255a61675bbb97e85d7a5087ee4b878359/src/shibuya/theme/shibuya/layout/default.html#L49
{{ body }}is placed inside the{% block content %}{% block body %}wraps the{% block content %}pydata-sphinx-theme
https://github.com/pydata/pydata-sphinx-theme/tree/main/src/pydata_sphinx_theme/theme/pydata_sphinx_theme
{{ body }}is placed inside the{% block body %}page.html, sobasic/page.htmlis used via inheritancebasic, the{% block content %}wraps the{% block body %}Proposed solution
Prototype implementation
At least for the themes listed above, it seems sufficient to control whether the comment section is inserted into the
content blockor thebody block.As a prototype, I implemented an approach that adds a theme-specific setting
theme_content_blockinconf.pyto select one of the two.The code diff is available here:
PR: #324
And the ablog documentation built with different themes can be found below: