In both #597 and #467 possible solutions include making changes to the existing themes so that users can override part of the template without having to re-implement the entire template. While those issues address specific requests, this is intended as an attempt to define a general model/policy for how this should work. Once the decisions are made, someone(s) can go through the templates and start to implement it.
I see three potential approaches:
Break out each overridable piece of the template into a separate file and use an include in the parent template to pull it in. The parent template would look like this:
Then the file
If a user wants to override "somefeature," she can create a directory and assign it to the
For example, to disable analytics, a user would simply create a blank file with the appropriate name (
Wrap each overridable piece in a separate block, like this:
The default implementation would then be defined right there in the built-in template (as it is now).
To override "somefeature," the user would create a directory and assign it to the
Jinja would need to be configured so that if a base template exists in the users
Implement both solutions together so that the
Then the user can choose either method to override the default behavior.
Note that in all three scenarios the user does not need to change any settings to alter the behavior except for the
A benefit of option 1 is that each feature is broken out into a separate file, which keeps everything modular. Of course, as more features are broken out, the number of files grows. And as a user overrides more features, that users number of files also grows. But users don't need to know anything about template inheritance.
A benefit of option 2 is that there is no additional files (everything can be contained in one file). And the user only needs to add one file. However, that one file could become unwieldy, expressly for beginners. Additionally, users need to understand how inheritance works to at least some extent, which could be overwhelming for beginners.
Option 3 provides the benefits of both and allows the users to eliminate the negatives according to their individual priorities.
Personally, I like option 3. My suggestion would be to use includes (wrapped in blocks) for a few of the more popular features and then wrap most (all) of the various parts of the template in a series of blocks. Fully document the includes (with example code, etc.) for beginners and simply mention that the blocks exist for advanced users.
This proposal was based in part on observing how various Sphinx themes have addressed this issue. A few have implemented option 3 and those themes now have a bunch of alternate themes available (some thirds party, some built-in) which inherit from them using blocks. At the same time, users can easily override a few basic features using includes. When the alternate theme also makes use of the includes (often including the parent's implementation), the user can even use the same override mechanisms when using the alternate theme. To be clear, I'm not suggesting MkDocs should strive to build up such a large collection of (only slightly different) built-in themes, or even support multiple levels of inheritance. I just mention it as an example of the flexibility option 3 could potentially provide users.
Any and all feedback is welcome.
The text was updated successfully, but these errors were encountered:
I have done some more research on how to implement this and I found a potential issue with the use of blocks. As I explained previously:
The user would then create a
Edit: See this comment for a simpler solution.
A workaround it to use a PrefixLoader. But then what prefix would we use? If the prefix is the name of the theme, then one might do
The problem is that MkdDocs code needs to be aware of theme prefixes. Every attempt to load a template from the Environment will need to include the prefix. So a call to load
I liked the idea of blocks because it leaves the existing templates pretty much as-is (only a few additional lines of template code are added). However, there is a lot more work in the Python code to make it work properly. However, while the "includes" method would require a major refactor of the templates (breaking one file up into a bunch of "included" files) there would be no changes needed on the Python code side of things.
I should note that there is an alternative (simpler) solution to my previous comment to make extending blocks work. In the included themes simply rename
If this is the route taken, I would think that the use of "base" and "main" should probably be reversed. But then MkDocs would need to be altered to load
And then there was this comment:
I'm thinking a
#826 highlights another problem with theme customization: how to disable a JS/CSS feature. In the case of #826, the feature is search, but the same applies to client side syntax highlighting. In both cases, there are JS and CSS that is served with every page that is not needed. With a fully customized theme, this is not a problem, but when overriding/customizing a provided theme, the only option now is to create a blank
Just noticed this was still open. This has been addressed across multiple PRs, many of which are linked above. While some of the suggestions above have not been implemented, those were questionable anyway and the major thrust of this issue has been implemented. I see no reason to leave this open.