Exemplo n.º 1
0
    def remove_excluded_image(self, img):
        # Remove excluded images
        # img is something like galleries/demo/tesla2_lg.jpg so it's the *source* path
        # and we should remove both the large and thumbnail *destination* paths

        img = os.path.relpath(img, self.kw['gallery_path'])
        output_folder = os.path.dirname(
            os.path.join(
                self.kw["output_folder"],
                self.site.path("gallery", os.path.dirname(img))))
        img_path = os.path.join(output_folder, os.path.basename(img))
        fname, ext = os.path.splitext(img_path)
        thumb_path = fname + '.thumbnail' + ext

        yield utils.apply_filters({
            'basename': '_render_galleries_clean',
            'name': thumb_path,
            'actions': [
                (utils.remove_file, (thumb_path,))
            ],
            'clean': True,
            'uptodate': [utils.config_changed(self.kw)],
        }, self.kw['filters'])

        yield utils.apply_filters({
            'basename': '_render_galleries_clean',
            'name': img_path,
            'actions': [
                (utils.remove_file, (img_path,))
            ],
            'clean': True,
            'uptodate': [utils.config_changed(self.kw)],
        }, self.kw['filters'])
Exemplo n.º 2
0
    def remove_excluded_image(self, img, input_folder):
        # 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

        output_folder = os.path.dirname(
            os.path.join(self.kw["output_folder"], self.site.path("gallery", os.path.dirname(img)))
        )
        img = os.path.relpath(img, input_folder)
        img_path = os.path.join(output_folder, os.path.basename(img))
        fname, ext = os.path.splitext(img_path)
        thumb_path = fname + ".thumbnail" + ext

        yield utils.apply_filters(
            {
                "basename": "_render_galleries_clean",
                "name": thumb_path,
                "actions": [(utils.remove_file, (thumb_path,))],
                "clean": True,
                "uptodate": [utils.config_changed(self.kw, "nikola.plugins.task.galleries:clean_thumb")],
            },
            self.kw["filters"],
        )

        yield utils.apply_filters(
            {
                "basename": "_render_galleries_clean",
                "name": img_path,
                "actions": [(utils.remove_file, (img_path,))],
                "clean": True,
                "uptodate": [utils.config_changed(self.kw, "nikola.plugins.task.galleries:clean_file")],
            },
            self.kw["filters"],
        )
Exemplo n.º 3
0
    def gen_tasks(self):
        """Create tasks to copy the assets of the whole theme chain.

        If a file is present on two themes, use the version
        from the "youngest" theme.
        """

        kw = {
            "themes": self.site.THEMES,
            "output_folder": self.site.config['OUTPUT_FOLDER'],
            "filters": self.site.config['FILTERS'],
            "code_color_scheme": self.site.config['CODE_COLOR_SCHEME'],
        }
        flag = True
        has_code_css = False
        tasks = {}
        code_css_path = os.path.join(kw['output_folder'], 'assets', 'css', 'code.css')
        for theme_name in kw['themes']:
            src = os.path.join(utils.get_theme_path(theme_name), 'assets')
            dst = os.path.join(kw['output_folder'], 'assets')
            for task in utils.copy_tree(src, dst):
                if task['name'] in tasks:
                    continue
                if task['targets'][0] == code_css_path:
                    has_code_css = True
                tasks[task['name']] = task
                task['uptodate'] = [utils.config_changed(kw)]
                task['basename'] = self.name
                flag = False
                yield utils.apply_filters(task, kw['filters'])

        if flag:
            yield {
                'basename': self.name,
                'name': 'None',
                'uptodate': [True],
                'actions': [],
            }

        if not has_code_css:  # Generate it

            def create_code_css():
                from pygments.formatters import get_formatter_by_name
                formatter = get_formatter_by_name('html', style=kw["code_color_scheme"])
                utils.makedirs(os.path.dirname(code_css_path))
                with codecs.open(code_css_path, 'wb+', 'utf8') as outf:
                    outf.write(formatter.get_style_defs('.code'))
                    outf.write("table.codetable { width: 100%;} td.linenos {text-align: right; width: 4em;}")

            task = {
                'basename': self.name,
                'name': code_css_path,
                'targets': [code_css_path],
                'uptodate': [utils.config_changed(kw)],
                'actions': [(create_code_css, [])],
                'clean': True,
            }
            yield utils.apply_filters(task, kw['filters'])
Exemplo n.º 4
0
    def gen_tasks(self):
        """Create tasks to copy the assets of the whole theme chain.

        If a file is present on two themes, use the version
        from the "youngest" theme.
        """

        kw = {
            "themes": self.site.THEMES,
            "output_folder": self.site.config["OUTPUT_FOLDER"],
            "filters": self.site.config["FILTERS"],
            "code_color_scheme": self.site.config["CODE_COLOR_SCHEME"],
        }
        has_code_css = False
        tasks = {}
        code_css_path = os.path.join(kw["output_folder"], "assets", "css", "code.css")

        yield self.group_task()

        for theme_name in kw["themes"]:
            src = os.path.join(utils.get_theme_path(theme_name), "assets")
            dst = os.path.join(kw["output_folder"], "assets")
            for task in utils.copy_tree(src, dst):
                if task["name"] in tasks:
                    continue
                if task["targets"][0] == code_css_path:
                    has_code_css = True
                tasks[task["name"]] = task
                task["uptodate"] = [utils.config_changed(kw)]
                task["basename"] = self.name
                yield utils.apply_filters(task, kw["filters"])

        if not has_code_css:  # Generate it

            def create_code_css():
                from pygments.formatters import get_formatter_by_name

                formatter = get_formatter_by_name("html", style=kw["code_color_scheme"])
                utils.makedirs(os.path.dirname(code_css_path))
                with codecs.open(code_css_path, "wb+", "utf8") as outf:
                    outf.write(formatter.get_style_defs(["pre.code", "div.code pre"]))
                    outf.write("\ntable.codetable { width: 100%;} td.linenos {text-align: right; width: 4em;}\n")

            task = {
                "basename": self.name,
                "name": code_css_path,
                "targets": [code_css_path],
                "uptodate": [utils.config_changed(kw)],
                "actions": [(create_code_css, [])],
                "clean": True,
            }
            yield utils.apply_filters(task, kw["filters"])
Exemplo n.º 5
0
    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(
                self.kw["output_folder"],
                self.site.path("gallery_global", gallery_name)))
        # Do thumbnails and copy originals
        # img is "galleries/name/image_name.jpg"
        # img_name is "image_name.jpg"
        # fname, ext are "image_name", ".jpg"
        # thumb_path is
        # "output/GALLERY_PATH/name/image_name.thumbnail.jpg"
        img_name = os.path.basename(img)
        fname, ext = os.path.splitext(img_name)
        thumb_path = os.path.join(
            output_gallery,
            ".thumbnail".join([fname, ext]))
        # thumb_path is "output/GALLERY_PATH/name/image_name.jpg"
        orig_dest_path = os.path.join(output_gallery, img_name)
        yield utils.apply_filters({
            'basename': self.name,
            'name': thumb_path,
            'file_dep': [img],
            'targets': [thumb_path],
            'actions': [
                (self.resize_image,
                    (img, thumb_path, self.kw['thumbnail_size'], True, self.kw['preserve_exif_data'],
                     self.kw['exif_whitelist'], self.kw['preserve_icc_profiles']))
            ],
            'clean': True,
            'uptodate': [utils.config_changed({
                1: self.kw['thumbnail_size']
            }, 'nikola.plugins.task.galleries:resize_thumb')],
        }, self.kw['filters'])

        yield utils.apply_filters({
            'basename': self.name,
            'name': orig_dest_path,
            'file_dep': [img],
            'targets': [orig_dest_path],
            'actions': [
                (self.resize_image,
                    (img, orig_dest_path, self.kw['max_image_size'], True, self.kw['preserve_exif_data'],
                     self.kw['exif_whitelist'], self.kw['preserve_icc_profiles']))
            ],
            'clean': True,
            'uptodate': [utils.config_changed({
                1: self.kw['max_image_size']
            }, 'nikola.plugins.task.galleries:resize_max')],
        }, self.kw['filters'])
Exemplo n.º 6
0
    def gen_tasks(self):
        self.site.scan_posts()

        kw = {
            "translations": self.site.config['TRANSLATIONS'],
            "output_folder": self.site.config['OUTPUT_FOLDER'],
            "filters": self.site.config['FILTERS'],
            "timeline": self.site.timeline,
        }

        posts = self.site.timeline[:]
        dst_path = os.path.join(kw["output_folder"], "assets", "js",
                                "tipuesearch_content.json")

        def save_data():
            pages = []
            for lang in kw["translations"]:
                for post in posts:
                    # Don't index drafts (Issue #387)
                    if post.is_draft or post.is_private or post.publish_later:
                        continue
                    text = post.text(lang, strip_html=True)
                    text = text.replace('^', '')

                    data = {}
                    data["title"] = post.title(lang)
                    data["text"] = text
                    data["tags"] = ",".join(post.tags)
                    data["url"] = post.permalink(lang, absolute=True)
                    pages.append(data)
            output = json.dumps({"pages": pages}, indent=2)
            makedirs(os.path.dirname(dst_path))
            with codecs.open(dst_path, "wb+", "utf8") as fd:
                fd.write(output)

        task = {
            "basename": str(self.name),
            "name": dst_path,
            "targets": [dst_path],
            "actions": [(save_data, [])],
            'uptodate': [config_changed(kw)],
            'calc_dep': ['_scan_locs:sitemap']
        }
        yield apply_filters(task, kw['filters'])

        # Copy all the assets to the right places
        asset_folder = os.path.join(os.path.dirname(__file__), "files")
        for task in copy_tree(asset_folder, kw["output_folder"]):
            task["basename"] = str(self.name)
            yield apply_filters(task, kw['filters'])
Exemplo n.º 7
0
    def create_target_images(self, img):
        gallery_name = os.path.relpath(os.path.dirname(img), self.kw['gallery_path'])
        output_gallery = os.path.dirname(
            os.path.join(
                self.kw["output_folder"],
                self.site.path("gallery", gallery_name)))
        # Do thumbnails and copy originals
        # img is "galleries/name/image_name.jpg"
        # img_name is "image_name.jpg"
        # fname, ext are "image_name", ".jpg"
        # thumb_path is
        # "output/GALLERY_PATH/name/image_name.thumbnail.jpg"
        img_name = os.path.basename(img)
        fname, ext = os.path.splitext(img_name)
        thumb_path = os.path.join(
            output_gallery,
            ".thumbnail".join([fname, ext]))
        # thumb_path is "output/GALLERY_PATH/name/image_name.jpg"
        orig_dest_path = os.path.join(output_gallery, img_name)
        yield utils.apply_filters({
            'basename': self.name,
            'name': thumb_path,
            'file_dep': [img],
            'targets': [thumb_path],
            'actions': [
                (self.resize_image,
                    (img, thumb_path, self.kw['thumbnail_size']))
            ],
            'clean': True,
            'uptodate': [utils.config_changed({
                1: self.kw['thumbnail_size']
            })],
        }, self.kw['filters'])

        yield utils.apply_filters({
            'basename': self.name,
            'name': orig_dest_path,
            'file_dep': [img],
            'targets': [orig_dest_path],
            'actions': [
                (self.resize_image,
                    (img, orig_dest_path, self.kw['max_image_size']))
            ],
            'clean': True,
            'uptodate': [utils.config_changed({
                1: self.kw['max_image_size']
            })],
        }, self.kw['filters'])
Exemplo n.º 8
0
    def gen_tasks(self):
        """Create tasks to copy the assets of the whole theme chain.

        If a file is present on two themes, use the version
        from the "youngest" theme.
        """

        kw = {
            "themes": self.site.THEMES,
            "output_folder": self.site.config['OUTPUT_FOLDER'],
            "filters": self.site.config['FILTERS'],
        }
        flag = True
        tasks = {}
        for theme_name in kw['themes']:
            src = os.path.join(utils.get_theme_path(theme_name), 'assets')
            dst = os.path.join(kw['output_folder'], 'assets')
            for task in utils.copy_tree(src, dst):
                if task['name'] in tasks:
                    continue
                tasks[task['name']] = task
                task['uptodate'] = [utils.config_changed(kw)]
                task['basename'] = self.name
                flag = False
                yield utils.apply_filters(task, kw['filters'])

        if flag:
            yield {
                'basename': self.name,
                'name': 'None',
                'uptodate': [True],
                'actions': [],
            }
Exemplo n.º 9
0
 def author_rss(self, author, lang, posts, kw):
     """Create a RSS feed for a single author in a given language."""
     kind = "author"
     # Render RSS
     output_name = os.path.normpath(
         os.path.join(kw['output_folder'],
                      self.site.path(kind + "_rss", author, lang)))
     feed_url = urljoin(self.site.config['BASE_URL'], self.site.link(kind + "_rss", author, lang).lstrip('/'))
     deps = []
     deps_uptodate = []
     post_list = sorted(posts, key=lambda a: a.date)
     post_list.reverse()
     for post in post_list:
         deps += post.deps(lang)
         deps_uptodate += post.deps_uptodate(lang)
     task = {
         'basename': str(self.name),
         'name': output_name,
         'file_dep': deps,
         'targets': [output_name],
         'actions': [(utils.generic_rss_renderer,
                     (lang, "{0} ({1})".format(kw["blog_title"](lang), self._get_title(author)),
                      kw["site_url"], None, post_list,
                      output_name, kw["feed_teasers"], kw["feed_plain"], kw['feed_length'],
                      feed_url, None, kw["feed_link_append_query"]))],
         'clean': True,
         'uptodate': [utils.config_changed(kw, 'nikola.plugins.task.authors:rss')] + deps_uptodate,
         'task_dep': ['render_posts'],
     }
     return utils.apply_filters(task, kw['filters'])
Exemplo n.º 10
0
Arquivo: tags.py Projeto: AN6U5/nikola
 def tag_rss(self, tag, lang, posts, kw, is_category):
     """RSS for a single tag / language"""
     kind = "category" if is_category else "tag"
     # Render RSS
     output_name = os.path.normpath(
         os.path.join(kw['output_folder'],
                      self.site.path(kind + "_rss", tag, lang)))
     feed_url = urljoin(self.site.config['BASE_URL'], self.site.link(kind + "_rss", tag, lang).lstrip('/'))
     deps = []
     post_list = sorted(posts, key=lambda a: a.date)
     post_list.reverse()
     for post in post_list:
         deps += post.deps(lang)
     task = {
         'basename': str(self.name),
         'name': output_name,
         'file_dep': deps,
         'targets': [output_name],
         'actions': [(utils.generic_rss_renderer,
                     (lang, "{0} ({1})".format(kw["blog_title"](lang), tag),
                      kw["site_url"], None, post_list,
                      output_name, kw["rss_teasers"], kw["rss_plain"], kw['feed_length'],
                      feed_url))],
         'clean': True,
         'uptodate': [utils.config_changed(kw)],
         'task_dep': ['render_posts'],
     }
     return utils.apply_filters(task, kw['filters'])
Exemplo n.º 11
0
 def _generate_classification_page_as_rss(self, taxonomy, classification, filtered_posts, title, description, kw, lang):
     """Create a RSS feed for a single classification in a given language."""
     kind = taxonomy.classification_name
     # Render RSS
     output_name = os.path.normpath(os.path.join(self.site.config['OUTPUT_FOLDER'], self.site.path(kind + "_rss", classification, lang)))
     feed_url = urljoin(self.site.config['BASE_URL'], self.site.link(kind + "_rss", classification, lang).lstrip('/'))
     deps = []
     deps_uptodate = []
     for post in filtered_posts:
         deps += post.deps(lang)
         deps_uptodate += post.deps_uptodate(lang)
     blog_title = kw["blog_title"](lang)
     task = {
         'basename': str(self.name),
         'name': output_name,
         'file_dep': deps,
         'targets': [output_name],
         'actions': [(utils.generic_rss_renderer,
                     (lang, "{0} ({1})".format(blog_title, title) if blog_title != title else blog_title,
                      kw["site_url"], description, filtered_posts,
                      output_name, kw["feed_teasers"], kw["feed_plain"], kw['feed_length'],
                      feed_url, _enclosure, kw["feed_links_append_query"]))],
         'clean': True,
         'uptodate': [utils.config_changed(kw, 'nikola.plugins.task.taxonomies:rss')] + deps_uptodate,
         'task_dep': ['render_posts'],
     }
     return utils.apply_filters(task, kw['filters'])
Exemplo n.º 12
0
    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'],
            'filters': self.site.config['FILTERS'],
        }

        flag = False
        for src in kw['files_folders']:
            dst = kw['output_folder']
            filters = kw['filters']
            real_dst = os.path.join(dst, kw['files_folders'][src])
            for task in utils.copy_tree(src, real_dst, link_cutoff=dst):
                flag = True
                task['basename'] = self.name
                task['uptodate'] = task.get('uptodate', []) +\
                    [utils.config_changed(kw)]
                yield utils.apply_filters(task, filters)
        if not flag:
            yield {
                'basename': self.name,
                'actions': (),
            }
Exemplo n.º 13
0
    def gen_tasks(self):
        """Copy static files into the output folder."""
        self.kw = {
            'image_thumbnail_size': self.site.config['IMAGE_THUMBNAIL_SIZE'],
            'image_thumbnail_format': self.site.config['IMAGE_THUMBNAIL_FORMAT'],
            'max_image_size': self.site.config['MAX_IMAGE_SIZE'],
            'image_folders': self.site.config['IMAGE_FOLDERS'],
            'output_folder': self.site.config['OUTPUT_FOLDER'],
            'filters': self.site.config['FILTERS'],
            'preserve_exif_data': self.site.config['PRESERVE_EXIF_DATA'],
            'exif_whitelist': self.site.config['EXIF_WHITELIST'],
            'preserve_icc_profiles': self.site.config['PRESERVE_ICC_PROFILES'],
        }

        self.image_ext_list = self.image_ext_list_builtin
        self.image_ext_list.extend(self.site.config.get('EXTRA_IMAGE_EXTENSIONS', []))

        yield self.group_task()
        for src in self.kw['image_folders']:
            dst = self.kw['output_folder']
            filters = self.kw['filters']
            real_dst = os.path.join(dst, self.kw['image_folders'][src])
            for task in self.process_tree(src, real_dst):
                task['basename'] = self.name
                task['uptodate'] = [utils.config_changed(self.kw)]
                yield utils.apply_filters(task, filters)
Exemplo n.º 14
0
    def gen_tasks(self):
        """Bundle assets using WebAssets."""

        kw = {
            'filters': self.site.config['FILTERS'],
            'output_folder': self.site.config['OUTPUT_FOLDER'],
            'cache_folder': self.site.config['CACHE_FOLDER'],
            'theme_bundles': get_theme_bundles(self.site.THEMES),
            'themes': self.site.THEMES,
            'files_folders': self.site.config['FILES_FOLDERS'],
            'code_color_scheme': self.site.config['CODE_COLOR_SCHEME'],
        }

        def build_bundle(output, inputs):
            out_dir = os.path.join(kw['output_folder'],
                                   os.path.dirname(output))
            inputs = [i for i in inputs if os.path.isfile(
                os.path.join(out_dir, i))]
            cache_dir = os.path.join(kw['cache_folder'], 'webassets')
            utils.makedirs(cache_dir)
            env = webassets.Environment(out_dir, os.path.dirname(output),
                                        cache=cache_dir)
            if inputs:
                bundle = webassets.Bundle(*inputs, output=os.path.basename(output))
                env.register(output, bundle)
                # This generates the file
                env[output].urls()
            else:
                with open(os.path.join(out_dir, os.path.basename(output)), 'wb+'):
                    pass  # Create empty file

        yield self.group_task()
        if (webassets is not None and self.site.config['USE_BUNDLES'] is not
                False):
            for name, _files in kw['theme_bundles'].items():
                output_path = os.path.join(kw['output_folder'], name)
                dname = os.path.dirname(name)
                files = []
                for fname in _files:
                    # paths are relative to dirname
                    files.append(os.path.join(dname, fname))
                file_dep = [os.path.join(kw['output_folder'], fname)
                            for fname in files if
                            utils.get_asset_path(fname, self.site.THEMES, self.site.config['FILES_FOLDERS'])]
                task = {
                    'file_dep': list(file_dep),
                    'task_dep': ['copy_assets'],
                    'basename': str(self.name),
                    'name': str(output_path),
                    'actions': [(build_bundle, (name, files))],
                    'targets': [output_path],
                    'uptodate': [
                        utils.config_changed({
                            1: kw,
                            2: file_dep
                        })],
                    'clean': True,
                }
                yield utils.apply_filters(task, kw['filters'])
Exemplo n.º 15
0
    def _prepare_tag_cloud(self, lang, config):
        """Create tag cloud task."""
        # Collect information
        fn = os.path.join(self.site.config['OUTPUT_FOLDER'], config['filename'])
        css_fn = os.path.join(self.site.config['OUTPUT_FOLDER'], config['style_filename'])
        taxonomy_type = config['taxonomy_type']
        posts_per_tag = self.site.posts_per_classification[taxonomy_type][lang]
        taxonomy = self.site.taxonomy_plugins[taxonomy_type]

        # Compose list of tags, their post count and links
        tag_count_url_list = []
        for tag in natsort.humansorted(list(posts_per_tag.keys())):
            tag_count_url_list.append((
                taxonomy.get_classification_friendly_name(tag, lang),
                len([post for post in posts_per_tag[tag] if self.site.config['SHOW_UNTRANSLATED_POSTS'] or post.is_translation_available(lang)]),
                self.site.link(taxonomy_type, tag, lang)
            ))

        # Get tag cloud data
        tags, level_weights = engine.create_tag_cloud_data(tag_count_url_list, max_number_of_levels=config['max_number_of_levels'], max_tags=config['max_tags'], minimal_number_of_appearances=config['minimal_number_of_appearances'])

        # Determine url type for rewriting. Must not be relative.
        url_type = self.site.config['URL_TYPE']
        if url_type == 'rel_path':
            url_type = 'full_path'

        # Create task for HTML fragment
        task = {
            'basename': self.name,
            'name': fn,
            'targets': [fn],
            'actions': [(self._render_tag_cloud_html, [fn, tags, level_weights, config, lang, url_type])],
            'clean': True,
            'uptodate': [utils.config_changed({1: tags, 2: level_weights}, 'nikola.plugins.render_tag_cloud:tags'), utils.config_changed(config, 'nikola.plugins.render_tag_cloud:config')]
        }
        yield utils.apply_filters(task, self.site.config["FILTERS"])
        # Create task for CSS
        task = {
            'basename': self.name,
            'name': css_fn,
            'targets': [css_fn],
            'actions': [(self._render_tag_cloud_css, [css_fn, tags, level_weights, config])],
            'clean': True,
            'uptodate': [utils.config_changed({1: tags, 2: level_weights}, 'nikola.plugins.render_tag_cloud:tags'), utils.config_changed(config, 'nikola.plugins.render_tag_cloud:config')]
        }
        yield utils.apply_filters(task, self.site.config["FILTERS"])
Exemplo n.º 16
0
    def gen_tasks(self):
        """Bundle assets using WebAssets."""

        kw = {
            'filters': self.site.config['FILTERS'],
            'output_folder': self.site.config['OUTPUT_FOLDER'],
            'cache_folder': self.site.config['CACHE_FOLDER'],
            'theme_bundles': get_theme_bundles(self.site.THEMES),
            'themes': self.site.THEMES,
            'files_folders': self.site.config['FILES_FOLDERS'],
            'code_color_scheme': self.site.config['CODE_COLOR_SCHEME'],
        }

        def build_bundle(output, inputs):
            out_dir = os.path.join(kw['output_folder'],
                                   os.path.dirname(output))
            inputs = [i for i in inputs if os.path.isfile(
                os.path.join(out_dir, i))]
            cache_dir = os.path.join(kw['cache_folder'], 'webassets')
            if not os.path.isdir(cache_dir):
                os.makedirs(cache_dir)
            env = webassets.Environment(out_dir, os.path.dirname(output),
                                        cache=cache_dir)
            bundle = webassets.Bundle(*inputs, output=os.path.basename(output))
            env.register(output, bundle)
            # This generates the file
            env[output].urls()

        flag = False
        if (webassets is not None and self.site.config['USE_BUNDLES'] is not
                False):
            for name, files in kw['theme_bundles'].items():
                output_path = os.path.join(kw['output_folder'], name)
                dname = os.path.dirname(name)
                file_dep = [utils.get_asset_path(
                    os.path.join(dname, fname), kw['themes'],
                    kw['files_folders'])
                    for fname in files
                ]
                file_dep = filter(None, file_dep)  # removes missing files
                task = {
                    'file_dep': file_dep,
                    'basename': str(self.name),
                    'name': str(output_path),
                    'actions': [(build_bundle, (name, files))],
                    'targets': [output_path],
                    'uptodate': [utils.config_changed(kw)],
                    'clean': True,
                }
                flag = True
                yield utils.apply_filters(task, kw['filters'])
        if flag is False:  # No page rendered, yield a dummy task
            yield {
                'basename': self.name,
                'uptodate': [True],
                'name': 'None',
                'actions': [],
            }
Exemplo n.º 17
0
    def create_target_images(self, img, input_path):
        gallery_name = os.path.dirname(img)
        output_gallery = os.path.dirname(
            os.path.join(self.kw["output_folder"], self.site.path("gallery", gallery_name))
        )
        # Do thumbnails and copy originals
        # img is "galleries/name/image_name.jpg"
        # img_name is "image_name.jpg"
        # fname, ext are "image_name", ".jpg"
        # thumb_path is
        # "output/GALLERY_PATH/name/image_name.thumbnail.jpg"
        img_name = os.path.basename(img)
        fname, ext = os.path.splitext(img_name)
        thumb_path = os.path.join(output_gallery, ".thumbnail".join([fname, ext]))
        # thumb_path is "output/GALLERY_PATH/name/image_name.jpg"
        orig_dest_path = os.path.join(output_gallery, img_name)
        yield utils.apply_filters(
            {
                "basename": self.name,
                "name": thumb_path,
                "file_dep": [img],
                "targets": [thumb_path],
                "actions": [(self.resize_image, (img, thumb_path, self.kw["thumbnail_size"]))],
                "clean": True,
                "uptodate": [
                    utils.config_changed({1: self.kw["thumbnail_size"]}, "nikola.plugins.task.galleries:resize_thumb")
                ],
            },
            self.kw["filters"],
        )

        yield utils.apply_filters(
            {
                "basename": self.name,
                "name": orig_dest_path,
                "file_dep": [img],
                "targets": [orig_dest_path],
                "actions": [(self.resize_image, (img, orig_dest_path, self.kw["max_image_size"]))],
                "clean": True,
                "uptodate": [
                    utils.config_changed({1: self.kw["max_image_size"]}, "nikola.plugins.task.galleries:resize_max")
                ],
            },
            self.kw["filters"],
        )
Exemplo n.º 18
0
    def gen_tasks(self):
        """Generate (ogg) RSS feeds."""
        kw = {
            "translations": self.site.config["TRANSLATIONS"],
            "filters": self.site.config["FILTERS"],
            "blog_title": self.site.config["BLOG_TITLE"],
            "site_url": self.site.config["SITE_URL"],
            "base_url": self.site.config["BASE_URL"],
            "blog_description": self.site.config["BLOG_DESCRIPTION"],
            "output_folder": self.site.config["OUTPUT_FOLDER"],
            "feed_teasers": self.site.config["FEED_TEASERS"],
            "feed_plain": self.site.config["FEED_PLAIN"],
            "show_untranslated_posts": self.site.config['SHOW_UNTRANSLATED_POSTS'],
            "feed_length": self.site.config['FEED_LENGTH'],
            "feed_previewimage": self.site.config["FEED_PREVIEWIMAGE"],
            "tzinfo": self.site.tzinfo,
            "feed_read_more_link": self.site.config["FEED_READ_MORE_LINK"],
            "feed_links_append_query": self.site.config["FEED_LINKS_APPEND_QUERY"],
        }
        self.site.scan_posts()
        # Check for any changes in the state of use_in_feeds for any post.
        # Issue #934
        kw['use_in_feeds_status'] = ''.join(
            ['T' if x.use_in_feeds else 'F' for x in self.site.timeline]
        )
        yield self.group_task()
        for lang in kw["translations"]:
            output_name = os.path.join(kw['output_folder'],
                                       self.site.path("rss_ogg", None, lang))
            deps = []
            deps_uptodate = []
            if kw["show_untranslated_posts"]:
                posts = self.site.posts[:kw['feed_length']]
            else:
                posts = [x for x in self.site.posts if x.is_translation_available(lang)][:kw['feed_length']]
            for post in posts:
                deps += post.deps(lang)
                deps_uptodate += post.deps_uptodate(lang)

            feed_url = urljoin(self.site.config['BASE_URL'], self.site.link("rss", None, lang).lstrip('/'))

            task = {
                'basename': 'generate_rss_ogg',
                'name': os.path.normpath(output_name),
                'file_dep': deps,
                'targets': [output_name],
                'actions': [(utils.generic_rss_renderer,
                            (lang, kw["blog_title"](lang), kw["site_url"],
                             kw["blog_description"](lang), posts, output_name,
                             kw["feed_teasers"], kw["feed_plain"], kw['feed_length'], feed_url,
                             self._enclosure, kw["feed_links_append_query"]))],

                'task_dep': ['render_posts'],
                'clean': True,
                'uptodate': [utils.config_changed(kw, 'nikola.plugins.task.rss')] + deps_uptodate,
            }
            yield utils.apply_filters(task, kw['filters'])
Exemplo n.º 19
0
    def gen_tasks(self):
        self.kw = {
            "strip_indexes": self.site.config["STRIP_INDEXES"],
            "output_folder": self.site.config["OUTPUT_FOLDER"],
            "cache_folder": self.site.config["CACHE_FOLDER"],
            "default_lang": self.site.config["DEFAULT_LANG"],
            "filters": self.site.config["FILTERS"],
            "translations": self.site.config["TRANSLATIONS"],
            "global_context": self.site.GLOBAL_CONTEXT,
            "tzinfo": self.site.tzinfo,
        }
        # print(dir(self.site.compilers["markdown"].compile_html))
        # yield self.group_task()
        template_name = "documentation.mako"
        template_dep = self.site.template_system.template_deps(template_name)
        # template_dep += [template_name]
        class_template_name = "documentation_class.mako"
        class_template_dep = self.site.template_system.template_deps(class_template_name)
        index_block_template_name = "documentation_index_block.mako"
        index_block_template_dep = self.site.template_system.template_deps(index_block_template_name)
        module_intro_template_name = "documentation_module_intro.mako"
        module_intro_template_dep = self.site.template_system.template_deps(module_intro_template_name)
        # class_template_dep += [class_template_name]
        tdst = []
        for lang in self.kw["translations"]:
            short_tdst = os.path.join(self.kw["translations"][lang], "documentation", "index.html")
            tdst.append(os.path.normpath(os.path.join(self.kw["output_folder"], short_tdst)))

        docs_md = []
        directory = os.path.join(self.site.original_cwd, "documentation")
        for root, subFolders, files in os.walk(directory):
            for file in files:
                f = os.path.join(root, file)
                docs_md.append(f)

        yield utils.apply_filters(
            {
                "basename": self.name,
                "name": "documentation",
                "file_dep": template_dep
                + docs_md
                + class_template_dep
                + index_block_template_dep
                + module_intro_template_dep
                + [__file__],
                "targets": tdst,
                "actions": [(self.create_docs, ())],
                "clean": True,
                "uptodate": [utils.config_changed({1: self.kw})],
            },
            self.kw["filters"],
        )
Exemplo n.º 20
0
 def gen_tasks(self):
     self.kw = {
         'strip_indexes': self.site.config['STRIP_INDEXES'],
         'output_folder': self.site.config['OUTPUT_FOLDER'],
         'cache_folder': self.site.config['CACHE_FOLDER'],
         'default_lang': self.site.config['DEFAULT_LANG'],
         'filters': self.site.config['FILTERS'],
         'translations': self.site.config['TRANSLATIONS'],
         'global_context': self.site.GLOBAL_CONTEXT,
         'tzinfo': self.site.tzinfo,
     }
     #print(dir(self.site.compilers["markdown"].compile_html))
     #yield self.group_task()
     template_name = "documentation.mako"
     template_dep = self.site.template_system.template_deps(template_name)
     #template_dep += [template_name]
     class_template_name = "documentation_class.mako"
     class_template_dep = self.site.template_system.template_deps(class_template_name)
     index_block_template_name = "documentation_index_block.mako"
     index_block_template_dep = self.site.template_system.template_deps(index_block_template_name)
     module_intro_template_name = "documentation_module_intro.mako"
     module_intro_template_dep = self.site.template_system.template_deps(module_intro_template_name)
     #class_template_dep += [class_template_name]
     tdst = []
     for lang in self.kw['translations']:
         short_tdst = os.path.join(self.kw['translations'][lang], "documentation", "index.html")
         tdst.append(os.path.normpath(os.path.join(self.kw['output_folder'], short_tdst)))
         
     docs_md = []
     directory = os.path.join(self.site.original_cwd, "documentation")
     for root, subFolders, files in os.walk(directory):
         for file in files:
             f = os.path.join(root,file)
             docs_md.append(f)
         
     yield utils.apply_filters({
         'basename': self.name,
         'name': "documentation",
         'file_dep': template_dep + docs_md + class_template_dep + index_block_template_dep + module_intro_template_dep + [__file__],
         'targets': tdst,
         'actions': [
             (self.create_docs, ())
         ],
         'clean': True,
         'uptodate': [utils.config_changed({
             1: self.kw,
         })],
     }, self.kw['filters'])
Exemplo n.º 21
0
    def gen_tasks(self):
        """Bundle assets using WebAssets."""

        kw = {
            'filters': self.site.config['FILTERS'],
            'output_folder': self.site.config['OUTPUT_FOLDER'],
            'theme_bundles': get_theme_bundles(self.site.THEMES),
        }

        def build_bundle(output, inputs):
            out_dir = os.path.join(kw['output_folder'], os.path.dirname(output))
            inputs = [i for i in inputs if os.path.isfile(
                os.path.join(out_dir, i))]
            cache_dir = os.path.join('cache','webassets')
            os.makedirs(cache_dir)
            env = webassets.Environment(out_dir, os.path.dirname(output),
                cache=cache_dir)
            bundle = webassets.Bundle(*inputs,
                output=os.path.basename(output))
            env.register(output, bundle)
            # This generates the file
            env[output].urls()

        flag = False
        if webassets is not None and self.site.config['USE_BUNDLES'] != False:
            for name, files in kw['theme_bundles'].items():
                output_path = os.path.join(kw['output_folder'], name)
                dname = os.path.dirname(name)
                file_dep = [os.path.join('output', dname, fname)
                    for fname in files]
                task = {
                    'file_dep': file_dep,
                    'basename': self.name,
                    'name': output_path,
                    'actions': [(build_bundle, (name, files))],
                    'targets': [output_path],
                    'uptodate': [utils.config_changed(kw)]
                    }
                flag = True
                yield utils.apply_filters(task, kw['filters'])
        if flag is False:  # No page rendered, yield a dummy task
            yield {
                'basename': self.name,
                'uptodate': [True],
                'name': 'None',
                'actions': [],
            }
Exemplo n.º 22
0
    def gen_tasks(self):
        """Bundle assets using WebAssets."""

        kw = {
            "filters": self.site.config["FILTERS"],
            "output_folder": self.site.config["OUTPUT_FOLDER"],
            "cache_folder": self.site.config["CACHE_FOLDER"],
            "theme_bundles": get_theme_bundles(self.site.THEMES),
            "themes": self.site.THEMES,
            "files_folders": self.site.config["FILES_FOLDERS"],
            "code_color_scheme": self.site.config["CODE_COLOR_SCHEME"],
        }

        def build_bundle(output, inputs):
            out_dir = os.path.join(kw["output_folder"], os.path.dirname(output))
            inputs = [i for i in inputs if os.path.isfile(os.path.join(out_dir, i))]
            cache_dir = os.path.join(kw["cache_folder"], "webassets")
            if not os.path.isdir(cache_dir):
                os.makedirs(cache_dir)
            env = webassets.Environment(out_dir, os.path.dirname(output), cache=cache_dir)
            bundle = webassets.Bundle(*inputs, output=os.path.basename(output))
            env.register(output, bundle)
            # This generates the file
            env[output].urls()

        flag = False
        if webassets is not None and self.site.config["USE_BUNDLES"] is not False:
            for name, files in kw["theme_bundles"].items():
                output_path = os.path.join(kw["output_folder"], name)
                dname = os.path.dirname(name)
                file_dep = [
                    utils.get_asset_path(os.path.join(dname, fname), kw["themes"], kw["files_folders"])
                    for fname in files
                ]
                file_dep = filter(None, file_dep)  # removes missing files
                task = {
                    "file_dep": file_dep,
                    "basename": str(self.name),
                    "name": str(output_path),
                    "actions": [(build_bundle, (name, files))],
                    "targets": [output_path],
                    "uptodate": [utils.config_changed(kw)],
                }
                flag = True
                yield utils.apply_filters(task, kw["filters"])
        if flag is False:  # No page rendered, yield a dummy task
            yield {"basename": self.name, "uptodate": [True], "name": "None", "actions": []}
Exemplo n.º 23
0
    def gen_tasks(self):
        """Generate a robots.txt file."""
        kw = {
            "base_url": self.site.config["BASE_URL"],
            "site_url": self.site.config["SITE_URL"],
            "output_folder": self.site.config["OUTPUT_FOLDER"],
            "files_folders": self.site.config["FILES_FOLDERS"],
            "robots_exclusions": self.site.config["ROBOTS_EXCLUSIONS"],
            "filters": self.site.config["FILTERS"],
        }

        sitemapindex_url = urljoin(kw["base_url"], "sitemapindex.xml")
        robots_path = os.path.join(kw["output_folder"], "robots.txt")

        def write_robots():
            if kw["site_url"] != urljoin(kw["site_url"], "/"):
                utils.LOGGER.warn("robots.txt not ending up in server root, will be useless")

            with io.open(robots_path, "w+", encoding="utf8") as outf:
                outf.write("Sitemap: {0}\n\n".format(sitemapindex_url))
                if kw["robots_exclusions"]:
                    outf.write("User-Agent: *\n")
                    for loc in kw["robots_exclusions"]:
                        outf.write("Disallow: {0}\n".format(loc))

        yield self.group_task()

        if not utils.get_asset_path("robots.txt", [], files_folders=kw["files_folders"], output_dir=False):
            yield utils.apply_filters(
                {
                    "basename": self.name,
                    "name": robots_path,
                    "targets": [robots_path],
                    "actions": [(write_robots)],
                    "uptodate": [utils.config_changed(kw, "nikola.plugins.task.robots")],
                    "clean": True,
                    "task_dep": ["sitemap"],
                },
                kw["filters"],
            )
        elif kw["robots_exclusions"]:
            utils.LOGGER.warn(
                "Did not generate robots.txt as one already exists in FILES_FOLDERS. ROBOTS_EXCLUSIONS will not have any affect on the copied file."
            )
        else:
            utils.LOGGER.debug("Did not generate robots.txt as one already exists in FILES_FOLDERS.")
Exemplo n.º 24
0
    def gen_tasks(self):
        """Bundle assets using WebAssets."""

        kw = {
            "filters": self.site.config["FILTERS"],
            "output_folder": self.site.config["OUTPUT_FOLDER"],
            "cache_folder": self.site.config["CACHE_FOLDER"],
            "theme_bundles": get_theme_bundles(self.site.THEMES),
            "themes": self.site.THEMES,
            "files_folders": self.site.config["FILES_FOLDERS"],
            "code_color_scheme": self.site.config["CODE_COLOR_SCHEME"],
        }

        def build_bundle(output, inputs):
            out_dir = os.path.join(kw["output_folder"], os.path.dirname(output))
            inputs = [i for i in inputs if os.path.isfile(os.path.join(out_dir, i))]
            cache_dir = os.path.join(kw["cache_folder"], "webassets")
            utils.makedirs(cache_dir)
            env = webassets.Environment(out_dir, os.path.dirname(output), cache=cache_dir)
            if inputs:
                bundle = webassets.Bundle(*inputs, output=os.path.basename(output))
                env.register(output, bundle)
                # This generates the file
                env[output].urls()
            else:
                with open(os.path.join(out_dir, os.path.basename(output)), "wb+"):
                    pass  # Create empty file

        yield self.group_task()
        if webassets is not None and self.site.config["USE_BUNDLES"] is not False:
            for name, files in kw["theme_bundles"].items():
                output_path = os.path.join(kw["output_folder"], name)
                dname = os.path.dirname(name)
                file_dep = [os.path.join(kw["output_folder"], dname, fname) for fname in files]
                file_dep = filter(os.path.isfile, file_dep)  # removes missing files
                task = {
                    "file_dep": list(file_dep),
                    "task_dep": ["copy_assets"],
                    "basename": str(self.name),
                    "name": str(output_path),
                    "actions": [(build_bundle, (name, files))],
                    "targets": [output_path],
                    "uptodate": [utils.config_changed(kw)],
                    "clean": True,
                }
                yield utils.apply_filters(task, kw["filters"])
Exemplo n.º 25
0
    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'],
            'filters': self.site.config['FILTERS'],
        }

        yield self.group_task()
        for src in kw['files_folders']:
            dst = kw['output_folder']
            filters = kw['filters']
            real_dst = os.path.join(dst, kw['files_folders'][src])
            for task in utils.copy_tree(src, real_dst, link_cutoff=dst):
                task['basename'] = self.name
                task['uptodate'] = [utils.config_changed(kw, 'nikola.plugins.task.copy_files')]
                yield utils.apply_filters(task, filters, skip_ext=['.html'])
Exemplo n.º 26
0
 def tag_rss(self, tag, lang, posts, kw, is_category):
     """RSS for a single tag / language"""
     kind = "category" if is_category else "tag"
     # Render RSS
     output_name = os.path.normpath(os.path.join(kw["output_folder"], self.site.path(kind + "_rss", tag, lang)))
     feed_url = urljoin(self.site.config["BASE_URL"], self.site.link(kind + "_rss", tag, lang).lstrip("/"))
     deps = []
     deps_uptodate = []
     post_list = sorted(posts, key=lambda a: a.date)
     post_list.reverse()
     for post in post_list:
         deps += post.deps(lang)
         deps_uptodate += post.deps_uptodate(lang)
     task = {
         "basename": str(self.name),
         "name": output_name,
         "file_dep": deps,
         "targets": [output_name],
         "actions": [
             (
                 utils.generic_rss_renderer,
                 (
                     lang,
                     "{0} ({1})".format(kw["blog_title"](lang), self._get_title(tag, is_category)),
                     kw["site_url"],
                     None,
                     post_list,
                     output_name,
                     kw["rss_teasers"],
                     kw["rss_plain"],
                     kw["feed_length"],
                     feed_url,
                     None,
                     kw["rss_link_append_query"],
                 ),
             )
         ],
         "clean": True,
         "uptodate": [utils.config_changed(kw, "nikola.plugins.task.tags:rss")] + deps_uptodate,
         "task_dep": ["render_posts"],
     }
     return utils.apply_filters(task, kw["filters"])
Exemplo n.º 27
0
    def gen_tasks(self):
        """Generate redirections tasks."""
        kw = {
            'redirections': self.site.config['REDIRECTIONS'],
            'output_folder': self.site.config['OUTPUT_FOLDER'],
            'filters': self.site.config['FILTERS'],
        }

        yield self.group_task()
        if kw['redirections']:
            for src, dst in kw["redirections"]:
                src_path = os.path.join(kw["output_folder"], src.lstrip('/'))
                yield utils.apply_filters({
                    'basename': self.name,
                    'name': src_path,
                    'targets': [src_path],
                    'actions': [(utils.create_redirect, (src_path, dst))],
                    'clean': True,
                    'uptodate': [utils.config_changed(kw, 'nikola.plugins.task.redirect')],
                }, kw["filters"])
Exemplo n.º 28
0
    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"],
            "filters": self.site.config["FILTERS"],
        }

        flag = False
        for src in kw["files_folders"]:
            dst = kw["output_folder"]
            filters = kw["filters"]
            real_dst = os.path.join(dst, kw["files_folders"][src])
            for task in utils.copy_tree(src, real_dst, link_cutoff=dst):
                flag = True
                task["basename"] = self.name
                task["uptodate"] = [utils.config_changed(kw)]
                yield utils.apply_filters(task, filters)
        if not flag:
            yield {"basename": self.name, "actions": ()}
Exemplo n.º 29
0
 def gen_tasks(self):
     """Generate RSS feeds."""
     kw = {
         "output_folder": self.site.config["OUTPUT_FOLDER"],
         "filters": self.site.config["FILTERS"],
         "index_file": self.site.config["INDEX_FILE"],
         "translations": self.site.config["TRANSLATIONS"],
         "show_untranslated_posts": self.site.config["SHOW_UNTRANSLATED_POSTS"],
         "site_url": self.site.config["SITE_URL"],
         "base_url": self.site.config["BASE_URL"],
         "json_posts_length": self.site.config["RECENT_POSTS_JSON_LENGTH"] if "RECENT_POSTS_JSON_LENGTH" in self.site.config else self.site.config["INDEX_DISPLAY_POST_COUNT"],
         "json_descriptions": self.site.config["RECENT_POSTS_JSON_DESCRIPTION"] if "RECENT_POSTS_JSON_DESCRIPTION" in self.site.config else False,
         "json_previewimage": self.site.conf["RECENT_POSTS_JSON_PREVIEWIMAGE"] if "RECENT_POSTS_JSON_PREVIEWIMAGE" in self.site.config else False,
     }
     self.site.scan_posts()
     yield self.group_task()
     for lang in kw["translations"]:
         output_path = os.path.join(kw["output_folder"],
                                    self.site.path("recent_posts_json", None, lang))
         deps = []
         deps_uptodate = []
         if kw["show_untranslated_posts"]:
             posts = self.site.posts[:kw["json_posts_length"]]
         else:
             posts = [x for x in self.site.posts if x.is_translation_available(lang)][:kw["json_posts_length"]]
         for post in posts:
             deps += post.deps(lang)
             deps_uptodate += post.deps_uptodate(lang)
         task = {
             "basename": "recent_posts_json",
             "name": os.path.normpath(output_path),
             "file_dep": deps,
             "targets": [output_path],
             "actions": [(self.make_json,
                         (posts, kw["json_descriptions"], kw["json_previewimage"], output_path))],
             "task_dep": ["render_posts"],
             "clean": True,
             "uptodate": [utils.config_changed(kw, "nikola.plugins.task.recent_pots_json")] + deps_uptodate,
         }
         yield utils.apply_filters(task, kw["filters"])
Exemplo n.º 30
0
 def tag_rss(self, tag, lang, posts, kw, is_category):
     """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(
         os.path.join(kw['output_folder'],
                      self.site.path(kind + "_rss", tag, lang)))
     feed_url = urljoin(
         self.site.config['BASE_URL'],
         self.site.link(kind + "_rss", tag, lang).lstrip('/'))
     deps = []
     deps_uptodate = []
     post_list = sorted(posts, key=lambda a: a.date)
     post_list.reverse()
     for post in post_list:
         deps += post.deps(lang)
         deps_uptodate += post.deps_uptodate(lang)
     task = {
         'basename':
         str(self.name),
         'name':
         output_name,
         'file_dep':
         deps,
         'targets': [output_name],
         'actions':
         [(utils.generic_rss_renderer,
           (lang, "{0} ({1})".format(kw["blog_title"](lang),
                                     self._get_title(tag, is_category)),
            kw["site_url"], None, post_list, output_name,
            kw["feed_teasers"], kw["feed_plain"], kw['feed_length'],
            feed_url, _enclosure, kw["feed_link_append_query"]))],
         'clean':
         True,
         'uptodate':
         [utils.config_changed(kw, 'nikola.plugins.task.tags:rss')] +
         deps_uptodate,
         'task_dep': ['render_posts'],
     }
     return utils.apply_filters(task, kw['filters'])
Exemplo n.º 31
0
    def gen_tasks(self):
        """Render the tag cloud."""
        self.site.scan_posts()
        yield self.group_task()

        # Tag cloud json file
        tag_cloud_data = {}
        for tag, posts in self.site.posts_per_tag.items():
            if tag in self.site.config['HIDDEN_TAGS']:
                continue
            tag_posts = dict(posts=[{'title': post.meta[post.default_lang]['title'],
                                     'date': post.date.strftime('%m/%d/%Y'),
                                     'isodate': post.date.isoformat(),
                                     'url': post.permalink(post.default_lang)}
                                    for post in reversed(sorted(self.site.timeline, key=lambda post: post.date))
                                    if tag in post.alltags])
            tag_cloud_data[tag] = [len(posts), self.site.link(
                'tag', tag, self.site.config['DEFAULT_LANG']), tag_posts]
        output_name = os.path.join(self.site.config['OUTPUT_FOLDER'],
                                   '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, sort_keys=True)

        if self.site.config['WRITE_TAG_CLOUD']:
            task = {
                'basename': str(self.name),
                'name': str(output_name)
            }

            task['uptodate'] = [utils.config_changed(tag_cloud_data, 'nikola.plugins.task.tags:tagdata')]
            task['targets'] = [output_name]
            task['actions'] = [(write_tag_data, [tag_cloud_data])]
            task['clean'] = True
            yield utils.apply_filters(task, self.site.config['FILTERS'])
Exemplo n.º 32
0
    def gen_tasks(self):
        """Render the tag cloud."""
        self.site.scan_posts()
        yield self.group_task()

        # Tag cloud json file
        tag_cloud_data = {}
        for tag, posts in self.site.posts_per_tag.items():
            if tag in self.site.config['HIDDEN_TAGS']:
                continue
            tag_posts = dict(posts=[{'title': post.meta[post.default_lang]['title'],
                                     'date': post.date.strftime('%m/%d/%Y'),
                                     'isodate': post.date.isoformat(),
                                     'url': post.permalink(post.default_lang)}
                                    for post in reversed(sorted(self.site.timeline, key=lambda post: post.date))
                                    if tag in post.alltags])
            tag_cloud_data[tag] = [len(posts), self.site.link(
                'tag', tag, self.site.config['DEFAULT_LANG']), tag_posts]
        output_name = os.path.join(self.site.config['OUTPUT_FOLDER'],
                                   '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, sort_keys=True)

        if self.site.config['WRITE_TAG_CLOUD']:
            task = {
                'basename': str(self.name),
                'name': str(output_name)
            }

            task['uptodate'] = [utils.config_changed(tag_cloud_data, 'nikola.plugins.task.tags:tagdata')]
            task['targets'] = [output_name]
            task['actions'] = [(write_tag_data, [tag_cloud_data])]
            task['clean'] = True
            yield utils.apply_filters(task, self.site.config['FILTERS'])
Exemplo n.º 33
0
    def gen_tasks(self):
        """Copy static files into the output folder."""

        self.kw = {
            'thumbnail_size': self.site.config['THUMBNAIL_SIZE'],
            'max_image_size': self.site.config['MAX_IMAGE_SIZE'],
            'image_folders': self.site.config['IMAGE_FOLDERS'],
            'output_folder': self.site.config['OUTPUT_FOLDER'],
            'filters': self.site.config['FILTERS'],
        }

        self.image_ext_list = self.image_ext_list_builtin
        self.image_ext_list.extend(self.site.config.get('EXTRA_IMAGE_EXTENSIONS', []))

        yield self.group_task()
        for src in self.kw['image_folders']:
            dst = self.kw['output_folder']
            filters = self.kw['filters']
            real_dst = os.path.join(dst, self.kw['image_folders'][src])
            for task in self.process_tree(src, real_dst):
                task['basename'] = self.name
                task['uptodate'] = [utils.config_changed(self.kw)]
                yield utils.apply_filters(task, filters)
Exemplo n.º 34
0
    def generate_feed_task(self,
                           lang,
                           title,
                           link,
                           description,
                           timeline,
                           feed_url,
                           output_name,
                           primary_author=None):
        """Generate a task to create a feed."""
        # Build dependency list
        deps = []
        deps_uptodate = []
        for post in timeline:
            deps += post.deps(lang)
            deps_uptodate += post.deps_uptodate(lang)

        task = {
            'basename':
            str(self.name),
            'name':
            str(output_name),
            'targets': [output_name],
            'file_dep':
            deps,
            'task_dep': ['render_posts', 'render_taxonomies'],
            'actions':
            [(self.generate_feed, (lang, title, link, description, timeline,
                                   feed_url, output_name, primary_author))],
            'uptodate':
            [utils.config_changed(self.kw, 'jsonfeed:' + output_name)] +
            deps_uptodate,
            'clean':
            True
        }

        yield utils.apply_filters(task, self.site.config['FILTERS'])
Exemplo n.º 35
0
    def gen_tasks(self):
        self.site.scan_posts()
        kw = {
            "translations": self.site.config["TRANSLATIONS"],
            "timeline": self.site.timeline,
            "default_lang": self.site.config["DEFAULT_LANG"],
            "show_untranslated_posts":
            self.site.config["SHOW_UNTRANSLATED_POSTS"],
            "demote_headers": self.site.config["DEMOTE_HEADERS"],
        }
        self.tl_changed = False
        yield self.group_task()

        def tl_ch():
            self.tl_changed = True

        yield {
            "basename": self.name,
            "name": "timeline_changes",
            "actions": [tl_ch],
            "uptodate": [utils.config_changed({1: kw["timeline"]})],
        }
        for lang in kw["translations"]:
            deps_dict = copy(kw)
            deps_dict.pop("timeline")
            for post in kw["timeline"]:
                if not should_generate_pdf(self.site, post, lang):
                    self.logger.info("not generating pdf for " + post.title())
                    continue

                yield utils.apply_filters(
                    self.get_task(deps_dict, post, lang),
                    {
                        os.path.splitext(get_pdf_dest(self.site, post, lang))[-1]:
                        self.get_metadata_filters(post, lang)
                    },
                )
Exemplo n.º 36
0
    def gen_tasks(self):
        """Create tasks to copy the assets of the whole theme chain.

        If a file is present on two themes, use the version
        from the "youngest" theme.
        """

        kw = {
            "themes": self.site.THEMES,
            "output_folder": self.site.config['OUTPUT_FOLDER'],
            "filters": self.site.config['FILTERS'],
        }

        tasks = {}
        for theme_name in kw['themes']:
            src = os.path.join(utils.get_theme_path(theme_name), 'assets')
            dst = os.path.join(kw['output_folder'], 'assets')
            for task in utils.copy_tree(src, dst):
                if task['name'] in tasks:
                    continue
                tasks[task['name']] = task
                task['uptodate'] = [utils.config_changed(kw)]
                task['basename'] = self.name
                yield utils.apply_filters(task, kw['filters'])
Exemplo n.º 37
0
    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'],
            'filters': self.site.config['FILTERS'],
        }

        flag = False
        for src in kw['files_folders']:
            dst = kw['output_folder']
            filters = kw['filters']
            real_dst = os.path.join(dst, kw['files_folders'][src])
            for task in utils.copy_tree(src, real_dst, link_cutoff=dst):
                flag = True
                task['basename'] = self.name
                task['uptodate'] = [utils.config_changed(kw)]
                yield utils.apply_filters(task, filters)
        if not flag:
            yield {
                'basename': self.name,
                'actions': (),
            }
Exemplo n.º 38
0
    def gen_tasks(self):
        """Create tasks to copy the assets of the whole theme chain.

        If a file is present on two themes, use the version
        from the "youngest" theme.
        """

        kw = {
            "themes": self.site.THEMES,
            "output_folder": self.site.config['OUTPUT_FOLDER'],
            "filters": self.site.config['FILTERS'],
            "code_color_scheme": self.site.config['CODE_COLOR_SCHEME'],
        }
        flag = True
        has_code_css = False
        tasks = {}
        code_css_path = os.path.join(kw['output_folder'], 'assets', 'css', 'code.css')
        for theme_name in kw['themes']:
            src = os.path.join(utils.get_theme_path(theme_name), 'assets')
            dst = os.path.join(kw['output_folder'], 'assets')
            for task in utils.copy_tree(src, dst):
                if task['name'] in tasks:
                    continue
                if task['targets'][0] == code_css_path:
                    has_code_css = True
                tasks[task['name']] = task
                task['uptodate'] = [utils.config_changed(kw)]
                task['basename'] = self.name
                flag = False
                yield utils.apply_filters(task, kw['filters'])

        if flag:
            yield {
                'basename': self.name,
                'name': 'None',
                'uptodate': [True],
                'actions': [],
            }

        if not has_code_css:  # Generate it

            def create_code_css():
                from pygments.formatters import get_formatter_by_name
                formatter = get_formatter_by_name('html', style=kw["code_color_scheme"])
                try:
                    os.makedirs(os.path.dirname(code_css_path))
                except:
                    pass
                with codecs.open(code_css_path, 'wb+', 'utf8') as outf:
                    outf.write(formatter.get_style_defs('.code'))
                    outf.write("table.codetable { width: 100%;} td.linenos {text-align: right; width: 4em;}")

            task = {
                'basename': self.name,
                'name': code_css_path,
                'targets': [code_css_path],
                'uptodate': [utils.config_changed(kw)],
                'actions': [(create_code_css, [])],
                'clean': True,
            }
            yield utils.apply_filters(task, kw['filters'])
Exemplo n.º 39
0
    def gen_tasks(self):
        """Render image galleries."""

        self.logger = utils.get_logger('render_galleries',
                                       self.site.loghandlers)
        self.image_ext_list = [
            '.jpg', '.png', '.jpeg', '.gif', '.svg', '.bmp', '.tiff'
        ]
        self.image_ext_list.extend(
            self.site.config.get('EXTRA_IMAGE_EXTENSIONS', []))

        self.kw = {
            'thumbnail_size': self.site.config['THUMBNAIL_SIZE'],
            'max_image_size': self.site.config['MAX_IMAGE_SIZE'],
            'output_folder': self.site.config['OUTPUT_FOLDER'],
            'cache_folder': self.site.config['CACHE_FOLDER'],
            'default_lang': self.site.config['DEFAULT_LANG'],
            'use_filename_as_title': self.site.config['USE_FILENAME_AS_TITLE'],
            'gallery_path': self.site.config['GALLERY_PATH'],
            'sort_by_date': self.site.config['GALLERY_SORT_BY_DATE'],
            'filters': self.site.config['FILTERS'],
            'translations': self.site.config['TRANSLATIONS'],
            'global_context': self.site.GLOBAL_CONTEXT,
            "feed_length": self.site.config['FEED_LENGTH'],
        }

        yield self.group_task()

        template_name = "gallery.tmpl"

        # Find all galleries we need to process
        self.find_galleries()

        # Create all output folders
        for task in self.create_galleries():
            yield task

        # For each gallery:
        for gallery in self.gallery_list:

            # Create subfolder list
            folder_list = [
                (x, x.split(os.sep)[-2])
                for x in glob.glob(os.path.join(gallery, '*') + os.sep)
            ]

            # Parse index into a post (with translations)
            post = self.parse_index(gallery)

            # Create image list, filter exclusions
            image_list = self.get_image_list(gallery)

            # Sort as needed
            # Sort by date
            if self.kw['sort_by_date']:
                image_list.sort(key=lambda a: self.image_date(a))
            else:  # Sort by name
                image_list.sort()

            # Create thumbnails and large images in destination
            for image in image_list:
                for task in self.create_target_images(image):
                    yield task

            # Remove excluded images
            for image in self.get_excluded_images(gallery):
                for task in self.remove_excluded_image(image):
                    yield task

            crumbs = utils.get_crumbs(gallery)

            # Create index.html for each language
            for lang in self.kw['translations']:
                dst = os.path.join(
                    self.kw['output_folder'],
                    self.site.path(
                        "gallery",
                        os.path.relpath(gallery, self.kw['gallery_path']),
                        lang))
                dst = os.path.normpath(dst)

                context = {}
                context["lang"] = lang
                if post:
                    context["title"] = post.title(lang)
                else:
                    context["title"] = os.path.basename(gallery)
                context["description"] = None

                image_name_list = [os.path.basename(p) for p in image_list]

                if self.kw['use_filename_as_title']:
                    img_titles = []
                    for fn in image_name_list:
                        name_without_ext = os.path.splitext(fn)[0]
                        img_titles.append(
                            'id="{0}" alt="{1}" title="{2}"'.format(
                                name_without_ext, name_without_ext,
                                utils.unslugify(name_without_ext)))
                else:
                    img_titles = [''] * len(image_name_list)

                thumbs = [
                    '.thumbnail'.join(os.path.splitext(p)) for p in image_list
                ]
                thumbs = [
                    os.path.join(self.kw['output_folder'], t) for t in thumbs
                ]

                folders = []

                # Generate friendly gallery names
                for path, folder in folder_list:
                    fpost = self.parse_index(path)
                    if fpost:
                        ft = fpost.title(lang) or folder
                    else:
                        ft = folder
                    folders.append((folder, ft))

                ## TODO: in v7 remove images from context, use photo_array
                context["images"] = list(
                    zip(image_name_list, thumbs, img_titles))
                context["folders"] = folders
                context["crumbs"] = crumbs
                context["permalink"] = self.site.link(
                    "gallery", os.path.basename(gallery), lang)
                # FIXME: use kw
                context["enable_comments"] = (
                    self.site.config["COMMENTS_IN_GALLERIES"])
                context["thumbnail_size"] = self.kw["thumbnail_size"]

                # FIXME: render post in a task
                if post:
                    post.compile(lang)
                    context['text'] = post.text(lang)
                else:
                    context['text'] = ''

                file_dep = self.site.template_system.template_deps(
                    template_name) + image_list + thumbs

                yield utils.apply_filters(
                    {
                        'basename':
                        self.name,
                        'name':
                        dst,
                        'file_dep':
                        file_dep,
                        'targets': [dst],
                        'actions': [(self.render_gallery_index,
                                     (template_name, dst, context, image_list,
                                      thumbs, file_dep))],
                        'clean':
                        True,
                        'uptodate': [
                            utils.config_changed(
                                {
                                    1: self.kw,
                                    2:
                                    self.site.config["COMMENTS_IN_GALLERIES"],
                                    3: context,
                                })
                        ],
                    }, self.kw['filters'])

                # RSS for the gallery
                rss_dst = os.path.join(
                    self.kw['output_folder'],
                    self.site.path(
                        "gallery_rss",
                        os.path.relpath(gallery, self.kw['gallery_path']),
                        lang))
                rss_dst = os.path.normpath(rss_dst)

                yield utils.apply_filters(
                    {
                        'basename':
                        self.name,
                        'name':
                        rss_dst,
                        'file_dep':
                        file_dep,
                        'targets': [rss_dst],
                        'actions':
                        [(self.gallery_rss,
                          (image_list, img_titles, lang,
                           self.site.link("gallery_rss",
                                          os.path.basename(gallery),
                                          lang), rss_dst, context['title']))],
                        'clean':
                        True,
                        'uptodate': [utils.config_changed({
                            1: self.kw,
                        })],
                    }, self.kw['filters'])
Exemplo n.º 40
0
    def gen_tasks(self):
        """Create tasks to copy the assets of the whole theme chain.

        If a file is present on two themes, use the version
        from the "youngest" theme.
        """
        kw = {
            "themes":
            self.site.THEMES,
            "translations":
            self.site.translations,
            "files_folders":
            self.site.config['FILES_FOLDERS'],
            "output_folder":
            self.site.config['OUTPUT_FOLDER'],
            "filters":
            self.site.config['FILTERS'],
            "code_color_scheme":
            self.site.config['CODE_COLOR_SCHEME'],
            "code.css_selectors": ['pre.code', '.highlight pre'],
            "code.css_head":
            '/* code.css file generated by Nikola */\n',
            "code.css_close":
            "\ntable.codetable { width: 100%;} td.linenos {text-align: right; width: 4em;}\n",
        }
        tasks = {}
        code_css_path = os.path.join(kw['output_folder'], 'assets', 'css',
                                     'code.css')
        code_css_input = utils.get_asset_path(
            'assets/css/code.css',
            themes=kw['themes'],
            files_folders=kw['files_folders'],
            output_dir=None)
        yield self.group_task()

        main_theme = utils.get_theme_path(kw['themes'][0])
        theme_ini = utils.parse_theme_meta(main_theme)
        if theme_ini:
            ignored_assets = theme_ini.get("Nikola",
                                           "ignored_assets",
                                           fallback='').split(',')
            ignore_colorbox_i18n = theme_ini.get("Nikola",
                                                 "ignore_colorbox_i18n",
                                                 fallback="unused")
        else:
            ignored_assets = []
            ignore_colorbox_i18n = "unused"

        if ignore_colorbox_i18n == "unused":
            # Check what colorbox languages we need so we can ignore the rest
            needed_colorbox_languages = [
                LEGAL_VALUES['COLORBOX_LOCALES'][i] for i in kw['translations']
            ]
            needed_colorbox_languages = [
                i for i in needed_colorbox_languages if i
            ]  # remove '' for en
            # ignored_filenames is passed to copy_tree to avoid creating
            # directories. Since ignored_assets are full paths, and copy_tree
            #  works on single filenames, we can’t use that here.
            if not needed_colorbox_languages:
                ignored_filenames = set(["colorbox-i18n"])
            else:
                ignored_filenames = set()

        for theme_name in kw['themes']:
            src = os.path.join(utils.get_theme_path(theme_name), 'assets')
            dst = os.path.join(kw['output_folder'], 'assets')
            for task in utils.copy_tree(src,
                                        dst,
                                        ignored_filenames=ignored_filenames):
                asset_name = os.path.relpath(task['name'], dst)
                if task['name'] in tasks or asset_name in ignored_assets:
                    continue
                elif asset_name.startswith(_COLORBOX_PREFIX):
                    if ignore_colorbox_i18n == "all" or ignore_colorbox_i18n is True:
                        continue

                    colorbox_lang = asset_name[_COLORBOX_SLICE]
                    if ignore_colorbox_i18n == "unused" and colorbox_lang not in needed_colorbox_languages:
                        continue
                tasks[task['name']] = task
                task['uptodate'] = [
                    utils.config_changed(kw, 'nikola.plugins.task.copy_assets')
                ]
                task['basename'] = self.name
                if code_css_input:
                    if 'file_dep' not in task:
                        task['file_dep'] = []
                    task['file_dep'].append(code_css_input)
                yield utils.apply_filters(task, kw['filters'])

        # Check whether or not there is a code.css file around.
        if not code_css_input and kw['code_color_scheme']:

            def create_code_css():
                from pygments.formatters import get_formatter_by_name
                formatter = get_formatter_by_name(
                    'html', style=kw["code_color_scheme"])
                utils.makedirs(os.path.dirname(code_css_path))
                with io.open(code_css_path, 'w+', encoding='utf8') as outf:
                    outf.write(kw["code.css_head"])
                    outf.write(
                        formatter.get_style_defs(kw["code.css_selectors"]))
                    outf.write(kw["code.css_close"])

            if os.path.exists(code_css_path):
                with io.open(code_css_path, 'r', encoding='utf-8') as fh:
                    testcontents = fh.read(len(
                        kw["code.css_head"])) == kw["code.css_head"]
            else:
                testcontents = False

            task = {
                'basename':
                self.name,
                'name':
                code_css_path,
                'targets': [code_css_path],
                'uptodate': [
                    utils.config_changed(kw,
                                         'nikola.plugins.task.copy_assets'),
                    testcontents
                ],
                'actions': [(create_code_css, [])],
                'clean':
                True,
            }
            yield utils.apply_filters(task, kw['filters'])
Exemplo n.º 41
0
    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', []))

        for k, v in self.site.GLOBAL_CONTEXT['template_hooks'].items():
            self.kw['||template_hooks|{0}||'.format(k)] = v.calculate_deps()

        self.site.scan_posts()
        yield self.group_task()

        template_name = "gallery.tmpl"

        # Create all output folders
        for task in self.create_galleries():
            yield task

        # For each gallery:
        for gallery, input_folder, output_folder in self.gallery_list:

            # Create subfolder list
            folder_list = [
                (x, x.split(os.sep)[-2])
                for x in glob.glob(os.path.join(gallery, '*') + os.sep)
            ]

            # Parse index into a post (with translations)
            post = self.parse_index(gallery, input_folder, output_folder)

            # Create image list, filter exclusions
            image_list = self.get_image_list(gallery)

            # Create thumbnails and large images in destination
            for image in image_list:
                for task in self.create_target_images(image, input_folder):
                    yield task

            # Remove excluded images
            for image in self.get_excluded_images(gallery):
                for task in self.remove_excluded_image(image, input_folder):
                    yield task

            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))
                dst = os.path.normpath(dst)

                for k in self.site._GLOBAL_CONTEXT_TRANSLATABLE:
                    self.kw[k] = self.site.GLOBAL_CONTEXT[k](lang)

                context = {}

                # Do we have a metadata file?
                meta_path, order, captions, img_metadata = self.find_metadata(
                    gallery, lang)
                context['meta_path'] = meta_path
                context['order'] = order
                context['captions'] = captions
                context["lang"] = lang
                if post:
                    context["title"] = post.title(lang)
                else:
                    context["title"] = os.path.basename(gallery)
                context["description"] = None

                image_name_list = [os.path.basename(p) for p in image_list]

                if captions:
                    img_titles = []
                    for fn in image_name_list:
                        if fn in captions:
                            img_titles.append(captions[fn])
                        else:
                            if self.kw['use_filename_as_title']:
                                img_titles.append(fn)
                            else:
                                img_titles.append('')
                            self.logger.debug(
                                "Image {0} found in gallery but not listed in {1}"
                                .format(fn, context['meta_path']))
                elif self.kw['use_filename_as_title']:
                    img_titles = []
                    for fn in image_name_list:
                        name_without_ext = os.path.splitext(
                            os.path.basename(fn))[0]
                        img_titles.append(
                            utils.unslugify(name_without_ext, lang))
                else:
                    img_titles = [''] * len(image_name_list)

                thumbs = [
                    '.thumbnail'.join(os.path.splitext(p)) for p in image_list
                ]
                thumbs = [
                    os.path.join(self.kw['output_folder'], output_folder,
                                 os.path.relpath(t, input_folder))
                    for t in thumbs
                ]
                dst_img_list = [
                    os.path.join(output_folder,
                                 os.path.relpath(t, input_folder))
                    for t in image_list
                ]
                dest_img_list = [
                    os.path.join(self.kw['output_folder'], t)
                    for t in dst_img_list
                ]

                folders = []

                # Generate friendly gallery names
                for path, folder in folder_list:
                    fpost = self.parse_index(path, input_folder, output_folder)
                    if fpost:
                        ft = fpost.title(lang) or folder
                    else:
                        ft = folder
                    if not folder.endswith('/'):
                        folder += '/'
                    folders.append((folder, ft))

                context["gallery_path"] = gallery
                context["folders"] = natsort.natsorted(folders,
                                                       alg=natsort.ns.F
                                                       | natsort.ns.IC)
                context["crumbs"] = utils.get_crumbs(gallery,
                                                     index_folder=self,
                                                     lang=lang)
                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 {
                        'basename':
                        self.name,
                        'name':
                        post.translated_base_path(lang),
                        'targets': [post.translated_base_path(lang)],
                        'file_dep':
                        post.fragment_deps(lang),
                        'actions': [(post.compile, [lang])],
                        'uptodate': [
                            utils.config_changed(
                                self.kw.copy(),
                                'nikola.plugins.task.galleries:post')
                        ] + post.fragment_deps_uptodate(lang)
                    }
                    context['post'] = post
                else:
                    context['post'] = None
                file_dep = self.site.template_system.template_deps(
                    template_name) + image_list + thumbs
                file_dep_dest = self.site.template_system.template_deps(
                    template_name) + dest_img_list + thumbs
                if post:
                    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,
                        'file_dep':
                        file_dep,
                        'targets': [dst],
                        'actions':
                        [(self.render_gallery_index,
                          (template_name, dst, context.copy(), dest_img_list,
                           img_titles, thumbs, img_metadata))],
                        'clean':
                        True,
                        'uptodate': [
                            utils.config_changed(
                                {
                                    1: self.kw.copy(),
                                    2:
                                    self.site.config["COMMENTS_IN_GALLERIES"],
                                    3: context.copy(),
                                }, 'nikola.plugins.task.galleries:gallery')
                        ],
                    }, self.kw['filters'])

                # RSS for the gallery
                if self.kw["generate_rss"]:
                    rss_dst = os.path.join(
                        self.kw['output_folder'],
                        self.site.path("gallery_rss", gallery, lang))
                    rss_dst = os.path.normpath(rss_dst)

                    yield utils.apply_filters(
                        {
                            'basename':
                            self.name,
                            'name':
                            rss_dst,
                            'file_dep':
                            file_dep_dest,
                            'targets': [rss_dst],
                            'actions':
                            [(self.gallery_rss,
                              (image_list, dst_img_list, img_titles, lang,
                               self.site.link("gallery_rss", gallery, lang),
                               rss_dst, context['title']))],
                            'clean':
                            True,
                            'uptodate': [
                                utils.config_changed({
                                    1: self.kw.copy(),
                                }, 'nikola.plugins.task.galleries:rss')
                            ],
                        }, self.kw['filters'])
Exemplo n.º 42
0
    def gen_tasks(self):
        """Build HTML fragments from metadata and text."""
        self.site.scan_posts()
        kw = {
            "translations": self.site.config["TRANSLATIONS"],
            "timeline": self.site.timeline,
            "default_lang": self.site.config["DEFAULT_LANG"],
            "show_untranslated_posts":
            self.site.config['SHOW_UNTRANSLATED_POSTS'],
            "demote_headers": self.site.config['DEMOTE_HEADERS'],
        }
        self.tl_changed = False

        yield self.group_task()

        def tl_ch():
            self.tl_changed = True

        yield {
            'basename': self.name,
            'name': 'timeline_changes',
            'actions': [tl_ch],
            'uptodate': [utils.config_changed({1: kw['timeline']})],
        }

        for lang in kw["translations"]:
            deps_dict = copy(kw)
            deps_dict.pop('timeline')
            for post in kw['timeline']:
                if not post.is_translation_available(
                        lang
                ) and not self.site.config['SHOW_UNTRANSLATED_POSTS']:
                    continue
                # 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####")
                ]
                extra_targets = post.compiler.get_extra_targets(
                    post, lang, dest)
                task = {
                    'basename':
                    self.name,
                    'name':
                    dest,
                    'file_dep':
                    file_dep,
                    'targets': [dest] + extra_targets,
                    'actions': [
                        (post.compile, (lang, )),
                        (update_deps, (
                            post,
                            lang,
                        )),
                    ],
                    'clean':
                    True,
                    'uptodate': [
                        utils.config_changed(
                            deps_dict, 'nikola.plugins.task.posts'), lambda p=
                        post, l=lang: self.dependence_on_timeline(p, l)
                    ] + post.fragment_deps_uptodate(lang),
                    'task_dep': ['render_posts:timeline_changes']
                }

                # Apply filters specified in the metadata
                ff = [x.strip() for x in post.meta('filters', lang).split(',')]
                flist = []
                for i, f in enumerate(ff):
                    if not f:
                        continue
                    _f = self.site.filters.get(f)
                    if _f is not None:  # A registered filter
                        flist.append(_f)
                    else:
                        flist.append(f)
                yield utils.apply_filters(task,
                                          {os.path.splitext(dest)[-1]: flist})
Exemplo n.º 43
0
    def gen_tasks(self):
        """Create tasks to copy the assets of the whole theme chain.

        If a file is present on two themes, use the version
        from the "youngest" theme.
        """
        kw = {
            "themes":
            self.site.THEMES,
            "translations":
            self.site.translations,
            "files_folders":
            self.site.config['FILES_FOLDERS'],
            "output_folder":
            self.site.config['OUTPUT_FOLDER'],
            "filters":
            self.site.config['FILTERS'],
            "code_color_scheme":
            self.site.config['CODE_COLOR_SCHEME'],
            "code.css_selectors":
            ['pre.code', '.code .codetable', '.highlight pre'],
            "code.css_wrappers": ['.highlight', '.code'],
            "code.css_head":
            '/* code.css file generated by Nikola */\n',
            "code.css_close":
            ("\ntable.codetable, table.highlighttable { width: 100%;}\n"
             ".codetable td.linenos, td.linenos { text-align: right; width: 3.5em; "
             "padding-right: 0.5em; background: rgba(127, 127, 127, 0.2) }\n"
             ".codetable td.code, td.code { padding-left: 0.5em; }\n"),
        }
        tasks = {}
        code_css_path = os.path.join(kw['output_folder'], 'css', 'code.css')
        code_css_input = utils.get_asset_path(
            'assets/css/code.css',
            themes=kw['themes'],
            files_folders=kw['files_folders'],
            output_dir=None)
        yield self.group_task()

        main_theme = utils.get_theme_path(kw['themes'][0])
        theme_ini = utils.parse_theme_meta(main_theme)
        if theme_ini:
            ignored_assets = theme_ini.get("Nikola",
                                           "ignored_assets",
                                           fallback='').split(',')
            ignored_assets = [
                os.path.normpath(asset_name.strip())
                for asset_name in ignored_assets
            ]
        else:
            ignored_assets = []

        for theme_name in kw['themes']:
            src = os.path.join(utils.get_theme_path(theme_name), 'assets')
            dst = kw['output_folder']
            for task in utils.copy_tree(src, dst):
                asset_name = os.path.relpath(task['name'], dst)
                if task['name'] in tasks or asset_name in ignored_assets:
                    continue
                tasks[task['name']] = task
                task['uptodate'] = [
                    utils.config_changed(kw, 'nikola.plugins.task.copy_assets')
                ]
                task['basename'] = self.name
                if code_css_input:
                    if 'file_dep' not in task:
                        task['file_dep'] = []
                    task['file_dep'].append(code_css_input)
                yield utils.apply_filters(task, kw['filters'])

        # Check whether or not there is a code.css file around.
        if not code_css_input and kw['code_color_scheme']:

            def create_code_css():
                formatter = BetterHtmlFormatter(style=kw["code_color_scheme"])
                utils.makedirs(os.path.dirname(code_css_path))
                with io.open(code_css_path, 'w+', encoding='utf-8') as outf:
                    outf.write(kw["code.css_head"])
                    outf.write(
                        formatter.get_style_defs(kw["code.css_selectors"],
                                                 kw["code.css_wrappers"]))
                    outf.write(kw["code.css_close"])

            if os.path.exists(code_css_path):
                with io.open(code_css_path, 'r', encoding='utf-8-sig') as fh:
                    testcontents = fh.read(len(
                        kw["code.css_head"])) == kw["code.css_head"]
            else:
                testcontents = False

            task = {
                'basename':
                self.name,
                'name':
                code_css_path,
                'targets': [code_css_path],
                'uptodate': [
                    utils.config_changed(kw,
                                         'nikola.plugins.task.copy_assets'),
                    testcontents
                ],
                'actions': [(create_code_css, [])],
                'clean':
                True,
            }
            yield utils.apply_filters(task, kw['filters'])
Exemplo n.º 44
0
    def gen_tasks(self):
        """Generate RSS feeds."""
        kw = {
            "translations": self.site.config["TRANSLATIONS"],
            "filters": self.site.config["FILTERS"],
            "blog_title": self.site.config["BLOG_TITLE"],
            "site_url": self.site.config["SITE_URL"],
            "base_url": self.site.config["BASE_URL"],
            "blog_description": self.site.config["BLOG_DESCRIPTION"],
            "output_folder": self.site.config["OUTPUT_FOLDER"],
            "feed_teasers": self.site.config["FEED_TEASERS"],
            "feed_plain": self.site.config["FEED_PLAIN"],
            "show_untranslated_posts":
            self.site.config['SHOW_UNTRANSLATED_POSTS'],
            "feed_length": self.site.config['FEED_LENGTH'],
            "feed_previewimage": self.site.config["FEED_PREVIEWIMAGE"],
            "tzinfo": self.site.tzinfo,
            "feed_read_more_link": self.site.config["FEED_READ_MORE_LINK"],
            "feed_links_append_query":
            self.site.config["FEED_LINKS_APPEND_QUERY"],
        }
        self.site.scan_posts()
        # Check for any changes in the state of use_in_feeds for any post.
        # Issue #934
        kw['use_in_feeds_status'] = ''.join(
            ['T' if x.use_in_feeds else 'F' for x in self.site.timeline])
        yield self.group_task()
        for lang in kw["translations"]:
            output_name = os.path.join(kw['output_folder'],
                                       self.site.path("rss", None, lang))
            deps = []
            deps_uptodate = []
            if kw["show_untranslated_posts"]:
                posts = self.site.posts[:kw['feed_length']]
            else:
                posts = [
                    x for x in self.site.posts
                    if x.is_translation_available(lang)
                ][:kw['feed_length']]
            for post in posts:
                deps += post.deps(lang)
                deps_uptodate += post.deps_uptodate(lang)

            feed_url = urljoin(self.site.config['BASE_URL'],
                               self.site.link("rss", None, lang).lstrip('/'))

            task = {
                'basename':
                'generate_rss',
                'name':
                os.path.normpath(output_name),
                'file_dep':
                deps,
                'targets': [output_name],
                'actions':
                [(utils.generic_rss_renderer,
                  (lang, kw["blog_title"](lang), kw["site_url"],
                   kw["blog_description"](lang), posts, output_name,
                   kw["feed_teasers"], kw["feed_plain"], kw['feed_length'],
                   feed_url, _enclosure, kw["feed_links_append_query"]))],
                'task_dep': ['render_posts'],
                'clean':
                True,
                'uptodate':
                [utils.config_changed(kw, 'nikola.plugins.task.rss')] +
                deps_uptodate,
            }
            yield utils.apply_filters(task, kw['filters'])
Exemplo n.º 45
0
    def gen_tasks(self):
        """Render the tag pages and feeds."""

        kw = {
            "translations": self.site.config["TRANSLATIONS"],
            "blog_title": self.site.config["BLOG_TITLE"],
            "site_url": self.site.config["SITE_URL"],
            "messages": self.site.MESSAGES,
            "output_folder": self.site.config['OUTPUT_FOLDER'],
            "filters": self.site.config['FILTERS'],
            "tag_pages_are_indexes": self.site.config['TAG_PAGES_ARE_INDEXES'],
            "index_display_post_count": self.site.config['INDEX_DISPLAY_POST_COUNT'],
            "index_teasers": self.site.config['INDEX_TEASERS'],
            "generate_rss": self.site.config['GENERATE_RSS'],
            "rss_teasers": self.site.config["RSS_TEASERS"],
            "rss_plain": self.site.config["RSS_PLAIN"],
            "show_untranslated_posts": self.site.config['SHOW_UNTRANSLATED_POSTS'],
            "feed_length": self.site.config['FEED_LENGTH'],
            "taglist_minimum_post_count": self.site.config['TAGLIST_MINIMUM_POSTS'],
            "tzinfo": self.site.tzinfo,
        }

        self.site.scan_posts()
        yield self.group_task()

        yield self.list_tags_page(kw)

        if not self.site.posts_per_tag and not self.site.posts_per_category:
            return

        tag_list = list(self.site.posts_per_tag.items())
        cat_list = list(self.site.posts_per_category.items())

        def render_lists(tag, posts, is_category=True):
            post_list = sorted(posts, key=lambda a: a.date)
            post_list.reverse()
            for lang in kw["translations"]:
                if kw["show_untranslated_posts"]:
                    filtered_posts = post_list
                else:
                    filtered_posts = [x for x in post_list if x.is_translation_available(lang)]
                if kw["generate_rss"]:
                    yield self.tag_rss(tag, lang, filtered_posts, kw, is_category)
                # Render HTML
                if kw['tag_pages_are_indexes']:
                    yield self.tag_page_as_index(tag, lang, filtered_posts, kw, is_category)
                else:
                    yield self.tag_page_as_list(tag, lang, filtered_posts, kw, is_category)

        for tag, posts in tag_list:
            for task in render_lists(tag, posts, False):
                yield task

        for tag, posts in cat_list:
            if tag == '':  # This is uncategorized posts
                continue
            for task in render_lists(tag, posts, True):
                yield task

        # Tag cloud json file
        tag_cloud_data = {}
        for tag, posts in self.site.posts_per_tag.items():
            tag_posts = dict(posts=[{'title': post.meta[post.default_lang]['title'],
                                     'date': post.date.strftime('%m/%d/%Y'),
                                     'isodate': post.date.isoformat(),
                                     'url': post.permalink(post.default_lang)}
                                    for post in reversed(sorted(self.site.timeline, key=lambda post: post.date))
                                    if tag in post.alltags])
            tag_cloud_data[tag] = [len(posts), self.site.link(
                'tag', tag, self.site.config['DEFAULT_LANG']), tag_posts]
        output_name = os.path.join(kw['output_folder'],
                                   'assets', 'js', 'tag_cloud_data.json')

        def write_tag_data(data):
            utils.makedirs(os.path.dirname(output_name))
            with open(output_name, 'w+') as fd:
                json.dump(data, fd)

        task = {
            'basename': str(self.name),
            'name': str(output_name)
        }

        task['uptodate'] = [utils.config_changed(tag_cloud_data)]
        task['targets'] = [output_name]
        task['actions'] = [(write_tag_data, [tag_cloud_data])]
        task['clean'] = True
        yield utils.apply_filters(task, kw['filters'])
Exemplo n.º 46
0
    def gen_tasks(self):
        """Bundle assets using WebAssets."""

        kw = {
            'filters': self.site.config['FILTERS'],
            'output_folder': self.site.config['OUTPUT_FOLDER'],
            'cache_folder': self.site.config['CACHE_FOLDER'],
            'theme_bundles': get_theme_bundles(self.site.THEMES),
            'themes': self.site.THEMES,
            'files_folders': self.site.config['FILES_FOLDERS'],
            'code_color_scheme': self.site.config['CODE_COLOR_SCHEME'],
        }

        def build_bundle(output, inputs):
            out_dir = os.path.join(kw['output_folder'],
                                   os.path.dirname(output))
            inputs = [
                i for i in inputs if os.path.isfile(os.path.join(out_dir, i))
            ]
            cache_dir = os.path.join(kw['cache_folder'], 'webassets')
            if not os.path.isdir(cache_dir):
                os.makedirs(cache_dir)
            env = webassets.Environment(out_dir,
                                        os.path.dirname(output),
                                        cache=cache_dir)
            bundle = webassets.Bundle(*inputs, output=os.path.basename(output))
            env.register(output, bundle)
            # This generates the file
            env[output].urls()

        flag = False
        if (webassets is not None
                and self.site.config['USE_BUNDLES'] is not False):
            for name, files in kw['theme_bundles'].items():
                output_path = os.path.join(kw['output_folder'], name)
                dname = os.path.dirname(name)
                file_dep = [
                    os.path.join(kw['output_folder'], dname, fname)
                    for fname in files
                ]
                file_dep = filter(os.path.isfile,
                                  file_dep)  # removes missing files
                task = {
                    'file_dep': file_dep,
                    'task_dep': ['copy_assets'],
                    'basename': str(self.name),
                    'name': str(output_path),
                    'actions': [(build_bundle, (name, files))],
                    'targets': [output_path],
                    'uptodate': [utils.config_changed(kw)],
                    'clean': True,
                }
                flag = True
                yield utils.apply_filters(task, kw['filters'])
        if flag is False:  # No page rendered, yield a dummy task
            yield {
                'basename': self.name,
                'uptodate': [True],
                'name': 'None',
                'actions': [],
            }
Exemplo n.º 47
0
    def gen_tasks(self):
        """Create tasks to copy the assets of the whole theme chain.

        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'],
            "output_folder": self.site.config['OUTPUT_FOLDER'],
            "filters": self.site.config['FILTERS'],
            "code_color_scheme": self.site.config['CODE_COLOR_SCHEME'],
            "code.css_selectors": 'pre.code',
            "code.css_head": '/* code.css file generated by Nikola */\n',
            "code.css_close": "\ntable.codetable { width: 100%;} td.linenos {text-align: right; width: 4em;}\n",
        }
        tasks = {}
        code_css_path = os.path.join(kw['output_folder'], 'assets', 'css', 'code.css')
        code_css_input = utils.get_asset_path('assets/css/code.css',
                                              themes=kw['themes'],
                                              files_folders=kw['files_folders'], output_dir=None)
        yield self.group_task()

        for theme_name in kw['themes']:
            src = os.path.join(utils.get_theme_path(theme_name), 'assets')
            dst = os.path.join(kw['output_folder'], 'assets')
            for task in utils.copy_tree(src, dst):
                if task['name'] in tasks:
                    continue
                tasks[task['name']] = task
                task['uptodate'] = [utils.config_changed(kw, 'nikola.plugins.task.copy_assets')]
                task['basename'] = self.name
                if code_css_input:
                    if 'file_dep' not in task:
                        task['file_dep'] = []
                    task['file_dep'].append(code_css_input)
                yield utils.apply_filters(task, kw['filters'])

        # Check whether or not there is a code.css file around.
        if not code_css_input and kw['code_color_scheme']:
            def create_code_css():
                from pygments.formatters import get_formatter_by_name
                formatter = get_formatter_by_name('html', style=kw["code_color_scheme"])
                utils.makedirs(os.path.dirname(code_css_path))
                with io.open(code_css_path, 'w+', encoding='utf8') as outf:
                    outf.write(kw["code.css_head"])
                    outf.write(formatter.get_style_defs(kw["code.css_selectors"]))
                    outf.write(kw["code.css_close"])

            if os.path.exists(code_css_path):
                with io.open(code_css_path, 'r', encoding='utf-8') as fh:
                    testcontents = fh.read(len(kw["code.css_head"])) == kw["code.css_head"]
            else:
                testcontents = False

            task = {
                'basename': self.name,
                'name': code_css_path,
                'targets': [code_css_path],
                'uptodate': [utils.config_changed(kw, 'nikola.plugins.task.copy_assets'), testcontents],
                'actions': [(create_code_css, [])],
                'clean': True,
            }
            yield utils.apply_filters(task, kw['filters'])
Exemplo n.º 48
0
    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:
                with open(in_name, 'r') as fd:
                    try:
                        lexer = get_lexer_for_filename(in_name)
                    except:
                        lexer = TextLexer()
                    code = highlight(
                        fd.read(), lexer,
                        HtmlFormatter(cssclass='code',
                                      linenos="table",
                                      nowrap=False,
                                      lineanchors=utils.slugify(in_name,
                                                                force=True),
                                      anchorlinenos=True))
                # the pygments highlighter uses <div class="codehilite"><pre>
                # for code.  We switch it to reST's <pre class="code">.
                code = CODERE.sub('<pre class="code literal-block">\\1</pre>',
                                  code)
                title = os.path.basename(in_name)
            else:
                code = ''
                title = os.path.split(os.path.dirname(out_name))[1]
            crumbs = utils.get_crumbs(os.path.relpath(
                out_name, self.kw['output_folder']),
                                      is_file=True)
            permalink = self.site.link(
                'listing',
                os.path.join(
                    input_folder,
                    os.path.relpath(
                        out_name[:-5],  # remove '.html'
                        os.path.join(self.kw['output_folder'],
                                     output_folder))))
            if self.site.config['COPY_SOURCES']:
                source_link = permalink[:-5]  # remove '.html'
            else:
                source_link = None
            context = {
                'code': code,
                'title': title,
                'crumbs': crumbs,
                'permalink': permalink,
                'lang': self.kw['default_lang'],
                'folders': natsort.natsorted(folders),
                'files': natsort.natsorted(files),
                'description': title,
                'source_link': source_link,
            }
            self.site.render_template('listing.tmpl', out_name, context)

        yield self.group_task()

        template_deps = self.site.template_system.template_deps('listing.tmpl')

        for input_folder, output_folder in self.kw['listings_folders'].items():
            for root, dirs, files in os.walk(input_folder, followlinks=True):
                files = [
                    f for f in files
                    if os.path.splitext(f)[-1] not in ignored_extensions
                ]

                uptodate = {'c': self.site.GLOBAL_CONTEXT}

                for k, v in self.site.GLOBAL_CONTEXT['template_hooks'].items():
                    uptodate['||template_hooks|{0}||'.format(k)] = v._items

                for k in self.site._GLOBAL_CONTEXT_TRANSLATABLE:
                    uptodate[k] = self.site.GLOBAL_CONTEXT[k](
                        self.kw['default_lang'])

                # save navigation links as dependencies
                uptodate['navigation_links'] = uptodate['c'][
                    'navigation_links'](self.kw['default_lang'])

                uptodate['kw'] = self.kw

                uptodate2 = uptodate.copy()
                uptodate2['f'] = files
                uptodate2['d'] = dirs

                # Compute relative path; can't use os.path.relpath() here as it returns "." instead of ""
                rel_path = root[len(input_folder):]
                if rel_path[:1] == os.sep:
                    rel_path = rel_path[1:]

                rel_name = os.path.join(rel_path, self.kw['index_file'])
                rel_output_name = os.path.join(output_folder, rel_path,
                                               self.kw['index_file'])

                # Render all files
                out_name = os.path.join(self.kw['output_folder'],
                                        rel_output_name)
                yield utils.apply_filters(
                    {
                        'basename':
                        self.name,
                        'name':
                        out_name,
                        'file_dep':
                        template_deps,
                        'targets': [out_name],
                        'actions': [(render_listing, [
                            None, out_name, input_folder, output_folder, dirs,
                            files
                        ])],
                        # This is necessary to reflect changes in blog title,
                        # sidebar links, etc.
                        'uptodate': [utils.config_changed(uptodate2)],
                        'clean':
                        True,
                    },
                    self.kw["filters"])
                for f in files:
                    ext = os.path.splitext(f)[-1]
                    if ext in ignored_extensions:
                        continue
                    in_name = os.path.join(root, f)
                    # Record file names
                    rel_name = os.path.join(rel_path, f + '.html')
                    rel_output_name = os.path.join(output_folder, rel_path,
                                                   f + '.html')
                    self.register_output_name(input_folder, rel_name,
                                              rel_output_name)
                    # Set up output name
                    out_name = os.path.join(self.kw['output_folder'],
                                            rel_output_name)
                    # Yield task
                    yield utils.apply_filters(
                        {
                            'basename':
                            self.name,
                            'name':
                            out_name,
                            'file_dep':
                            template_deps + [in_name],
                            'targets': [out_name],
                            'actions': [(render_listing, [
                                in_name, out_name, input_folder, output_folder
                            ])],
                            # This is necessary to reflect changes in blog title,
                            # sidebar links, etc.
                            'uptodate': [utils.config_changed(uptodate)],
                            'clean':
                            True,
                        },
                        self.kw["filters"])
                    if self.site.config['COPY_SOURCES']:
                        rel_name = os.path.join(rel_path, f)
                        rel_output_name = os.path.join(output_folder, rel_path,
                                                       f)
                        self.register_output_name(input_folder, rel_name,
                                                  rel_output_name)
                        out_name = os.path.join(self.kw['output_folder'],
                                                rel_output_name)
                        yield utils.apply_filters(
                            {
                                'basename': self.name,
                                'name': out_name,
                                'file_dep': [in_name],
                                'targets': [out_name],
                                'actions':
                                [(utils.copy_file, [in_name, out_name])],
                                'clean': True,
                            }, self.kw["filters"])
Exemplo n.º 49
0
    def gen_tasks(self):
        """Bundle assets."""
        kw = {
            'filters': self.site.config['FILTERS'],
            'output_folder': self.site.config['OUTPUT_FOLDER'],
            'cache_folder': self.site.config['CACHE_FOLDER'],
            'theme_bundles': get_theme_bundles(self.site.THEMES),
            'themes': self.site.THEMES,
            'files_folders': self.site.config['FILES_FOLDERS'],
            'code_color_scheme': self.site.config['CODE_COLOR_SCHEME'],
        }

        def build_bundle(output, inputs):
            out_dir = os.path.join(kw['output_folder'],
                                   os.path.dirname(output))
            inputs = [
                os.path.join(out_dir, os.path.relpath(i, out_dir))
                for i in inputs if os.path.isfile(i)
            ]
            with open(os.path.join(out_dir, os.path.basename(output)),
                      'wb+') as out_fh:
                for i in inputs:
                    with open(i, 'rb') as in_fh:
                        shutil.copyfileobj(in_fh, out_fh)
                    out_fh.write(b'\n')

        yield self.group_task()

        if self.site.config['USE_BUNDLES']:
            for name, _files in kw['theme_bundles'].items():
                output_path = os.path.join(kw['output_folder'], name)
                dname = os.path.dirname(name)
                files = []
                for fname in _files:
                    # paths are relative to dirname
                    files.append(os.path.join(dname, fname))
                file_dep = [
                    os.path.join(kw['output_folder'], fname) for fname in files
                    if utils.get_asset_path(fname,
                                            self.site.THEMES,
                                            self.site.config['FILES_FOLDERS'],
                                            output_dir=kw['output_folder'])
                    or fname == os.path.join('assets', 'css', 'code.css')
                ]
                # code.css will be generated by us if it does not exist in
                # FILES_FOLDERS or theme assets.  It is guaranteed that the
                # generation will happen before this task.
                task = {
                    'file_dep':
                    list(file_dep),
                    'task_dep': ['copy_assets', 'copy_files'],
                    'basename':
                    str(self.name),
                    'name':
                    str(output_path),
                    'actions': [(build_bundle, (name, file_dep))],
                    'targets': [output_path],
                    'uptodate': [
                        utils.config_changed({
                            1: kw,
                            2: file_dep
                        }, 'nikola.plugins.task.bundles')
                    ],
                    'clean':
                    True,
                }
                yield utils.apply_filters(task, kw['filters'])
Exemplo n.º 50
0
    def gen_tasks(self):
        kw = {
            'root':
            Path(self.site.GLOBAL_CONTEXT['data']['class_config']
                 ['root']).expanduser(),
            'homework':
            self.site.GLOBAL_CONTEXT['data']['class_config'].get(
                'homework', []),
            'quizzes':
            self.site.GLOBAL_CONTEXT['data']['class_config']['quizzes'],
            'course-material':
            self.site.GLOBAL_CONTEXT['data']['class_config']
            ['course-materials'],
            'output_folder':
            Path(self.site.config['OUTPUT_FOLDER']),
            'filters':
            self.site.config['FILTERS'],
        }
        yield self.group_task()

        handouts = [
            q['due-date'] for q in kw['quizzes'] if q.get('handout', False)
        ]
        dest = kw['output_folder'] / 'slides'
        filters = kw['filters']
        for handout in handouts:
            handout_file = kw['root'] / f'topic-slides/{handout}.zip'
            real_dest = dest / handout_file.name
            yield utils.apply_filters(
                {
                    'basename': self.name,
                    'name': str(real_dest),
                    'file_dep': [handout_file],
                    'targets': [real_dest],
                    'actions': [(utils.copy_file, (handout_file, real_dest))],
                    'uptodate': [utils.config_changed(kw, self.name)],
                    'clean': True,
                }, filters)

        syllabus_file = kw['root'] / 'syllabus/syllabus.pdf'
        real_dest = kw['output_folder'] / 'syllabus/syllabus.pdf'
        yield utils.apply_filters(
            {
                'basename': self.name,
                'name': str(real_dest),
                'file_dep': [syllabus_file],
                'targets': [real_dest],
                'actions': [(utils.copy_file, (syllabus_file, real_dest))],
                'uptodate': [utils.config_changed(kw, self.name)],
                'clean': True,
            }, filters)

        for homework in kw['homework']:
            hw_num = homework['number']
            src = kw['root'] / f'homework/homework-{hw_num}/output'
            dest_dir = kw['output_folder'] / f'homework/homework-{hw_num}'
            due_date = datetime.strptime(homework['due-date'],
                                         '%d-%b-%Y').replace(hour=12)
            late_date = due_date + timedelta(days=3)
            no_solution = homework.get('no-solution', False)
            force_solution = homework.get('force-solution', False)
            if (datetime.today() < late_date
                    or no_solution) and not force_solution:
                ignored = set([
                    f'homework-{hw_num}-soln.zip',
                    f'homework-{hw_num}-soln.pdf'
                ])
            else:
                ignored = []

            for hw_file in src.iterdir():
                if hw_file.name in ignored or hw_file.name == '.DS_Store':
                    continue
                real_dest = dest_dir / hw_file.name
                yield utils.apply_filters(
                    {
                        'basename': self.name,
                        'name': str(real_dest),
                        'file_dep': [hw_file],
                        'targets': [real_dest],
                        'actions': [(utils.copy_file, (hw_file, real_dest))],
                        'uptodate': [utils.config_changed(kw, self.name)],
                        'clean': True,
                    }, filters)

        for quiz in kw["quizzes"]:
            src = kw["root"] / "quizzes" / "online"
            due_date = datetime.strptime(quiz['due-date'],
                                         '%d-%b-%Y').replace(hour=12)
            file_stem = src.joinpath(due_date.strftime("%b. %-d, %Y"))
            file_name = file_stem.with_suffix(file_stem.suffix +
                                              " Lectures.md")
            if quiz.get("no_solution", False) or not file_name.exists():
                continue
            output_file = file_stem.with_suffix(file_stem.suffix +
                                                " Lectures.pdf")
            if not output_file.exists():
                yield {
                    "basename":
                    self.name,
                    "name":
                    file_name.name,
                    "file_dep": [file_name],
                    "targets": [output_file],
                    "actions": [(ppd.convert_file, (str(file_name), "latex"), {
                        "format": "markdown",
                        "outputfile": str(output_file),
                        "extra_args": ["-V", "geometry:margin=1in"]
                    })],
                    "uptodate": [utils.config_changed(kw, self.name)],
                    "clean":
                    True,
                }
            real_dest = kw[
                "output_folder"] / "quiz-solutions" / output_file.name
            if datetime.today() > due_date:
                yield utils.apply_filters(
                    {
                        "basename": self.name,
                        "name": real_dest.name,
                        "file_dep": [output_file],
                        "targets": [real_dest],
                        "actions": [(utils.copy_file,
                                     (output_file, real_dest))],
                        "uptodate": [utils.config_changed(kw, self.name)],
                        "clean": True,
                    }, filters)

        for item in kw['course-material']:
            src = kw['root'] / item['source']
            dest = kw['output_folder'] / 'course-materials' / item.get(
                'dest', item['source'])
            yield utils.apply_filters(
                {
                    'basename': self.name,
                    'name': str(dest),
                    'file_dep': [src],
                    'targets': [dest],
                    'actions': [(utils.copy_file, (src, dest))],
                    'uptodate': [utils.config_changed(kw, self.name)],
                    'clean': True,
                }, filters)
Exemplo n.º 51
0
    def gen_tasks(self):
        """Render the tag pages and feeds."""

        kw = {
            "translations":
            self.site.config["TRANSLATIONS"],
            "blog_title":
            self.site.config["BLOG_TITLE"],
            "site_url":
            self.site.config["SITE_URL"],
            "base_url":
            self.site.config["BASE_URL"],
            "messages":
            self.site.MESSAGES,
            "output_folder":
            self.site.config['OUTPUT_FOLDER'],
            "filters":
            self.site.config['FILTERS'],
            'tag_path':
            self.site.config['TAG_PATH'],
            "tag_pages_are_indexes":
            self.site.config['TAG_PAGES_ARE_INDEXES'],
            "tag_pages_descriptions":
            self.site.config['TAG_PAGES_DESCRIPTIONS'],
            'category_path':
            self.site.config['CATEGORY_PATH'],
            'category_prefix':
            self.site.config['CATEGORY_PREFIX'],
            "category_pages_are_indexes":
            self.site.config['CATEGORY_PAGES_ARE_INDEXES'],
            "category_pages_descriptions":
            self.site.config['CATEGORY_PAGES_DESCRIPTIONS'],
            "generate_rss":
            self.site.config['GENERATE_RSS'],
            "rss_teasers":
            self.site.config["RSS_TEASERS"],
            "rss_plain":
            self.site.config["RSS_PLAIN"],
            "show_untranslated_posts":
            self.site.config['SHOW_UNTRANSLATED_POSTS'],
            "feed_length":
            self.site.config['FEED_LENGTH'],
            "taglist_minimum_post_count":
            self.site.config['TAGLIST_MINIMUM_POSTS'],
            "tzinfo":
            self.site.tzinfo,
            "pretty_urls":
            self.site.config['PRETTY_URLS'],
            "strip_indexes":
            self.site.config['STRIP_INDEXES'],
            "index_file":
            self.site.config['INDEX_FILE'],
        }

        self.site.scan_posts()
        yield self.group_task()

        yield self.list_tags_page(kw)

        if not self.site.posts_per_tag and not self.site.posts_per_category:
            return

        if kw['category_path'] == kw['tag_path']:
            tags = {
                self.slugify_name(tag): tag
                for tag in self.site.posts_per_tag.keys()
            }
            categories = {
                kw['category_prefix'] + self.slugify_name(category): category
                for category in self.site.posts_per_category.keys()
            }
            intersect = set(tags.keys()) & set(categories.keys())
            if len(intersect) > 0:
                for slug in intersect:
                    utils.LOGGER.error(
                        "Category '{0}' and tag '{1}' both have the same slug '{2}'!"
                        .format(categories[slug], tags[slug], slug))
                sys.exit(1)

        tag_list = list(self.site.posts_per_tag.items())
        cat_list = list(self.site.posts_per_category.items())

        def render_lists(tag, posts, is_category=True):
            post_list = sorted(posts, key=lambda a: a.date)
            post_list.reverse()
            for lang in kw["translations"]:
                if kw["show_untranslated_posts"]:
                    filtered_posts = post_list
                else:
                    filtered_posts = [
                        x for x in post_list
                        if x.is_translation_available(lang)
                    ]
                if kw["generate_rss"]:
                    yield self.tag_rss(tag, lang, filtered_posts, kw,
                                       is_category)
                # Render HTML
                if kw['category_pages_are_indexes'] if is_category else kw[
                        'tag_pages_are_indexes']:
                    yield self.tag_page_as_index(tag, lang, filtered_posts, kw,
                                                 is_category)
                else:
                    yield self.tag_page_as_list(tag, lang, filtered_posts, kw,
                                                is_category)

        for tag, posts in tag_list:
            for task in render_lists(tag, posts, False):
                yield task

        for tag, posts in cat_list:
            if tag == '':  # This is uncategorized posts
                continue
            for task in render_lists(tag, posts, True):
                yield task

        # Tag cloud json file
        tag_cloud_data = {}
        for tag, posts in self.site.posts_per_tag.items():
            tag_posts = dict(
                posts=[{
                    'title': post.meta[post.default_lang]['title'],
                    'date': post.date.strftime('%m/%d/%Y'),
                    'isodate': post.date.isoformat(),
                    'url': post.permalink(post.default_lang)
                } for post in reversed(
                    sorted(self.site.timeline, key=lambda post: post.date))
                       if tag in post.alltags])
            tag_cloud_data[tag] = [
                len(posts),
                self.site.link('tag', tag, self.site.config['DEFAULT_LANG']),
                tag_posts
            ]
        output_name = os.path.join(kw['output_folder'], 'assets', 'js',
                                   'tag_cloud_data.json')

        def write_tag_data(data):
            utils.makedirs(os.path.dirname(output_name))
            with open(output_name, 'w+') as fd:
                json.dump(data, fd)

        if self.site.config['WRITE_TAG_CLOUD']:
            task = {'basename': str(self.name), 'name': str(output_name)}

            task['uptodate'] = [
                utils.config_changed(tag_cloud_data,
                                     'nikola.plugins.task.tags:tagdata')
            ]
            task['targets'] = [output_name]
            task['actions'] = [(write_tag_data, [tag_cloud_data])]
            task['clean'] = True
            yield utils.apply_filters(task, kw['filters'])
Exemplo n.º 52
0
    def gen_tasks(self):
        """Render the tag pages and feeds."""
        kw = {
            "translations":
            self.site.config["TRANSLATIONS"],
            "blog_title":
            self.site.config["BLOG_TITLE"],
            "site_url":
            self.site.config["SITE_URL"],
            "base_url":
            self.site.config["BASE_URL"],
            "messages":
            self.site.MESSAGES,
            "output_folder":
            self.site.config['OUTPUT_FOLDER'],
            "filters":
            self.site.config['FILTERS'],
            'tag_path':
            self.site.config['TAG_PATH'],
            "tag_pages_are_indexes":
            self.site.config['TAG_PAGES_ARE_INDEXES'],
            'category_path':
            self.site.config['CATEGORY_PATH'],
            'category_prefix':
            self.site.config['CATEGORY_PREFIX'],
            "category_pages_are_indexes":
            self.site.config['CATEGORY_PAGES_ARE_INDEXES'],
            "generate_rss":
            self.site.config['GENERATE_RSS'],
            "feed_teasers":
            self.site.config["FEED_TEASERS"],
            "feed_plain":
            self.site.config["FEED_PLAIN"],
            "feed_link_append_query":
            self.site.config["FEED_LINKS_APPEND_QUERY"],
            "show_untranslated_posts":
            self.site.config['SHOW_UNTRANSLATED_POSTS'],
            "feed_length":
            self.site.config['FEED_LENGTH'],
            "taglist_minimum_post_count":
            self.site.config['TAGLIST_MINIMUM_POSTS'],
            "tzinfo":
            self.site.tzinfo,
            "pretty_urls":
            self.site.config['PRETTY_URLS'],
            "strip_indexes":
            self.site.config['STRIP_INDEXES'],
            "index_file":
            self.site.config['INDEX_FILE'],
            "category_pages_descriptions":
            self.site.config['CATEGORY_PAGES_DESCRIPTIONS'],
            "category_pages_titles":
            self.site.config['CATEGORY_PAGES_TITLES'],
            "tag_pages_descriptions":
            self.site.config['TAG_PAGES_DESCRIPTIONS'],
            "tag_pages_titles":
            self.site.config['TAG_PAGES_TITLES'],
        }

        self.site.scan_posts()
        yield self.group_task()

        yield self.list_tags_page(kw)

        if not self.site.posts_per_tag and not self.site.posts_per_category:
            return

        for lang in kw["translations"]:
            if kw['category_path'][lang] == kw['tag_path'][lang]:
                tags = {
                    self.slugify_tag_name(tag, lang): tag
                    for tag in self.site.tags_per_language[lang]
                }
                cats = {
                    tuple(self.slugify_category_name(category, lang)): category
                    for category in self.site.posts_per_category.keys()
                }
                categories = {k[0]: v for k, v in cats.items() if len(k) == 1}
                intersect = set(tags.keys()) & set(categories.keys())
                if len(intersect) > 0:
                    for slug in intersect:
                        utils.LOGGER.error(
                            "Category '{0}' and tag '{1}' both have the same slug '{2}' for language {3}!"
                            .format('/'.join(categories[slug]), tags[slug],
                                    slug, lang))
                    sys.exit(1)

            # Test for category slug clashes
            categories = {}
            for category in self.site.posts_per_category.keys():
                slug = tuple(self.slugify_category_name(category, lang))
                for part in slug:
                    if len(part) == 0:
                        utils.LOGGER.error(
                            "Category '{0}' yields invalid slug '{1}'!".format(
                                category, '/'.join(slug)))
                        sys.exit(1)
                if slug in categories:
                    other_category = categories[slug]
                    utils.LOGGER.error(
                        'You have categories that are too similar: {0} and {1} (language {2})'
                        .format(category, other_category, lang))
                    utils.LOGGER.error('Category {0} is used in: {1}'.format(
                        category, ', '.join([
                            p.source_path
                            for p in self.site.posts_per_category[category]
                        ])))
                    utils.LOGGER.error('Category {0} is used in: {1}'.format(
                        other_category, ', '.join([
                            p.source_path for p in
                            self.site.posts_per_category[other_category]
                        ])))
                    sys.exit(1)
                categories[slug] = category

        tag_list = list(self.site.posts_per_tag.items())
        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"]:
                if kw["show_untranslated_posts"]:
                    filtered_posts = post_list
                else:
                    filtered_posts = [
                        x for x in post_list
                        if x.is_translation_available(lang)
                    ]
                if kw["generate_rss"]:
                    yield self.tag_rss(tag, lang, filtered_posts, kw,
                                       is_category)
                # Render HTML
                if kw['category_pages_are_indexes'] if is_category else kw[
                        'tag_pages_are_indexes']:
                    yield self.tag_page_as_index(tag, lang, filtered_posts, kw,
                                                 is_category)
                else:
                    yield self.tag_page_as_list(tag, lang, filtered_posts, kw,
                                                is_category)

        for tag, posts in tag_list:
            for task in render_lists(tag, posts, False):
                yield task

        for path, posts in cat_list:
            for task in render_lists(path, posts, True):
                yield task

        # Tag cloud json file
        tag_cloud_data = {}
        for tag, posts in self.site.posts_per_tag.items():
            if tag in self.site.config['HIDDEN_TAGS']:
                continue
            tag_posts = dict(
                posts=[{
                    'title': post.meta[post.default_lang]['title'],
                    'date': post.date.strftime('%m/%d/%Y'),
                    'isodate': post.date.isoformat(),
                    'url': post.permalink(post.default_lang)
                } for post in reversed(
                    sorted(self.site.timeline, key=lambda post: post.date))
                       if tag in post.alltags])
            tag_cloud_data[tag] = [
                len(posts),
                self.site.link('tag', tag, self.site.config['DEFAULT_LANG']),
                tag_posts
            ]
        output_name = os.path.join(kw['output_folder'], '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, sort_keys=True)

        if self.site.config['WRITE_TAG_CLOUD']:
            task = {'basename': str(self.name), 'name': str(output_name)}

            task['uptodate'] = [
                utils.config_changed(tag_cloud_data,
                                     'nikola.plugins.task.tags:tagdata')
            ]
            task['targets'] = [output_name]
            task['actions'] = [(write_tag_data, [tag_cloud_data])]
            task['clean'] = True
            yield utils.apply_filters(task, kw['filters'])
Exemplo n.º 53
0
    def gen_tasks(self):
        """Bundle assets using WebAssets."""
        kw = {
            'filters': self.site.config['FILTERS'],
            'output_folder': self.site.config['OUTPUT_FOLDER'],
            'cache_folder': self.site.config['CACHE_FOLDER'],
            'theme_bundles': get_theme_bundles(self.site.THEMES),
            'themes': self.site.THEMES,
            'files_folders': self.site.config['FILES_FOLDERS'],
            'code_color_scheme': self.site.config['CODE_COLOR_SCHEME'],
        }

        def build_bundle(output, inputs):
            out_dir = os.path.join(kw['output_folder'],
                                   os.path.dirname(output))
            inputs = [
                os.path.relpath(i, out_dir) for i in inputs
                if os.path.isfile(i)
            ]
            cache_dir = os.path.join(kw['cache_folder'], 'webassets')
            utils.makedirs(cache_dir)
            env = webassets.Environment(out_dir,
                                        os.path.dirname(output),
                                        cache=cache_dir)
            if inputs:
                bundle = webassets.Bundle(*inputs,
                                          output=os.path.basename(output))
                env.register(output, bundle)
                # This generates the file
                try:
                    env[output].build(force=True)
                except Exception as e:
                    self.logger.error("Failed to build bundles.")
                    self.logger.exception(e)
                    self.logger.notice(
                        "Try running ``nikola clean`` and building again.")
            else:
                with open(os.path.join(out_dir, os.path.basename(output)),
                          'wb+'):
                    pass  # Create empty file

        yield self.group_task()
        if (webassets is not None
                and self.site.config['USE_BUNDLES'] is not False):
            for name, _files in kw['theme_bundles'].items():
                output_path = os.path.join(kw['output_folder'], name)
                dname = os.path.dirname(name)
                files = []
                for fname in _files:
                    # paths are relative to dirname
                    files.append(os.path.join(dname, fname))
                file_dep = [
                    os.path.join(kw['output_folder'], fname) for fname in files
                    if utils.get_asset_path(fname,
                                            self.site.THEMES,
                                            self.site.config['FILES_FOLDERS'],
                                            output_dir=kw['output_folder'])
                    or fname == os.path.join('assets', 'css', 'code.css')
                ]
                # code.css will be generated by us if it does not exist in
                # FILES_FOLDERS or theme assets.  It is guaranteed that the
                # generation will happen before this task.
                task = {
                    'file_dep':
                    list(file_dep),
                    'task_dep': ['copy_assets', 'copy_files'],
                    'basename':
                    str(self.name),
                    'name':
                    str(output_path),
                    'actions': [(build_bundle, (name, file_dep))],
                    'targets': [output_path],
                    'uptodate': [
                        utils.config_changed({
                            1: kw,
                            2: file_dep
                        }, 'nikola.plugins.task.bundles')
                    ],
                    'clean':
                    True,
                }
                yield utils.apply_filters(task, kw['filters'])
Exemplo n.º 54
0
    def gen_tasks(self):
        """Generate JSON with recent post for each section."""
        kw = {
            "output_folder":
            self.site.config["OUTPUT_FOLDER"],
            "filters":
            self.site.config["FILTERS"],
            "index_file":
            self.site.config["INDEX_FILE"],
            "translations":
            self.site.config["TRANSLATIONS"],
            "show_untranslated_posts":
            self.site.config["SHOW_UNTRANSLATED_POSTS"],
            "site_url":
            self.site.config["SITE_URL"],
            "base_url":
            self.site.config["BASE_URL"],
            "json_posts_length":
            self.site.config["RECENT_POSTS_JSON_LENGTH"]
            if "RECENT_POSTS_JSON_LENGTH" in self.site.config else
            self.site.config["INDEX_DISPLAY_POST_COUNT"],
            "json_descriptions":
            self.site.config["RECENT_POSTS_JSON_DESCRIPTION"]
            if "RECENT_POSTS_JSON_DESCRIPTION" in self.site.config else False,
            "json_previewimage":
            self.site.config["RECENT_POSTS_JSON_PREVIEWIMAGE"]
            if "RECENT_POSTS_JSON_PREVIEWIMAGE" in self.site.config else False,
        }
        self.site.scan_posts()
        yield self.group_task()
        for lang in kw["translations"]:
            output_path = os.path.join(
                kw["output_folder"],
                self.site.path("recent_posts_json", None, lang))
            deps = []
            deps_uptodate = []
            if kw["show_untranslated_posts"]:
                posts = self.site.posts
            else:
                posts = [
                    x for x in self.site.posts
                    if x.is_translation_available(lang)
                ]
            for post in posts[:kw["json_posts_length"]]:
                deps += post.deps(lang)
                deps_uptodate += post.deps_uptodate(lang)
            task = {
                "basename":
                "recent_posts_json",
                "name":
                os.path.normpath(output_path),
                "file_dep":
                deps,
                "targets": [output_path],
                "actions":
                [(self.make_json,
                  (posts[:kw["json_posts_length"]], kw["json_descriptions"],
                   kw["json_previewimage"], output_path, lang))],
                "task_dep": ["render_posts"],
                "clean":
                True,
                "uptodate": [
                    utils.config_changed(
                        kw, "nikola.plugins.task.recent_pots_json")
                ] + deps_uptodate,
            }
            yield utils.apply_filters(task, kw["filters"])

            if self.site.config['POSTS_SECTIONS']:
                groups = defaultdict(list)
                for post in posts:
                    groups[post.section_slug(lang)].append(post)

                for section_slug, post_list in groups.items():
                    output_path = os.path.join(
                        kw["output_folder"],
                        self.site.path("recent_posts_json", section_slug,
                                       lang))
                    deps = []
                    deps_uptodate = []
                    for post in post_list:
                        deps += post.deps(lang)
                        deps_uptodate += post.deps_uptodate(lang)
                    task = {
                        "basename":
                        "recent_posts_json",
                        "name":
                        os.path.normpath(output_path),
                        "file_dep":
                        deps,
                        "targets": [output_path],
                        "actions":
                        [(self.make_json,
                          (post_list[:kw["json_posts_length"]],
                           kw["json_descriptions"], kw["json_previewimage"],
                           output_path, lang))],
                        "task_dep": ["render_posts"],
                        "clean":
                        True,
                        "uptodate": [
                            utils.config_changed(
                                kw, "nikola.plugins.task.recent_pots_json")
                        ] + deps_uptodate,
                    }
                    yield utils.apply_filters(task, kw["filters"])
Exemplo n.º 55
0
    def gen_tasks(self):
        """Generate a sitemap."""
        kw = {
            "base_url":
            self.site.config["BASE_URL"],
            "site_url":
            self.site.config["SITE_URL"],
            "output_folder":
            self.site.config["OUTPUT_FOLDER"],
            "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', '.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']
        base_url = kw['base_url']
        mapped_exts = kw['mapped_extensions']

        output_path = kw['output_folder']
        sitemapindex_path = os.path.join(output_path, "sitemapindex.xml")
        sitemap_path = os.path.join(output_path, "sitemap.xml")
        base_path = get_base_path(kw['base_url'])
        sitemapindex = {}
        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
                path = os.path.relpath(root, output)
                # ignore the current directory.
                if path == '.':
                    path = syspath = ''
                else:
                    syspath = path + os.sep
                    path = path.replace(os.sep, '/') + '/'
                lastmod = self.get_lastmod(root)
                loc = urljoin(base_url, base_path + path)
                if kw['index_file'] in files and kw[
                        'strip_indexes']:  # ignore folders when not stripping urls
                    post = self.site.post_per_file.get(syspath +
                                                       kw['index_file'])
                    if post and (post.is_draft or post.is_private
                                 or post.publish_later):
                        continue
                    alternates = []
                    if post:
                        for lang in post.translated_to:
                            alt_url = post.permalink(lang=lang, absolute=True)
                            if encodelink(loc) == alt_url:
                                continue
                            alternates.append(
                                alternates_format.format(lang, alt_url))
                    urlset[loc] = loc_format.format(encodelink(loc), lastmod,
                                                    ''.join(alternates))
                for fname in files:
                    if kw['strip_indexes'] and fname == kw['index_file']:
                        continue  # We already mapped the folder
                    if os.path.splitext(fname)[-1] in mapped_exts:
                        real_path = os.path.join(root, fname)
                        path = os.path.relpath(real_path, output)
                        if path.endswith(
                                kw['index_file']) and kw['strip_indexes']:
                            # ignore index files when stripping urls
                            continue
                        if not robot_fetch(path):
                            continue

                        # read in binary mode to make ancient files work
                        fh = open(real_path, 'rb')
                        filehead = fh.read(1024)
                        fh.close()

                        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'
                            ]
                            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[],
                        # sitemap_path is included after it is generated
                        if path.endswith('.xml') or path.endswith(
                                '.atom') or path.endswith('.rss'):
                            known_elm_roots = (b'<feed', b'<rss', b'<urlset')
                            if any([
                                    elm_root in filehead.lower()
                                    for elm_root in known_elm_roots
                            ]) and path != sitemap_path:
                                path = path.replace(os.sep, '/')
                                lastmod = self.get_lastmod(real_path)
                                loc = urljoin(base_url, base_path + path)
                                sitemapindex[loc] = sitemap_format.format(
                                    encodelink(loc), lastmod)
                                continue
                            else:
                                continue  # ignores all XML files except those presumed to be RSS
                        post = self.site.post_per_file.get(syspath)
                        if post and (post.is_draft or post.is_private
                                     or post.publish_later):
                            continue
                        path = path.replace(os.sep, '/')
                        lastmod = self.get_lastmod(real_path)
                        loc = urljoin(base_url, base_path + path)
                        alternates = []
                        if post:
                            for lang in post.translated_to:
                                alt_url = post.permalink(lang=lang,
                                                         absolute=True)
                                if encodelink(loc) == alt_url:
                                    continue
                                alternates.append(
                                    alternates_format.format(lang, alt_url))
                        urlset[loc] = loc_format.format(
                            encodelink(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)])
                if not robot.can_fetch("*", '/' + path):
                    return False  # not robot food
            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:
                outf.write(urlset_header)
                for k in sorted(urlset.keys()):
                    outf.write(urlset[k])
                outf.write(urlset_footer)
            sitemap_url = urljoin(base_url, base_path + "sitemap.xml")
            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)

        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
            # task, so rebuilds are triggered.  (Issue #1032)
            output = kw["output_folder"]
            file_dep = []

            for i in urlset.keys():
                p = os.path.join(output,
                                 urlparse(i).path.replace(base_path, '', 1))
                if not p.endswith('sitemap.xml') and not os.path.isdir(p):
                    file_dep.append(p)
                if os.path.isdir(p) and os.path.exists(
                        os.path.join(p, 'index.html')):
                    file_dep.append(p + 'index.html')

            for i in sitemapindex.keys():
                p = os.path.join(output,
                                 urlparse(i).path.replace(base_path, '', 1))
                if not p.endswith('sitemap.xml') and not os.path.isdir(p):
                    file_dep.append(p)
                if os.path.isdir(p) and os.path.exists(
                        os.path.join(p, 'index.html')):
                    file_dep.append(p + 'index.html')

            return {'file_dep': file_dep}

        yield {
            "basename": "_scan_locs",
            "name": "sitemap",
            "actions": [(scan_locs_task)]
        }

        yield self.group_task()
        yield apply_filters(
            {
                "basename":
                "sitemap",
                "name":
                sitemap_path,
                "targets": [sitemap_path],
                "actions": [(write_sitemap, )],
                "uptodate":
                [config_changed(kw, 'nikola.plugins.task.sitemap:write')],
                "clean":
                True,
                "task_dep": ["render_site"],
                "calc_dep": ["_scan_locs:sitemap"],
            }, kw['filters'])
        yield apply_filters(
            {
                "basename":
                "sitemap",
                "name":
                sitemapindex_path,
                "targets": [sitemapindex_path],
                "actions": [(write_sitemapindex, )],
                "uptodate": [
                    config_changed(kw,
                                   'nikola.plugins.task.sitemap:write_index')
                ],
                "clean":
                True,
                "file_dep": [sitemap_path]
            }, kw['filters'])
Exemplo n.º 56
0
    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=[]):
            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
                with io.open(in_name, "r", encoding="utf8") as in_file:
                    nb_json = ipynb_compiler._nbformat_read(in_file)
                    ipynb_raw = ipynb_compiler._compile_string(nb_json)
                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)
                    except:
                        try:
                            lexer = guess_lexer(fd.read())
                        except:
                            lexer = TextLexer()
                        fd.seek(0)
                    code = highlight(fd.read(), lexer,
                                     utils.NikolaPygmentsHTML(in_name))
                title = os.path.basename(in_name)
            else:
                code = ''
                title = os.path.split(os.path.dirname(out_name))[1]
            crumbs = utils.get_crumbs(os.path.relpath(
                out_name, self.kw['output_folder']),
                                      is_file=True)
            permalink = self.site.link(
                'listing',
                os.path.join(
                    input_folder,
                    os.path.relpath(
                        out_name[:-5],  # remove '.html'
                        os.path.join(self.kw['output_folder'],
                                     output_folder))))
            if in_name:
                source_link = permalink[:-5]  # remove '.html'
            else:
                source_link = None
            context = {
                'code':
                code,
                'title':
                title,
                'crumbs':
                crumbs,
                'permalink':
                permalink,
                'lang':
                self.kw['default_lang'],
                'folders':
                natsort.natsorted(folders, alg=natsort.ns.F | natsort.ns.IC),
                'files':
                natsort.natsorted(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()

        template_deps = self.site.template_system.template_deps('listing.tmpl')

        for input_folder, output_folder in self.kw['listings_folders'].items():
            for root, dirs, files in os.walk(input_folder, followlinks=True):
                files = [
                    f for f in files
                    if os.path.splitext(f)[-1] not in ignored_extensions
                ]

                uptodate = {'c': self.site.GLOBAL_CONTEXT}

                for k, v in self.site.GLOBAL_CONTEXT['template_hooks'].items():
                    uptodate['||template_hooks|{0}||'.format(k)] = v._items

                for k in self.site._GLOBAL_CONTEXT_TRANSLATABLE:
                    uptodate[k] = self.site.GLOBAL_CONTEXT[k](
                        self.kw['default_lang'])

                # save navigation links as dependencies
                uptodate['navigation_links'] = uptodate['c'][
                    'navigation_links'](self.kw['default_lang'])

                uptodate['kw'] = self.kw

                uptodate2 = uptodate.copy()
                uptodate2['f'] = files
                uptodate2['d'] = dirs

                # Compute relative path; can't use os.path.relpath() here as it returns "." instead of ""
                rel_path = root[len(input_folder):]
                if rel_path[:1] == os.sep:
                    rel_path = rel_path[1:]

                rel_name = os.path.join(rel_path, self.kw['index_file'])
                rel_output_name = os.path.join(output_folder, rel_path,
                                               self.kw['index_file'])

                # Render all files
                out_name = os.path.join(self.kw['output_folder'],
                                        rel_output_name)
                yield utils.apply_filters(
                    {
                        'basename':
                        self.name,
                        'name':
                        out_name,
                        'file_dep':
                        template_deps,
                        'targets': [out_name],
                        'actions': [(render_listing, [
                            None, out_name, input_folder, output_folder, dirs,
                            files
                        ])],
                        # This is necessary to reflect changes in blog title,
                        # sidebar links, etc.
                        'uptodate': [
                            utils.config_changed(
                                uptodate2,
                                'nikola.plugins.task.listings:folder')
                        ],
                        'clean':
                        True,
                    },
                    self.kw["filters"])
                for f in files:
                    ext = os.path.splitext(f)[-1]
                    if ext in ignored_extensions:
                        continue
                    in_name = os.path.join(root, f)
                    # Record file names
                    rel_name = os.path.join(rel_path, f + '.html')
                    rel_output_name = os.path.join(output_folder, rel_path,
                                                   f + '.html')
                    self.register_output_name(input_folder, rel_name,
                                              rel_output_name)
                    # Set up output name
                    out_name = os.path.join(self.kw['output_folder'],
                                            rel_output_name)
                    # Yield task
                    yield utils.apply_filters(
                        {
                            'basename':
                            self.name,
                            'name':
                            out_name,
                            'file_dep':
                            template_deps + [in_name],
                            'targets': [out_name],
                            'actions': [(render_listing, [
                                in_name, out_name, input_folder, output_folder
                            ])],
                            # This is necessary to reflect changes in blog title,
                            # sidebar links, etc.
                            'uptodate': [
                                utils.config_changed(
                                    uptodate,
                                    'nikola.plugins.task.listings:source')
                            ],
                            'clean':
                            True,
                        },
                        self.kw["filters"])

                    rel_name = os.path.join(rel_path, f)
                    rel_output_name = os.path.join(output_folder, rel_path, f)
                    self.register_output_name(input_folder, rel_name,
                                              rel_output_name)
                    out_name = os.path.join(self.kw['output_folder'],
                                            rel_output_name)
                    yield utils.apply_filters(
                        {
                            'basename': self.name,
                            'name': out_name,
                            'file_dep': [in_name],
                            'targets': [out_name],
                            'actions': [(utils.copy_file, [in_name, out_name])
                                        ],
                            'clean': True,
                        }, self.kw["filters"])
Exemplo n.º 57
0
    def gen_tasks(self):
        """Render project list."""

        self.image_ext_list = [
            '.jpg', '.png', '.jpeg', '.gif', '.svg', '.bmp', '.tiff'
        ]
        self.image_ext_list.extend(
            self.site.config.get('EXTRA_IMAGE_EXTENSIONS', []))

        self.kw = {
            'project_path': self.site.config['PROJECT_PATH'],
            'index_file': self.site.config['INDEX_FILE'],
            'strip_indexes': self.site.config['STRIP_INDEXES'],
            'output_folder': self.site.config['OUTPUT_FOLDER'],
            'cache_folder': self.site.config['CACHE_FOLDER'],
            'default_lang': self.site.config['DEFAULT_LANG'],
            'filters': self.site.config['FILTERS'],
            'translations': self.site.config['TRANSLATIONS'],
            'global_context': self.site.GLOBAL_CONTEXT,
            'tzinfo': self.site.tzinfo,
        }

        for k, v in self.site.GLOBAL_CONTEXT['template_hooks'].items():
            self.kw['||template_hooks|{0}||'.format(k)] = v._items

        yield self.group_task()

        template_name = "projects.tmpl"

        self.find_projects()

        # 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)

            short_tdst = os.path.join(self.kw['translations'][lang],
                                      self.kw['project_path'],
                                      self.kw['index_file'])
            short_jdst = os.path.join(self.kw['translations'][lang],
                                      self.kw['project_path'], 'projects.json')
            tdst = os.path.normpath(
                os.path.join(self.kw['output_folder'], short_tdst))
            jdst = os.path.normpath(
                os.path.join(self.kw['output_folder'], short_jdst))

            context = {}
            context["lang"] = lang

            # TODO: tranlsations?
            context["title"] = "Projects"
            context["description"] = None

            def sortf(p):
                return ((-int(p.meta('sort')) if p.meta('sort') != '' else -1),
                        p.title())

            context["featured"] = sorted(
                (p for p in self.projects
                 if p.meta('featured') not in ('False', '0', 'false', 'no',
                                               '')),
                key=sortf)
            context["projects"] = sorted(
                (p for p in self.projects
                 if p.meta('hidden') not in ('False', '0', 'false', 'no')),
                key=sortf)

            link = short_tdst.replace('\\', '/')
            index_len = len(self.kw['index_file'])
            if self.kw['strip_indexes'] and link[-(
                    1 + index_len):] == '/' + self.kw['index_file']:
                link = link[:-index_len]
            context["permalink"] = '/' + link

            all_meta = [(p.title(), p.meta('status')) for p in self.projects]
            all_meta += [p.meta('previewimage') for p in context["featured"]]
            all_meta += [p.source_path for p in context["featured"]]

            template_dep = self.site.template_system.template_deps(
                template_name)
            file_dep = []

            for p in self.projects:
                file_dep += [
                    p.translated_base_path(l) for l in self.kw['translations']
                    if l in p.translated_to
                ]

            yield utils.apply_filters(
                {
                    'basename':
                    self.name,
                    'name':
                    tdst,
                    'file_dep':
                    file_dep + template_dep,
                    'targets': [tdst],
                    'actions': [(self.site.render_template,
                                 (template_name, tdst, context))],
                    'clean':
                    True,
                    'uptodate':
                    [utils.config_changed({
                        1: self.kw,
                        2: all_meta,
                    })],
                }, self.kw['filters'])

            yield utils.apply_filters(
                {
                    'basename': self.name,
                    'name': jdst,
                    'file_dep': file_dep,
                    'targets': [jdst],
                    'actions': [(self.generate_json, (jdst, lang))],
                    'clean': True,
                    'uptodate': [utils.config_changed({
                        1: self.kw,
                    })],
                }, self.kw['filters'])
Exemplo n.º 58
0
    def gen_tasks(self):
        if 'PKGINDEX_CONFIG' not in self.site.config:
            return
        self.kw = {
            'output_folder': self.site.config['OUTPUT_FOLDER'],
            'filters': self.site.config['FILTERS'],
            'pkgindex_dirs': self.site.config['PKGINDEX_DIRS'],
            'pkgindex_handlers': self.site.config['PKGINDEX_HANDLERS'],
            'pkgindex_config': self.site.config['PKGINDEX_CONFIG'],
            'base_url': self.site.config['BASE_URL'],
        }
        yield self.group_task()
        self.site.scan_posts()

        zip_json = {}
        zip_deps = {}
        for dir in self.site.pkgindex_entries:
            utils.makedirs(
                os.path.join(self.kw['output_folder'],
                             self.kw['pkgindex_dirs'][dir][0]))
            zip_json[dir] = {}
            zip_deps[dir] = []

        for dir, posts in self.site.pkgindex_entries.items():
            for post in posts:
                directory = os.path.dirname(post.source_path)
                pkg_name = os.path.basename(directory)
                if pkg_name in self.kw['pkgindex_config'].get(
                        'zip_ignore', []):
                    continue
                destination = os.path.join(self.kw['output_folder'],
                                           self.kw['pkgindex_dirs'][dir][0],
                                           pkg_name + '.zip')
                output_dest = '/'.join(
                    (self.kw['pkgindex_dirs'][dir][0], pkg_name + '.zip'))
                for d in post.meta('allver'):
                    zip_json['v{0}'.format(d)][pkg_name] = urljoin(
                        self.kw['base_url'], output_dest)
                    zip_deps['v{0}'.format(d)].append(destination)
                # Prefix to slice out from names
                d = len(directory) - len(pkg_name)
                zip_files = []
                file_dep = []
                # Get list of dependencies and files to zip
                for root, dirs, files in os.walk(directory):
                    for file in files:
                        if file.endswith(
                            ('.pyc', '.DS_Store')) or file == '.git':
                            continue
                        zip_files.append(
                            (os.path.join(root,
                                          file), os.path.join(root[d:], file)))
                        file_dep.append(os.path.join(root, file))
                yield utils.apply_filters(
                    {
                        'basename':
                        self.name,
                        'name':
                        destination,
                        'file_dep':
                        file_dep,
                        'targets': [destination],
                        'actions': [(make_zip, (zip_files, destination))],
                        'clean':
                        True,
                        'uptodate': [
                            utils.config_changed(self.kw,
                                                 'pkgindex_zip:' + destination)
                        ],
                    }, self.kw['filters'])

        # Generate JSON file of {slug: path_to_zip}
        for dir, data in zip_json.items():
            destination = os.path.join(
                self.kw['output_folder'], self.kw['pkgindex_dirs'][dir][0],
                self.kw['pkgindex_config']['json_filename'])
            yield utils.apply_filters(
                {
                    'basename':
                    self.name,
                    'name':
                    destination,
                    'file_dep':
                    zip_deps[dir],
                    'targets': [destination],
                    'actions': [(write_json, (data, destination))],
                    'clean':
                    True,
                    'uptodate': [
                        utils.config_changed(self.kw,
                                             'pkgindex_zip:' + destination)
                    ],
                }, self.kw['filters'])
Exemplo n.º 59
0
    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(self.kw["output_folder"],
                         self.site.path("gallery_global", gallery_name)))
        # Do thumbnails and copy originals
        # img is "galleries/name/image_name.jpg"
        # img_name is "image_name.jpg"
        # fname, ext are "image_name", ".jpg"
        # thumb_path is
        # "output/GALLERY_PATH/name/image_name.thumbnail.jpg"
        img_name = os.path.basename(img)
        fname, ext = os.path.splitext(img_name)
        thumb_path = os.path.join(output_gallery,
                                  ".thumbnail".join([fname, ext]))
        # thumb_path is "output/GALLERY_PATH/name/image_name.jpg"
        orig_dest_path = os.path.join(output_gallery, img_name)
        yield utils.apply_filters(
            {
                'basename':
                self.name,
                'name':
                thumb_path,
                'file_dep': [img],
                'targets': [thumb_path],
                'actions':
                [(self.resize_image,
                  (img, thumb_path, self.kw['thumbnail_size'], True,
                   self.kw['preserve_exif_data'], self.kw['exif_whitelist'],
                   self.kw['preserve_icc_profiles']))],
                'clean':
                True,
                'uptodate': [
                    utils.config_changed(
                        {1: self.kw['thumbnail_size']},
                        'nikola.plugins.task.galleries:resize_thumb')
                ],
            }, self.kw['filters'])

        yield utils.apply_filters(
            {
                'basename':
                self.name,
                'name':
                orig_dest_path,
                'file_dep': [img],
                'targets': [orig_dest_path],
                'actions':
                [(self.resize_image,
                  (img, orig_dest_path, self.kw['max_image_size'], True,
                   self.kw['preserve_exif_data'], self.kw['exif_whitelist'],
                   self.kw['preserve_icc_profiles']))],
                'clean':
                True,
                'uptodate': [
                    utils.config_changed(
                        {1: self.kw['max_image_size']},
                        'nikola.plugins.task.galleries:resize_max')
                ],
            }, self.kw['filters'])
    def gen_tasks(self):
        if 'PKGINDEX_CONFIG' not in self.site.config:
            return
        self.kw = {
            'output_folder': self.site.config['OUTPUT_FOLDER'],
            'filters': self.site.config['FILTERS'],
            'pkgindex_dirs': self.site.config['PKGINDEX_DIRS'],
            'pkgindex_handlers': self.site.config['PKGINDEX_HANDLERS'],
            'pkgindex_config': self.site.config['PKGINDEX_CONFIG'],
            'base_url': self.site.config['BASE_URL'],
            'revision': '2',
        }
        yield self.group_task()
        self.site.scan_posts()

        demo_deps = {}
        for dir, posts in self.site.pkgindex_entries.items():
            demo_deps[dir] = []
            for post in posts:
                directory = os.path.dirname(post.source_path)
                pkg_name = os.path.basename(directory)
                output_dir = post.folder_relative + '/' + pkg_name
                if output_dir in self.kw['pkgindex_config'][
                        'demo_screenshots_map']:
                    # the map is effectively an ignore list
                    continue

                demo_source = os.path.join('demo_sites',
                                           self.kw['pkgindex_dirs'][dir][0],
                                           pkg_name)
                demo_destination = os.path.join(
                    self.kw['output_folder'], self.kw['pkgindex_dirs'][dir][0],
                    pkg_name, 'demo')
                png_destination = os.path.join(
                    self.kw['output_folder'], self.kw['pkgindex_dirs'][dir][0],
                    pkg_name + '.png')
                png_thumbnail_destination = os.path.join(
                    self.kw['output_folder'], self.kw['pkgindex_dirs'][dir][0],
                    pkg_name + '.thumbnail.png')

                index = os.path.join(demo_destination, 'index.html')

                demo_deps[dir].append(demo_destination)
                # Prefix to slice out from names
                d = len(directory) - len(pkg_name)
                zip_files = []
                file_dep = []
                # Get list of dependencies and files to zip
                for root, dirs, files in os.walk(directory):
                    for file in files:
                        if file.endswith(
                            ('.pyc', '.DS_Store')) or file == '.git':
                            continue
                        zip_files.append(
                            (os.path.join(root,
                                          file), os.path.join(root[d:], file)))
                        file_dep.append(os.path.join(root, file))

                # those are separate variables to avoid cyclic dependencies
                file_dep += [LOREM_BASE]
                file_dep_png = file_dep + [index]

                yield utils.apply_filters(
                    {
                        'basename':
                        self.name,
                        'name':
                        demo_destination,
                        'file_dep':
                        file_dep,
                        'targets': [index],
                        'actions': [(build_demo, (pkg_name, dir, demo_source,
                                                  demo_destination))],
                        'clean':
                        True,
                        'uptodate': [
                            utils.config_changed(
                                self.kw, 'pkgindex_demo:' + demo_destination)
                        ],
                    }, self.kw['filters'])

                yield utils.apply_filters(
                    {
                        'basename':
                        self.name,
                        'name':
                        png_destination,
                        'file_dep':
                        file_dep_png,
                        'targets': [png_destination],
                        'actions': [(take_screenshot,
                                     (index, png_destination))],
                        'clean':
                        True,
                        'uptodate': [
                            utils.config_changed(
                                self.kw,
                                'pkgindex_screenshot:' + png_destination)
                        ],
                    }, self.kw['filters'])

                yield utils.apply_filters(
                    {
                        'basename':
                        self.name,
                        'name':
                        png_thumbnail_destination,
                        'file_dep': [png_destination],
                        'targets': [png_thumbnail_destination],
                        'actions':
                        [(make_thumbnail,
                          (png_destination, png_thumbnail_destination))],
                        'clean':
                        True,
                        'uptodate': [
                            utils.config_changed(
                                self.kw, 'pkgindex_screenshot_thumbnail:' +
                                png_destination)
                        ],
                    }, self.kw['filters'])