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:
co-authored by
Claude Opus 5.5
parent
7e13068dd2
commit
e58a11c2b4
Executable
+61
@@ -0,0 +1,61 @@
|
||||
"""Godkendelsesstemplet på blogindlæg: HMAC-SHA256 over sti, indhold og billeder.
|
||||
|
||||
canonical() skal matche godkendelsestjenesten (service/app.py i agw/pw-drafts) byte for byte.
|
||||
"""
|
||||
import hashlib
|
||||
import hmac
|
||||
import os
|
||||
import re
|
||||
|
||||
BLOG = "content/blog"
|
||||
|
||||
|
||||
def canonical(rel, text, assets=()):
|
||||
"""assets: [(sti, sha256-hex)] for billederne i bundlen, sorteret efter sti."""
|
||||
lines = text.replace("\r\n", "\n").split("\n")
|
||||
if lines and lines[0] == "---" and "---" in lines[1:]:
|
||||
end = lines.index("---", 1)
|
||||
lines = [l for i, l in enumerate(lines) if not (0 < i < end and re.match(r"\s*godkendt:", l))]
|
||||
return f"{rel}\n" + "\n".join(lines) + "".join(f"\n@asset {p} {h}" for p, h in assets)
|
||||
|
||||
|
||||
def sign(key, rel, text, assets=()):
|
||||
return "v1:" + hmac.new(key, canonical(rel, text, assets).encode(), hashlib.sha256).hexdigest()
|
||||
|
||||
|
||||
def sha256_file(path):
|
||||
with open(path, "rb") as f:
|
||||
return hashlib.sha256(f.read()).hexdigest()
|
||||
|
||||
|
||||
def assets_for(slug):
|
||||
"""Alt i bundlen ud over index.md er billeder, og de ligger fladt."""
|
||||
d = f"{BLOG}/{slug}"
|
||||
out = []
|
||||
for name in os.listdir(d):
|
||||
if name == "index.md":
|
||||
continue
|
||||
p = f"{d}/{name}"
|
||||
if not os.path.isfile(p):
|
||||
raise ValueError(f"{p}: undermapper understøttes ikke")
|
||||
if name.endswith(".md"):
|
||||
raise ValueError(f"{p}: kun index.md må være markdown i en bundle")
|
||||
out.append((p, sha256_file(p)))
|
||||
return sorted(out)
|
||||
|
||||
|
||||
def read_text(path):
|
||||
with open(path, "rb") as f:
|
||||
return f.read().decode()
|
||||
|
||||
|
||||
def stamp_of(text):
|
||||
"""(stempel eller None, om indlægget er markeret draft: true)"""
|
||||
lines = text.replace("\r\n", "\n").split("\n")
|
||||
end = lines.index("---", 1) if lines[0] == "---" and "---" in lines[1:] else -1
|
||||
if end < 0:
|
||||
return None, False
|
||||
fm = lines[1:end]
|
||||
g = next((l for l in fm if re.match(r"\s*godkendt:", l)), None)
|
||||
draft = any(re.fullmatch(r"draft:\s*true\s*", l) for l in fm)
|
||||
return (re.sub(r"^\s*godkendt:\s*", "", g).strip("'\"") if g else None), draft
|
||||
Reference in New Issue
Block a user