#!/usr/bin/env python import argparse import copy import os import pathlib import shutil import bs4 import markdown def main(): parser = argparse.ArgumentParser() parser.add_argument("src", help="source directory", nargs="?", default="./src") parser.add_argument("out", help="output directory", nargs="?", default="./out") args = parser.parse_args() src = pathlib.Path(args.src) out = pathlib.Path(args.out) md = markdown.Markdown(extensions=["attr_list", "footnotes", "meta"]) # Clean the output directory if out.exists(): print("Removing ", out) shutil.rmtree(out) # Load the template template = bs4.BeautifulSoup( (src / ".template.html").read_text(encoding="utf8"), features="html.parser") count = 0 for dirpath, _, filenames in os.walk(src): dirpath = pathlib.Path(dirpath).relative_to(src) for filename in filenames: if filename[0] == ".": continue # Skip dotfiles count += 1 # Future-proofing if filename.rsplit(".")[-1] not in ("html", "md", "txt"): raise Exception("Support for this filetype is not yet supported:", filename) path = src / dirpath / filename dest = out / dirpath / filename os.makedirs(dest.parent, exist_ok=True) content = path.read_text(encoding="utf8") meta = {} # Preprocess markdown into html if dest.name.endswith(".md"): print("Converting", path) md.reset() dest = dest.with_suffix(".html") content = md.convert(content) meta = md.Meta if dest.name.endswith("html"): # Inject content into the template page_content = bs4.BeautifulSoup(content, features="html.parser") page = copy.copy(template) article = page.new_tag("article") article.append(page_content) page.article.replace_with(article) # Inject path into the nav for i in range(len(dirpath.parts)): a = page.new_tag("a") a["href"] = "/" + "/".join(dirpath.parts[:i+1]) + "/" a.string = dirpath.parts[i] page.nav.append(a) page.nav.append(page.new_string("/")) # Apply metadata to the template if meta_title := meta.get("title"): title = "".join(meta_title) page.title.string = title page.header.h1.string = title # The fully templated page is the new content content = str(page) # Write the destination file print("Writing ", dest) dest.write_text(content) print("Processed", count, "files") if __name__ == "__main__": main()