diff options
Diffstat (limited to 'ssg.py')
-rw-r--r-- | ssg.py | 71 |
1 files changed, 71 insertions, 0 deletions
@@ -0,0 +1,71 @@ +"""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(), argv=sys.argv): + 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["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 |