93 lines
2.5 KiB
Python
93 lines
2.5 KiB
Python
import json
|
|
import os
|
|
from dataclasses import asdict, dataclass, fields
|
|
from os import environ as env
|
|
from pathlib import Path
|
|
from shutil import copytree
|
|
|
|
from moody import render
|
|
from watchdog.events import FileSystemEventHandler
|
|
from watchdog.observers import Observer
|
|
|
|
|
|
def dataclass_from_dict(klass, dikt):
|
|
try:
|
|
fieldtypes = {f.name: f.type for f in fields(klass)}
|
|
return klass(**{f: dataclass_from_dict(fieldtypes[f], dikt[f]) for f in dikt})
|
|
except:
|
|
if isinstance(dikt, (tuple, list)):
|
|
return [dataclass_from_dict(klass.__args__[0], f) for f in dikt]
|
|
return dikt # Not a dataclass field
|
|
|
|
|
|
@dataclass
|
|
class Link:
|
|
href: str
|
|
text: str
|
|
icon: str
|
|
cls: str
|
|
|
|
|
|
@dataclass
|
|
class Data:
|
|
links: list[Link]
|
|
description: str | None = None
|
|
|
|
|
|
def write_files(rendered: str, src_dir: Path, out_dir: Path):
|
|
# Copy the static files
|
|
copytree(src_dir / "www", out_dir, dirs_exist_ok=True)
|
|
|
|
# Write out the index file
|
|
with open(out_dir / "index.html", "w") as fp:
|
|
fp.write(rendered)
|
|
|
|
|
|
def build_project(src_dir: Path, build_dir: Path):
|
|
if not os.path.exists(build_dir):
|
|
os.mkdir(build_dir)
|
|
|
|
data_path = env.get("DATA_FILE", src_dir / "data.json")
|
|
|
|
# Load the data
|
|
with open(data_path) as fp:
|
|
data: Data = dataclass_from_dict(Data, json.load(fp)) # pyright: ignore
|
|
|
|
# Render the template with the correct data
|
|
with open(src_dir / "index.html") as fp:
|
|
rendered = render(fp.read(), links=data.links, description=data.description)
|
|
|
|
write_files(rendered, src_dir, build_dir)
|
|
|
|
|
|
class CatchAllHandler(FileSystemEventHandler):
|
|
def __init__(self, src_dir: Path, build_dir: Path):
|
|
self.src_dir = src_dir
|
|
self.build_dir = build_dir
|
|
self.count = 0
|
|
|
|
def on_modified(self, event):
|
|
print(f"Files changed, rebuilding project [{self.count}]")
|
|
build_project(self.src_dir, self.build_dir)
|
|
self.count += 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
src_dir = Path(__file__).parent.resolve()
|
|
build_dir = Path(env.get("BUILD_DIR", src_dir.parent.resolve() / "build"))
|
|
watch_files = bool(env.get("WATCH_SRC"))
|
|
|
|
build_project(src_dir, build_dir)
|
|
|
|
if watch_files:
|
|
# Create the structure to watch for changes
|
|
observer = Observer()
|
|
observer.schedule(CatchAllHandler(src_dir, build_dir), src_dir, recursive=True)
|
|
observer.start()
|
|
|
|
try:
|
|
while observer.is_alive():
|
|
observer.join()
|
|
finally:
|
|
observer.stop()
|
|
observer.join()
|