1
0
Fork 0
forked from github/pelican

Merge pull request #1756 from avaris/articles_order_by

Fix #1647: Fix ARTICLE_ORDER_BY and add the ability to reverse order
This commit is contained in:
Justin Mayer 2015-06-13 12:55:28 -07:00
commit 3c8a7c9fd7
5 changed files with 115 additions and 35 deletions

View file

@ -277,14 +277,6 @@ Setting name (followed by default value, if any) What does it do?
====================================================== ==============================================================
``ARTICLE_URL = '{slug}.html'`` The URL to refer to an article.
``ARTICLE_SAVE_AS = '{slug}.html'`` The place where we will save an article.
``ARTICLE_ORDER_BY = 'slug'`` The metadata attribute used to sort articles. By default,
the ``articles_page.object_list`` template variable is
ordered by slug. If you modify this, make sure all
articles contain the attribute you specify. You can also
specify a "sorting" function of one argument that is used
to extract a comparison key from each article. For example,
sorting by title without using the built-in functionality
would use the function ``operator.attrgetter('title')``.
``ARTICLE_LANG_URL = '{slug}-{lang}.html'`` The URL to refer to an article which doesn't use the
default language.
``ARTICLE_LANG_SAVE_AS = '{slug}-{lang}.html'`` The place where we will save an article which
@ -299,17 +291,6 @@ Setting name (followed by default value, if any) What does it do?
``PAGE_SAVE_AS = 'pages/{slug}.html'`` The location we will save the page. This value has to be
the same as PAGE_URL or you need to use a rewrite in
your server config.
``PAGE_ORDER_BY = 'basename'`` The metadata attribute used to sort pages. By default
the ``PAGES`` template variable is ordered by basename
(i.e., path not included). Note that the option ``'basename'``
is a special option supported in the source code. If
you modify this setting, make sure all pages contain
the attribute you specify. You can also specify a "sorting"
function of one argument that is used to extract a comparison
key from each page. For example, the basename function looks
similar to
``lambda x: os.path.basename(getattr(x, 'source_path', ''))``.
``PAGE_LANG_URL = 'pages/{slug}-{lang}.html'`` The URL we will use to link to a page which doesn't
use the default language.
``PAGE_LANG_SAVE_AS = 'pages/{slug}-{lang}.html'`` The location we will save the page which doesn't
@ -644,14 +625,26 @@ Setting name (followed by default value, if any) What does it do?
Ordering content
================
================================================ =====================================================
================================================ ==============================================================
Setting name (followed by default value) What does it do?
================================================ =====================================================
================================================ ==============================================================
``NEWEST_FIRST_ARCHIVES = True`` Order archives by newest first by date. (False:
orders by date with older articles first.)
``REVERSE_CATEGORY_ORDER = False`` Reverse the category order. (True: lists by reverse
alphabetical order; default lists alphabetically.)
================================================ =====================================================
``ARTICLE_ORDER_BY = 'reversed-date'`` Defines how the articles (``articles_page.object_list`` in
the template) are sorted. Valid options are: metadata as a
string (use ``reversed-`` prefix the reverse the sort order),
special option ``'basename'`` which will use the basename of
the file (without path) or a custom function to extract the
sorting key from articles. The default value,
``'reversed-date'``, will sort articles by date in reverse
order (i.e. newest article comes first).
``PAGE_ORDER_BY = 'basename'`` Defines how the pages (``PAGES`` variable in the template)
are sorted. Options are same as ``ARTICLE_ORDER_BY``.
The default value, ``'basename'`` will sort pages by their
basename.
================================================ ==============================================================
Themes

View file

@ -561,8 +561,7 @@ class ArticlesGenerator(CachingGenerator):
self.tags[tag].append(article)
for author in getattr(article, 'authors', []):
self.authors[author].append(article)
# sort the articles by date
self.articles.sort(key=attrgetter('date'), reverse=True)
self.dates = list(self.articles)
self.dates.sort(key=attrgetter('date'),
reverse=self.context['NEWEST_FIRST_ARCHIVES'])

View file

@ -65,7 +65,7 @@ DEFAULT_CONFIG = {
'OUTPUT_RETENTION': [],
'ARTICLE_URL': '{slug}.html',
'ARTICLE_SAVE_AS': '{slug}.html',
'ARTICLE_ORDER_BY': 'slug',
'ARTICLE_ORDER_BY': 'reversed-date',
'ARTICLE_LANG_URL': '{slug}-{lang}.html',
'ARTICLE_LANG_SAVE_AS': '{slug}-{lang}.html',
'DRAFT_URL': 'drafts/{slug}.html',

View file

@ -387,6 +387,65 @@ class TestArticlesGenerator(unittest.TestCase):
'パイソン', 'マック'])
self.assertEqual(tags, tags_expected)
def test_article_order_by(self):
settings = get_settings(filenames={})
settings['DEFAULT_CATEGORY'] = 'Default'
settings['DEFAULT_DATE'] = (1970, 1, 1)
settings['CACHE_CONTENT'] = False # cache not needed for this logic tests
settings['ARTICLE_ORDER_BY'] = 'title'
generator = ArticlesGenerator(
context=settings.copy(), settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
generator.generate_context()
expected = [
'An Article With Code Block To Test Typogrify Ignore',
'Article title',
'Article with Nonconformant HTML meta tags',
'Article with markdown and summary metadata multi',
'Article with markdown and summary metadata single',
'Article with markdown containing footnotes',
'Article with template',
'Rst with filename metadata',
'Test Markdown extensions',
'Test markdown File',
'Test md File',
'Test mdown File',
'Test mkd File',
'This is a super article !',
'This is a super article !',
'This is a super article !',
'This is a super article !',
'This is a super article !',
'This is a super article !',
'This is an article with category !',
'This is an article with multiple authors in lastname, firstname format!',
'This is an article with multiple authors in list format!',
'This is an article with multiple authors!',
'This is an article with multiple authors!',
'This is an article without category !',
'This is an article without category !',
'マックOS X 10.8でパイソンとVirtualenvをインストールと設定']
articles = [article.title for article in generator.articles]
self.assertEqual(articles, expected)
# reversed title
settings = get_settings(filenames={})
settings['DEFAULT_CATEGORY'] = 'Default'
settings['DEFAULT_DATE'] = (1970, 1, 1)
settings['CACHE_CONTENT'] = False # cache not needed for this logic tests
settings['ARTICLE_ORDER_BY'] = 'reversed-title'
generator = ArticlesGenerator(
context=settings.copy(), settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
generator.generate_context()
articles = [article.title for article in generator.articles]
self.assertEqual(articles, list(reversed(expected)))
class TestPageGenerator(unittest.TestCase):
# Note: Every time you want to test for a new field; Make sure the test
@ -473,6 +532,23 @@ class TestPageGenerator(unittest.TestCase):
pages = self.distill_pages(generator.pages)
self.assertEqual(pages_expected_sorted_by_title, pages)
# sort by title reversed
pages_expected_sorted_by_title = [
['This is a test page with a preset template', 'published',
'custom'],
['This is a test page', 'published', 'page'],
['This is a markdown test page', 'published', 'page'],
['Page with a bunch of links', 'published', 'page'],
['A Page (Test) for sorting', 'published', 'page'],
]
settings['PAGE_ORDER_BY'] = 'reversed-title'
generator = PagesGenerator(
context=settings.copy(), settings=settings,
path=CUR_DIR, theme=settings['THEME'], output_path=None)
generator.generate_context()
pages = self.distill_pages(generator.pages)
self.assertEqual(pages_expected_sorted_by_title, pages)
def test_tag_and_category_links_on_generated_pages(self):
"""
Test to ensure links of the form {tag}tagname and {category}catname

View file

@ -541,16 +541,28 @@ def process_translations(content_list, order_by=None):
try:
index.sort(key=order_by)
except Exception:
logger.error('Error sorting with function {}'.format(order_by))
elif order_by == 'basename':
index.sort(key=lambda x: os.path.basename(x.source_path or ''))
elif order_by != 'slug':
try:
index.sort(key=attrgetter(order_by))
except AttributeError:
error_msg = ('There is no "{}" attribute in the item metadata.'
'Defaulting to slug order.')
logger.warning(error_msg.format(order_by))
logger.error('Error sorting with function %s', order_by)
elif isinstance(order_by, six.string_types):
if order_by.startswith('reversed-'):
order_reversed = True
order_by = order_by.replace('reversed-', '', 1)
else:
order_reversed = False
if order_by == 'basename':
index.sort(key=lambda x: os.path.basename(x.source_path or ''),
reverse=order_reversed)
# already sorted by slug, no need to sort again
elif not (order_by == 'slug' and not order_reversed):
try:
index.sort(key=attrgetter(order_by),
reverse=order_reversed)
except AttributeError:
logger.warning('There is no "%s" attribute in the item '
'metadata. Defaulting to slug order.', order_by)
else:
logger.warning('Invalid *_ORDER_BY setting (%s).'
'Valid options are strings and functions.', order_by)
return index, translations