import argparse import datetime from dataclasses import dataclass from pathlib import Path from typing import NamedTuple from typing import Optional from typing import Sequence from typing import Union import jinja2 import marshmallow as msh import ruamel.yaml yaml = ruamel.yaml.YAML(typ="safe") @dataclass class MediaContainer: title: str asset: str anchor: Optional[Union[str, int]] = None source: Optional[str] = None content: Optional[str] = None hide_source: bool = False class MediaSerializer(msh.Schema): title = msh.fields.String() asset = msh.fields.URL() anchor = msh.fields.String(required=False) source = msh.fields.URL(required=False) content = msh.fields.String(required=False) hide_source = msh.fields.Boolean(required=False) @dataclass class LinkContainer: link: str title: Optional[str] = None icon: Optional[str] = None class LinkSerializer(msh.Schema): link = msh.fields.URL() title = msh.fields.String(required=False) icon = msh.fields.String(required=False) class Location(NamedTuple): title: str link: str class LocationSeralizer(msh.Schema): title = msh.fields.String() link = msh.fields.URL() @dataclass class PostContainer: title: str location: Location date: datetime.date banner: str media: Sequence[MediaContainer] links: Sequence[LinkContainer] = () slug: Optional[str] = None class PostSerializer(msh.Schema): title = msh.fields.String() location = msh.fields.Nested(LocationSeralizer) date = msh.fields.Date() banner = msh.fields.URL() slug = msh.fields.String(required=False) links = msh.fields.List(msh.fields.Nested(LinkSerializer), required=False) media = msh.fields.List() def get_args() -> argparse.Namespace: parser = argparse.ArgumentParser() parser.add_argument( "-c", "--check", action="store_true", help="Check the config without building" ) return parser.parse_args() def main(): cwd = Path.cwd().resolve() output = cwd / "explore" with (cwd / "config.yaml").open() as infile: config = yaml.load(infile) env = jinja2.Environment( loader=jinja2.FileSystemLoader(str(cwd / "templates")), autoescape=jinja2.select_autoescape(["html", "xml"]), ) if not output.exists(): output.mkdir() index = env.get_template("index.html.j2").render(config=config) with (output / "index.html").open("w") as outfile: outfile.write(index) post_template = env.get_template("post.html.j2") for post_data in config["posts"]: post = post_template.render(post=post_data) with (output / f"{post_data['slug']}.html").open("w") as outfile: outfile.write(post) nginx = env.get_template("nginx.conf.d.j2").render(config=config) with (cwd / "nginx.conf").open("w") as outfile: outfile.write(nginx) if __name__ == "__main__": main()