# Copyright (C) 2023-2024 Tomasz Kramkowski # SPDX-License-Identifier: MIT """A basic static site generator""" __version__ = "0.4.0" import sys from argparse import ArgumentParser, BooleanOptionalAction, Namespace from collections.abc import Callable from pathlib import Path from typing import Any import jinja2 import tomllib from jinja2 import Environment, FileSystemLoader def parse_args( p: ArgumentParser = ArgumentParser(), argv: list[str] = sys.argv ) -> Namespace: p.add_argument( "-o", "--output", default=Path("output"), help="Output directory", type=Path ) p.add_argument("-p", "--prefix", default="", help="href prefix") p.add_argument( "--minify", default=True, action=BooleanOptionalAction, help="minify output" ) return p.parse_args(argv[1:]) class Generator: output: Path minify: bool minifiers: dict[str, Callable[[str | bytes], str | bytes]] env: Environment def __init__(self, args: Namespace) -> None: self.output = args.output self.minify = args.minify self.minifiers = dict() self.env = Environment( loader=FileSystemLoader("."), autoescape=jinja2.select_autoescape() ) self.env.globals[ # pyright: ignore [reportUnknownMemberType] "prefix" ] = args.prefix def write(self, dest: str, content: str | bytes) -> None: dest_path: Path = self.output / Path(dest) if self.minify and dest_path.suffix and dest_path.suffix in self.minifiers: content = self.minifiers[dest_path.suffix](content) dest_path.parent.mkdir(parents=True, exist_ok=True) with open(dest_path, "wb") as f: if isinstance(content, str): content = content.encode() f.write(content) def copy(self, dest: str, source: str | None = None) -> None: if source is None: source = dest with open(source, "rb") as f: self.write(dest, f.read()) def generate( self, dest: str, template: str | None = None, env: dict[str, Any] = dict() ) -> None: if template is None: template = dest self.write(dest, self.env.get_template(template).render(**env)) def parse(source: str | Path) -> dict[str, Any]: with open(source) as f: toml, content = f.read().split("\n\n", maxsplit=1) vars = tomllib.loads(toml) vars["content"] = content return vars