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'], "code.css_selectors": ['pre.code', 'div.code pre'], "code.css_close": "\ntable.codetable { width: 100%;} td.linenos {text-align: right; width: 4em;}\n", } 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 has_code_css = task['targets'][0] == code_css_path 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(kw["code.css_selectors"])) outf.write(kw["code.css_close"]) 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): """Generate CSS out of LESS sources.""" kw = { 'cache_folder': self.site.config['CACHE_FOLDER'], 'themes': self.site.THEMES, } # Find where in the theme chain we define the LESS targets # There can be many *.less in the folder, but we only will build # the ones listed in less/targets targets_path = utils.get_asset_path( os.path.join(self.sources_folder, "targets"), self.site.THEMES) try: with codecs.open(targets_path, "rb", "utf-8") as inf: targets = [x.strip() for x in inf.readlines()] except Exception: targets = [] for theme_name in kw['themes']: src = os.path.join(utils.get_theme_path(theme_name), self.sources_folder) for task in utils.copy_tree( src, os.path.join(kw['cache_folder'], self.sources_folder)): #task['basename'] = self.name yield task # Build targets and write CSS files base_path = utils.get_theme_path(self.site.THEMES[0]) dst_dir = os.path.join(self.site.config['OUTPUT_FOLDER'], 'assets', 'css') # Make everything depend on all sources, rough but enough deps = glob.glob( os.path.join(base_path, self.sources_folder, "*{0}".format(self.sources_ext))) def compile_target(target, dst): if not os.path.isdir(dst_dir): os.makedirs(dst_dir) src = os.path.join(kw['cache_folder'], self.sources_folder, target) compiled = subprocess.check_output([self.compiler_name, src]) with open(dst, "wb+") as outf: outf.write(compiled) for target in targets: dst = os.path.join(dst_dir, target.replace(self.sources_ext, ".css")) yield { 'basename': self.name, 'name': dst, 'targets': [dst], 'file_dep': deps, 'actions': ((compile_target, [target, dst]), ), 'uptodate': [utils.config_changed(kw)], 'clean': True } if not targets: 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'], } 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 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'] = task.get('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'] = 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): """Generate tasks.""" conf = self.site.config['PROPAGANDA'] images_folder = os.path.join(self.site.config['OUTPUT_FOLDER'], 'propaganda') filters = self.site.config['FILTERS'] # copy files to static site for task in utils.copy_tree(conf['source_folder'], images_folder, link_cutoff=images_folder): task['basename'] = self.name task['uptodate'] = [ utils.config_changed(conf, 'nikola.plugins.task.propaganda') ] yield utils.apply_filters(task, filters, skip_ext=['.html']) conf["items"] = os.listdir(conf['source_folder']) # generate html to insert into sidebar for key, task_conf in conf["tasks"].items(): task = self._gen_html_task(images_folder, task_conf, key) yield utils.apply_filters(task, filters)
def gen_tasks(self): """Generate CSS out of LESS sources.""" kw = { 'cache_folder': self.site.config['CACHE_FOLDER'], 'themes': self.site.THEMES, } # Find where in the theme chain we define the LESS targets # There can be many *.less in the folder, but we only will build # the ones listed in less/targets targets_path = utils.get_asset_path(os.path.join(self.sources_folder, "targets"), self.site.THEMES) try: with codecs.open(targets_path, "rb", "utf-8") as inf: targets = [x.strip() for x in inf.readlines()] except Exception: targets = [] for theme_name in kw['themes']: src = os.path.join(utils.get_theme_path(theme_name), self.sources_folder) for task in utils.copy_tree(src, os.path.join(kw['cache_folder'], self.sources_folder)): task['basename'] = 'prepare_less_sources' yield task # Build targets and write CSS files base_path = utils.get_theme_path(self.site.THEMES[0]) dst_dir = os.path.join(self.site.config['OUTPUT_FOLDER'], 'assets', 'css') # Make everything depend on all sources, rough but enough deps = glob.glob(os.path.join( base_path, self.sources_folder, "*{0}".format(self.sources_ext))) def compile_target(target, dst): utils.makedirs(dst_dir) src = os.path.join(kw['cache_folder'], self.sources_folder, target) try: compiled = subprocess.check_output([self.compiler_name, src]) except OSError: utils.req_missing([self.compiler_name], 'build LESS files (and use this theme)', False, False) with open(dst, "wb+") as outf: outf.write(compiled) yield self.group_task() for target in targets: dst = os.path.join(dst_dir, target.replace(self.sources_ext, ".css")) yield { 'basename': self.name, 'name': dst, 'targets': [dst], 'file_dep': deps, 'task_dep': ['prepare_less_sources'], 'actions': ((compile_target, [target, dst]), ), 'uptodate': [utils.config_changed(kw)], 'clean': True }
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 gen_tasks(self): self.site.scan_posts() kw = { "translations": self.site.config['TRANSLATIONS'], "output_folder": self.site.config['OUTPUT_FOLDER'], } 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_retired 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["loc"] = post.permalink(lang) 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) yield { "basename": str(self.name), "name": dst_path, "targets": [dst_path], "actions": [(save_data, [])], 'uptodate': [config_changed(kw), result_dep('sitemap')] } # Note: The task should run everytime a new file is added or a # file is changed. We cheat, and depend on the sitemap task, # to run everytime a new file is added. # 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 task
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.js") 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) output = 'var tipuesearch = ' + output + ';' 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 gen_tasks(self): """Render the tag pages and feeds.""" kw = { "output_folder": self.site.config['OUTPUT_FOLDER'], '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'], "taglist_minimum_post_count": self.site.config['TAGLIST_MINIMUM_POSTS'], "pretty_urls": self.site.config['PRETTY_URLS'], "strip_indexes": self.site.config['STRIP_INDEXES'], } self.site.scan_posts() # Copy all the assets to the right places asset_folder = os.path.join(os.path.dirname(__file__), "files") for task in utils.copy_tree(asset_folder, kw["output_folder"]): task["basename"] = str(self.name) 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'] or len( posts) < kw['taglist_minimum_post_count']: continue tag_cloud_data[tag] = [ len(posts), self.site.link('tag', tag, self.site.config['DEFAULT_LANG']) ] output_name = os.path.join(kw['output_folder'], 'assets', 'js', 'tx3_tag_cloud.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) 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 task
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 gen_tasks(self): self.site.scan_posts() kw = { "translations": self.site.config['TRANSLATIONS'], "output_folder": self.site.config['OUTPUT_FOLDER'], } 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["loc"] = post.permalink(lang) 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) yield { "basename": str(self.name), "name": dst_path, "targets": [dst_path], "actions": [(save_data, [])], 'uptodate': [config_changed(kw), result_dep('sitemap')] } # Note: The task should run everytime a new file is added or a # file is changed. We cheat, and depend on the sitemap task, # to run everytime a new file is added. # 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 task
def gen_tasks(self): """Generate CSS out of LESS sources.""" kw = {"cache_folder": self.site.config["CACHE_FOLDER"], "themes": self.site.THEMES} # Find where in the theme chain we define the LESS targets # There can be many *.less in the folder, but we only will build # the ones listed in less/targets targets_path = utils.get_asset_path(os.path.join(self.sources_folder, "targets"), self.site.THEMES) try: with codecs.open(targets_path, "rb", "utf-8") as inf: targets = [x.strip() for x in inf.readlines()] except Exception: targets = [] for theme_name in kw["themes"]: src = os.path.join(utils.get_theme_path(theme_name), self.sources_folder) for task in utils.copy_tree(src, os.path.join(kw["cache_folder"], self.sources_folder)): # task['basename'] = self.name yield task # Build targets and write CSS files base_path = utils.get_theme_path(self.site.THEMES[0]) dst_dir = os.path.join(self.site.config["OUTPUT_FOLDER"], "assets", "css") # Make everything depend on all sources, rough but enough deps = glob.glob(os.path.join(base_path, self.sources_folder, "*{0}".format(self.sources_ext))) def compile_target(target, dst): if not os.path.isdir(dst_dir): os.makedirs(dst_dir) src = os.path.join(kw["cache_folder"], self.sources_folder, target) compiled = subprocess.check_output([self.compiler_name, src]) with open(dst, "wb+") as outf: outf.write(compiled) for target in targets: dst = os.path.join(dst_dir, target.replace(self.sources_ext, ".css")) yield { "basename": self.name, "name": dst, "targets": [dst], "file_dep": deps, "actions": ((compile_target, [target, dst]),), "uptodate": [utils.config_changed(kw)], "clean": True, } if not targets: yield {"basename": self.name, "actions": []}
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 gen_tasks(self): """Render the tag pages and feeds.""" kw = { "output_folder": self.site.config['OUTPUT_FOLDER'], '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'], "taglist_minimum_post_count": self.site.config['TAGLIST_MINIMUM_POSTS'], "pretty_urls": self.site.config['PRETTY_URLS'], "strip_indexes": self.site.config['STRIP_INDEXES'], } self.site.scan_posts() # Copy all the assets to the right places asset_folder = os.path.join(os.path.dirname(__file__), "files") for task in utils.copy_tree(asset_folder, kw["output_folder"]): task["basename"] = str(self.name) 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'] or len(posts) < kw['taglist_minimum_post_count']: continue tag_cloud_data[tag] = [len(posts), self.site.link( 'tag', tag, self.site.config['DEFAULT_LANG'])] output_name = os.path.join(kw['output_folder'], 'assets', 'js', 'tx3_tag_cloud.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) 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 task
def gen_tasks(self): self.site.scan_posts() kw = { "translations": self.site.config['TRANSLATIONS'], "output_folder": self.site.config['OUTPUT_FOLDER'], } 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: data = {} data["title"] = post.title(lang) data["text"] = post.text(lang) data["tags"] = ",".join(post.tags) data["loc"] = post.permalink(lang) pages.append(data) output = json.dumps({"pages": pages}, indent=2) try: os.makedirs(os.path.dirname(dst_path)) except: pass with open(dst_path, "wb+") as fd: fd.write(output) yield { "basename": str(self.name), "name": os.path.join("assets", "js", "tipuesearch_content.js"), "targets": [dst_path], "actions": [(save_data, [])], 'uptodate': [config_changed(kw)] } # 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 task
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 CSS out of Sass sources.""" self.logger = utils.get_logger('build_sass', self.site.loghandlers) self.compiler_name = self.site.config['SASS_COMPILER'] self.compiler_options = self.site.config['SASS_OPTIONS'] kw = { 'cache_folder': self.site.config['CACHE_FOLDER'], 'themes': self.site.THEMES, } tasks = {} # Find where in the theme chain we define the Sass targets # There can be many *.sass/*.scss in the folder, but we only # will build the ones listed in sass/targets if os.path.isfile(os.path.join(self.sources_folder, "targets")): targets_path = os.path.join(self.sources_folder, "targets") else: targets_path = utils.get_asset_path(os.path.join(self.sources_folder, "targets"), self.site.THEMES) try: with codecs.open(targets_path, "rb", "utf-8") as inf: targets = [x.strip() for x in inf.readlines()] except Exception: targets = [] for task in utils.copy_tree(self.sources_folder, os.path.join(kw['cache_folder'], self.sources_folder)): if task['name'] in tasks: continue task['basename'] = 'prepare_sass_sources' tasks[task['name']] = task yield task for theme_name in kw['themes']: src = os.path.join(utils.get_theme_path(theme_name), self.sources_folder) for task in utils.copy_tree(src, os.path.join(kw['cache_folder'], self.sources_folder)): if task['name'] in tasks: continue task['basename'] = 'prepare_sass_sources' tasks[task['name']] = task yield task # Build targets and write CSS files base_path = utils.get_theme_path(self.site.THEMES[0]) dst_dir = os.path.join(self.site.config['OUTPUT_FOLDER'], 'assets', 'css') # Make everything depend on all sources, rough but enough deps = [] for ext in self.sources_ext: if os.path.isfile(os.path.join(self.sources_folder, "targets")): deps += glob.glob(os.path.join(kw['cache_folder'], self.sources_folder, '*{0}'.format(ext))) else: deps += glob.glob(os.path.join(base_path, self.sources_folder, '*{0}'.format(ext))) def compile_target(target, dst): utils.makedirs(dst_dir) run_in_shell = sys.platform == 'win32' src = os.path.join(kw['cache_folder'], self.sources_folder, target) try: compiled = subprocess.check_output([self.compiler_name] + self.compiler_options + [src], shell=run_in_shell) except OSError: utils.req_missing([self.compiler_name], 'build Sass files (and use this theme)', False, False) with open(dst, "wb+") as outf: outf.write(compiled) yield self.group_task() # We can have file conflicts. This is a way to prevent them. # I orignally wanted to use sets and their cannot-have-duplicates # magic, but I decided not to do this so we can show the user # what files were problematic. # If we didn’t do this, there would be a cryptic message from doit # instead. seennames = {} for target in targets: base = os.path.splitext(target)[0] dst = os.path.join(dst_dir, base + ".css") if base in seennames: self.logger.error( 'Duplicate filenames for Sass compiled files: {0} and ' '{1} (both compile to {2})'.format( seennames[base], target, base + ".css")) else: seennames.update({base: target}) yield { 'basename': self.name, 'name': dst, 'targets': [dst], 'file_dep': deps, 'task_dep': ['prepare_sass_sources'], 'actions': ((compile_target, [target, dst]), ), 'uptodate': [utils.config_changed(kw)], 'clean': True }
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): """Generate CSS out of Sass sources.""" self.logger = utils.get_logger('build_sass', utils.STDERR_HANDLER) self.compiler_name = self.site.config['SASS_COMPILER'] self.compiler_options = self.site.config['SASS_OPTIONS'] kw = { 'cache_folder': self.site.config['CACHE_FOLDER'], 'themes': self.site.THEMES, } tasks = {} # Find where in the theme chain we define the Sass targets # There can be many *.sass/*.scss in the folder, but we only # will build the ones listed in sass/targets if os.path.isfile(os.path.join(self.sources_folder, "targets")): targets_path = os.path.join(self.sources_folder, "targets") else: targets_path = utils.get_asset_path( os.path.join(self.sources_folder, "targets"), self.site.THEMES) try: with codecs.open(targets_path, "rb", "utf-8") as inf: targets = [x.strip() for x in inf.readlines()] except Exception: targets = [] for task in utils.copy_tree( self.sources_folder, os.path.join(kw['cache_folder'], self.sources_folder)): if task['name'] in tasks: continue task['basename'] = 'prepare_sass_sources' tasks[task['name']] = task yield task for theme_name in kw['themes']: src = os.path.join(utils.get_theme_path(theme_name), self.sources_folder) for task in utils.copy_tree( src, os.path.join(kw['cache_folder'], self.sources_folder)): if task['name'] in tasks: continue task['basename'] = 'prepare_sass_sources' tasks[task['name']] = task yield task # Build targets and write CSS files dst_dir = os.path.join(self.site.config['OUTPUT_FOLDER'], 'assets', 'css') # Make everything depend on all sources, rough but enough deps = [] for task in tasks.keys(): for ext in self.sources_ext: if task.endswith(ext): deps.append(task) def compile_target(target, dst): utils.makedirs(dst_dir) run_in_shell = sys.platform == 'win32' src = os.path.join(kw['cache_folder'], self.sources_folder, target) try: compiled = subprocess.check_output( [self.compiler_name] + self.compiler_options + [src], shell=run_in_shell) except OSError: utils.req_missing([self.compiler_name], 'build Sass files (and use this theme)', False, False) with open(dst, "wb+") as outf: outf.write(compiled) yield self.group_task() # We can have file conflicts. This is a way to prevent them. # I orignally wanted to use sets and their cannot-have-duplicates # magic, but I decided not to do this so we can show the user # what files were problematic. # If we didn’t do this, there would be a cryptic message from doit # instead. seennames = {} for target in targets: base = os.path.splitext(target)[0] dst = os.path.join(dst_dir, base + ".css") if base in seennames: self.logger.error( 'Duplicate filenames for Sass compiled files: {0} and ' '{1} (both compile to {2})'.format(seennames[base], target, base + ".css")) else: seennames.update({base: target}) yield { 'basename': self.name, 'name': dst, 'targets': [dst], 'file_dep': deps, 'task_dep': ['prepare_sass_sources'], 'actions': ((compile_target, [target, dst]), ), 'uptodate': [utils.config_changed(kw)], 'clean': True }
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): """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): """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): """Generate CSS out of LESS sources.""" self.compiler_name = self.site.config['LESS_COMPILER'] self.compiler_options = self.site.config['LESS_OPTIONS'] kw = { 'cache_folder': self.site.config['CACHE_FOLDER'], 'themes': self.site.THEMES, } tasks = {} # Find where in the theme chain we define the LESS targets # There can be many *.less in the folder, but we only will build # the ones listed in less/targets if os.path.isfile(os.path.join(self.sources_folder, "targets")): targets_path = os.path.join(self.sources_folder, "targets") else: targets_path = utils.get_asset_path(os.path.join(self.sources_folder, "targets"), self.site.THEMES) try: with codecs.open(targets_path, "rb", "utf-8") as inf: targets = [x.strip() for x in inf.readlines()] except Exception: targets = [] for task in utils.copy_tree(self.sources_folder, os.path.join(kw['cache_folder'], self.sources_folder)): if task['name'] in tasks: continue task['basename'] = 'prepare_less_sources' tasks[task['name']] = task yield task for theme_name in kw['themes']: src = os.path.join(utils.get_theme_path(theme_name), self.sources_folder) for task in utils.copy_tree(src, os.path.join(kw['cache_folder'], self.sources_folder)): if task['name'] in tasks: continue task['basename'] = 'prepare_less_sources' tasks[task['name']] = task yield task # Build targets and write CSS files dst_dir = os.path.join(self.site.config['OUTPUT_FOLDER'], 'assets', 'css') # Make everything depend on all sources, rough but enough deps = [] for task in tasks.keys(): if task.endswith(self.sources_ext): deps.append(task) def compile_target(target, dst): utils.makedirs(dst_dir) src = os.path.join(kw['cache_folder'], self.sources_folder, target) run_in_shell = sys.platform == 'win32' try: compiled = subprocess.check_output([self.compiler_name] + self.compiler_options + [src], shell=run_in_shell) except OSError: utils.req_missing([self.compiler_name], 'build LESS files (and use this theme)', False, False) with open(dst, "wb+") as outf: outf.write(compiled) yield self.group_task() for target in targets: dst = os.path.join(dst_dir, target.replace(self.sources_ext, ".css")) yield { 'basename': self.name, 'name': dst, 'targets': [dst], 'file_dep': deps, 'task_dep': ['prepare_less_sources'], 'actions': ((compile_target, [target, dst]), ), 'uptodate': [utils.config_changed(kw)], 'clean': True }
def gen_tasks(self): """Generate CSS out of LESS sources.""" self.compiler_name = self.site.config['LESS_COMPILER'] self.compiler_options = self.site.config['LESS_OPTIONS'] kw = { 'cache_folder': self.site.config['CACHE_FOLDER'], 'themes': self.site.THEMES, } tasks = {} # Find where in the theme chain we define the LESS targets # There can be many *.less in the folder, but we only will build # the ones listed in less/targets if os.path.isfile(os.path.join(self.sources_folder, "targets")): targets_path = os.path.join(self.sources_folder, "targets") else: targets_path = utils.get_asset_path(os.path.join(self.sources_folder, "targets"), self.site.THEMES) try: with codecs.open(targets_path, "rb", "utf-8") as inf: targets = [x.strip() for x in inf.readlines()] except Exception: targets = [] for task in utils.copy_tree(self.sources_folder, os.path.join(kw['cache_folder'], self.sources_folder)): if task['name'] in tasks: continue task['basename'] = 'prepare_less_sources' tasks[task['name']] = task yield task for theme_name in kw['themes']: src = os.path.join(utils.get_theme_path(theme_name), self.sources_folder) for task in utils.copy_tree(src, os.path.join(kw['cache_folder'], self.sources_folder)): task['basename'] = 'prepare_less_sources' yield task # Build targets and write CSS files base_path = utils.get_theme_path(self.site.THEMES[0]) dst_dir = os.path.join(self.site.config['OUTPUT_FOLDER'], 'assets', 'css') # Make everything depend on all sources, rough but enough deps = [] if os.path.isfile(os.path.join(self.sources_folder, "targets")): deps += glob.glob(os.path.join(kw['cache_folder'], self.sources_folder, '*{0}'.format(self.sources_ext))) else: deps += glob.glob(os.path.join(base_path, self.sources_folder, '*{0}'.format(self.sources_ext))) def compile_target(target, dst): utils.makedirs(dst_dir) src = os.path.join(kw['cache_folder'], self.sources_folder, target) run_in_shell = sys.platform == 'win32' try: compiled = subprocess.check_output([self.compiler_name] + self.compiler_options + [src], shell=run_in_shell) except OSError: utils.req_missing([self.compiler_name], 'build LESS files (and use this theme)', False, False) with open(dst, "wb+") as outf: outf.write(compiled) yield self.group_task() for target in targets: dst = os.path.join(dst_dir, target.replace(self.sources_ext, ".css")) yield { 'basename': self.name, 'name': dst, 'targets': [dst], 'file_dep': deps, 'task_dep': ['prepare_less_sources'], 'actions': ((compile_target, [target, dst]), ), 'uptodate': [utils.config_changed(kw)], 'clean': True }
def gen_tasks(self): """Generate CSS out of Sass sources.""" self.logger = utils.get_logger('build_sass', self.site.loghandlers) kw = { 'cache_folder': self.site.config['CACHE_FOLDER'], 'themes': self.site.THEMES, } # Find where in the theme chain we define the Sass targets # There can be many *.sass/*.scss in the folder, but we only # will build the ones listed in sass/targets targets_path = utils.get_asset_path( os.path.join(self.sources_folder, "targets"), self.site.THEMES) try: with codecs.open(targets_path, "rb", "utf-8") as inf: targets = [x.strip() for x in inf.readlines()] except Exception: targets = [] for theme_name in kw['themes']: src = os.path.join(utils.get_theme_path(theme_name), self.sources_folder) for task in utils.copy_tree( src, os.path.join(kw['cache_folder'], self.sources_folder)): task['basename'] = 'prepare_sass_sources' yield task # Build targets and write CSS files base_path = utils.get_theme_path(self.site.THEMES[0]) dst_dir = os.path.join(self.site.config['OUTPUT_FOLDER'], 'assets', 'css') # Make everything depend on all sources, rough but enough deps = glob.glob( os.path.join(base_path, self.sources_folder, *("*{0}".format(ext) for ext in self.sources_ext))) def compile_target(target, dst): utils.makedirs(dst_dir) src = os.path.join(kw['cache_folder'], self.sources_folder, target) compiled = subprocess.check_output([self.compiler_name, src]) with open(dst, "wb+") as outf: outf.write(compiled) yield self.group_task() # We can have file conflicts. This is a way to prevent them. # I orignally wanted to use sets and their cannot-have-duplicates # magic, but I decided not to do this so we can show the user # what files were problematic. # If we didn’t do this, there would be a cryptic message from doit # instead. seennames = {} for target in targets: base = os.path.splitext(target)[0] dst = os.path.join(dst_dir, base + ".css") if base in seennames: self.logger.error( 'Duplicate filenames for SASS compiled files: {0} and ' '{1} (both compile to {2})'.format(seennames[base], target, base + ".css")) else: seennames.update({base: target}) yield { 'basename': self.name, 'name': dst, 'targets': [dst], 'file_dep': deps, 'task_dep': ['prepare_sass_sources'], 'actions': ((compile_target, [target, dst]), ), 'uptodate': [utils.config_changed(kw)], 'clean': True }