website/generator/__main__.py

105 lines
3.5 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
from pathlib import Path
import os
import time
def make_absurl_filter(site_conf: any) -> Callable[[str], str]:
return functools.partial(get_absolute_url, site_conf)
class CLI:
@staticmethod
def generate(
base_dir: str = "site", output_dir: str = "_dist", production: bool = False
):
start = time.time()
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": git.get_latest_commit_datetime(base_dir),
}
jinja_env = build_jinja_env(site_config)
# rprint(INFO_LEADER + "Processing content")
process.content(base_dir, html_dir, jinja_env, site_config)
# rprint(INFO_LEADER + "Processing blog")
process.blog(base_dir, html_dir, jinja_env, site_config)
# rprint(INFO_LEADER + "Generating Caddy config")
process.caddy_config(base_dir, output_dir, jinja_env, site_config)
# rprint(INFO_LEADER + "Processing Sass")
process.sass(base_dir, output_dir)
if production:
# rprint(INFO_LEADER + "Compressing PNG")
process.compress_png(output_dir)
# rprint(INFO_LEADER + "Stripping EXIF data")
process.strip_exif(output_dir)
end = time.time()
rprint(INFO_LEADER + f"Finished working in {round(end-start, 3)} seconds")
@staticmethod
def watch(base_dir: str = "site", output_dir: str = "_dist"):
import inotify.adapters
import inotify.constants
import threading
import http.server
if os.path.exists(output_dir):
rprint(WARN_LEADER + f"clobbering {output_dir}")
def run():
if os.path.exists(output_dir):
shutil.rmtree(output_dir)
CLI.generate(base_dir, output_dir=output_dir)
debounced_run = debounce(1)(run)
run()
server = http.server.HTTPServer(
("127.0.0.1", 8000),
lambda a, b, c: http.server.SimpleHTTPRequestHandler(
a, b, c, directory=Path(output_dir) / "html"
),
)
threading.Thread(target=server.serve_forever, daemon=True).start()
i = inotify.adapters.InotifyTree(base_dir, mask=inotify.constants.IN_CLOSE_WRITE|inotify.constants.IN_MOVE|inotify.constants.IN_CREATE|inotify.constants.IN_DELETE)
rprint(INFO_LEADER + f"Listening on http://127.0.0.1:8000")
rprint(INFO_LEADER + f"Watching {base_dir} directory for updates")
for (header, type_names, path, filename) in i.event_gen(yield_nones=False):
rprint(INFO_LEADER + f"Change detected in {path}/{filename}")
debounced_run()
if __name__ == "__main__":
fire.Fire(CLI)