Browse Source

The multi_part plugin has been set as deprecated
Added series plugin

Leonardo Giordani 9 years ago
parent
commit
62e09d3648
5 changed files with 139 additions and 10 deletions
  1. 2 0
      multi_part/Readme.md
  2. 16 10
      multi_part/multi_part.py
  3. 45 0
      series/Readme.md
  4. 1 0
      series/__init__.py
  5. 75 0
      series/series.py

+ 2 - 0
multi_part/Readme.md

@@ -1,6 +1,8 @@
 Multi parts posts
 -----------------
 
+**This plugin has been deprecated. See the series plugin for a better support of multi part articles.**
+
 The multi-part posts plugin allow you to write multi-part posts.
 
 In order to mark posts as part of a multi-part post, use the `:parts:` metadata:

+ 16 - 10
multi_part/multi_part.py

@@ -12,22 +12,28 @@ from collections import defaultdict
 
 from pelican import signals
 
+from logging import warning
+
+warning_message = """multi_part plugin: this plugin has been deprecated.
+The 'series' plugin provides better support for multi part articles.
+"""
 
 def aggregate_multi_part(generator):
-        multi_part = defaultdict(list)
+    warning(warning_message)
+    multi_part = defaultdict(list)
 
-        for article in generator.articles:
-            if 'parts' in article.metadata:
-                multi_part[article.metadata['parts']].append(article)
+    for article in generator.articles:
+        if 'parts' in article.metadata:
+            multi_part[article.metadata['parts']].append(article)
 
-        for part_id in multi_part:
-            parts = multi_part[part_id]
+    for part_id in multi_part:
+        parts = multi_part[part_id]
 
-            # Sort by date
-            parts.sort(key=lambda x: x.metadata['date'])
+        # Sort by date
+        parts.sort(key=lambda x: x.metadata['date'])
 
-            for article in parts:
-                article.metadata['parts_articles'] = parts
+        for article in parts:
+            article.metadata['parts_articles'] = parts
 
 
 def register():

+ 45 - 0
series/Readme.md

@@ -0,0 +1,45 @@
+Series plugin
+-------------
+
+The series plugin allows you to join different posts into a series.
+
+In order to mark posts as part of a series, use the `:series:` metadata:
+
+    :series:  NAME_OF_THIS_SERIES
+
+or, in Markdown syntax
+
+    Series: NAME_OF_THIS_SERIES
+
+The plugin collects all articles belonging to the same series and provides
+series-related variables that you can use in your template.
+
+By default articles in a series are ordered by date and then automatically numbered.
+
+If you want to force a given order just specify the `:series_index` metadata,
+starting from 1. All articles with this enforced index are put at the beginning of
+the series and ordered according to the index itself. All the remaining articles
+come after them, ordered by date.
+
+The plugin provides the following variables to your templates
+
+    * `article.series.series` is the name of the series as specified in the article metadata
+    * `article.series.index` is the index of the current article inside the series
+    * `article.series.all` is an ordered list of all articles in the series (including the current one)
+    * `article.series.all_previous` is an ordered list of the articles published before the current one
+    * `article.series.all_next` is an ordered list of the articles published after the current one
+    * `article.series.previous` is the previous article in the series (a shortcut to `article.series.all_previous[-1]`)
+    * `article.series.next` is the next article in the series (a shortcut to `article.series.all_next[0]`)
+
+For example:
+
+    {% if article.series %}
+        <p>This post is part {{ article.series.index }} of the "{{ article.series.series }}" series:</p>
+        <ol class="parts">
+            {% for part_article in article.series.all %}
+                <li {% if part_article == article %}class="active"{% endif %}>
+                    <a href='{{ SITEURL }}/{{ part_article.url }}'>{{ part_article.title }}</a>
+                </li>
+            {% endfor %}
+        </ol>
+    {% endif %}

+ 1 - 0
series/__init__.py

@@ -0,0 +1 @@
+from .series import *

+ 75 - 0
series/series.py

@@ -0,0 +1,75 @@
+# -*- coding: utf-8 -*-
+"""
+This plugin extends the original series plugin
+by FELD Boris <lothiraldan@gmail.com>
+
+Copyright (c) Leonardo Giordani <giordani.leonardo@gmail.com>
+
+Joins articles in a series and provides variables to
+manage the series in the template.
+"""
+
+from collections import defaultdict
+
+from pelican import signals
+
+from logging import warning
+
+from operator import itemgetter
+
+
+def aggregate_series(generator):
+    series = defaultdict(list)
+
+    # This cycles through all articles in the given generator
+    # and collects the 'series' metadata, if present.
+    # The 'series_index' metadata is also stored, if specified
+    for article in generator.articles:
+        if 'series' in article.metadata:
+            article_entry = (
+                article.metadata.get('series_index', None),
+                article.metadata['date'],
+                article
+            )
+
+            series[article.metadata['series']].append(article_entry)
+
+    # This uses items() which on Python2 is not a generator
+    # but we are dealing with a small amount of data so
+    # there shouldn't be performance issues =)
+    for series_name, series_articles in series.items():
+        # This is not DRY but very simple to understand
+        forced_order_articles = [
+            art_tup for art_tup in series_articles if art_tup[0] is not None]
+
+        date_order_articles = [
+            art_tup for art_tup in series_articles if art_tup[0] is None]
+
+        forced_order_articles.sort(key=itemgetter(0))
+        date_order_articles.sort(key=itemgetter(1))
+
+        all_articles = forced_order_articles + date_order_articles
+        ordered_articles = [art_tup[2] for art_tup in all_articles]
+        enumerated_articles = enumerate(ordered_articles)
+
+        for index, article in enumerated_articles:
+            article.series = dict()
+            article.series['name'] = series_name
+            article.series['index'] = index + 1
+            article.series['all'] = ordered_articles
+            article.series['all_previous'] = ordered_articles[0: index]
+            article.series['all_next'] = ordered_articles[index + 1:]
+
+            if index > 0:
+                article.series['previous'] = ordered_articles[index - 1]
+            else:
+                article.series['previous'] = None
+
+            try:
+                article.series['next'] = ordered_articles[index + 1]
+            except IndexError:
+                article.series['next'] = None
+
+
+def register():
+    signals.article_generator_finalized.connect(aggregate_series)