summaryrefslogtreecommitdiffstats
path: root/ssg/__init__.py
blob: c1c7d91235252a8c580e22eda04c1648e36a523b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/usr/bin/env python3

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