Skip to content

Support themes generically #323

@ykrods

Description

@ykrods

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:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions