diff options
Diffstat (limited to 'scripts/jinjify.py')
| -rwxr-xr-x | scripts/jinjify.py | 86 |
1 files changed, 62 insertions, 24 deletions
diff --git a/scripts/jinjify.py b/scripts/jinjify.py index abd18e9..629ffb1 100755 --- a/scripts/jinjify.py +++ b/scripts/jinjify.py @@ -1,4 +1,6 @@ #!/usr/bin/env python +"""Script to convert templates from Mako to Jinja2.""" + import io import glob import sys @@ -6,20 +8,25 @@ import os import re import json import shutil +import tempfile -import colorama import jinja2 dumb_replacements = [ - ["{% if any(post.is_mathjax for post in posts) %}", '{% if posts|selectattr("is_mathjax")|list %}'], + ["{% if any(post.has_math for post in posts) %}", '{% if posts|selectattr("has_math")|list %}'], ["json.dumps(title)", "title|tojson"], ["{{ parent.extra_head() }}", "{{ super() }}"], + ["{{ parent.content() }}", "{{ super() }}"], ["prefix='\\", "prefix='"], ["og: http://ogp.me/ns# \\", "og: http://ogp.me/ns#"], ["article: http://ogp.me/ns/article# \\", "article: http://ogp.me/ns/article#"], ["fb: http://ogp.me/ns/fb# \\", "fb: http://ogp.me/ns/fb#"], ['dir="rtl" \\', 'dir="rtl"'], ['sorted(translations)', 'translations|sort'], + ['abs(i - current_page)', '(i - current_page)|abs'], + ['loop.index', 'loop.index0'], + ['is None', 'is none'], + ['is not None', 'is not none'], ] dumber_replacements = [ @@ -37,11 +44,11 @@ def jinjify(in_theme, out_theme): out_templates_path = os.path.join(out_theme, "templates") try: os.makedirs(out_templates_path) - except: + except Exception: pass lookup = jinja2.Environment() lookup.filters['tojson'] = json.dumps - lookup.loader = jinja2.FileSystemLoader([out_templates_path], encoding='utf-8') + lookup.loader = jinja2.FileSystemLoader([out_templates_path], encoding='utf-8-sig') for template in glob.glob(os.path.join(in_templates_path, "*.tmpl")): out_template = os.path.join(out_templates_path, os.path.basename(template)) with io.open(template, "r", encoding="utf-8") as inf: @@ -71,21 +78,17 @@ def jinjify(in_theme, out_theme): child = os.path.basename(out_theme.rstrip('/')) mappings = { 'base-jinja': 'base', - 'bootstrap3-jinja': 'base-jinja', + 'bootstrap4-jinja': 'base-jinja', } if child in mappings: parent = mappings[child] - with io.open(os.path.join(out_theme, "parent"), "w+", encoding='utf-8') as outf: - outf.write(u'{0}\n'.format(parent)) - - with io.open(os.path.join(out_theme, "engine"), "w+", encoding='utf-8') as outf: - outf.write(u"jinja\n") - - # Copy assets in bootstrap/bootstrap3 - if child == 'bootstrap3-jinja': - shutil.rmtree(os.path.join(out_theme, "assets")) + # Copy assets in bootstrap/bootstrap4 + if child == 'bootstrap4-jinja': + assets_dir = os.path.join(out_theme, "assets") + if os.path.exists(assets_dir): + shutil.rmtree(assets_dir) shutil.copytree( os.path.join(in_theme, "assets"), os.path.join(out_theme, "assets"), symlinks=True) @@ -99,7 +102,7 @@ def jinjify(in_theme, out_theme): def error(msg): - print(colorama.Fore.RED + "ERROR:" + msg) + print("\033[1;31mERROR: {0}\033[0m".format(msg)) def mako2jinja(input_file): @@ -108,7 +111,7 @@ def mako2jinja(input_file): # TODO: OMG, this code is so horrible. Look at it; just look at it: - macro_start = re.compile(r'(.*)<%.*def name="(.*?)".*>(.*)', re.IGNORECASE) + macro_start = re.compile(r'(.*)<%\s*def name="([^"]*?)"\s*>(.*)', re.IGNORECASE) macro_end = re.compile(r'(.*)</%def>(.*)', re.IGNORECASE) if_start = re.compile(r'(.*)% *if (.*):(.*)', re.IGNORECASE) @@ -158,6 +161,14 @@ def mako2jinja(input_file): if m_func_len: line = func_len.sub(r'\1|length', line) + # Macro start/end + m_macro_start = macro_start.search(line) + if m_macro_start: + line = m_macro_start.expand(r'\1{% macro \2 %}\3') + '\n' + m_macro_end = macro_end.search(line) + if m_macro_end: + line = m_macro_end.expand(r'\1{% endmacro %}\2') + '\n' + # Process line for single 'whole line' replacements m_macro_start = macro_start.search(line) m_macro_end = macro_end.search(line) @@ -178,11 +189,6 @@ def mako2jinja(input_file): if m_comment_single_line: output += m_comment_single_line.expand(r'{# \1 #}') + '\n' - elif m_macro_start: - output += m_macro_start.expand(r'\1{% macro \2 %}\3') + '\n' - elif m_macro_end: - output += m_macro_end.expand(r'\1{% endmacro %}\1') + '\n' - elif m_if_start: output += m_if_start.expand(r'\1{% if \2 %}\3') + '\n' elif m_if_else: @@ -215,16 +221,48 @@ def mako2jinja(input_file): return output + +def jinjify_shortcodes(in_dir, out_dir): + for fname in os.listdir(in_dir): + if not fname.endswith('.tmpl'): + continue + in_file = os.path.join(in_dir, fname) + out_file = os.path.join(out_dir, fname) + with open(in_file) as inf: + data = mako2jinja(inf) + with open(out_file, 'w') as outf: + outf.write(data) + + +def usage(): + print("Usage: python {} [in-dir] [out-dir]".format(sys.argv[0])) + print("OR") + print("Usage: python {} [in-file] [out-file]".format(sys.argv[0])) + if __name__ == "__main__": if len(sys.argv) == 1: print('Performing standard conversions:') for m, j in ( ('nikola/data/themes/base', 'nikola/data/themes/base-jinja'), - ('nikola/data/themes/bootstrap3', 'nikola/data/themes/bootstrap3-jinja') + ('nikola/data/themes/bootstrap4', 'nikola/data/themes/bootstrap4-jinja'), + ('nikola/data/themes/bootblog4', 'nikola/data/themes/bootblog4-jinja'), ): print(' {0} -> {1}'.format(m, j)) jinjify(m, j) + jinjify_shortcodes('nikola/data/shortcodes/mako', 'nikola/data/shortcodes/jinja') elif len(sys.argv) != 3: - print('ERROR: needs input and output directory, or no arguments for default conversions.') - else: + print('ERROR: needs input and output directory (file), or no arguments for default conversions.') + usage() + elif os.path.isdir(sys.argv[1]) and (os.path.isdir(sys.argv[2]) or not os.path.exists(sys.argv[2])): jinjify(sys.argv[1], sys.argv[2]) + elif os.path.isfile(sys.argv[1]) and (os.path.isfile(sys.argv[2]) or not os.path.exists(sys.argv[2])): + tmpdir = tempfile.mkdtemp() + indir = os.path.sep.join((tmpdir, 'in', 'templates')) + outdir = os.path.sep.join((tmpdir, 'out', 'templates')) + os.makedirs(indir) + shutil.copy(sys.argv[1], indir) + jinjify(os.path.dirname(indir), os.path.dirname(outdir)) + shutil.move(os.path.sep.join((outdir, os.path.basename(sys.argv[1]))), sys.argv[2]) + else: + print('ERROR: the two arguments must be both directories or files') + usage() |
