website/generator/__main__.py
2024-02-11 00:55:23 +00:00

91 lines
3.1 KiB
Python

from rich import print as rprint
import git
from util import *
from jinja2 import Environment, FileSystemLoader, select_autoescape
import fire
from collections.abc import Callable
import process
import functools
import shutil
def make_absurl_filter(site_conf: any) -> Callable[[str], str]:
return functools.partial(get_absolute_url, site_conf)
class CLI:
@staticmethod
def g(*args, **kwargs):
return CLI.generate(*args, **kwargs)
@staticmethod
def generate(base_dir: str, output_dir: str = "_dist"):
base_dir = Path(base_dir)
output_dir = Path(output_dir)
html_dir = output_dir / "html"
if output_dir.exists() and not is_directory_empty(output_dir):
rprint(
WARN_LEADER
+ f"A directory called [bold]{output_dir}[/bold] already exists and is not "
f"empty"
)
with open(base_dir / "config.yml") as f:
site_config = load_yaml(f.read())
assert (
"build" not in site_config
), "build section of site config must not exist so it can be written at runtime"
site_config["build"] = {
"hash": git.get_latest_commit_hash(base_dir)[:7],
"date": datetime.datetime.utcnow(),
}
jinja_env = Environment(
loader=FileSystemLoader("site/content"), autoescape=select_autoescape()
)
jinja_env.filters["absurl"] = make_absurl_filter(site_config)
jinja_env.filters["fmtdate"] = lambda x: x.strftime("%Y-%m-%d")
process.content(base_dir, html_dir, jinja_env, site_config)
process.blog(base_dir, html_dir, jinja_env, site_config)
process.caddy_config(base_dir, output_dir, jinja_env, site_config)
thing_overrides = {"rendered": "page"}
res_parts = []
for (key, count) in get_counts().items():
s = "" if count == 1 else "s"
res_parts.append(f"{key} {count} {thing_overrides.get(key, 'file')}{s}")
rprint(INFO_LEADER + "Finished working, " + ", ".join(res_parts))
@staticmethod
def watch(base_dir: str, output_dir: str = "_dist"):
import pyinotify
if os.path.exists(output_dir):
rprint(WARN_LEADER + f"{output_dir} already exists and will be clobbered when regeneration is triggered")
@debounce(1)
def run():
if os.path.exists(output_dir):
shutil.rmtree(output_dir)
reset_counts() # boys and girls, this is why global state is bad
CLI.generate(base_dir, output_dir=output_dir)
class OnWriteHandler(pyinotify.ProcessEvent):
def process_IN_MODIFY(self, event):
rprint(INFO_LEADER + f"Change detected in {event.pathname}")
run()
wm = pyinotify.WatchManager()
notifier = pyinotify.Notifier(wm, default_proc_fun=OnWriteHandler())
wm.add_watch(base_dir, pyinotify.ALL_EVENTS, rec=True, auto_add=True)
rprint(INFO_LEADER + f"Watching {base_dir}")
notifier.loop()
if __name__ == "__main__":
fire.Fire(CLI)