-
Josh Borrow authoredJosh Borrow authored
compiler.py 4.36 KiB
""" Short compilation script from the website
(essentially just stitches together a bunch of jinja templates)
Created 16-08-2017 by Josh Borrow (joshua.borrow@durham.ac.uk)
"""
import os
from distutils.dir_util import copy_tree
import jinja2
import yaml
def get_from_filesystem(template_names, template_dir=".", data_dir="../data"):
""" Takes a list of template names and returns a zipped list of template
objects and associated data values that are ready for rendering wih the
render_template function. """
template_loader = jinja2.FileSystemLoader(searchpath=template_dir)
template_env = jinja2.Environment(loader=template_loader)
templates = list(map(template_env.get_template, template_names))
data = get_associated_data(template_names, data_dir)
return zip(templates, data)
def get_associated_data(template_names, data_dir="../data"):
""" Grabs the data from yaml files within the data directory if they exist,
and if not returns an empty dictionary for that item. """
data = []
for template in template_names:
# swap that .html for a .yaml
stub = template.split(".")[0]
filename = f"{data_dir}/{stub}.yaml"
try:
with open(filename, "r") as f:
data.append(yaml.load(f))
except FileNotFoundError:
data.append({})
return data
def render_template(template, args, data_dir="../data"):
""" Args is a dictionary of the local variables required for
rendering the template. """
# Interestingly this is the fastest way to concatenate two dictionaries,
# see https://stackoverflow.com/questions/1781571
args = dict(global_variables(template, data_dir), **args)
return template.render(**args)
def process_navbar(raw, active):
""" Processes the navbar from our favourite friends over at global.yaml """
output = []
for key, item in enumerate(raw["navbar"]):
classes = []
if key != len(raw["navbar"])-1: # Lines between items are handled
classes.append("rightborder") # by borders on the right of items
if item[1] == active: # If current template
classes.append("active")
output.append([item[0], item[1], " ".join(classes)])
raw["navbar"] = output
return raw
def global_variables(active, data_dir="../data"):
""" Grabs the global variables from the data directory and sticks them into
a dicitonary ready for template rendering.
Active is the name of the current page's template and is used in the
production of the processed navbar. """
with open("{}/global.yaml".format(data_dir), "r") as f:
raw = yaml.load(f) # We need to process the navbar.
return process_navbar(raw, active)
def render(render_pages, data_dir, template_dir, output_dir):
""" Main rendering function for all of the pages. """
data = get_from_filesystem(render_pages, template_dir, data_dir)
output = [render_template(page, args, data_dir) for page, args in data]
# Save the files into the output_dir
if not os.path.exists(output_dir):
os.makedirs(output_dir)
for page, data in zip(render_pages, output):
with open("{}/{}".format(output_dir, page), "w") as f:
f.write(data)
return
def copy_static(directories, output_dir):
""" Copies the (static) files from the original directory to the output """
if type(directories) == list:
for directory in directories:
copy_tree(directory, output_dir)
else:
copy_tree(directories, output_dir)
return
if __name__ == "__main__":
import about
DATA_DIR = "./data"
TEMPLATE_DIR = "./templates"
OUTPUT_DIR = "./compiled"
PAGES = [
"index.html",
"pubs.html",
"talks.html",
"about.html",
]
STATIC = [
"stylesheets",
"images",
]
print("Compiling markdown to HTML and saving in the about.yaml file...")
about.compile_to_yaml(
in_filename="about_meta.yaml",
out_filename="about.yaml",
data_dir=DATA_DIR
)
print("Rendering templates...")
render(
render_pages=PAGES,
data_dir=DATA_DIR,
template_dir=TEMPLATE_DIR,
output_dir=OUTPUT_DIR,
)
print("Copying static files...")
copy_static(
STATIC,
OUTPUT_DIR
)