From 2e2ab76e994f4422d7496b9ff3742c43f3fdbab0 Mon Sep 17 00:00:00 2001 From: blissful Date: Sat, 22 Jun 2024 21:54:22 -0400 Subject: [PATCH] add atom feed --- Makefile | 2 +- flake.nix | 1 + scripts/build.py | 61 ++++++++++++++++++++++++++++++++++------ src/index.jinja | 8 ++++-- src/posts/index.json | 2 +- src/posts/template.jinja | 2 +- 6 files changed, 62 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 7140ca9..511c7a9 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ watch: make build echo "Started watcher..." while true; do \ - inotifywait -qr -e modify -e create -e delete -e move --include 'src/.*$$' .; \ + inotifywait -qr -e modify -e create -e delete -e move --include 'src/.*$$' --include 'scripts/.*$$' .; \ make build; \ done diff --git a/flake.nix b/flake.nix index 7cd514d..60d598e 100644 --- a/flake.nix +++ b/flake.nix @@ -26,6 +26,7 @@ }; py = pkgs.python311.withPackages (ps: with ps; [ jinja2 + pytz ]); shellHook = '' find-up () { diff --git a/scripts/build.py b/scripts/build.py index bb6eab8..6f189ff 100755 --- a/scripts/build.py +++ b/scripts/build.py @@ -1,40 +1,40 @@ #!/usr/bin/env python3 from __future__ import annotations + import json import os import shutil import subprocess import tempfile +import dataclasses + from datetime import datetime from pathlib import Path -import dataclasses from typing import Any +from xml.etree.ElementTree import Element, SubElement, ElementTree import jinja2 # type: ignore +import pytz # type: ignore -def formatdate(x: str) -> str: - """Convert 2024/06/08 to June 8, 2024""" - dt = datetime.strptime(x, "%Y-%m-%d") - return dt.strftime("%B %-d, %Y") +je = jinja2.Environment() -je = jinja2.Environment() -je.filters["formatdate"] = formatdate +# DATA @dataclasses.dataclass class PostMeta: title: str - date: str + timestamp: datetime public: bool @classmethod def parse(cls, d: dict[str, Any]) -> PostMeta: return cls( title=d["title"], - date=d["date"], + timestamp=datetime.fromisoformat(d["timestamp"]), public=d["public"], ) @@ -42,6 +42,25 @@ def parse(cls, d: dict[str, Any]) -> PostMeta: PostIndex = dict[str, PostMeta] +# UTILS + + +def site_updated_at() -> datetime: + r = subprocess.run(["git", "log", "-1", "--format=%cI"], capture_output=True, text=True) + text = r.stdout.strip() + return datetime.fromisoformat(text).astimezone(pytz.utc) + + +def article_updated_at(slug: str) -> datetime: + p = f"src/posts/tex/{slug}.tex" + r = subprocess.run(["git", "log", "-1", "--format=%cI", p], capture_output=True, text=True) + text = r.stdout.strip() + return datetime.fromisoformat(text).astimezone(pytz.utc) + + +# BUILD STEPS + + def empty_dist() -> None: # Removing and recreating the directory messes with the `make watch+serve` workflow. So we # instead empty the directory each time if it already exists. @@ -118,6 +137,29 @@ def compile_posts(posts: PostIndex): fp.write(post) +def compile_feed(posts: PostIndex): + # fmt: off + feed = Element("feed", xmlns="http://www.w3.org/2005/Atom") + SubElement(feed, "title", text="sunsetglow") + SubElement(feed, "link", href="https://sunsetglow.net/atom.xml", rel="self", type="application/atom+xml") + SubElement(feed, "link", href="https://sunsetglow.net/", rel="alternate", type="text/html") + SubElement(feed, "updated", text=site_updated_at().isoformat()) + SubElement(feed, "id", text="tag:sunsetglow.net,2024:site") + + for slug, meta in posts.items(): + post = SubElement(feed, "entry") + SubElement(post, "id", text=f"tag:sunsetglow.net,{meta.timestamp.isoformat()}:{slug}") + SubElement(post, "link", text=f"https://sunsetglow.net/posts/{slug}.html", type="text/html") + SubElement(post, "title", text=meta.title) + SubElement(post, "published", text=meta.timestamp.isoformat()) + SubElement(post, "updated", text=article_updated_at(slug).isoformat()) + # fmt: on + + tree = ElementTree(feed) + with open("dist/atom.xml", "wb") as fh: + tree.write(fh, encoding="utf-8", xml_declaration=True) + + def main(): os.chdir(os.environ["PROJECT_ROOT"]) @@ -128,6 +170,7 @@ def main(): shutil.copytree("src/assets", "dist/assets") compile_index(posts) compile_posts(posts) + compile_feed(posts) if __name__ == "__main__": diff --git a/src/index.jinja b/src/index.jinja index 7e7a7d4..b2db182 100644 --- a/src/index.jinja +++ b/src/index.jinja @@ -5,11 +5,12 @@ + sunset glow
-
sunset glow
+
sunset glow (feed)
About:
    @@ -30,7 +31,10 @@
    Writing:
diff --git a/src/posts/index.json b/src/posts/index.json index cb710c5..f1b4b2d 100644 --- a/src/posts/index.json +++ b/src/posts/index.json @@ -1,7 +1,7 @@ { "frontend-build-systems": { "title": "Exposition of Frontend Build Systems", - "date": "2024-06-08", + "timestamp": "2024-06-08T03:46:00Z", "public": true } } diff --git a/src/posts/template.jinja b/src/posts/template.jinja index 80d4642..95f020f 100644 --- a/src/posts/template.jinja +++ b/src/posts/template.jinja @@ -14,7 +14,7 @@
{{ meta.title }}
-
{{ meta.date | formatdate }}
+
{{ meta.timestamp.strftime("%B %-d, %Y") }}