Deploy / build (push) Successful in 17s
Every post now carries one unique local-ComfyUI/Ideogram 4 base frame, composited into EN + ZH share cards, a banner and list thumbs. - the shipped prompts_catalog held only 21 distinct metaphors for 72 posts (16 shared one visual), so all 72 were rewritten as unique object+state metaphors and 10 frames re-rolled after OCR found pseudo-text rendered at legible size - render_from_art.mjs emits JPEG by default (558 KB PNG -> 84 KB mozjpeg q85); the ZH 1200x630 card did not exist before this batch - 288 frontmatter fields migrated; the 144 v1 PNGs are gone - PostList's thumb helper keys off the base slug (a ZH card is zh-<slug>.jpg while the thumb is <slug>-800.webp, which 404'd the whole ZH listing) - [...slug].astro's <picture> regex accepts .jpg - the repo now carries the art inputs (metaphors.json, captions/<slug>.json, refreshed prompts_catalog.json) so a frame is reproducible from git alone
74 lines
2.6 KiB
Python
74 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
"""migrate_to_v2_assets.py — point the content at the v2 artwork filenames.
|
|
|
|
The v2 renderer (render_from_art.mjs) writes JPEG/WebP, not PNG:
|
|
public/banners/<slug>.jpg (hero fallback; <picture> derives .webp)
|
|
public/og/<slug>.jpg (EN share card)
|
|
public/og/zh-<slug>.jpg (ZH share card)
|
|
|
|
Until this migration runs, every page still points at the v1 PNG paths, so it has
|
|
to happen in the SAME commit as the images or the site serves 404 heroes.
|
|
|
|
Idempotent: it only rewrites values that still look like the v1 paths, keeps each
|
|
file's quoting style, and prints what it changed. Run with --write to apply.
|
|
|
|
python scripts/og-gen/migrate_to_v2_assets.py # report only
|
|
python scripts/og-gen/migrate_to_v2_assets.py --write
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import re
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
POSTS = ROOT / "src" / "content" / "posts"
|
|
ZH = POSTS / "zh"
|
|
|
|
# ogImage: "/og/<slug>.png" or ogImage: /og/<slug>.png (quotes optional)
|
|
OG_RE = re.compile(r'^(ogImage:[ \t]*)(?P<q>"?)/og/(?P<name>[a-z0-9-]+)\.png(?P=q)[ \t]*$', re.M)
|
|
BANNER_RE = re.compile(r'^(banner:[ \t]*)(?P<q>"?)/banners/(?P<name>[a-z0-9-]+)\.png(?P=q)[ \t]*$', re.M)
|
|
|
|
|
|
def migrate(path: Path, zh: bool, write: bool) -> list[str]:
|
|
text = path.read_text(encoding="utf-8")
|
|
slug = path.stem
|
|
changes: list[str] = []
|
|
|
|
def og_sub(m: re.Match) -> str:
|
|
target = f"/og/zh-{slug}.jpg" if zh else f"/og/{slug}.jpg"
|
|
changes.append(f"ogImage {m.group(3)}.png -> {target}")
|
|
return f"{m.group(1)}{m.group('q')}{target}{m.group('q')}"
|
|
|
|
def banner_sub(m: re.Match) -> str:
|
|
target = f"/banners/{slug}.jpg"
|
|
changes.append(f"banner {m.group(3)}.png -> {target}")
|
|
return f"{m.group(1)}{m.group('q')}{target}{m.group('q')}"
|
|
|
|
new = OG_RE.sub(og_sub, text)
|
|
new = BANNER_RE.sub(banner_sub, new)
|
|
if new != text and write:
|
|
path.write_text(new, encoding="utf-8")
|
|
return changes
|
|
|
|
|
|
def main() -> None:
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--write", action="store_true")
|
|
args = ap.parse_args()
|
|
|
|
total = 0
|
|
files_changed = 0
|
|
for folder, zh in ((POSTS, False), (ZH, True)):
|
|
for p in sorted(folder.glob("*.md")):
|
|
ch = migrate(p, zh, args.write)
|
|
if ch:
|
|
files_changed += 1
|
|
total += len(ch)
|
|
print(f"{'WROTE' if args.write else 'would'} {p.relative_to(ROOT)}: " + "; ".join(ch))
|
|
print(f"\n{files_changed} files, {total} field(s) {'' if args.write else '(report only — pass --write)'}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|