support both implicit and explicit inheritance with THEMES

This commit is contained in:
Ondrej Grover 2014-11-05 09:53:20 +01:00
commit b22f760042
4 changed files with 51 additions and 41 deletions

View file

@ -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 the paths defined in this settings, they will be
progressively overwritten. progressively overwritten.
``CSS_FILE = 'main.css'`` Specify the CSS file you want to load. ``CSS_FILE = 'main.css'`` Specify the CSS file you want to load.
``THEMES = {}`` Extra themes that can be inherited from. They can also ``THEMES = ('simple', ('!simple', 'simple'))`` Extra themes that can be inherited from, either
inherit from each other. Use a dictionary to make a list implicitly (just a path to the theme) or explicitly
of all the available list. The key in the dictionary will using a prefix marker (tuple of prefix and path to
also be the prefix you use to inherit from the theme. theme). They can also inherit from each other,
but only in the specified order.
Example: ``THEMES = {'!foo': foo, '!foobar':foobar}`` See :ref:`theme_inheritance` for details.
================================================ ===================================================== ================================================ =====================================================

View file

@ -346,45 +346,50 @@ Here is a complete list of the feed variables::
TRANSLATION_FEED_ATOM TRANSLATION_FEED_ATOM
TRANSLATION_FEED_RSS TRANSLATION_FEED_RSS
.. _theme_inheritance:
Inheritance Theme inheritance
=========== =================
Since version 3.4, Pelican supports inheritance from the ``simple`` theme, as well Since version 3.6, Pelican supports both implicit and explicit
as any themes specified in the ``THEMES`` setting. You can re-use inheritance from any theme specified in the ``THEMES`` setting. By
their theme templates in your own themes. 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 Implicit Inheritance
-------------------- --------------------
If one of the mandatory files in the ``templates/`` directory of your theme is If one of the mandatory files in the ``templates/`` directory of your
missing, it will be replaced by the matching template from the ``simple`` theme. theme is missing, it will be replaced by a matching template from any
So if the HTML structure of a template in the ``simple`` theme is right for you, 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. you don't have to write a new template from scratch.
Explicit Inheritance Explicit Inheritance
-------------------- --------------------
You explicitly extend templates from the ``simple`` themes in your own themes by You explicitly extend templates from explicitly inherited themes in
using the ``{% extends %}`` directive as in the following example: 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 .. code-block:: html+jinja
{% extends "!simple/index.html" %} <!-- extends the ``index.html`` template from the ``simple`` theme --> {% extends "!simple/index.html" %} <!-- extends the ``index.html`` template from the ``simple`` theme -->
{% extends "index.html" %} <!-- "regular" extending -->
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 the ``index.html`` template from the ``foo`` theme --> {% extends "!foo/index.html" %} <!-- extends the ``index.html`` template from the ``foo`` theme -->
{% extends "index.html" %} <!-- "regular" extending, either finds a sibling template or one in an implicitly inherited theme -->
Example Example
------- -------

View file

@ -54,24 +54,28 @@ class Generator(object):
os.path.join(self.theme, 'templates'))) os.path.join(self.theme, 'templates')))
self._templates_path += self.settings['EXTRA_TEMPLATES_PATHS'] 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, explicit_themes = {}
"themes", "simple", "templates")) themes = [FileSystemLoader(self._templates_path)]
themes = {}
for theme in self.themes: for theme in self.themes:
templates_path = os.path.join(self.themes[theme], "templates") if isinstance(theme, tuple): # explicit inheritance
logger.debug('Template path for theme %s: %s', theme, 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) 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([ themes.append(PrefixLoader(explicit_themes))
FileSystemLoader(self._templates_path), loader=ChoiceLoader(themes)
simple_loader, # implicit inheritance
PrefixLoader({'!simple':simple_loader}),
PrefixLoader(themes) # explicit one
])
self.env = Environment( self.env = Environment(
trim_blocks=True, trim_blocks=True,
@ -731,7 +735,8 @@ class StaticGenerator(Generator):
os.curdir) os.curdir)
for theme in self.themes: 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, self.settings['THEME_STATIC_DIR'], self.output_path,
os.curdir) os.curdir)

View file

@ -34,7 +34,7 @@ DEFAULT_CONFIG = {
'PAGE_PATHS': ['pages'], 'PAGE_PATHS': ['pages'],
'PAGE_EXCLUDES': [], 'PAGE_EXCLUDES': [],
'THEME': DEFAULT_THEME, 'THEME': DEFAULT_THEME,
'THEMES': {}, 'THEMES': ('simple', ('!simple', 'simple')),
'OUTPUT_PATH': 'output', 'OUTPUT_PATH': 'output',
'READERS': {}, 'READERS': {},
'STATIC_PATHS': ['images'], 'STATIC_PATHS': ['images'],