diff options
| author | 2015-08-26 07:57:04 -0300 | |
|---|---|---|
| committer | 2015-08-26 07:57:04 -0300 | |
| commit | 8041475aab2b8efad7d2857027331bd626d26312 (patch) | |
| tree | 3980e1763c067079a4cebb425d642ca9eac834bf /nikola/plugins/task | |
| parent | b0b24795b24ee6809397fbbadf42f31f310a219f (diff) | |
Imported Upstream version 7.6.4
Diffstat (limited to 'nikola/plugins/task')
35 files changed, 368 insertions, 188 deletions
diff --git a/nikola/plugins/task/__init__.py b/nikola/plugins/task/__init__.py index a1d17a6..fd9a48f 100644 --- a/nikola/plugins/task/__init__.py +++ b/nikola/plugins/task/__init__.py @@ -23,3 +23,5 @@ # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +"""Tasks for Nikola.""" diff --git a/nikola/plugins/task/archive.plugin b/nikola/plugins/task/archive.plugin index 6687209..25f1195 100644 --- a/nikola/plugins/task/archive.plugin +++ b/nikola/plugins/task/archive.plugin @@ -1,10 +1,13 @@ [Core] -Name = render_archive -Module = archive +name = render_archive +module = archive [Documentation] -Author = Roberto Alsina -Version = 1.0 -Website = http://getnikola.com -Description = Generates the blog's archive pages. +author = Roberto Alsina +version = 1.0 +website = http://getnikola.com +description = Generates the blog's archive pages. + +[Nikola] +plugincategory = Task diff --git a/nikola/plugins/task/archive.py b/nikola/plugins/task/archive.py index 533be69..126aed4 100644 --- a/nikola/plugins/task/archive.py +++ b/nikola/plugins/task/archive.py @@ -24,6 +24,8 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +"""Render the post archives.""" + import copy import os @@ -35,17 +37,20 @@ from nikola.utils import config_changed, adjust_name_for_index_path, adjust_name class Archive(Task): + """Render the post archives.""" name = "render_archive" def set_site(self, site): + """Set Nikola 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, title, deps_translatable=None): + """Prepare an archive task.""" # name: used to build permalink and destination # posts, items: posts or items; only one of them should be used, # the other be None @@ -53,17 +58,20 @@ class Archive(Task): # title: the (translated) title for the generated page # deps_translatable: dependencies (None if not added) assert posts is not None or items is not None - + task_cfg = [copy.copy(kw)] context = {} context["lang"] = lang context["title"] = title context["permalink"] = self.site.link("archive", name, lang) + context["pagekind"] = ["list", "archive_page"] if posts is not None: context["posts"] = posts - n = len(posts) + # Depend on all post metadata because it can be used in templates (Issue #1931) + task_cfg.append([repr(p) for p in posts]) else: + # Depend on the content of items, to rebuild if links change (Issue #1931) context["items"] = items - n = len(items) + task_cfg.append(items) task = self.site.generic_post_list_renderer( lang, [], @@ -73,7 +81,7 @@ class Archive(Task): context, ) - task_cfg = {1: copy.copy(kw), 2: n} + task_cfg = {i: x for i, x in enumerate(task_cfg)} if deps_translatable is not None: task_cfg[3] = deps_translatable task['uptodate'] = task['uptodate'] + [config_changed(task_cfg, 'nikola.plugins.task.archive')] @@ -81,6 +89,7 @@ class Archive(Task): return task def _generate_posts_task(self, kw, name, lang, posts, title, deps_translatable=None): + """Genereate a task for an archive with posts.""" posts = sorted(posts, key=lambda a: a.date) posts.reverse() if kw['archives_are_indexes']: @@ -97,13 +106,15 @@ class Archive(Task): uptodate = [] if deps_translatable is not None: uptodate += [config_changed(deps_translatable, 'nikola.plugins.task.archive')] + context = {"archive_name": name, + "is_feed_stale": kw["is_feed_stale"], + "pagekind": ["index", "archive_page"]} yield self.site.generic_index_renderer( lang, posts, title, "archiveindex.tmpl", - {"archive_name": name, - "is_feed_stale": kw["is_feed_stale"]}, + context, kw, str(self.name), page_link, @@ -113,6 +124,7 @@ class Archive(Task): yield self._prepare_task(kw, name, lang, posts, None, "list_post.tmpl", title, deps_translatable) def gen_tasks(self): + """Generate archive tasks.""" kw = { "messages": self.site.MESSAGES, "translations": self.site.config['TRANSLATIONS'], @@ -211,6 +223,7 @@ class Archive(Task): yield self._prepare_task(kw, None, lang, None, items, "list.tmpl", kw["messages"][lang]["Archive"]) def archive_path(self, name, lang, is_feed=False): + """Return archive paths.""" if is_feed: extension = ".atom" archive_file = os.path.splitext(self.site.config['ARCHIVE_FILENAME'])[0] + extension @@ -228,4 +241,5 @@ class Archive(Task): archive_file] if _f] def archive_atom_path(self, name, lang): + """Return Atom archive paths.""" return self.archive_path(name, lang, is_feed=True) diff --git a/nikola/plugins/task/bundles.plugin b/nikola/plugins/task/bundles.plugin index 3fe049b..ca997d0 100644 --- a/nikola/plugins/task/bundles.plugin +++ b/nikola/plugins/task/bundles.plugin @@ -1,10 +1,13 @@ [Core] -Name = create_bundles -Module = bundles +name = create_bundles +module = bundles [Documentation] -Author = Roberto Alsina -Version = 1.0 -Website = http://getnikola.com -Description = Theme bundles using WebAssets +author = Roberto Alsina +version = 1.0 +website = http://getnikola.com +description = Theme bundles using WebAssets + +[Nikola] +plugincategory = Task diff --git a/nikola/plugins/task/bundles.py b/nikola/plugins/task/bundles.py index 6f88d0c..b9c57b9 100644 --- a/nikola/plugins/task/bundles.py +++ b/nikola/plugins/task/bundles.py @@ -24,6 +24,8 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +"""Bundle assets using WebAssets.""" + from __future__ import unicode_literals import os @@ -38,12 +40,14 @@ from nikola import utils class BuildBundles(LateTask): + """Bundle assets using WebAssets.""" name = "create_bundles" def set_site(self, site): - self.logger = utils.get_logger('bundles', site.loghandlers) + """Set Nikola site.""" + self.logger = utils.get_logger('bundles', utils.STDERR_HANDLER) if webassets is None and site.config['USE_BUNDLES']: utils.req_missing(['webassets'], 'USE_BUNDLES', optional=True) self.logger.warn('Setting USE_BUNDLES to False.') @@ -52,7 +56,6 @@ class BuildBundles(LateTask): def gen_tasks(self): """Bundle assets using WebAssets.""" - kw = { 'filters': self.site.config['FILTERS'], 'output_folder': self.site.config['OUTPUT_FOLDER'], diff --git a/nikola/plugins/task/copy_assets.plugin b/nikola/plugins/task/copy_assets.plugin index 0530ebf..c182150 100644 --- a/nikola/plugins/task/copy_assets.plugin +++ b/nikola/plugins/task/copy_assets.plugin @@ -1,10 +1,13 @@ [Core] -Name = copy_assets -Module = copy_assets +name = copy_assets +module = copy_assets [Documentation] -Author = Roberto Alsina -Version = 1.0 -Website = http://getnikola.com -Description = Copy theme assets into output. +author = Roberto Alsina +version = 1.0 +website = http://getnikola.com +description = Copy theme assets into output. + +[Nikola] +plugincategory = Task diff --git a/nikola/plugins/task/copy_assets.py b/nikola/plugins/task/copy_assets.py index a72bfdf..58521d4 100644 --- a/nikola/plugins/task/copy_assets.py +++ b/nikola/plugins/task/copy_assets.py @@ -24,6 +24,8 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +"""Copy theme assets into output.""" + from __future__ import unicode_literals import io @@ -34,6 +36,7 @@ from nikola import utils class CopyAssets(Task): + """Copy theme assets into output.""" name = "copy_assets" @@ -44,7 +47,6 @@ class CopyAssets(Task): If a file is present on two themes, use the version from the "youngest" theme. """ - kw = { "themes": self.site.THEMES, "files_folders": self.site.config['FILES_FOLDERS'], diff --git a/nikola/plugins/task/copy_files.plugin b/nikola/plugins/task/copy_files.plugin index 073676b..ce8f5d0 100644 --- a/nikola/plugins/task/copy_files.plugin +++ b/nikola/plugins/task/copy_files.plugin @@ -1,10 +1,13 @@ [Core] -Name = copy_files -Module = copy_files +name = copy_files +module = copy_files [Documentation] -Author = Roberto Alsina -Version = 1.0 -Website = http://getnikola.com -Description = Copy static files into the output. +author = Roberto Alsina +version = 1.0 +website = http://getnikola.com +description = Copy static files into the output. + +[Nikola] +plugincategory = Task diff --git a/nikola/plugins/task/copy_files.py b/nikola/plugins/task/copy_files.py index 9a039f1..1232248 100644 --- a/nikola/plugins/task/copy_files.py +++ b/nikola/plugins/task/copy_files.py @@ -24,6 +24,8 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +"""Copy static files into the output folder.""" + import os from nikola.plugin_categories import Task @@ -31,13 +33,13 @@ from nikola import utils class CopyFiles(Task): + """Copy static files into the output folder.""" name = "copy_files" def gen_tasks(self): """Copy static files into the output folder.""" - kw = { 'files_folders': self.site.config['FILES_FOLDERS'], 'output_folder': self.site.config['OUTPUT_FOLDER'], diff --git a/nikola/plugins/task/galleries.plugin b/nikola/plugins/task/galleries.plugin index 73085cd..9d3fa28 100644 --- a/nikola/plugins/task/galleries.plugin +++ b/nikola/plugins/task/galleries.plugin @@ -1,10 +1,13 @@ [Core] -Name = render_galleries -Module = galleries +name = render_galleries +module = galleries [Documentation] -Author = Roberto Alsina -Version = 1.0 -Website = http://getnikola.com -Description = Create image galleries automatically. +author = Roberto Alsina +version = 1.0 +website = http://getnikola.com +description = Create image galleries automatically. + +[Nikola] +plugincategory = Task diff --git a/nikola/plugins/task/galleries.py b/nikola/plugins/task/galleries.py index e887f18..c0df4a4 100644 --- a/nikola/plugins/task/galleries.py +++ b/nikola/plugins/task/galleries.py @@ -24,10 +24,12 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +"""Render image galleries.""" + from __future__ import unicode_literals -import io import datetime import glob +import io import json import mimetypes import os @@ -55,17 +57,19 @@ _image_size_cache = {} class Galleries(Task, ImageProcessor): + """Render image galleries.""" name = 'render_galleries' dates = {} def set_site(self, site): + """Set Nikola site.""" site.register_path_handler('gallery', self.gallery_path) site.register_path_handler('gallery_global', self.gallery_global_path) site.register_path_handler('gallery_rss', self.gallery_rss_path) - self.logger = utils.get_logger('render_galleries', site.loghandlers) + self.logger = utils.get_logger('render_galleries', utils.STDERR_HANDLER) self.kw = { 'thumbnail_size': site.config['THUMBNAIL_SIZE'], @@ -118,17 +122,20 @@ class Galleries(Task, ImageProcessor): sys.exit(1) def gallery_path(self, name, lang): + """Return a gallery path.""" gallery_path = self._find_gallery_path(name) return [_f for _f in [self.site.config['TRANSLATIONS'][lang]] + gallery_path.split(os.sep) + [self.site.config['INDEX_FILE']] if _f] def gallery_global_path(self, name, lang): + """Return the global gallery path, which contains images.""" gallery_path = self._find_gallery_path(name) return [_f for _f in gallery_path.split(os.sep) + [self.site.config['INDEX_FILE']] if _f] def gallery_rss_path(self, name, lang): + """Return path to the RSS file for a gallery.""" gallery_path = self._find_gallery_path(name) return [_f for _f in [self.site.config['TRANSLATIONS'][lang]] + gallery_path.split(os.sep) + @@ -136,7 +143,6 @@ class Galleries(Task, ImageProcessor): def gen_tasks(self): """Render image galleries.""" - self.image_ext_list = self.image_ext_list_builtin self.image_ext_list.extend(self.site.config.get('EXTRA_IMAGE_EXTENSIONS', [])) @@ -183,11 +189,13 @@ class Galleries(Task, ImageProcessor): crumbs = utils.get_crumbs(gallery, index_folder=self) - # Create index.html for each language for lang in self.kw['translations']: # save navigation links as dependencies self.kw['navigation_links|{0}'.format(lang)] = self.kw['global_context']['navigation_links'](lang) + # Create index.html for each language + for lang in self.kw['translations']: + dst = os.path.join( self.kw['output_folder'], self.site.path("gallery", gallery, lang)) @@ -238,6 +246,7 @@ class Galleries(Task, ImageProcessor): context["permalink"] = self.site.link("gallery", gallery, lang) context["enable_comments"] = self.kw['comments_in_galleries'] context["thumbnail_size"] = self.kw["thumbnail_size"] + context["pagekind"] = ["gallery_front"] if post: yield { @@ -246,7 +255,7 @@ class Galleries(Task, ImageProcessor): 'targets': [post.translated_base_path(lang)], 'file_dep': post.fragment_deps(lang), 'actions': [(post.compile, [lang])], - 'uptodate': [utils.config_changed(self.kw, 'nikola.plugins.task.galleries:post')] + post.fragment_deps_uptodate(lang) + 'uptodate': [utils.config_changed(self.kw.copy(), 'nikola.plugins.task.galleries:post')] + post.fragment_deps_uptodate(lang) } context['post'] = post else: @@ -259,6 +268,8 @@ class Galleries(Task, ImageProcessor): file_dep += [post.translated_base_path(l) for l in self.kw['translations']] file_dep_dest += [post.translated_base_path(l) for l in self.kw['translations']] + context["pagekind"] = ["gallery_page"] + yield utils.apply_filters({ 'basename': self.name, 'name': dst, @@ -268,14 +279,14 @@ class Galleries(Task, ImageProcessor): (self.render_gallery_index, ( template_name, dst, - context, + context.copy(), dest_img_list, img_titles, thumbs, file_dep))], 'clean': True, 'uptodate': [utils.config_changed({ - 1: self.kw, + 1: self.kw.copy(), 2: self.site.config["COMMENTS_IN_GALLERIES"], 3: context.copy(), }, 'nikola.plugins.task.galleries:gallery')], @@ -305,21 +316,19 @@ class Galleries(Task, ImageProcessor): ))], 'clean': True, 'uptodate': [utils.config_changed({ - 1: self.kw, + 1: self.kw.copy(), }, 'nikola.plugins.task.galleries:rss')], }, self.kw['filters']) def find_galleries(self): - """Find all galleries to be processed according to conf.py""" - + """Find all galleries to be processed according to conf.py.""" self.gallery_list = [] for input_folder, output_folder in self.kw['gallery_folders'].items(): for root, dirs, files in os.walk(input_folder, followlinks=True): self.gallery_list.append((root, input_folder, output_folder)) def create_galleries_paths(self): - """Given a list of galleries, puts their paths into self.gallery_links.""" - + """Given a list of galleries, put their paths into self.gallery_links.""" # gallery_path is "gallery/foo/name" self.proper_gallery_links = dict() self.improper_gallery_links = dict() @@ -350,7 +359,6 @@ class Galleries(Task, ImageProcessor): def create_galleries(self): """Given a list of galleries, create the output folders.""" - # gallery_path is "gallery/foo/name" for gallery_path, input_folder, _ in self.gallery_list: # have to use dirname because site.path returns .../index.html @@ -366,12 +374,11 @@ class Galleries(Task, ImageProcessor): 'actions': [(utils.makedirs, (output_gallery,))], 'targets': [output_gallery], 'clean': True, - 'uptodate': [utils.config_changed(self.kw, 'nikola.plugins.task.galleries:mkdir')], + 'uptodate': [utils.config_changed(self.kw.copy(), 'nikola.plugins.task.galleries:mkdir')], } def parse_index(self, gallery, input_folder, output_folder): - """Returns a Post object if there is an index.txt.""" - + """Return a Post object if there is an index.txt.""" index_path = os.path.join(gallery, "index.txt") destination = os.path.join( self.kw["output_folder"], output_folder, @@ -397,6 +404,7 @@ class Galleries(Task, ImageProcessor): return post def get_excluded_images(self, gallery_path): + """Get list of excluded images.""" exclude_path = os.path.join(gallery_path, "exclude.meta") try: @@ -409,7 +417,7 @@ class Galleries(Task, ImageProcessor): return excluded_image_list def get_image_list(self, gallery_path): - + """Get list of included images.""" # Gather image_list contains "gallery/name/image_name.jpg" image_list = [] @@ -424,6 +432,7 @@ class Galleries(Task, ImageProcessor): return image_list def create_target_images(self, img, input_path): + """Copy images to output.""" gallery_name = os.path.dirname(img) output_gallery = os.path.dirname( os.path.join( @@ -473,6 +482,7 @@ class Galleries(Task, ImageProcessor): }, self.kw['filters']) def remove_excluded_image(self, img, input_folder): + """Remove excluded images.""" # Remove excluded images # img is something like input_folder/demo/tesla2_lg.jpg so it's the *source* path # and we should remove both the large and thumbnail *destination* paths @@ -493,7 +503,7 @@ class Galleries(Task, ImageProcessor): (utils.remove_file, (thumb_path,)) ], 'clean': True, - 'uptodate': [utils.config_changed(self.kw, 'nikola.plugins.task.galleries:clean_thumb')], + 'uptodate': [utils.config_changed(self.kw.copy(), 'nikola.plugins.task.galleries:clean_thumb')], }, self.kw['filters']) yield utils.apply_filters({ @@ -503,7 +513,7 @@ class Galleries(Task, ImageProcessor): (utils.remove_file, (img_path,)) ], 'clean': True, - 'uptodate': [utils.config_changed(self.kw, 'nikola.plugins.task.galleries:clean_file')], + 'uptodate': [utils.config_changed(self.kw.copy(), 'nikola.plugins.task.galleries:clean_file')], }, self.kw['filters']) def render_gallery_index( @@ -516,7 +526,6 @@ class Galleries(Task, ImageProcessor): thumbs, file_dep): """Build the gallery index.""" - # The photo array needs to be created here, because # it relies on thumbnails already being created on # output @@ -543,7 +552,7 @@ class Galleries(Task, ImageProcessor): }, }) context['photo_array'] = photo_array - context['photo_array_json'] = json.dumps(photo_array) + context['photo_array_json'] = json.dumps(photo_array, sort_keys=True) self.site.render_template(template_name, output_name, context) def gallery_rss(self, img_list, dest_img_list, img_titles, lang, permalink, output_path, title): @@ -552,7 +561,6 @@ class Galleries(Task, ImageProcessor): This doesn't use generic_rss_renderer because it doesn't involve Post objects. """ - def make_url(url): return urljoin(self.site.config['BASE_URL'], url.lstrip('/')) diff --git a/nikola/plugins/task/gzip.plugin b/nikola/plugins/task/gzip.plugin index 4867fd6..7834d22 100644 --- a/nikola/plugins/task/gzip.plugin +++ b/nikola/plugins/task/gzip.plugin @@ -1,10 +1,13 @@ [Core] -Name = gzip -Module = gzip +name = gzip +module = gzip [Documentation] -Author = Roberto Alsina -Version = 1.0 -Website = http://getnikola.com -Description = Create gzipped copies of files +author = Roberto Alsina +version = 1.0 +website = http://getnikola.com +description = Create gzipped copies of files + +[Nikola] +plugincategory = Task diff --git a/nikola/plugins/task/gzip.py b/nikola/plugins/task/gzip.py index 5799839..cf16f63 100644 --- a/nikola/plugins/task/gzip.py +++ b/nikola/plugins/task/gzip.py @@ -35,12 +35,14 @@ from nikola.plugin_categories import TaskMultiplier class GzipFiles(TaskMultiplier): + """If appropiate, create tasks to create gzipped versions of files.""" name = "gzip" is_default = True def process(self, task, prefix): + """Process tasks.""" if not self.site.config['GZIP_FILES']: return [] if task.get('name') is None: @@ -70,6 +72,7 @@ class GzipFiles(TaskMultiplier): def create_gzipped_copy(in_path, out_path, command=None): + """Create gzipped copy of in_path and save it as out_path.""" if command: subprocess.check_call(shlex.split(command.format(filename=in_path))) else: diff --git a/nikola/plugins/task/indexes.plugin b/nikola/plugins/task/indexes.plugin index 5d2bf5a..d9b0e5f 100644 --- a/nikola/plugins/task/indexes.plugin +++ b/nikola/plugins/task/indexes.plugin @@ -1,10 +1,13 @@ [Core] -Name = render_indexes -Module = indexes +name = render_indexes +module = indexes [Documentation] -Author = Roberto Alsina -Version = 1.0 -Website = http://getnikola.com -Description = Generates the blog's index pages. +author = Roberto Alsina +version = 1.0 +website = http://getnikola.com +description = Generates the blog's index pages. + +[Nikola] +plugincategory = Task diff --git a/nikola/plugins/task/indexes.py b/nikola/plugins/task/indexes.py index 03d36b1..c02818e 100644 --- a/nikola/plugins/task/indexes.py +++ b/nikola/plugins/task/indexes.py @@ -24,6 +24,8 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +"""Render the blog indexes.""" + from __future__ import unicode_literals from collections import defaultdict import os @@ -33,16 +35,19 @@ from nikola import utils class Indexes(Task): + """Render the blog indexes.""" name = "render_indexes" def set_site(self, site): + """Set Nikola site.""" site.register_path_handler('index', self.index_path) site.register_path_handler('index_atom', self.index_atom_path) return super(Indexes, self).set_site(site) def gen_tasks(self): + """Render the blog indexes.""" self.site.scan_posts() yield self.group_task() @@ -80,7 +85,10 @@ class Indexes(Task): indexes_title = kw['indexes_title'](lang) or kw['blog_title'](lang) self.number_of_pages[lang] = (len(filtered_posts) + kw['index_display_post_count'] - 1) // kw['index_display_post_count'] - yield self.site.generic_index_renderer(lang, filtered_posts, indexes_title, template_name, {}, kw, 'render_indexes', page_link, page_path) + context = {} + context["pagekind"] = ["index"] + + yield self.site.generic_index_renderer(lang, filtered_posts, indexes_title, template_name, context, kw, 'render_indexes', page_link, page_path) if not self.site.config["STORY_INDEX"]: return @@ -93,13 +101,17 @@ class Indexes(Task): "strip_indexes": self.site.config['STRIP_INDEXES'], } template_name = "list.tmpl" + index_len = len(kw['index_file']) for lang in kw["translations"]: # Need to group by folder to avoid duplicated tasks (Issue #758) # Group all pages by path prefix groups = defaultdict(list) for p in self.site.timeline: if not p.is_post: - dirname = os.path.dirname(p.destination_path(lang)) + destpath = p.destination_path(lang) + if destpath[-(1 + index_len):] == '/' + kw['index_file']: + destpath = destpath[:-(1 + index_len)] + dirname = os.path.dirname(destpath) groups[dirname].append(p) for dirname, post_list in groups.items(): context = {} @@ -108,10 +120,12 @@ class Indexes(Task): output_name = os.path.join(kw['output_folder'], dirname, kw['index_file']) short_destination = os.path.join(dirname, kw['index_file']) link = short_destination.replace('\\', '/') - index_len = len(kw['index_file']) if kw['strip_indexes'] and link[-(1 + index_len):] == '/' + kw['index_file']: link = link[:-index_len] context["permalink"] = link + context["pagekind"] = ["list"] + if dirname == "/": + context["pagekind"].append("front_page") for post in post_list: # If there is an index.html pending to be created from @@ -133,6 +147,7 @@ class Indexes(Task): yield task def index_path(self, name, lang, is_feed=False): + """Return path to an index.""" extension = None if is_feed: extension = ".atom" @@ -149,4 +164,5 @@ class Indexes(Task): extension=extension) def index_atom_path(self, name, lang): + """Return path to an Atom index.""" return self.index_path(name, lang, is_feed=True) diff --git a/nikola/plugins/task/listings.plugin b/nikola/plugins/task/listings.plugin index a5ba77a..435234b 100644 --- a/nikola/plugins/task/listings.plugin +++ b/nikola/plugins/task/listings.plugin @@ -1,10 +1,13 @@ [Core] -Name = render_listings -Module = listings +name = render_listings +module = listings [Documentation] -Author = Roberto Alsina -Version = 1.0 -Website = http://getnikola.com -Description = Render code listings into output +author = Roberto Alsina +version = 1.0 +website = http://getnikola.com +description = Render code listings into output + +[Nikola] +plugincategory = Task diff --git a/nikola/plugins/task/listings.py b/nikola/plugins/task/listings.py index b913330..5f79724 100644 --- a/nikola/plugins/task/listings.py +++ b/nikola/plugins/task/listings.py @@ -24,10 +24,13 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +"""Render code listings.""" + from __future__ import unicode_literals, print_function import sys import os +import lxml.html from pygments import highlight from pygments.lexers import get_lexer_for_filename, TextLexer @@ -38,7 +41,8 @@ from nikola import utils class Listings(Task): - """Render pretty listings.""" + + """Render code listings.""" name = "render_listings" @@ -51,6 +55,7 @@ class Listings(Task): self.proper_input_file_mapping[rel_output_name] = rel_output_name def set_site(self, site): + """Set Nikola site.""" site.register_path_handler('listing', self.listing_path) # We need to prepare some things for the listings path handler to work. @@ -105,12 +110,21 @@ class Listings(Task): def gen_tasks(self): """Render pretty code listings.""" - # Things to ignore in listings ignored_extensions = (".pyc", ".pyo") def render_listing(in_name, out_name, input_folder, output_folder, folders=[], files=[]): - if in_name: + needs_ipython_css = False + if in_name and in_name.endswith('.ipynb'): + # Special handling: render ipynbs in listings (Issue #1900) + ipynb_compiler = self.site.plugin_manager.getPluginByName("ipynb", "PageCompiler").plugin_object + ipynb_raw = ipynb_compiler.compile_html_string(in_name, True) + ipynb_html = lxml.html.fromstring(ipynb_raw) + # The raw HTML contains garbage (scripts and styles), we can’t leave it in + code = lxml.html.tostring(ipynb_html.xpath('//*[@id="notebook"]')[0], encoding='unicode') + title = os.path.basename(in_name) + needs_ipython_css = True + elif in_name: with open(in_name, 'r') as fd: try: lexer = get_lexer_for_filename(in_name) @@ -149,7 +163,12 @@ class Listings(Task): files, alg=natsort.ns.F | natsort.ns.IC), 'description': title, 'source_link': source_link, + 'pagekind': ['listing'], } + if needs_ipython_css: + # If someone does not have ipynb posts and only listings, we + # need to enable ipynb CSS for ipynb listings. + context['needs_ipython_css'] = True self.site.render_template('listing.tmpl', out_name, context) yield self.group_task() @@ -236,6 +255,7 @@ class Listings(Task): }, self.kw["filters"]) def listing_path(self, namep, lang): + """Return path to a listing.""" namep = namep.replace('/', os.sep) nameh = namep + '.html' for name in (namep, nameh): diff --git a/nikola/plugins/task/pages.plugin b/nikola/plugins/task/pages.plugin index 4cad7b7..023d41b 100644 --- a/nikola/plugins/task/pages.plugin +++ b/nikola/plugins/task/pages.plugin @@ -1,10 +1,13 @@ [Core] -Name = render_pages -Module = pages +name = render_pages +module = pages [Documentation] -Author = Roberto Alsina -Version = 1.0 -Website = http://getnikola.com -Description = Create pages in the output. +author = Roberto Alsina +version = 1.0 +website = http://getnikola.com +description = Create pages in the output. + +[Nikola] +plugincategory = Task diff --git a/nikola/plugins/task/pages.py b/nikola/plugins/task/pages.py index d0edb56..e6a8a82 100644 --- a/nikola/plugins/task/pages.py +++ b/nikola/plugins/task/pages.py @@ -24,12 +24,15 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +"""Render pages into output.""" + from __future__ import unicode_literals from nikola.plugin_categories import Task from nikola.utils import config_changed class RenderPages(Task): + """Render pages into output.""" name = "render_pages" @@ -49,8 +52,11 @@ class RenderPages(Task): for post in self.site.timeline: if not kw["show_untranslated_posts"] and not post.is_translation_available(lang): continue - for task in self.site.generic_page_renderer(lang, post, - kw["filters"]): + if post.is_post: + context = {'pagekind': ['post_page']} + else: + context = {'pagekind': ['story_page']} + for task in self.site.generic_page_renderer(lang, post, kw["filters"], context): task['uptodate'] = task['uptodate'] + [config_changed(kw, 'nikola.plugins.task.pages')] task['basename'] = self.name task['task_dep'] = ['render_posts'] diff --git a/nikola/plugins/task/posts.plugin b/nikola/plugins/task/posts.plugin index 707b3c2..79b7c51 100644 --- a/nikola/plugins/task/posts.plugin +++ b/nikola/plugins/task/posts.plugin @@ -1,10 +1,13 @@ [Core] -Name = render_posts -Module = posts +name = render_posts +module = posts [Documentation] -Author = Roberto Alsina -Version = 1.0 -Website = http://getnikola.com -Description = Create HTML fragments out of posts. +author = Roberto Alsina +version = 1.0 +website = http://getnikola.com +description = Create HTML fragments out of posts. + +[Nikola] +plugincategory = Task diff --git a/nikola/plugins/task/posts.py b/nikola/plugins/task/posts.py index d3f17fd..a3a8375 100644 --- a/nikola/plugins/task/posts.py +++ b/nikola/plugins/task/posts.py @@ -24,6 +24,8 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +"""Build HTML fragments from metadata and text.""" + from copy import copy import os @@ -32,7 +34,7 @@ from nikola import filters, utils def update_deps(post, lang, task): - """Updates file dependencies as they might have been updated during compilation. + """Update file dependencies as they might have been updated during compilation. This is done for example by the ReST page compiler, which writes its dependencies into a .dep file. This file is read and incorporated when calling @@ -42,6 +44,7 @@ def update_deps(post, lang, task): class RenderPosts(Task): + """Build HTML fragments from metadata and text.""" name = "render_posts" @@ -74,7 +77,11 @@ class RenderPosts(Task): deps_dict = copy(kw) deps_dict.pop('timeline') for post in kw['timeline']: - + # Extra config dependencies picked from config + for p in post.fragment_deps(lang): + if p.startswith('####MAGIC####CONFIG:'): + k = p.split('####MAGIC####CONFIG:', 1)[-1] + deps_dict[k] = self.site.config.get(k) dest = post.translated_base_path(lang) file_dep = [p for p in post.fragment_deps(lang) if not p.startswith("####MAGIC####")] task = { @@ -110,6 +117,7 @@ class RenderPosts(Task): yield utils.apply_filters(task, {os.path.splitext(dest): flist}) def dependence_on_timeline(self, post, lang): + """Check if a post depends on the timeline.""" if "####MAGIC####TIMELINE" not in post.fragment_deps(lang): return True # No dependency on timeline elif self.tl_changed: diff --git a/nikola/plugins/task/redirect.plugin b/nikola/plugins/task/redirect.plugin index 0228c70..c3137b9 100644 --- a/nikola/plugins/task/redirect.plugin +++ b/nikola/plugins/task/redirect.plugin @@ -1,10 +1,13 @@ [Core] -Name = redirect -Module = redirect +name = redirect +module = redirect [Documentation] -Author = Roberto Alsina -Version = 1.0 -Website = http://getnikola.com -Description = Create redirect pages. +author = Roberto Alsina +version = 1.0 +website = http://getnikola.com +description = Create redirect pages. + +[Nikola] +plugincategory = Task diff --git a/nikola/plugins/task/redirect.py b/nikola/plugins/task/redirect.py index 428dd5a..8530f5e 100644 --- a/nikola/plugins/task/redirect.py +++ b/nikola/plugins/task/redirect.py @@ -24,6 +24,8 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +"""Generate redirections.""" + from __future__ import unicode_literals import os @@ -33,13 +35,13 @@ from nikola import utils class Redirect(Task): - """Generate redirections""" + + """Generate redirections.""" name = "redirect" def gen_tasks(self): """Generate redirections tasks.""" - kw = { 'redirections': self.site.config['REDIRECTIONS'], 'output_folder': self.site.config['OUTPUT_FOLDER'], diff --git a/nikola/plugins/task/robots.plugin b/nikola/plugins/task/robots.plugin index b4b43a3..72ce31f 100644 --- a/nikola/plugins/task/robots.plugin +++ b/nikola/plugins/task/robots.plugin @@ -1,10 +1,13 @@ [Core] -Name = robots -Module = robots +name = robots +module = robots [Documentation] -Author = Daniel Aleksandersen -Version = 1.0 -Website = http://getnikola.com -Description = Generate /robots.txt exclusion file and promote sitemap. +author = Daniel Aleksandersen +version = 1.0 +website = http://getnikola.com +description = Generate /robots.txt exclusion file and promote sitemap. + +[Nikola] +plugincategory = Task diff --git a/nikola/plugins/task/robots.py b/nikola/plugins/task/robots.py index 2f25a21..65254b6 100644 --- a/nikola/plugins/task/robots.py +++ b/nikola/plugins/task/robots.py @@ -24,6 +24,8 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +"""Generate a robots.txt file.""" + from __future__ import print_function, absolute_import, unicode_literals import io import os @@ -37,12 +39,13 @@ from nikola import utils class RobotsFile(LateTask): - """Generate a robots.txt.""" + + """Generate a robots.txt file.""" name = "robots_file" def gen_tasks(self): - """Generate a robots.txt.""" + """Generate a robots.txt file.""" kw = { "base_url": self.site.config["BASE_URL"], "site_url": self.site.config["SITE_URL"], diff --git a/nikola/plugins/task/rss.plugin b/nikola/plugins/task/rss.plugin index 56f0bf4..cf9b7a7 100644 --- a/nikola/plugins/task/rss.plugin +++ b/nikola/plugins/task/rss.plugin @@ -1,10 +1,13 @@ [Core] -Name = generate_rss -Module = rss +name = generate_rss +module = rss [Documentation] -Author = Roberto Alsina -Version = 1.0 -Website = http://getnikola.com -Description = Generate RSS feeds. +author = Roberto Alsina +version = 1.0 +website = http://getnikola.com +description = Generate RSS feeds. + +[Nikola] +plugincategory = Task diff --git a/nikola/plugins/task/rss.py b/nikola/plugins/task/rss.py index 26a4da1..9020a06 100644 --- a/nikola/plugins/task/rss.py +++ b/nikola/plugins/task/rss.py @@ -24,6 +24,8 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +"""Generate RSS feeds.""" + from __future__ import unicode_literals, print_function import os try: @@ -36,11 +38,13 @@ from nikola.plugin_categories import Task class GenerateRSS(Task): + """Generate RSS feeds.""" name = "generate_rss" def set_site(self, site): + """Set Nikola site.""" site.register_path_handler('rss', self.rss_path) return super(GenerateRSS, self).set_site(site) @@ -102,5 +106,6 @@ class GenerateRSS(Task): yield utils.apply_filters(task, kw['filters']) def rss_path(self, name, lang): + """Return RSS path.""" return [_f for _f in [self.site.config['TRANSLATIONS'][lang], self.site.config['RSS_PATH'], 'rss.xml'] if _f] diff --git a/nikola/plugins/task/scale_images.plugin b/nikola/plugins/task/scale_images.plugin index c0f0f28..d906b8c 100644 --- a/nikola/plugins/task/scale_images.plugin +++ b/nikola/plugins/task/scale_images.plugin @@ -1,9 +1,13 @@ [Core] -Name = scale_images -Module = scale_images +name = scale_images +module = scale_images [Documentation] -Author = Pelle Nilsson -Version = 1.0 -Website = http://getnikola.com -Description = Create down-scaled images and thumbnails. +author = Pelle Nilsson +version = 1.0 +website = http://getnikola.com +description = Create down-scaled images and thumbnails. + +[Nikola] +plugincategory = Task + diff --git a/nikola/plugins/task/scale_images.py b/nikola/plugins/task/scale_images.py index f97027e..22ed2ab 100644 --- a/nikola/plugins/task/scale_images.py +++ b/nikola/plugins/task/scale_images.py @@ -24,6 +24,8 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +"""Resize images and create thumbnails for them.""" + import os from nikola.plugin_categories import Task @@ -32,17 +34,18 @@ from nikola import utils class ScaleImage(Task, ImageProcessor): - """Copy static files into the output folder.""" + + """Resize images and create thumbnails for them.""" name = "scale_images" def set_site(self, site): - self.logger = utils.get_logger('scale_images', site.loghandlers) + """Set Nikola site.""" + self.logger = utils.get_logger('scale_images', utils.STDERR_HANDLER) return super(ScaleImage, self).set_site(site) def process_tree(self, src, dst): - """Processes all images in a src tree and put the (possibly) rescaled - images in the dst folder.""" + """Process all images in a src tree and put the (possibly) rescaled images in the dst folder.""" ignore = set(['.svn']) base_len = len(src.split(os.sep)) for root, dirs, files in os.walk(src, followlinks=True): @@ -68,12 +71,12 @@ class ScaleImage(Task, ImageProcessor): } def process_image(self, src, dst, thumb): + """Resize an image.""" self.resize_image(src, dst, self.kw['max_image_size'], False) self.resize_image(src, thumb, self.kw['image_thumbnail_size'], False) def gen_tasks(self): """Copy static files into the output folder.""" - self.kw = { 'image_thumbnail_size': self.site.config['IMAGE_THUMBNAIL_SIZE'], 'max_image_size': self.site.config['MAX_IMAGE_SIZE'], diff --git a/nikola/plugins/task/sitemap.plugin b/nikola/plugins/task/sitemap.plugin index 0b992b8..e3c991f 100644 --- a/nikola/plugins/task/sitemap.plugin +++ b/nikola/plugins/task/sitemap.plugin @@ -1,10 +1,13 @@ [Core] -Name = sitemap -Module = sitemap +name = sitemap +module = sitemap [Documentation] -Author = Roberto Alsina -Version = 1.0 -Website = http://getnikola.com -Description = Generate google sitemap. +author = Roberto Alsina +version = 1.0 +website = http://getnikola.com +description = Generate google sitemap. + +[Nikola] +plugincategory = Task diff --git a/nikola/plugins/task/sitemap/__init__.py b/nikola/plugins/task/sitemap/__init__.py index 92d557d..fd781d6 100644 --- a/nikola/plugins/task/sitemap/__init__.py +++ b/nikola/plugins/task/sitemap/__init__.py @@ -24,9 +24,12 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +"""Generate a sitemap.""" + from __future__ import print_function, absolute_import, unicode_literals import io import datetime +import dateutil.tz import os try: from urlparse import urljoin, urlparse @@ -42,6 +45,7 @@ from nikola.utils import config_changed, apply_filters urlset_header = """<?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" + xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"> @@ -58,6 +62,7 @@ urlset_footer = "</urlset>" sitemapindex_header = """<?xml version="1.0" encoding="UTF-8"?> <sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" + xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"> @@ -76,7 +81,7 @@ sitemapindex_footer = "</sitemapindex>" def get_base_path(base): - """returns the path of a base URL if it contains one. + """Return the path of a base URL if it contains one. >>> get_base_path('http://some.site') == '/' True @@ -101,6 +106,7 @@ def get_base_path(base): class Sitemap(LateTask): + """Generate a sitemap.""" name = "sitemap" @@ -114,10 +120,12 @@ class Sitemap(LateTask): "strip_indexes": self.site.config["STRIP_INDEXES"], "index_file": self.site.config["INDEX_FILE"], "sitemap_include_fileless_dirs": self.site.config["SITEMAP_INCLUDE_FILELESS_DIRS"], - "mapped_extensions": self.site.config.get('MAPPED_EXTENSIONS', ['.atom', '.html', '.htm', '.xml', '.rss']), + "mapped_extensions": self.site.config.get('MAPPED_EXTENSIONS', ['.atom', '.html', '.htm', '.php', '.xml', '.rss']), "robots_exclusions": self.site.config["ROBOTS_EXCLUSIONS"], "filters": self.site.config["FILTERS"], "translations": self.site.config["TRANSLATIONS"], + "tzinfo": self.site.config['__tzinfo__'], + "sitemap_plugin_revision": 1, } output = kw['output_folder'] @@ -132,6 +140,7 @@ class Sitemap(LateTask): urlset = {} def scan_locs(): + """Scan site locations.""" for root, dirs, files in os.walk(output, followlinks=True): if not dirs and not files and not kw['sitemap_include_fileless_dirs']: continue # Totally empty, not on sitemap @@ -169,17 +178,18 @@ class Sitemap(LateTask): filehead = fh.read(1024) fh.close() - if path.endswith('.html') or path.endswith('.htm'): + if path.endswith('.html') or path.endswith('.htm') or path.endswith('.php'): """ ignores "html" files without doctype """ if b'<!doctype html' not in filehead.lower(): continue """ ignores "html" files with noindex robot directives """ - robots_directives = [b'<meta content="noindex" name="robots"', - b'<meta content="none" name="robots"', - b'<meta name="robots" content="noindex"', - b'<meta name="robots" content="none"'] - if any([robot_directive in filehead.lower() for robot_directive in robots_directives]): + robots_directives = [b'<meta content=noindex name=robots', + b'<meta content=none name=robots', + b'<meta name=robots content=noindex', + b'<meta name=robots content=none'] + lowquothead = filehead.lower().decode('utf-8', 'ignore').replace('"', '').encode('utf-8') + if any([robot_directive in lowquothead for robot_directive in robots_directives]): continue # put Atom and RSS in sitemapindex[] instead of in urlset[], @@ -210,6 +220,7 @@ class Sitemap(LateTask): urlset[loc] = loc_format.format(loc, lastmod, '\n'.join(alternates)) def robot_fetch(path): + """Check if robots can fetch a file.""" for rule in kw["robots_exclusions"]: robot = robotparser.RobotFileParser() robot.parse(["User-Agent: *", "Disallow: {0}".format(rule)]) @@ -218,6 +229,7 @@ class Sitemap(LateTask): return True def write_sitemap(): + """Write sitemap to file.""" # Have to rescan, because files may have been added between # task dep scanning and task execution with io.open(sitemap_path, 'w+', encoding='utf8') as outf: @@ -229,16 +241,19 @@ class Sitemap(LateTask): sitemapindex[sitemap_url] = sitemap_format.format(sitemap_url, self.get_lastmod(sitemap_path)) def write_sitemapindex(): + """Write sitemap index.""" with io.open(sitemapindex_path, 'w+', encoding='utf8') as outf: outf.write(sitemapindex_header) for k in sorted(sitemapindex.keys()): outf.write(sitemapindex[k]) outf.write(sitemapindex_footer) - # Yield a task to calculate the dependencies of the sitemap - # Other tasks can depend on this output, instead of having - # to scan locations. def scan_locs_task(): + """Yield a task to calculate the dependencies of the sitemap. + + Other tasks can depend on this output, instead of having + to scan locations. + """ scan_locs() # Generate a list of file dependencies for the actual generation @@ -290,10 +305,15 @@ class Sitemap(LateTask): }, kw['filters']) def get_lastmod(self, p): + """Get last modification date.""" if self.site.invariant: return '2038-01-01' else: - return datetime.datetime.fromtimestamp(os.stat(p).st_mtime).isoformat().split('T')[0] + # RFC 3339 (web ISO 8601 profile) represented in UTC with Zulu + # zone desgignator as recommeded for sitemaps. Second and + # microsecond precision is stripped for compatibility. + lastmod = datetime.datetime.utcfromtimestamp(os.stat(p).st_mtime).replace(tzinfo=dateutil.tz.gettz('UTC'), second=0, microsecond=0).isoformat().replace('+00:00', 'Z') + return lastmod if __name__ == '__main__': import doctest diff --git a/nikola/plugins/task/sources.plugin b/nikola/plugins/task/sources.plugin index 5560df6..d232c2b 100644 --- a/nikola/plugins/task/sources.plugin +++ b/nikola/plugins/task/sources.plugin @@ -1,10 +1,13 @@ [Core] -Name = render_sources -Module = sources +name = render_sources +module = sources [Documentation] -Author = Roberto Alsina -Version = 1.0 -Website = http://getnikola.com -Description = Copy page sources into the output. +author = Roberto Alsina +version = 1.0 +website = http://getnikola.com +description = Copy page sources into the output. + +[Nikola] +plugincategory = Task diff --git a/nikola/plugins/task/sources.py b/nikola/plugins/task/sources.py index 840a31c..87b4ae7 100644 --- a/nikola/plugins/task/sources.py +++ b/nikola/plugins/task/sources.py @@ -24,6 +24,8 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +"""Copy page sources into the output.""" + import os from nikola.plugin_categories import Task @@ -31,20 +33,13 @@ from nikola import utils class Sources(Task): + """Copy page sources into the output.""" name = "render_sources" def gen_tasks(self): - """Publish the page sources into the output. - - Required keyword arguments: - - translations - default_lang - post_pages - output_folder - """ + """Publish the page sources into the output.""" kw = { "translations": self.site.config["TRANSLATIONS"], "output_folder": self.site.config["OUTPUT_FOLDER"], diff --git a/nikola/plugins/task/tags.plugin b/nikola/plugins/task/tags.plugin index 4ac3800..283a16a 100644 --- a/nikola/plugins/task/tags.plugin +++ b/nikola/plugins/task/tags.plugin @@ -1,10 +1,13 @@ [Core] -Name = render_tags -Module = tags +name = render_tags +module = tags [Documentation] -Author = Roberto Alsina -Version = 1.0 -Website = http://getnikola.com -Description = Render the tag pages and feeds. +author = Roberto Alsina +version = 1.0 +website = http://getnikola.com +description = Render the tag pages and feeds. + +[Nikola] +plugincategory = Task diff --git a/nikola/plugins/task/tags.py b/nikola/plugins/task/tags.py index 832ceff..3186636 100644 --- a/nikola/plugins/task/tags.py +++ b/nikola/plugins/task/tags.py @@ -24,6 +24,8 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +"""Render the tag/category pages and feeds.""" + from __future__ import unicode_literals import json import os @@ -39,11 +41,13 @@ from nikola import utils class RenderTags(Task): + """Render the tag/category pages and feeds.""" name = "render_tags" def set_site(self, site): + """Set Nikola site.""" site.register_path_handler('tag_index', self.tag_index_path) site.register_path_handler('category_index', self.category_index_path) site.register_path_handler('tag', self.tag_path) @@ -56,7 +60,6 @@ class RenderTags(Task): def gen_tasks(self): """Render the tag pages and feeds.""" - kw = { "translations": self.site.config["TRANSLATIONS"], "blog_title": self.site.config["BLOG_TITLE"], @@ -121,6 +124,7 @@ class RenderTags(Task): cat_list = list(self.site.posts_per_category.items()) def render_lists(tag, posts, is_category=True): + """Render tag pages as RSS files and lists/indexes.""" post_list = sorted(posts, key=lambda a: a.date) post_list.reverse() for lang in kw["translations"]: @@ -161,6 +165,7 @@ class RenderTags(Task): 'assets', 'js', 'tag_cloud_data.json') def write_tag_data(data): + """Write tag data into JSON file, for use in tag clouds.""" utils.makedirs(os.path.dirname(output_name)) with open(output_name, 'w+') as fd: json.dump(data, fd) @@ -178,20 +183,20 @@ class RenderTags(Task): yield utils.apply_filters(task, kw['filters']) def _create_tags_page(self, kw, include_tags=True, include_categories=True): - """a global "all your tags/categories" page for each language""" - tags = natsort.natsorted([tag for tag in self.site.posts_per_tag.keys() - if len(self.site.posts_per_tag[tag]) >= kw["taglist_minimum_post_count"]], - alg=natsort.ns.F | natsort.ns.IC) + """Create a global "all your tags/categories" page for each language.""" categories = [cat.category_name for cat in self.site.category_hierarchy] - has_tags = (tags != []) and include_tags has_categories = (categories != []) and include_categories template_name = "tags.tmpl" kw = kw.copy() - if include_tags: - kw['tags'] = tags if include_categories: kw['categories'] = categories for lang in kw["translations"]: + tags = natsort.natsorted([tag for tag in self.site.tags_per_language[lang] + if len(self.site.posts_per_tag[tag]) >= kw["taglist_minimum_post_count"]], + alg=natsort.ns.F | natsort.ns.IC) + has_tags = (tags != []) and include_tags + if include_tags: + kw['tags'] = tags output_name = os.path.join( kw['output_folder'], self.site.path('tag_index' if has_tags else 'category_index', None, lang)) output_name = output_name @@ -219,6 +224,7 @@ class RenderTags(Task): context["cat_items"] = None context["permalink"] = self.site.link("tag_index" if has_tags else "category_index", None, lang) context["description"] = context["title"] + context["pagekind"] = ["list", "tags_page"] task = self.site.generic_post_list_renderer( lang, [], @@ -232,7 +238,7 @@ class RenderTags(Task): yield task def list_tags_page(self, kw): - """a global "all your tags/categories" page for each language""" + """Create a global "all your tags/categories" page for each language.""" if self.site.config['TAG_PATH'] == self.site.config['CATEGORY_PATH']: yield self._create_tags_page(kw, True, True) else: @@ -254,9 +260,7 @@ class RenderTags(Task): return [(child.name, self.site.link("category", child.category_name)) for child in node.children] def tag_page_as_index(self, tag, lang, post_list, kw, is_category): - """render a sort of index page collection using only this - tag's posts.""" - + """Render a sort of index page collection using only this tag's posts.""" kind = "category" if is_category else "tag" def page_link(i, displayed_i, num_pages, force_addition, extension=None): @@ -284,12 +288,13 @@ class RenderTags(Task): context_source["description"] = self._get_description(tag, is_category, lang) if is_category: context_source["subcategories"] = self._get_subcategories(tag) + context_source["pagekind"] = ["index", "tag_page"] template_name = "tagindex.tmpl" yield self.site.generic_index_renderer(lang, post_list, indexes_title, template_name, context_source, kw, str(self.name), page_link, page_path) def tag_page_as_list(self, tag, lang, post_list, kw, is_category): - """We render a single flat link list with this tag's posts""" + """Render a single flat link list with this tag's posts.""" kind = "category" if is_category else "tag" template_name = "tag.tmpl" output_name = os.path.join(kw['output_folder'], self.site.path( @@ -308,6 +313,7 @@ class RenderTags(Task): context["description"] = self._get_description(tag, is_category, lang) if is_category: context["subcategories"] = self._get_subcategories(tag) + context["pagekind"] = ["list", "tag_page"] task = self.site.generic_post_list_renderer( lang, post_list, @@ -321,7 +327,7 @@ class RenderTags(Task): yield task def tag_rss(self, tag, lang, posts, kw, is_category): - """RSS for a single tag / language""" + """Create a RSS feed for a single tag in a given language.""" kind = "category" if is_category else "tag" # Render RSS output_name = os.path.normpath( @@ -352,21 +358,25 @@ class RenderTags(Task): return utils.apply_filters(task, kw['filters']) def slugify_tag_name(self, name): + """Slugify a tag name.""" if self.site.config['SLUG_TAG_PATH']: name = utils.slugify(name) return name def tag_index_path(self, name, lang): + """Return path to the tag index.""" return [_f for _f in [self.site.config['TRANSLATIONS'][lang], self.site.config['TAG_PATH'], self.site.config['INDEX_FILE']] if _f] def category_index_path(self, name, lang): + """Return path to the category index.""" return [_f for _f in [self.site.config['TRANSLATIONS'][lang], self.site.config['CATEGORY_PATH'], self.site.config['INDEX_FILE']] if _f] def tag_path(self, name, lang): + """Return path to a tag.""" if self.site.config['PRETTY_URLS']: return [_f for _f in [ self.site.config['TRANSLATIONS'][lang], @@ -380,16 +390,19 @@ class RenderTags(Task): self.slugify_tag_name(name) + ".html"] if _f] def tag_atom_path(self, name, lang): + """Return path to a tag Atom feed.""" return [_f for _f in [self.site.config['TRANSLATIONS'][lang], self.site.config['TAG_PATH'], self.slugify_tag_name(name) + ".atom"] if _f] def tag_rss_path(self, name, lang): + """Return path to a tag RSS feed.""" return [_f for _f in [self.site.config['TRANSLATIONS'][lang], self.site.config['TAG_PATH'], self.slugify_tag_name(name) + ".xml"] if _f] def slugify_category_name(self, name): + """Slugify a category name.""" path = self.site.parse_category_name(name) if self.site.config['CATEGORY_OUTPUT_FLAT_HIERARCHY']: path = path[-1:] # only the leaf @@ -404,6 +417,7 @@ class RenderTags(Task): return path def category_path(self, name, lang): + """Return path to a category.""" if self.site.config['PRETTY_URLS']: return [_f for _f in [self.site.config['TRANSLATIONS'][lang], self.site.config['CATEGORY_PATH']] if @@ -414,11 +428,13 @@ class RenderTags(Task): _f] + self._add_extension(self.slugify_category_name(name), ".html") def category_atom_path(self, name, lang): + """Return path to a category Atom feed.""" return [_f for _f in [self.site.config['TRANSLATIONS'][lang], self.site.config['CATEGORY_PATH']] if _f] + self._add_extension(self.slugify_category_name(name), ".atom") def category_rss_path(self, name, lang): + """Return path to a category RSS feed.""" return [_f for _f in [self.site.config['TRANSLATIONS'][lang], self.site.config['CATEGORY_PATH']] if _f] + self._add_extension(self.slugify_category_name(name), ".xml") |
