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'])
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"], )
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'])
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"])
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): 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'])
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'])
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': [], }
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'])
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'])
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'])
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': (), }
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)
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'])
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"])
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': [], }
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"], )
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'])
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"], )
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'])
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': [], }
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": []}
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.")
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"])
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'])
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"])
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"])
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": ()}
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"])
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'])
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'])
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)
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'])
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) }, )
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'])
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': (), }
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'])
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'])
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'])
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'])
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})
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'])
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'])
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'])
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': [], }
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'])
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"])
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'])
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)
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'])
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'])
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'])
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"])
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'])
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"])
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'])
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'])
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'])