feat: Archiv-Backfill, responsive Bilder und Site-Meta
Ergänzt Backfill- und Hilfsskripte, erzeugt nach der Pixazo-Generierung komprimierte srcset-Varianten, validiert leere Bilder und fügt Favicon, Web Manifest sowie Open-Graph-/Twitter-Tags in die Templates ein. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+38
-8
@@ -15,6 +15,7 @@ import requests
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
|
||||
import topics
|
||||
from images import create_responsive_variants, load_image_descriptor
|
||||
|
||||
GERMAN_MONTHS = [
|
||||
"Januar",
|
||||
@@ -205,7 +206,7 @@ def generate_hero_image(
|
||||
date_iso: str,
|
||||
prompt: str,
|
||||
negative_prompt: str,
|
||||
) -> str | None:
|
||||
) -> dict[str, str] | None:
|
||||
try:
|
||||
response = requests.post(
|
||||
"https://gateway.pixazo.ai/getImage/v1/getSDXLImage",
|
||||
@@ -233,12 +234,18 @@ def generate_hero_image(
|
||||
|
||||
img_response = requests.get(image_url, timeout=120)
|
||||
img_response.raise_for_status()
|
||||
if len(img_response.content) < 50_000:
|
||||
log(
|
||||
f"warning: hero image for {date_iso} too small "
|
||||
f"({len(img_response.content)} bytes), discarding"
|
||||
)
|
||||
return None
|
||||
|
||||
img_dir = site_dir / "img"
|
||||
img_dir.mkdir(parents=True, exist_ok=True)
|
||||
img_path = img_dir / f"{date_iso}.jpg"
|
||||
img_path.write_bytes(img_response.content)
|
||||
return f"/img/{date_iso}.jpg"
|
||||
return create_responsive_variants(img_dir, date_iso)
|
||||
except (requests.RequestException, OSError, KeyError, TypeError, ValueError) as exc:
|
||||
log(f"warning: hero image generation failed: {exc}")
|
||||
return None
|
||||
@@ -252,7 +259,8 @@ def render_template(name: str, context: dict) -> str:
|
||||
return env.get_template(name).render(**context)
|
||||
|
||||
|
||||
def build_archiv_entries(archive: list[dict]) -> list[dict]:
|
||||
def build_archiv_entries(archive: list[dict], site_dir: Path) -> list[dict]:
|
||||
img_dir = site_dir / "img"
|
||||
entries = []
|
||||
for item in sorted(archive, key=lambda e: e["date"], reverse=True):
|
||||
prompts = item.get("prompts")
|
||||
@@ -263,7 +271,9 @@ def build_archiv_entries(archive: list[dict]) -> list[dict]:
|
||||
"backronym": item["backronym"],
|
||||
"tagline": item["tagline"],
|
||||
"url": f"/archiv/{item['date']}.html",
|
||||
"image": f"/img/{item['date']}.jpg" if item.get("has_image") else None,
|
||||
"image": load_image_descriptor(img_dir, item["date"])
|
||||
if item.get("has_image")
|
||||
else None,
|
||||
"topics": item.get("topics", []),
|
||||
"prompts": prompts if isinstance(prompts, dict) else None,
|
||||
}
|
||||
@@ -323,18 +333,26 @@ def main() -> int:
|
||||
log("PIXAZO_API_KEY not set, skipping hero image")
|
||||
|
||||
human_date = date_human(today)
|
||||
startup_context = {
|
||||
startup_base = {
|
||||
"date": date_iso,
|
||||
"date_human": human_date,
|
||||
"theme": theme,
|
||||
"hero_image": hero_image,
|
||||
"s": llm_json,
|
||||
"site_url": os.environ.get("SITE_URL", "https://mobea.de"),
|
||||
}
|
||||
startup_html = render_template("startup.html.j2", startup_context)
|
||||
startup_html = render_template(
|
||||
"startup.html.j2",
|
||||
{**startup_base, "canonical_path": "/"},
|
||||
)
|
||||
archiv_day_html = render_template(
|
||||
"startup.html.j2",
|
||||
{**startup_base, "canonical_path": f"/archiv/{date_iso}.html"},
|
||||
)
|
||||
|
||||
archiv_day_path = site_dir / "archiv" / f"{date_iso}.html"
|
||||
write_text_atomic(index_path, startup_html)
|
||||
write_text_atomic(archiv_day_path, startup_html)
|
||||
write_text_atomic(archiv_day_path, archiv_day_html)
|
||||
log(f"wrote {index_path} and {archiv_day_path}")
|
||||
|
||||
archive_entry = {
|
||||
@@ -357,9 +375,21 @@ def main() -> int:
|
||||
save_json_atomic(data_dir / "archive.json", archive)
|
||||
log(f"updated {data_dir / 'archive.json'}")
|
||||
|
||||
latest_image = next(
|
||||
(
|
||||
f"/img/{entry['date']}.jpg"
|
||||
for entry in sorted(archive, key=lambda e: e["date"], reverse=True)
|
||||
if entry.get("has_image")
|
||||
),
|
||||
"/og-default.jpg",
|
||||
)
|
||||
archiv_html = render_template(
|
||||
"archiv.html.j2",
|
||||
{"entries": build_archiv_entries(archive)},
|
||||
{
|
||||
"entries": build_archiv_entries(archive, site_dir),
|
||||
"site_url": os.environ.get("SITE_URL", "https://mobea.de"),
|
||||
"og_image": latest_image,
|
||||
},
|
||||
)
|
||||
write_text_atomic(site_dir / "archiv" / "index.html", archiv_html)
|
||||
log(f"wrote {site_dir / 'archiv' / 'index.html'}")
|
||||
|
||||
Reference in New Issue
Block a user