manetta
4 years ago
6 changed files with 217 additions and 3 deletions
@ -0,0 +1,101 @@ |
|||||
|
Neighbor Articles Plugin for Pelican |
||||
|
==================================== |
||||
|
|
||||
|
**NOTE:** `This plugin has been moved to its own repository <https://github.com/pelican-plugins/neighbors>`_. Please file any issues/PRs there. Once all plugins have been migrated to the `new Pelican Plugins organization <https://github.com/pelican-plugins>`_, this monolithic repository will be archived. |
||||
|
|
||||
|
------------------------------------------------------------------------------- |
||||
|
|
||||
|
This plugin adds ``next_article`` (newer) and ``prev_article`` (older) |
||||
|
variables to the article's context. |
||||
|
|
||||
|
Also adds ``next_article_in_category`` and ``prev_article_in_category``. |
||||
|
|
||||
|
|
||||
|
Usage |
||||
|
----- |
||||
|
|
||||
|
.. code-block:: html+jinja |
||||
|
|
||||
|
<ul> |
||||
|
{% if article.prev_article %} |
||||
|
<li> |
||||
|
<a href="{{ SITEURL }}/{{ article.prev_article.url}}"> |
||||
|
{{ article.prev_article.title }} |
||||
|
</a> |
||||
|
</li> |
||||
|
{% endif %} |
||||
|
{% if article.next_article %} |
||||
|
<li> |
||||
|
<a href="{{ SITEURL }}/{{ article.next_article.url}}"> |
||||
|
{{ article.next_article.title }} |
||||
|
</a> |
||||
|
</li> |
||||
|
{% endif %} |
||||
|
</ul> |
||||
|
<ul> |
||||
|
{% if article.prev_article_in_category %} |
||||
|
<li> |
||||
|
<a href="{{ SITEURL }}/{{ article.prev_article_in_category.url}}"> |
||||
|
{{ article.prev_article_in_category.title }} |
||||
|
</a> |
||||
|
</li> |
||||
|
{% endif %} |
||||
|
{% if article.next_article_in_category %} |
||||
|
<li> |
||||
|
<a href="{{ SITEURL }}/{{ article.next_article_in_category.url}}"> |
||||
|
{{ article.next_article_in_category.title }} |
||||
|
</a> |
||||
|
</li> |
||||
|
{% endif %} |
||||
|
</ul> |
||||
|
|
||||
|
Usage with the Subcategory plugin |
||||
|
--------------------------------- |
||||
|
|
||||
|
If you want to get the neigbors within a subcategory it's a little different. |
||||
|
Since an article can belong to more than one subcategory, subcategories are |
||||
|
stored in a list. If you have an article with subcategories like |
||||
|
|
||||
|
``Category/Foo/Bar`` |
||||
|
|
||||
|
it will belong to both subcategory Foo, and Foo/Bar. Subcategory neighbors are |
||||
|
added to an article as ``next_article_in_subcategory#`` and |
||||
|
``prev_article_in_subcategory#`` where ``#`` is the level of subcategory. So using |
||||
|
the example from above, subcategory1 will be Foo, and subcategory2 Foo/Bar. |
||||
|
Therefor the usage with subcategories is: |
||||
|
|
||||
|
.. code-block:: html+jinja |
||||
|
|
||||
|
<ul> |
||||
|
{% if article.prev_article_in_subcategory1 %} |
||||
|
<li> |
||||
|
<a href="{{ SITEURL }}/{{ article.prev_article_in_subcategory1.url}}"> |
||||
|
{{ article.prev_article_in_subcategory1.title }} |
||||
|
</a> |
||||
|
</li> |
||||
|
{% endif %} |
||||
|
{% if article.next_article_in_subcategory1 %} |
||||
|
<li> |
||||
|
<a href="{{ SITEURL }}/{{ article.next_article_in_subcategory1.url}}"> |
||||
|
{{ article.next_article_in_subcategory1.title }} |
||||
|
</a> |
||||
|
</li> |
||||
|
{% endif %} |
||||
|
</ul> |
||||
|
<ul> |
||||
|
{% if article.prev_article_in_subcategory2 %} |
||||
|
<li> |
||||
|
<a href="{{ SITEURL }}/{{ article.prev_article_in_subcategory2.url}}"> |
||||
|
{{ article.prev_article_in_subcategory2.title }} |
||||
|
</a> |
||||
|
</li> |
||||
|
{% endif %} |
||||
|
{% if article.next_article_in_subcategory2 %} |
||||
|
<li> |
||||
|
<a href="{{ SITEURL }}/{{ article.next_article_in_subcategory2.url}}"> |
||||
|
{{ article.next_article_in_subcategory2.title }} |
||||
|
</a> |
||||
|
</li> |
||||
|
{% endif %} |
||||
|
</ul> |
||||
|
|
@ -0,0 +1 @@ |
|||||
|
from .neighbors import * |
@ -0,0 +1,63 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
""" |
||||
|
Neighbor Articles Plugin for Pelican |
||||
|
==================================== |
||||
|
|
||||
|
This plugin adds ``next_article`` (newer) and ``prev_article`` (older) |
||||
|
variables to the article's context |
||||
|
""" |
||||
|
from pelican import signals |
||||
|
|
||||
|
|
||||
|
def iter3(seq): |
||||
|
"""Generate one triplet per element in 'seq' following PEP-479.""" |
||||
|
nxt, cur = None, None |
||||
|
for prv in seq: |
||||
|
if cur: |
||||
|
yield nxt, cur, prv |
||||
|
nxt, cur = cur, prv |
||||
|
# Don't yield anything if empty seq |
||||
|
if cur: |
||||
|
# Yield last element in seq (also if len(seq) == 1) |
||||
|
yield nxt, cur, None |
||||
|
|
||||
|
|
||||
|
def get_translation(article, prefered_language): |
||||
|
if not article: |
||||
|
return None |
||||
|
for translation in article.translations: |
||||
|
if translation.lang == prefered_language: |
||||
|
return translation |
||||
|
return article |
||||
|
|
||||
|
|
||||
|
def set_neighbors(articles, next_name, prev_name): |
||||
|
for nxt, cur, prv in iter3(articles): |
||||
|
setattr(cur, next_name, nxt) |
||||
|
setattr(cur, prev_name, prv) |
||||
|
|
||||
|
for translation in cur.translations: |
||||
|
setattr(translation, next_name, |
||||
|
get_translation(nxt, translation.lang)) |
||||
|
setattr(translation, prev_name, |
||||
|
get_translation(prv, translation.lang)) |
||||
|
|
||||
|
def neighbors(generator): |
||||
|
set_neighbors(generator.articles, 'next_article', 'prev_article') |
||||
|
|
||||
|
for category, articles in generator.categories: |
||||
|
articles.sort(key=lambda x: x.date, reverse=True) |
||||
|
set_neighbors( |
||||
|
articles, 'next_article_in_category', 'prev_article_in_category') |
||||
|
|
||||
|
if hasattr(generator, 'subcategories'): |
||||
|
for subcategory, articles in generator.subcategories: |
||||
|
articles.sort(key=lambda x: x.date, reverse=True) |
||||
|
index = subcategory.name.count('/') |
||||
|
next_name = 'next_article_in_subcategory{}'.format(index) |
||||
|
prev_name = 'prev_article_in_subcategory{}'.format(index) |
||||
|
set_neighbors(articles, next_name, prev_name) |
||||
|
|
||||
|
|
||||
|
def register(): |
||||
|
signals.article_generator_finalized.connect(neighbors) |
@ -0,0 +1,14 @@ |
|||||
|
Title: Test md File |
||||
|
Category: test |
||||
|
Tags: foo, bar, foobar |
||||
|
Date: 2010-12-02 10:14 |
||||
|
Modified: 2010-12-02 10:20 |
||||
|
Summary: I have a lot to test |
||||
|
|
||||
|
Test Markdown File Header |
||||
|
========================= |
||||
|
|
||||
|
Used for pelican test |
||||
|
--------------------- |
||||
|
|
||||
|
The quick brown fox jumped over the lazy dog's back. |
@ -0,0 +1,35 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from os.path import dirname, join |
||||
|
from tempfile import TemporaryDirectory |
||||
|
|
||||
|
from pelican.generators import ArticlesGenerator |
||||
|
from pelican.tests.support import get_settings, unittest |
||||
|
|
||||
|
from .neighbors import neighbors |
||||
|
|
||||
|
|
||||
|
CUR_DIR = dirname(__file__) |
||||
|
|
||||
|
|
||||
|
class NeighborsTest(unittest.TestCase): |
||||
|
def test_neighbors_basic(self): |
||||
|
with TemporaryDirectory() as tmpdirname: |
||||
|
generator = _build_article_generator(join(CUR_DIR, '..', 'test_data'), tmpdirname) |
||||
|
neighbors(generator) |
||||
|
def test_neighbors_with_single_article(self): |
||||
|
with TemporaryDirectory() as tmpdirname: |
||||
|
generator = _build_article_generator(join(CUR_DIR, 'test_data'), tmpdirname) |
||||
|
neighbors(generator) |
||||
|
|
||||
|
|
||||
|
def _build_article_generator(content_path, output_path): |
||||
|
settings = get_settings(filenames={}) |
||||
|
settings['PATH'] = content_path |
||||
|
context = settings.copy() |
||||
|
context['generated_content'] = dict() |
||||
|
context['static_links'] = set() |
||||
|
article_generator = ArticlesGenerator( |
||||
|
context=context, settings=settings, |
||||
|
path=settings['PATH'], theme=settings['THEME'], output_path=output_path) |
||||
|
article_generator.generate_context() |
||||
|
return article_generator |
Loading…
Reference in new issue