feat: flyt sitet fra Astro til Zola

Samme indhold, URL'er og udseende, bygget af en enkelt zola-binær og Tailwind
standalone-CLI uden Node. Kanonisk domæne er asger.weirsoe.dk.

Blogindlæg ligger som page bundles med frontmatter Zola forstår, så de gamle
stempler er ugyldige, indtil scripts/omstempl.py er kørt med PUBLISH_KEY.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Asger Geel Weirsøe
2026-11-01 16:47:08 +01:00
co-authored by Claude Opus 5.5
parent 7e13068dd2
commit e58a11c2b4
159 changed files with 8031 additions and 3574 deletions
+77
View File
@@ -0,0 +1,77 @@
#!/usr/bin/env python3
"""Pinger IndexNow med de sider der er ændret i dette push. Kør efter buildet
(bruger public/sitemap-0.xml). --dry-run viser hvad der ville blive sendt."""
import json
import os
import re
import subprocess
import sys
import urllib.error
import urllib.request
HOST = "asger.weirsoe.dk"
KEY = "b68b31655cb9c1a662d53905dd0b1b06"
ORIGIN = f"https://{HOST}"
def git(*args):
r = subprocess.run(["git", *args], capture_output=True, text=True)
return r.stdout.strip() if r.returncode == 0 else None
def sitemap_urls():
with open("public/sitemap-0.xml") as f:
return set(re.findall(r"<loc>([^<]+)</loc>", f.read()))
def route_for_file(f):
"""Kanonisk form uden afsluttende skråstreg, som i sitemap'et."""
m = re.fullmatch(r"content/(.+?)(/index|/_index|_index)?\.md", f)
if m:
return "/" + m[1].rstrip("/") if m[1] != "_index" else "/"
m = re.fullmatch(r"templates/sider/(.+)\.html", f) or re.fullmatch(r"data/(.+)\.json", f)
if m:
name = {"forside": "", "forside-en": "en", "profiles": "profiler"}.get(m[1], m[1])
return "/en/" + name[:-3] if name.endswith("-en") else "/" + name
return None
def changed_files():
before, sha = os.environ.get("GITHUB_EVENT_BEFORE"), os.environ.get("GITHUB_SHA")
if before and not re.fullmatch(r"0*", before):
d = git("diff", "--name-only", before, sha or "HEAD")
if d is not None:
return d.split("\n") if d else []
d = git("diff", "--name-only", "HEAD~1", "HEAD")
return d.split("\n") if d else None
def main():
files = changed_files()
if files is None:
print("IndexNow: kan ikke bestemme hvad der ændrede sig (shallow clone?), springer over.")
return
valid = sitemap_urls()
urls = sorted({ORIGIN + r for r in map(route_for_file, files) if r} & valid)
if not urls:
print("IndexNow: ingen sider med ændret indhold i dette push, springer over.")
return
print(f"IndexNow: indsender {len(urls)} URL(er):")
for u in urls:
print(" ", u)
if "--dry-run" in sys.argv:
print("IndexNow: --dry-run, sender ikke.")
return
body = {"host": HOST, "key": KEY, "keyLocation": f"{ORIGIN}/{KEY}.txt", "urlList": urls}
req = urllib.request.Request("https://api.indexnow.org/indexnow", data=json.dumps(body).encode(),
headers={"Content-Type": "application/json; charset=utf-8"}, method="POST")
try:
with urllib.request.urlopen(req, timeout=30) as r:
print(f"IndexNow: HTTP {r.status} {r.reason}")
except urllib.error.URLError as e:
# Deployet er allerede ude, så vi fejler ikke buildet.
print(f"IndexNow: afvist: {e}")
if __name__ == "__main__":
main()