97 lines
3.0 KiB
Python
Executable File
97 lines
3.0 KiB
Python
Executable File
#!/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", "md_in_html", "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
|
|
|
|
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 ("html", "md"):
|
|
print("Copying ", path)
|
|
shutil.copyfile(path, dest)
|
|
continue
|
|
|
|
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()
|