#!/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("out", help="output directory") args = parser.parse_args() src = pathlib.Path("src") out = pathlib.Path(args.out) md = markdown.Markdown(extensions=["attr_list", "footnotes", "md_in_html", "meta"]) comment_md = markdown.Markdown() # 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 path = src / dirpath / filename dest = out / dirpath / filename os.makedirs(dest.parent, exist_ok=True) # Copy any file types without content processing if filename.rsplit(".")[-1] not in ("md",): print("Copying ", path) shutil.copyfile(path, dest) continue # Preprocess markdown into html if dest.name.endswith(".md"): print("Converting", path) md.reset() dest = dest.with_suffix(".html") content = md.convert(path.read_text(encoding="utf8")) meta = md.Meta or {} # 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) # Rewrite links with markdown extensions for a in page.css.select("a[href]"): if a["href"].endswith(".md"): a["href"] = a["href"][:-3] + ".html" # 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"): page.title.string = meta_title[0] page.header.h1.string = meta_title[0] if meta_date := meta.get("date"): p = page.new_tag("p") p["class"] = "metadata" p.string = "Date: " + meta_date[0] page.header.append(p) if meta_author := meta.get("author"): p = page.new_tag("p") p["class"] = "metadata" p.string = "Author: " + meta_author[0] page.header.append(p) if meta_source := meta.get("source"): for source_url in meta_source: a = page.new_tag("a") a["href"] = source_url a.string = source_url p = page.new_tag("p") p["class"] = "metadata" p.string = "URL: " p.append(a) page.header.append(p) if meta_comment := meta.get("comment"): for comment in meta_comment: aside = page.new_tag("aside") html = bs4.BeautifulSoup(comment_md.convert(comment), features="html.parser") aside.extend(html.p.contents) page.header.append(aside) # Write the fully templated page print("Writing ", dest) dest.write_text(str(page)) print("Processed", count, "files") if __name__ == "__main__": main()