123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- # -*- coding: utf-8 -*-
- """
- @Author: Alistair Magee
- Adds support for subcategories on pelican articles
- """
- import os
- from collections import defaultdict
- from operator import attrgetter
- from functools import partial
- from pelican import signals
- from pelican.urlwrappers import URLWrapper, Category
- from pelican.utils import (slugify, python_2_unicode_compatible)
- from six import text_type
- class SubCategory(URLWrapper):
- def __init__(self, name, parent, settings):
- super(SubCategory, self).__init__(name, settings)
- self.parent = parent
- self.shortname = name.split('/')
- self.shortname = self.shortname.pop()
- self.slug = slugify(self.shortname, settings.get('SLUG_SUBSTITUIONS', ()))
- if isinstance(self.parent, SubCategory):
- self.savepath = os.path.join(self.parent.savepath, self.slug)
- self.fullurl = '{}/{}'.format(self.parent.fullurl, self.slug)
- else: #parent is a category
- self.savepath = os.path.join(self.parent.slug, self.slug)
- self.fullurl = '{}/{}'.format(self.parent.slug, self.slug)
-
- def as_dict(self):
- d = self.__dict__
- d['shortname'] = self.shortname
- d['savepath'] = self.savepath
- d['fullurl'] = self.fullurl
- d['parent'] = self.parent
- return d
- def __hash__(self):
- return hash(self.fullurl)
- def _key(self):
- return self.fullurl
- def get_subcategories(generator, metadata):
- if 'SUBCATEGORY_SAVE_AS' not in generator.settings:
- generator.settings['SUBCATEGORY_SAVE_AS'] = os.path.join(
- 'subcategory', '{savepath}.html')
- if 'SUBCATEGORY_URL' not in generator.settings:
- generator.settings['SUBCATEGORY_URL'] = 'subcategory/{fullurl}.html'
- if 'subcategory_path' in metadata:
- category_list = text_type(metadata.get('subcategory_path')).split('/')
- else:
- category_list = text_type(metadata.get('category')).split('/')
- category = (category_list.pop(0)).strip()
- category = Category(category, generator.settings)
- metadata['category'] = category
- #generate a list of subcategories with their parents
- sub_list = []
- parent = category.name
- for subcategory in category_list:
- subcategory.strip()
- subcategory = parent + '/' + subcategory
- sub_list.append(subcategory)
- parent = subcategory
- metadata['subcategories'] = sub_list
- def create_subcategories(generator):
- generator.subcategories = []
- for article in generator.articles:
- parent = article.category
- actual_subcategories = []
- for subcategory in article.subcategories:
- #following line returns a list of items, tuples in this case
- sub_cat = [item for item in generator.subcategories
- if item[0].name == subcategory]
- if sub_cat:
- sub_cat[0][1].append(article)
- parent = sub_cat[0][0]
- actual_subcategories.append(parent)
- else:
- new_sub = SubCategory(subcategory, parent, generator.settings)
- generator.subcategories.append((new_sub, [article,]))
- parent = new_sub
- actual_subcategories.append(parent)
- article.subcategories = actual_subcategories
- """Add subpath and suburl to the article metadata. This allows the
- the last subcategory's fullurl and savepath to be used when definining
- Article URL's. If an article has no subcategories, the Category slug
- is used instead
- """
- try:
- last_subcat = article.subcategories[-1]
- article.metadata['subpath'] = last_subcat.savepath
- article.metadata['suburl'] = last_subcat.fullurl
- except IndexError: #No Subcategory
- article.metadata['subpath'] = article.category.slug
- article.metadata['suburl'] = article.category.slug
- def generate_subcategories(generator, writer):
- write = partial(writer.write_file,
- relative_urls=generator.settings['RELATIVE_URLS'])
- subcategory_template = generator.get_template('subcategory')
- for subcat, articles in generator.subcategories:
- articles.sort(key=attrgetter('date'), reverse=True)
- dates = [article for article in generator.dates if article in articles]
- write(subcat.save_as, subcategory_template, generator.context,
- subcategory=subcat, articles=articles, dates=dates,
- paginated={'articles': articles, 'dates': dates},
- page_name=subcat.page_name, all_articles=generator.articles)
- def generate_subcategory_feeds(generator, writer):
- for subcat, articles in generator.subcategories:
- articles.sort(key=attrgetter('date'), reverse=True)
- if generator.settings.get('SUBCATEGORY_FEED_ATOM'):
- writer.write_feed(articles, generator.context,
- generator.settings['SUBCATEGORY_FEED_ATOM']
- % subcat.fullurl)
- if generator.settings.get('SUBCATEGORY_FEED_RSS'):
- writer.write_feed(articles, generator.context,
- generator.settings['SUBCATEGORY_FEED_RSS']
- % subcat.fullurl, feed_type='rss')
- def generate(generator, writer):
- generate_subcategory_feeds(generator, writer)
- generate_subcategories(generator, writer)
- def register():
- signals.article_generator_context.connect(get_subcategories)
- signals.article_generator_finalized.connect(create_subcategories)
- signals.article_writer_finalized.connect(generate)
|