diff --git a/docs/settings.rst b/docs/settings.rst index 5e91711f..e8743238 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -720,12 +720,12 @@ Setting name (followed by default value, if any) What does it do? the paths defined in this settings, they will be progressively overwritten. ``CSS_FILE = 'main.css'`` Specify the CSS file you want to load. -``THEMES = {}`` Extra themes that can be inherited from. They can also - inherit from each other. Use a dictionary to make a list - of all the available list. The key in the dictionary will - also be the prefix you use to inherit from the theme. - - Example: ``THEMES = {'!foo': foo, '!foobar':foobar}`` +``THEMES = ('simple', ('!simple', 'simple'))`` Extra themes that can be inherited from, either + implicitly (just a path to the theme) or explicitly + using a prefix marker (tuple of prefix and path to + theme). They can also inherit from each other, + but only in the specified order. + See :ref:`theme_inheritance` for details. ================================================ ===================================================== diff --git a/docs/themes.rst b/docs/themes.rst index 4aa4da6b..81854382 100644 --- a/docs/themes.rst +++ b/docs/themes.rst @@ -346,45 +346,50 @@ Here is a complete list of the feed variables:: TRANSLATION_FEED_ATOM TRANSLATION_FEED_RSS +.. _theme_inheritance: -Inheritance -=========== +Theme inheritance +================= -Since version 3.4, Pelican supports inheritance from the ``simple`` theme, as well -as any themes specified in the ``THEMES`` setting. You can re-use -their theme templates in your own themes. +Since version 3.6, Pelican supports both implicit and explicit +inheritance from any theme specified in the ``THEMES`` setting. By +default the special ``simple`` theme is inherited both implicitly and +explicitly, so you can re-use its theme templates in your own themes. Implicit Inheritance -------------------- -If one of the mandatory files in the ``templates/`` directory of your theme is -missing, it will be replaced by the matching template from the ``simple`` theme. -So if the HTML structure of a template in the ``simple`` theme is right for you, +If one of the mandatory files in the ``templates/`` directory of your +theme is missing, it will be replaced by a matching template from any +of the implicitly inherited themes. So if the HTML structure of a +template in the by default inherited ``simple`` theme is right for you, you don't have to write a new template from scratch. Explicit Inheritance -------------------- -You explicitly extend templates from the ``simple`` themes in your own themes by -using the ``{% extends %}`` directive as in the following example: +You explicitly extend templates from explicitly inherited themes in +your own themes by using the ``{% extends %}`` directive as in the +following example: + +With the following ``THEMES`` setting which is the default plus an +extra explicitly inherited theme + +.. code-block:: python + + THEMES = ('simple', ('!simple', 'simple'), ('!foo', 'foo')) + +You can extend parent (inherited) or sibling (your own theme) templates .. code-block:: html+jinja {% extends "!simple/index.html" %} - {% extends "index.html" %} - -You can extend from a user created theme by adding that theme to the ``THEMES`` -setting. - -.. code-block:: python - - THEMES = {'!foo': 'foo'} - -.. code-block:: html+jinja - {% extends "!foo/index.html" %} + {% extends "index.html" %} + + Example ------- diff --git a/pelican/generators.py b/pelican/generators.py index f22b0463..d9d463ad 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -54,24 +54,28 @@ class Generator(object): os.path.join(self.theme, 'templates'))) self._templates_path += self.settings['EXTRA_TEMPLATES_PATHS'] - theme_path = os.path.dirname(os.path.abspath(__file__)) + pelican_theme_path = os.path.dirname(os.path.abspath(__file__)) + simple_theme_path = os.path.join(pelican_theme_path, + "themes", "simple", "templates") - simple_loader = FileSystemLoader(os.path.join(theme_path, - "themes", "simple", "templates")) - - themes = {} + explicit_themes = {} + themes = [FileSystemLoader(self._templates_path)] for theme in self.themes: - templates_path = os.path.join(self.themes[theme], "templates") - logger.debug('Template path for theme %s: %s', theme, + if isinstance(theme, tuple): # explicit inheritance + prefix, theme_path = theme + if prefix == '!simple': + theme_path = simple_theme_path + templates_path = os.path.join(theme_path, "templates") + logger.debug('Template path for prefix %s: %s', prefix, templates_path) - themes[theme] = FileSystemLoader(templates_path) + explicit_themes[prefix] = FileSystemLoader(templates_path) + else: # implicit inheritance + if theme == 'simple': + theme = simple_theme_path + themes.append(FileSystemLoader(theme)) - loader=ChoiceLoader([ - FileSystemLoader(self._templates_path), - simple_loader, # implicit inheritance - PrefixLoader({'!simple':simple_loader}), - PrefixLoader(themes) # explicit one - ]) + themes.append(PrefixLoader(explicit_themes)) + loader=ChoiceLoader(themes) self.env = Environment( trim_blocks=True, @@ -731,7 +735,8 @@ class StaticGenerator(Generator): os.curdir) for theme in self.themes: - self._copy_paths(self.settings['THEME_STATIC_PATHS'], self.themes[theme], + theme = theme[1] if isinstance(theme, tuple) else theme + self._copy_paths(self.settings['THEME_STATIC_PATHS'], theme, self.settings['THEME_STATIC_DIR'], self.output_path, os.curdir) diff --git a/pelican/settings.py b/pelican/settings.py index 9bb4e185..70ad3f82 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -34,7 +34,7 @@ DEFAULT_CONFIG = { 'PAGE_PATHS': ['pages'], 'PAGE_EXCLUDES': [], 'THEME': DEFAULT_THEME, - 'THEMES': {}, + 'THEMES': ('simple', ('!simple', 'simple')), 'OUTPUT_PATH': 'output', 'READERS': {}, 'STATIC_PATHS': ['images'],