make script faster

This commit is contained in:
vitrinekast
2025-02-16 11:08:10 +01:00
parent 8ccdb53a40
commit 9a93d5c603

187
app.py
View File

@ -10,8 +10,10 @@ import frontmatter
from slugify import slugify from slugify import slugify
import pypandoc import pypandoc
# TODO make newsletter URL's absolute to klank.school import xml.etree.ElementTree as ET
# TODO make newsletter URL's absolute to klank.school
env = Environment( env = Environment(
loader=PackageLoader("src"), loader=PackageLoader("src"),
autoescape=select_autoescape() autoescape=select_autoescape()
@ -19,17 +21,12 @@ env = Environment(
CONTENT_D = os.path.abspath("src/content") CONTENT_D = os.path.abspath("src/content")
OUTPUT_D = "dist" OUTPUT_D = "dist"
OUT_ASSETS = "dist/assets"
SRC_ASSETS = "src/assets"
documents = {} documents = {}
now = datetime.now()
def listDocuments(params): # Utils
param = params.split(" ")
template = env.select_template([f"snippets/list-documents.jinja"])
html = template.render(documents=documents, layout=param[0], type=param[1])
return html
def getParam(params, index): def getParam(params, index):
if len(params) > index: if len(params) > index:
return params[index] return params[index]
@ -37,9 +34,18 @@ def getParam(params, index):
return False return False
# jinja filter that can list documents
def listDocuments(params):
param = params.split(" ")
template = env.select_template(["snippets/list-documents.jinja"])
html = template.render(documents=documents, layout=param[0], type=param[1])
return html
# jinja filter that can list events
def listEvents(params): def listEvents(params):
param = params.split(" ") param = params.split(" ")
tag=getParam(param, 1) tag = getParam(param, 1)
if "events" not in documents: if "events" not in documents:
return "" return ""
@ -52,20 +58,21 @@ def listEvents(params):
else: else:
events = documents["events"] events = documents["events"]
template = env.select_template([f"snippets/list-events.jinja"]) template = env.select_template(["snippets/list-events.jinja"])
html = template.render(events=events, filter=param[0], tag=getParam(param, 1)) html = template.render(events=events, filter=param[0], tag=getParam(param, 1))
return html return html
# jinja filter to make a slug out of a stirng
def slugify_filter(value): def slugify_filter(value):
return slugify(value) return slugify(value)
# jinja filter for date formatting
def prettydate(value, format='%d/%m/%Y'): def prettydate(value, format='%d/%m/%Y'):
return datetime.fromtimestamp(int(value)).strftime(format) return datetime.fromtimestamp(int(value)).strftime(format)
# jinja filter to replace shortcodes in HTML
def shortcode_filter(value): def shortcode_filter(value):
shortcode_callbacks = { shortcode_callbacks = {
@ -91,12 +98,9 @@ env.filters["shortcode"] = shortcode_filter
env.filters["slugify"] = slugify_filter env.filters["slugify"] = slugify_filter
env.filters["prettydate"] = prettydate env.filters["prettydate"] = prettydate
# translate a single file into HTML
def render_single_file(template, page, path, dist, name = False): def render_single_file(page, path, dist, name = False):
modifier = False template = env.select_template([f"{name}.jinja", "post.jinja"])
print(f"rendering: {path}")
html = template.render(documents=documents, page=page, name=name) html = template.render(documents=documents, page=page, name=name)
name = Path(path).stem name = Path(path).stem
@ -107,30 +111,65 @@ def render_single_file(template, page, path, dist, name = False):
output_file.write(html) output_file.write(html)
# find a pre-rendered page
def get_existing_page(path, slug):
stem = Path(path).stem;
folder = os.path.basename(os.path.dirname(path))
if stem == "index" and folder != "content":
folder = Path(path).parent.parent.name
if slug in documents:
return documents[slug]
if folder == "content":
return False
for doc in documents[folder]:
if doc["slug"] == slug:
return doc
return False
# build a slug including the folder
def get_slug(path, folder, filename):
if folder == "content":
return slugify(filename)
else:
return slugify(f"{folder}/{filename}")
# compile markdown into cited HTML
def get_page_data(path, isPreload=False): def get_page_data(path, isPreload=False):
filename = Path(path).stem filename = Path(path).stem
folder = os.path.basename(os.path.dirname(path))
slug = get_slug(path, folder, filename)
prerendered = get_existing_page(path, slug)
if prerendered:
return prerendered
page = frontmatter.load(path) page = frontmatter.load(path)
page['slug'] = slugify(filename) page['slug'] = slug
page.filename = filename page.filename = filename
page.folder = os.path.basename(os.path.dirname(path)) page.folder = folder
latex = page.content
if "start_datetime" in page: if "start_datetime" in page:
now = datetime.now()
page["has_passed"] = datetime.fromtimestamp(page["start_datetime"]) < now page["has_passed"] = datetime.fromtimestamp(page["start_datetime"]) < now
if ".include" in page.content:
latex = pypandoc.convert_text( latex = pypandoc.convert_text(
page.content, page.content,
to='md', to='md',
format='md', format='md',
extra_args=[ extra_args=[
"-N", "-N",
"--section-divs", "--section-divs",
"--lua-filter=include-files.lua" "--lua-filter=include-files.lua"
]) ])
page.body = pypandoc.convert_text( page.body = pypandoc.convert_text(
latex, latex,
@ -146,53 +185,78 @@ def get_page_data(path, isPreload=False):
return page return page
# Do stuff to the circuit's pcb
def save_circuit_svg(filepath, outpath, name):
def render_posts(path): tree = ET.parse(filepath)
root = tree.getroot()
# Extract current width/height (in pixels)
width_px = float(root.get("width", 0))
height_px = float(root.get("height", 0))
DPI = 300
# Convert px to mm
width_mm = (width_px * 25.4) / DPI > 15
height_mm = (height_px * 25.4) / DPI
# Set new width/height in mm
root.set("width", f"{width_px}mm")
root.set("height", f"{height_px}mm")
os.makedirs(outpath, exist_ok = True)
tree.write(f"{outpath}/{name}")
# combine HTML & data with Jinja templates
def render_posts(path, output_path=OUTPUT_D):
name = Path(path).stem name = Path(path).stem
template = env.select_template([f"{name}.jinja", "post.jinja"])
for filename in os.listdir(path): for filename in os.listdir(path):
file_path = os.path.join(path, filename)
if filename.endswith(".md"): if filename.endswith(".md"):
post_path = os.path.join(path, filename) page = get_page_data(file_path)
page = get_page_data(post_path) render_single_file(page, file_path, f"{output_path}/{name}", name)
render_single_file(template, page, post_path, f"{OUTPUT_D}/{name}", name) elif os.path.isdir(file_path):
render_posts(file_path, f"{output_path}/{name}")
elif filename.endswith(".svg"):
save_circuit_svg(file_path, f"{output_path}/{name}", filename)
else:
print("doing nothing with", filename)
# Pre-load before compiling
def preload_documents(): def preload_documents():
print("preload any needed data") print("preload any needed data")
now = datetime.now() documents["meta"] = {"now": now.strftime("%d %B %Y")}
documents["meta"] = {}
documents["meta"]["now"] = now.strftime("%d %B %Y")
for subdir in os.listdir(CONTENT_D): for subdir in os.listdir(CONTENT_D):
path = os.path.join(CONTENT_D, subdir) path = os.path.join(CONTENT_D, subdir)
print(path)
if os.path.isdir(path): if os.path.isdir(path):
name = Path(path).stem name = Path(path).stem
if name not in documents: documents.setdefault(name, [])
documents[name] = []
files = os.listdir(path) for filename in sorted(os.listdir(path)):
files.sort()
for filename in files:
if filename.endswith(".md"): if filename.endswith(".md"):
post_path = os.path.join(path, filename) documents[name].append(get_page_data(os.path.join(path, filename), isPreload=True))
documents[name].append(get_page_data(post_path, isPreload=True))
elif Path(path).suffix == '.md': elif Path(path).suffix == '.md':
documents[Path(path).stem] = get_page_data(path, isPreload=True) documents[Path(path).stem] = get_page_data(path, isPreload=True)
def copy_assets(): def copy_assets():
if os.path.exists("dist/assets"): if os.path.exists(OUT_ASSETS):
shutil.rmtree("dist/assets") shutil.rmtree(OUT_ASSETS)
shutil.copytree("src/assets", "dist/assets") shutil.copytree(SRC_ASSETS, OUT_ASSETS)
def get_inventory(): def get_inventory():
with open("src/content/component-inventory.csv") as f: with open("src/content/component-inventory.csv") as f:
documents['inventory'] = [] documents['inventory'] = []
for line in csv.DictReader( for line in csv.DictReader(
@ -213,19 +277,14 @@ def main():
get_inventory() get_inventory()
preload_documents() preload_documents()
print("render the content")
for subdir in os.listdir(CONTENT_D): for subdir in os.listdir(CONTENT_D):
path = os.path.join(CONTENT_D, subdir) path = os.path.join(CONTENT_D, subdir)
if os.path.isdir(path): if os.path.isdir(path):
print("rendering posts", path)
render_posts(path) render_posts(path)
elif Path(path).suffix == '.md': elif Path(path).suffix == '.md':
template = env.select_template( render_single_file(get_page_data(path), path, OUTPUT_D)
[f"{Path(path).stem}.jinja", "post.jinja"])
page = get_page_data(path)
render_single_file(template, page, path, OUTPUT_D)
elif Path(path).suffix in [".csv"]: elif Path(path).suffix in [".csv"]:
print("not compiling this file!") print("not compiling this file!")