Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Atom feeds for archive indexes
* Autodiscoverable feeds for archive and tag index pages
* Generate paginated and properly archived feeds for archive indexes
  • Loading branch information
da2x committed May 4, 2015
1 parent 9910276 commit 728dd37
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 13 deletions.
2 changes: 1 addition & 1 deletion CHANGES.txt
Expand Up @@ -7,7 +7,7 @@ Features
* Substitutions for RSS_LINKS_APPEND_QUERY for identifying
the source feed (feedRelUri) and the kind of feed (feedFormat).
* New option GENERATE_ATOM, off by default
* Current and archive Atom feeds for indexes and category/tag indexes (RFC-4287 and RFC-5005)
* Current and archive Atom feeds for indexes; category, tag, and archive indexes (RFC-4287 and RFC-5005)
* Atom feed auto-discovery in HTML indexes and category/tag indexes
* .atom included in the sitemap index
* New post metadata "updated", inherits "date" if unset
Expand Down
11 changes: 11 additions & 0 deletions nikola/data/themes/base/templates/archiveindex.tmpl
@@ -1,2 +1,13 @@
## -*- coding: utf-8 -*-
<%inherit file="index.tmpl"/>

<%block name="extra_head">
${parent.extra_head()}
%if len(translations) > 1 and generate_atom:
%for language in translations:
<link rel="alternate" type="application/atom+xml" title="Atom for the ${archive_name} section (${language})" href="${_link("archive_atom", archive_name, language)}">
%endfor
%elif generate_atom:
<link rel="alternate" type="application/atom+xml" title="Atom for the ${archive_name} archive" href="${_link("archive_atom", archive_name)}">
%endif
</%block>
11 changes: 11 additions & 0 deletions nikola/data/themes/base/templates/tagindex.tmpl
@@ -1,2 +1,13 @@
## -*- coding: utf-8 -*-
<%inherit file="index.tmpl"/>

<%block name="extra_head">
${parent.extra_head()}
%if len(translations) > 1 and generate_atom:
%for language in translations:
<link rel="alternate" type="application/atom+xml" title="Atom for the ${tag} section (${language})" href="${_link(kind + "_atom", tag, language)}">
%endfor
%elif generate_atom:
<link rel="alternate" type="application/atom+xml" title="Atom for the ${tag} section" href="${_link("tag" + "_atom", tag)}">
%endif
</%block>
13 changes: 7 additions & 6 deletions nikola/nikola.py
Expand Up @@ -1571,8 +1571,8 @@ def generic_post_list_renderer(self, lang, posts, output_name,

def atom_feed_renderer(self, lang, posts, output_path, filters,
extra_context):
"""Renders Atom feeds and archives with lists of posts."""
"""Feeds become archives when no longer expected to change"""
"""Renders Atom feeds and archives with lists of posts. Feeds are
considered archives when no future updates to them are expected"""

def atom_link(link_rel, link_type, link_href):
link = lxml.etree.Element("link")
Expand All @@ -1593,6 +1593,7 @@ def atom_link(link_rel, link_type, link_href):
context["lang"] = lang
context["prevlink"] = None
context["nextlink"] = None
context["is_feed_stale"] = None
context.update(extra_context)
deps_context = copy(context)
deps_context["posts"] = [(p.meta[lang]['title'], p.permalink(lang)) for p in
Expand All @@ -1605,7 +1606,7 @@ def atom_link(link_rel, link_type, link_href):
deps_context['navigation_links'] = deps_context['global']['navigation_links'](lang)

nslist = {}
if not context["feedpagenum"] == context["feedpagecount"] - 1 and not context["feedpagenum"] == 0:
if context["is_feed_stale"] or (not context["feedpagenum"] == context["feedpagecount"] - 1 and not context["feedpagenum"] == 0):
nslist["fh"] = "http://purl.org/syndication/history/1.0"
if not self.config["RSS_TEASERS"]:
nslist["xh"] = "http://www.w3.org/1999/xhtml"
Expand Down Expand Up @@ -1634,17 +1635,17 @@ def atom_link(link_rel, link_type, link_href):
if "prevfeedlink" in context:
feed_root.append(atom_link("previous", "application/atom+xml",
self.abs_link(context["prevfeedlink"])))
if not context["feedpagenum"] == 0:
if context["is_feed_stale"] or not context["feedpagenum"] == 0:
feed_root.append(atom_link("current", "application/atom+xml",
self.abs_link(context["currentfeedlink"])))
# Older is "prev-archive" and newer is "next-archive" in archived feeds (opposite of paginated)
if "prevfeedlink" in context and not context["feedpagenum"] == context["feedpagecount"] - 1:
if "prevfeedlink" in context and (context["is_feed_stale"] or not context["feedpagenum"] == context["feedpagecount"] - 1):
feed_root.append(atom_link("next-archive", "application/atom+xml",
self.abs_link(context["prevfeedlink"])))
if "nextfeedlink" in context:
feed_root.append(atom_link("prev-archive", "application/atom+xml",
self.abs_link(context["nextfeedlink"])))
if not context["feedpagenum"] == context["feedpagecount"] - 1:
if context["is_feed_stale"] or not context["feedpagenum"] == context["feedpagecount"] - 1:
lxml.etree.SubElement(feed_root, "{http://purl.org/syndication/history/1.0}archive")
feed_root.append(atom_link("alternate", "text/html",
self.abs_link(context["permalink"])))
Expand Down
40 changes: 34 additions & 6 deletions nikola/plugins/task/archive.py
Expand Up @@ -28,6 +28,7 @@

# for tearDown with _reload we cannot use 'import from' to access LocaleBorg
import nikola.utils
import datetime
from nikola.plugin_categories import Task
from nikola.utils import config_changed, adjust_name_for_index_path, adjust_name_for_index_link

Expand All @@ -39,6 +40,7 @@ class Archive(Task):

def set_site(self, site):
site.register_path_handler('archive', self.archive_path)
site.register_path_handler('archive_atom', self.archive_atom_path)
return super(Archive, self).set_site(site)

def _prepare_task(self, kw, name, lang, posts, items, template_name,
Expand Down Expand Up @@ -81,6 +83,16 @@ def _generate_posts_task(self, kw, name, lang, posts, title, deps_translatable=N
posts = sorted(posts, key=lambda a: a.date)
posts.reverse()
if kw['archives_are_indexes']:
def page_link(i, displayed_i, num_pages, force_addition, extension=None):
feed = "_atom" if extension == ".atom" else ""
return adjust_name_for_index_link(self.site.link("archive" + feed, name, lang), i, displayed_i,
lang, self.site, force_addition, extension)

def page_path(i, displayed_i, num_pages, force_addition, extension=None):
feed = "_atom" if extension == ".atom" else ""
return adjust_name_for_index_path(self.site.path("archive" + feed, name, lang), i, displayed_i,
lang, self.site, force_addition, extension)

uptodate = []
if deps_translatable is not None:
uptodate += [config_changed(deps_translatable, 'nikola.plugins.task.archive')]
Expand All @@ -89,11 +101,12 @@ def _generate_posts_task(self, kw, name, lang, posts, title, deps_translatable=N
posts,
title,
"archiveindex.tmpl",
{},
{"archive_name": name,
"is_feed_stale": kw["is_feed_stale"]},
kw,
str(self.name),
lambda i, displayed_i, num_pages, force_addition: adjust_name_for_index_link(self.site.link("archive", name, lang), i, displayed_i, lang, self.site, force_addition),
lambda i, displayed_i, num_pages, force_addition: adjust_name_for_index_path(self.site.path("archive", name, lang), i, displayed_i, lang, self.site, force_addition),
page_link,
page_path,
uptodate)
else:
yield self._prepare_task(kw, name, lang, posts, None, "list_post.tmpl", title, deps_translatable)
Expand All @@ -113,6 +126,7 @@ def gen_tasks(self):
"pretty_urls": self.site.config['PRETTY_URLS'],
"strip_indexes": self.site.config['STRIP_INDEXES'],
"index_file": self.site.config['INDEX_FILE'],
"generate_atom": self.site.config["GENERATE_ATOM"],
}
self.site.scan_posts()
yield self.group_task()
Expand All @@ -138,8 +152,10 @@ def gen_tasks(self):
# Add archive per year or total archive
if year:
title = kw["messages"][lang]["Posts for year %s"] % year
kw["is_feed_stale"] = (datetime.datetime.utcnow().strftime("%Y") != year)
else:
title = kw["messages"][lang]["Archive"]
kw["is_feed_stale"] = False
deps_translatable = {}
for k in self.site._GLOBAL_CONTEXT_TRANSLATABLE:
deps_translatable[k] = self.site.GLOBAL_CONTEXT[k](lang)
Expand All @@ -158,6 +174,8 @@ def gen_tasks(self):
# Add archive per month
year, month = yearmonth.split('/')

kw["is_feed_stale"] = (datetime.datetime.utcnow().strftime("%Y/%m") != yearmonth)

# Filter untranslated posts (via Issue #1360)
if not kw["show_untranslated_posts"]:
posts = [p for p in posts if lang in p.translated_to]
Expand Down Expand Up @@ -189,12 +207,22 @@ def gen_tasks(self):
items = [(y, self.site.link("archive", y, lang)) for y in years]
yield self._prepare_task(kw, None, lang, None, items, "list.tmpl", kw["messages"][lang]["Archive"])

def archive_path(self, name, lang):
def archive_path(self, name, lang, is_feed=False):
if is_feed:
extension = ".atom"
archive_file = os.path.splitext(self.site.config['ARCHIVE_FILENAME'])[0] + extension
index_file = os.path.splitext(self.site.config['INDEX_FILE'])[0] + extension
else:
archive_file = self.site.config['ARCHIVE_FILENAME']
index_file = self.site.config['INDEX_FILE']
if name:
return [_f for _f in [self.site.config['TRANSLATIONS'][lang],
self.site.config['ARCHIVE_PATH'], name,
self.site.config['INDEX_FILE']] if _f]
index_file] if _f]
else:
return [_f for _f in [self.site.config['TRANSLATIONS'][lang],
self.site.config['ARCHIVE_PATH'],
self.site.config['ARCHIVE_FILENAME']] if _f]
archive_file] if _f]

def archive_atom_path(self, name, lang):
return self.archive_path(name, lang, is_feed=True)

0 comments on commit 728dd37

Please sign in to comment.