It would be useful to have the ability to inherit from themes other than simple. Currently there is a workaround to get that, for example for nmnlist:
THEME = 'mytheme'
EXTRA_TEMPLATES_PATHS = [ themes_path, themes_path + '/nmnlist/templates' ]
STATIC_PATHS = ['images', themes_path + '/nmnlist/static' ]
Then you extend, say, mytheme/templates/base.html from nmnlist/templates/base.html.
But that's a bit of a hack. It doesn't seem too difficult to add an option that lets the user configure a base theme instead of "simple". In generators.py:
simple_loader = FileSystemLoader(os.path.join(theme_path,
"themes", "simple", "templates"))
could be
simple_loader = FileSystemLoader(os.path.join(theme_path,
"themes", self.settings.get('BASE_THEME', 'simple'), "templates"))
Did you read the docs on theme inheritance?
Sure but it's all about simple theme.
@memeplex: I agree that this would be useful. Is this something you would be willing to work on?
Hi @memeplex. Just following up. Would you please let us know if this is something you'd like to work on?
Hi @justinmayer, sorry for the delay. To be completely honest, I don't think I could work on this during my current incarnation. It was just an idea, I could live without that feature, feel free to ditch it or postpone it sine die.
I've thought about this a lot in the course of developing Pelican Base Theme. On the pro side to this issue, 1) that theme demonstrates a use case for other themes to inherit. 2) It also seems like a straightforward improvement.
On the con side, 1) it may not be so straightforward. 2) It may be easy to get most of the benefits of inheritance without doing any work. A theme developer who forks Base could selectively merge upstream changes using the 3-way merge tool in git-merge.
@th3aftermath and I have been working on this. Here's our latest design, which he's coding: theme_inheritance.diff [Code's in PR below]. We limited the scope in this initial round of development to a single level of inheritance and a single parent, which I believe is appropriate and should satisfy the requirements of this issue, bringing much needed functionality to Pelican.
To use it, set BASE_THEME in your settingsfile.py to the parent theme and THEME to your child theme (relative or absolute). Just like with simple, the child them will override inheritable templates with the same name and inherit missing templates or specific jinja blocks called by super(), if the base.html template has {% extends "!base/base.html" %}. Notice the ! precedes the parent theme's name. See, for example, fixed_sidebar's templates/base.html. In this case, the base I am using is also named base. Perhaps the setting should be PARENT_THEME?
This code still needs a little more work. Autoreload doesn't watch for changes on the parent theme. More testing and examples would help verify usability and usefulness. Please let us know what you think.
In the future, I would like to have 2-levels of inheritance (maybe even n-levels, like Drupal's sub-theming). 2-levels would be very useful, because a common "starter" / "base" theme could have the broadest number of applications for re-use. Its child themes could fit general classes of use-cases. And then, a grandchild theme would fit a particular site and would contain all site-specific, non-reusable code.
I like the way theming in done within sphinx: a theme can define who its inherits from directly, which creates the ability to have an infinite number of subthemes.
This would mean themes would ship with metadata around them.
What do you think about that?
@mitchtbaum This seems like a good addition. What's the state of this?
I was just looking for something like this. Being able to make my own base theme that in turn inherited from something like bootstrap3 would be awesome.
Let me start by saying that I hear "add Multi-theme support" and I start thinking of theme mixins, which really excites me.
I have been combing through this feature request along with PRs getpelican/pelican#1297 (_Add configurable Base Theme setting_) and getpelican/pelican#1327 (_ Add Multi-theme support_), and a bit of the _add_multi_theme_support_ branch.
There seems to be a few things going on here. :-)
The idea of "PARENT_THEME from a metadata file within each theme" that @mitchtbaum mentioned in getpelican/pelican#1327 is great, but sounds like a V2ish type feature. I'm thinking that the original _Add Multi-theme support_ would more than suffice. Leave it to the theme maintainers to clearly document their dependency, or dependencies, then to the users to make sure that they update the THEMES properties correctly. Get all that logic squared away, then build on top of it in the future by adding theme metadata and the PARENT_THEME property.
I propose:
PARENT_THEME in there.I'm new to this whole thing. So chances are I am missing a few things. If so, I'm all ears.
Sorry, late to the party, but one of the first things I looked for when I started converting my blog to Pelican was a way to override parts of a theme without having to fork it with all the attendant update nastiness etc.
So...
Have all of the various theme inheritance options been brought into one, to borrow a term, "PEP" (Pelican Enhancement Proposal)?
If not, would it be possible to implement the simple solution proposed in the first post in this issue, maybe on its own branch for those who want to shake it around a bit?
The required modifications don't seem too traumatic. There is the issue of finding the BASE_THEME path and error checking around that since it's not part of Pelican itself as simple is, but I wouldn't think it would be a huge big deal.
It might be a good way to shake out the various use cases for a more thorough/permanent solution for a future release. Or, it might be good enough, and simple, too! :man_shrugging:
__Update__: I looked over the pull request Add Multi-theme support which seems to have been almost completed but abandoned back in October of last year (2016) and now has a bunch of conflicts that need to be resolved and is almost 600 commits behind master. Fooey.
Hi, thanks for taking the time to do this proposal. Any proposition that would allow this to happen would be useful, but needs to not break the current behavior for existant themes.
Dont hesitate to make a proposition !
Alex
@almet I'm looking at the tests first in anticipation of implementing a simple child theme scheme as discussed.
The first tests to pass are those that ensure that the inheritance from simple continues to do what the documentation says it does so I can make sure that my changes are 100% backwards compatible.
Except I don't seem to see any tests for that inheritance from simple.
Am I missing something? Entirely possible; this is my first foray into the Pelican source for anything other than checking my understanding when my stuff didn't do what I expected.
Why would something as simple as what's in PR getpelican/pelican#2072 (Add THEME_TEMPLATE_OVERRIDES) not do the job?
In the end, all that is needed is the ability to override template files. PR #2072 even allow for multiple inheritance without breaking backwards compatibility.
@digitalrounin I'm not saying that it wouldn't "do the job."
Right now I'm just trying to find out whether "doing the job", in whatever way, can provably not break backwards compatibility.
That said, I'm not sure that just overriding a template by inserting a search path is the same as theme inheritance as it doesn't seem to leave an obvious way to do the equivalent of extending the "parent" theme i.e:
{% extends "!simple/index.html" %} <!-- extends the ``index.html`` template from the ``simple`` theme -->
{% extends "index.html" %} <!-- "regular" extending -->
as mentioned in the docs on Inheritance.
I think that being able to inherit from the parent theme's templates, rather than just using the first one found in a THEME_TEMPLATE_OVERRIDES search path, is what makes a child theme a child theme.
Whether that particular definition of child theme ends up being correct or not, I'm taking the naive approach and starting from the beginning since this idea has been floating around for years and has never been added to Pelican core for whatever reason.
I'm wanting to start by finding and/or creating the passing tests that must continue to pass to prove 100% backwards compatibility.
Hopefully, working forward from there, I can help to produce a thoroughly tested solution that will be integrated into Pelican sooner rather than later.
I like the idea of having a child theme, and having the child theme define from which theme it is inheriting the templates. I believe the system could be a bit like what is done with sphinx (see http://www.sphinx-doc.org/en/stable/theming.html#creating-themes)
@almet If I'm understanding, you'd rather have some new metadata added to the themes rather than specifying inheritance in the settings?
The beauty of doing it in settings, in my mind, is that it's exactly the same as the current setup until you insert a parent theme in the theme search path in "front of" the built in simple so existing setups won't be affected at all.
It also doesn't hard-code the child theme to the parent. A well behaved child will just naturally extend the theme "above" it.
My particular concern with #2072 is that it requires complete duplication of the overridden parts rather than the extend model of the current inheritance.
@ssteinerx,
As I commented in #2072, THEME_TEMPLATE_OVERRIDES is not intended to be a replacement for inheritance, these two are not mutually exclusive. More in #2072.
As for managing inheritance via settings/configuration. Wouldn't that make it more complicated for the user? Seems like issues could arise if the correct parent template(s) are not included, or if the ordering is incorrect. There would have to be a certain amount of handholding (via documentation).
Managing via meta data seems to simplify things. It potentially allows for auto loading (downloading) dependencies?
In the past, I proposed implementing multi-theme support first followed by adding metadata support to themes. That could get ugly though.
I've responded in #2072 and agree that it will be a good stopgap.
Managing via meta data seems to simplify things. It potentially allows for auto loading (downloading) dependencies?
Yes, if you hard-code the child->parent relationship in metadata then pelican-themes can ensure that the required theme is installed. Handy, that.
I would also like mixins -- tiny block-level overrides. Not the whole template file, just an extension:
I'd like a 'mixin' to be able to consist of a single file e.g.
sidebar_mixin.html:
{
{% extends "index.html" %} <!-- extends next-up-the-tree's index.html ->
{% block sidebar %}
...additions to the sidebar...
{% endblock %}
Currently, only title, head, content, content_title blocks are defined in the simple theme, but this could be extended by theme authors, maybe with an expanded standard set of blocks.
The other issue that might be addressed by metadata is that theme authors have been adding settings to pelicanconf.py that are probably more properly isolated to a theme's own namespace rather than (dangerously) overwriting global data. While the global namespace could be considered a necessary evil in Pelican at this point, it shouldn't become the repository of all the things as is the current practice when a theme wants to add settings. Not only is there global namespace pollution but switching themes is nowhere as easy as it could/should be.
Three years worth of obviously, this is not a simple thing, and could easily be overcomplicated to the point of inscrutability: (see here)(https://developer.wordpress.org/files/2014/10/template-hierarchy.png) so let's keep it as simple as possible while allowing child themes/mixins to be both useful and usable.
Mixins would be great, but it would come at a cost: _resolution order_. If we have multiple themes each with their own chain of parents things will get complicated really fast. Not just in terms of implementation, but also for the theme maintainers. Then things could get really painful for an overly experimental blogger.
I'm not saying multiple inheritance shouldn't be done, just saying that it should be examined carefully before jumping into it.
And I am back tracking on my original comment on this thread a bit. But the more I thought about it... :-)
How about single inheritance via theme meta data like @almet proposed for a V1? That will pose its own set of issues. Then consider multiple inheritance for V2? I like the Python handles it with __mro__(). Maybe we can leverage that some how.
Given the lack of activity regarding this topic, I think it's best to close this issue for now. If someone wants to propose a solution — and be willing to implement it — please post a comment here and we can resume discussion about it.
Since both @thinkhuman and @copperchin have filed issues (see above links) to express interest in Pelican theme inheritance, I am re-opening this issue in hopes that they — along with anyone else who is interested in this feature — will work together on implementing an appropriate solution.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your participation and understanding.
@thinkhuman / @copperchin: Any progress on implementing this Pelican feature in which you expressed interest?
I was just thinking about this again recently, actually.
Unfortunately I'm currently busy trying to wrap up another project; I would still be interested in taking a stab at this in the coming weeks though.
So I'm only now just looking at this again.
This issue has a complex history -- looks like there have been many proposals and attempted implementations, but there're still a number of half-finished or abandoned works. It feels a shame throw all that work away.
Mainly, my main desire is to be able to use Jinja to extend from a single external theme, whether it's coming from local file storage (such as from a clone of pelican-themes) or from a CDN. Flask-bootstrap has an interesting way of approaching the resource lookup, which might be worth taking inspiration from?
That said, I'm wondering if it would be better to first resolve some of these related issues before continuing down this road? In particular, I'm looking at PR 1327 and wondering if I should try resolving the conflicts there so it can be merged.
I'm new here, haven't really looked under the hood yet, and not really sure about desired architecture or patterns. If anyone with a better understanding of the history here can tell me if my suggestion above is the right direction to head in, it'd be appreciated :)
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your participation and understanding.