def atom(cache): """Build atom feed.""" data = _complement(index=cache.index()) dest = os.path.join(conf.get('build_path'), conf.get('atom_location')) logger.info(_to('atom feed', dest)) helpers.makedirs(os.path.dirname(dest)) templates.render(data, 'atom.xml', dest)
def sitemap(cache): """Build sitemap.xml.""" data = _complement(index=cache.full_index()) dest = os.path.join(conf.get('build_path'), const.SITEMAP) logger.info(_to('sitemap', dest)) helpers.makedirs(os.path.dirname(dest)) templates.render(data, 'sitemap.xml', dest)
def theme_update(path=None, safe=False): conf.load(path) if safe: logger.info('saving current theme') assets_bak = "%s.bak" % pathes.theme_assets_installed() templates_bak = "%s.bak" % pathes.theme_templates_installed() try: for path in [templates_bak, assets_bak]: if os.path.isdir(path): shutil.rmtree(path, ignore_errors=True) shutil.move(pathes.theme_assets_installed(), assets_bak) shutil.move(pathes.theme_templates_installed(), templates_bak) except Exception as e: logger.error('error saving existing theme files: ' + str(e)) return logger.info('updating theme files') try: path = pathes.theme_assets_source() helpers.copydir(path, pathes.theme_assets_installed()) path = pathes.theme_templates_source() helpers.copydir(path, pathes.theme_templates_installed()) except Exception as e: logger.error('error updating theme: ' + str(e))
def post(path=None, name=None, force=False, edit=False): """Create new post.""" conf.load(path) path = source.PostSource.create(name, force) logger.info('post created: ' + path) if edit: helpers.execute(conf.get('editor_cmd'), path)
def static(cache): """Copy other assets as is to the build path.""" for source in cache.assets(processed=False): logger.info('copying: ' + source.rel_path()) helpers.makedirs(source.dest_dir()) shutil.copyfile(source.path(), source.dest()) helpers.utime(source.dest(), source.updated()) source.processed(True)
def archive(cache): """Build blog archive page.""" dest = os.path.join(conf.get('build_path'), conf.get('archive_location')) logger.info('archive: ' + conf.get('archive_location')) helpers.makedirs(os.path.dirname(dest)) page_data = {'title': 'Archive', 'tags': cache.tags()} data = _complement(page_data, index=cache.index()) templates.render(data, 'archive.html', dest)
def tags(cache): """Build blog tag pages.""" for tag in cache.tags(): tag = tag['name'] dest = helpers.tag_path(tag) logger.info(_to('tag', tag, dest)) helpers.makedirs(os.path.dirname(dest)) data = _complement({'title': tag}, index=cache.index(tag=tag)) templates.render(data, 'tag.html', dest)
def env(): global _env if _env is None: search_pathes = [pathes.templates(), pathes.theme_templates()] logger.info("templates pathes: [%s]" % ', '.join(search_pathes)) loader = jinja2.FileSystemLoader(searchpath=search_pathes) _env = jinja2.Environment(loader=loader, extensions=JINJA_EXTENSIONS) _env.filters.update(custom_filters()) _env.globals.update(custom_globals()) return _env
def pages(cache): """Build site pages.""" for source in cache.pages(): logger.info(_to('page', source.rel_path(), source.rel_dest())) helpers.makedirs(source.dest_dir()) try: data = _complement(source.data(), index=cache.index()) templates.render_page(data, source.dest()) except Exception as ex: logger.error('page building error: ' + str(ex)) logger.debug(traceback.format_exc())
def page(path=None, name=None, force=False, edit=False): """Create new page.""" conf.load(path) try: path = source.PageSource.create(name, force) except source.PageExistsException: logger.error('page already exists, use -f to overwrite') return logger.info('page created: ' + path) if edit: helpers.execute(conf.get('editor_cmd'), path)
def humans(cache): """Build humans.txt.""" for source in cache.assets(basename='humans.txt'): logger.info('processing ' + source.rel_path()) helpers.makedirs(source.dest_dir()) try: data = _complement({}) templates.render_file(source.path(), data, source.dest()) except Exception as ex: logger.error('humans.txt processing failed: ' + str(ex)) logger.debug(traceback.format_exc()) finally: source.processed(True)
def js(cache): """Minify JavaScript files to the build path.""" for source in cache.assets(ext='.js'): helpers.makedirs(source.dest_dir()) command = conf.get('min_js_cmd') if conf.get('min_js') and command: logger.info('minifying JavaScript: ' + source.rel_path()) helpers.execute(command, source.path(), source.dest()) else: logger.info('copying: ' + source.rel_path()) shutil.copyfile(source.path(), source.dest()) helpers.utime(source.dest(), source.updated()) source.processed(True)
def build(path=None, output=None): """Generate web content from source.""" conf.load(path) cache = Cache() if cache.processing_errors(): for file_name, error in cache.processing_errors(): message = "error processing source file '%s' - %s" logger.error(message % (file_name, error)) if output: conf.set('build_path', output) logger.info('build directory: ' + conf.get('build_path')) for builder in builders.order(): builder(cache)
def less(cache): """Compile and minify less files.""" for source in cache.assets(ext='.less'): helpers.makedirs(source.dest_dir()) logger.info('compiling LESS: ' + source.rel_path()) if conf.get('min_css') and conf.get('min_css_cmd'): tmp_file = os.path.join(source.dest_dir(), '_' + source.basename()) helpers.execute(conf.get('less_cmd'), source.path(), tmp_file) logger.info('minifying CSS: ' + source.rel_path()) helpers.execute(conf.get('min_css_cmd'), tmp_file, source.dest()) os.remove(tmp_file) else: helpers.execute(conf.get('less_cmd'), source.path(), source.dest()) helpers.utime(source.dest(), source.updated()) source.processed(True)
def init(path=None, force=False): """Create new website.""" conf.generate(path, force) try: src = pathes.proto() existing = helpers.copydir(src, pathes.site(), force=force) if len(existing): message = "some existing files were overwritten" if force else \ "some existing files were NOT overwritten (use --force " \ "to overwrite)" logger.warn("%s\n- %s" % (message, '\n- '.join(existing))) logger.info('website created successfully, have fun!') except Exception as ex: logger.error('initialization failed: ' + str(ex)) print(str(ex))
def deploy(path=None): """Deploy generated website to the remote web server.""" conf.load(path) helpers.check_build(conf.get('build_path')) logger.info('deploying website...') if not conf.get('deploy_cmd'): raise Exception('deploy command is not defined') cmd = conf.get('deploy_cmd').format(build_path=conf.get('build_path')) try: output = subprocess.check_output(cmd, shell=True) logger.debug("Command output:\n%s" % output.decode('utf-8')) logger.info('done') except subprocess.CalledProcessError as e: logger.error(e) logger.debug("Command output:\n%s" % e.output.decode('utf-8'))
def posts(cache): """Build blog posts and copy the latest post to the site root.""" for source in cache.posts(): logger.info(_to('post', source.rel_path(), source.rel_dest())) helpers.makedirs(source.dest_dir()) try: data = _complement(source.data()) templates.render_page(data, source.dest()) except Exception as ex: logger.error('post building error: ' + str(ex)) logger.debug(traceback.format_exc()) if conf.get('post_at_root_url'): # put the latest post at site root url last = cache.posts()[0] path = os.path.join(conf.get('build_path'), conf.get('index_page')) logger.info(_to('root', last.rel_dest(), conf.get('index_page'))) if any(cache.pages(dest=conf.get('index_page'))): logger.warn('root page will be overwritten by the latest post') try: shutil.copyfile(last.dest(), path) except FileNotFoundError: logger.error("latest post was not generated and can't be copied")
def clean(path=None): """Delete all generated content.""" conf.load(path) logger.info('cleaning output...') helpers.rmdir(conf.get('build_path')) logger.info('done')