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) 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
|