#!/usr/bin/env python3 """ Assemble a Roux issue's Hugo page bundles from a prompts JSON file. python3 scripts/build-issue.py --issue 02 --prompts data/prompts/issue-02.json Reads an array of objects with keys: slug, title, description, category, tags[], prompt, featured (optional bool) Writes content/posts///index.md for each, with plate numbers assigned by stable sort on slug (matches scripts/import-posts.py). Frontmatter shape mirrors the existing issue-01 bundles. `featured` comes from the JSON, so re-runs never lose the homepage flags (unlike issue 01's hand-added ones). Images are expected at content/posts///.png (written there by scripts/generate-images.py). Pass --images DIR to copy them in from a staging dir that holds either .png or /.png. """ import argparse import json import shutil from pathlib import Path SITE = Path(__file__).resolve().parent.parent def norm_desc(desc: str) -> str: desc = desc.strip() if desc: desc = desc[0].upper() + desc[1:] if not desc.endswith((".", "!", "?")): desc += "." return desc.replace('"', '\\"') def main() -> int: ap = argparse.ArgumentParser() ap.add_argument("--issue", required=True) ap.add_argument("--prompts", required=True, type=Path) ap.add_argument("--images", type=Path, help="staging dir to copy .png from") args = ap.parse_args() content = SITE / "content" / "posts" / args.issue content.mkdir(parents=True, exist_ok=True) entries = json.loads(args.prompts.read_text(encoding="utf-8")) entries.sort(key=lambda e: e["slug"]) missing_img = [] for idx, entry in enumerate(entries, start=1): slug = entry["slug"] plate = f"{idx:03d}" title = entry["title"].strip().replace('"', '\\"') desc = norm_desc(entry["description"]) cat = (entry.get("category") or "Uncategorised").strip() tags = [t.strip() for t in entry.get("tags", []) if t.strip()] bundle = content / slug bundle.mkdir(exist_ok=True) img_name = f"{slug}.png" dst_img = bundle / img_name if args.images and not dst_img.exists(): for cand in (args.images / img_name, args.images / slug / img_name): if cand.is_file(): shutil.copy2(cand, dst_img) break if not dst_img.exists(): missing_img.append(slug) cats_yaml = f' - "{cat}"' tags_yaml = "\n".join(f' - "{t}"' for t in tags) if tags else " []" featured_yaml = "\nfeatured: true" if entry.get("featured") else "" md = f"""--- title: "{title}" description: "{desc}" plate: "{plate}" slug: "{slug}" issues: - "{args.issue}" image: "{img_name}" weight: {idx}{featured_yaml} categories: {cats_yaml} tags: {tags_yaml} --- """ (bundle / "index.md").write_text(md, encoding="utf-8") print(f"Wrote {len(entries)} bundles to {content}") if missing_img: print(f"WARNING: {len(missing_img)} bundles have no image yet: " + ", ".join(missing_img[:10]) + ("…" if len(missing_img) > 10 else "")) return 0 if __name__ == "__main__": raise SystemExit(main())