varia.website/plugins/collate_content/collate_content.py

75 lines
2.7 KiB
Python

"""
collate_content.py
==================
(c) 2014 - Edward Stronge
Connects to the content generator finalized signal to combine
articles and pages sharing a category into lists that will be
available in the template context.
Thanks to #pelican member @kura for suggestions on creating this
plugin.
"""
from collections import defaultdict
import functools
import re
from pelican import signals
def group_content(generator, content_type):
"""
Assembles articles and pages into lists based on each
article or page's content. These lists are available
through the global context passed to the template engine.
When multiple categories are present, splits category names
based on commas and trims whitespace surrounding a
category's name. Thus, commas may not appear within a category
but they can be used to delimit categories and may be surrounded by
arbitrary amounts of whitespace.
For each category, substitutes '_' for all whitespace and '-'
characters, then creates a list named `SUBSTITUTED_CATEGORY_NAME`_articles
or `SUBSTITUTED_CATEGORY_NAME`_pages for Articles or Pages,
respectively.
Note that the *original* category name must appear in the
`CATEGORIES_TO_COLLATE` when using this plugin with category
filtering enabled.
"""
category_filter = generator.settings.get('CATEGORIES_TO_COLLATE', None)
filtering_active = type(category_filter) in (list, tuple, set)
collations = generator.context.get('collations', defaultdict(list))
for content in generator.context[content_type]:
category_list = [c.strip() for c in content.category.name.split(',')]
for category in category_list:
if filtering_active and category not in category_filter:
continue
category = substitute_category_name(category)
collations['%s_%s' % (category, content_type)].append(content)
generator.context['collations'] = collations
def substitute_category_name(category_name):
"""
Replaces whitespace and '-' characters in `category_name`
to allow category_name to be made into a valid Python
identifier.
Doesn't check all possible ways a string might be invalid;
the user of the collate_content module is advised to use
categories with Python-friendly names.
"""
return re.sub(r'\s', '_', category_name).replace('-', '_').lower()
ARTICLE_GROUPER = functools.partial(group_content, content_type='articles')
PAGE_GROUPER = functools.partial(group_content, content_type='pages')
def register():
"""Register the new plugin"""
signals.article_generator_finalized.connect(ARTICLE_GROUPER)
signals.page_generator_finalized.connect(PAGE_GROUPER)