"""generator HTML emitter.
Per BR5.1/BR5.3 (US5/US6): writes a self-contained zero-network newspaper.html,
file:// printable to A4 with margins, clean print. BR5.2: friendly guided
empty-state when no content.
"""
from __future__ import annotations
import html
from pathlib import Path
from .model import Article, Issue, MastheadConfig, Page
def _render_masthead(m: MastheadConfig) -> str:
return (
""
)
def _render_article(a: Article) -> str:
by = f"{html.escape(a.byline)}" if a.byline else ""
return (
f"{html.escape(a.headline)}
{by}"
f"{html.escape(a.body)}
"
)
def _render_page(page: Page, articles_by_id: dict[str, Article]) -> str:
cols = []
for col in page.columns:
cells = []
for item in col.items:
art = articles_by_id.get(item.source_ref)
if art:
cells.append(_render_article(art))
else:
cells.append(f"
({html.escape(item.kind)})
")
cols.append(f"{''.join(cells)}
")
return f"{html.escape(page.running_header)}{''.join(cols)}"
def emit_newspaper(issue: Issue, out_path: Path) -> None:
"""Write the self-contained, zero-network newspaper.html (BR5.1)."""
articles_by_id = {a.article_id: a for a in issue.articles}
pages = "".join(_render_page(p, articles_by_id) for p in issue.pages)
css = (
"@page { size: A4; margin: 15mm; }"
"body { font-family: serif; color: #111827; background: #fbf8f1; margin:0; }"
".masthead { border-bottom: 2px solid #000; margin-bottom: 12px; }"
".masthead h1 { margin: 0; font-size: 2.2em; }"
".meta { margin: 4px 0 8px; }"
".page { page-break-after: always; }"
".col { width: 32%; display: inline-block; vertical-align: top; padding-right: 8px; }"
".running { font-size: .8em; border-bottom: 1px solid #999; margin-bottom: 8px; }"
"@media print { .page { break-after: page; } }"
)
doc = (
""
"Wedding Newspaper"
+ _render_masthead(issue.masthead) + pages + ""
)
out_path.parent.mkdir(parents=True, exist_ok=True)
out_path.write_text(doc, encoding="utf-8")
def emit_empty_state(out_path: Path, masthead: MastheadConfig | None = None) -> None:
"""BR5.2/US10: friendly guided empty-state page with a sample-issue pointer."""
title = masthead.title if masthead else "The Wedding Times"
doc = (
""
"Welcome — Wedding Newspaper"
"Welcome to " + html.escape(title) + "
"
"Add a content/ folder of markdown or txt files and a "
"config.json, then run newspaper generate to "
"produce your paper. Try the sample issue first to see the layout.
"
""
)
out_path.parent.mkdir(parents=True, exist_ok=True)
out_path.write_text(doc, encoding="utf-8")