120 lines
4.2 KiB
Python
Executable File
120 lines
4.2 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"])
|
|
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()
|