81 lines
3.3 KiB
Python
81 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
build_listings.py -- keep the homepage "Latest news" in sync with the News hub.
|
|
|
|
Problem it solves: the landing page's "Latest news" block used to be a separate
|
|
hard-coded copy, so editing the News page never updated the homepage.
|
|
|
|
Source of truth = each language's News hub (`<lang>/news/index.html`), which is
|
|
edited by hand (it may include curated teaser cards without a detail page).
|
|
This script copies the first 3 News-hub cards into the homepage's "Latest news"
|
|
block, converting them to the homepage card format and fixing relative paths.
|
|
|
|
Run after editing any News page:
|
|
|
|
python tools/build_listings.py
|
|
|
|
Idempotent and safe to re-run. The homepage block is wrapped in
|
|
<!-- AUTO-LATEST-NEWS:START/END --> markers.
|
|
"""
|
|
import io, os, re
|
|
|
|
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
LANGS = ("en", "mk", "si")
|
|
N_LATEST = 3
|
|
|
|
CARD_RE = re.compile(r'<article class="newshub-card".*?</article>', re.DOTALL)
|
|
EXCERPT_RE = re.compile(r'\s*<p class="newshub-excerpt">.*?</p>', re.DOTALL)
|
|
# homepage .news-articles content, anchored by the trailing "See all" button
|
|
LANDING_RE = re.compile(
|
|
r'(<div class="news-articles">)(.*?)(</div>\s*<a href="[^"]*" class="btn btn-secondary">)',
|
|
re.DOTALL,
|
|
)
|
|
|
|
|
|
def hub_to_landing(card):
|
|
"""Convert one News-hub card to the homepage news-card format."""
|
|
card = EXCERPT_RE.sub("", card) # homepage cards have no excerpt
|
|
card = (card
|
|
.replace('class="newshub-card"', 'class="news-card"')
|
|
.replace('class="newshub-media"', 'class="news-card-media"')
|
|
.replace('class="newshub-body"', 'class="card-content"')
|
|
.replace('class="newshub-date"', 'class="author"'))
|
|
# homepage is one directory shallower than the News hub
|
|
card = card.replace('href="../../', 'href="../').replace('src="../../', 'src="../')
|
|
return card.strip()
|
|
|
|
|
|
def sync_lang(lang):
|
|
hub_path = os.path.join(ROOT, lang, "news", "index.html")
|
|
home_path = os.path.join(ROOT, lang, "index.html")
|
|
if not (os.path.exists(hub_path) and os.path.exists(home_path)):
|
|
print(f" [{lang}] skipped (missing news hub or homepage)")
|
|
return 0
|
|
|
|
hub = io.open(hub_path, encoding="utf-8").read()
|
|
cards = CARD_RE.findall(hub)[:N_LATEST]
|
|
if not cards:
|
|
print(f" [{lang}] no News-hub cards found")
|
|
return 0
|
|
|
|
inner = "\n".join(" " + hub_to_landing(c) for c in cards)
|
|
block = ("\n <!-- AUTO-LATEST-NEWS:START (generated from "
|
|
f"{lang}/news/ by tools/build_listings.py — edit the News page, not here) -->\n"
|
|
f"{inner}\n"
|
|
" <!-- AUTO-LATEST-NEWS:END -->\n ")
|
|
|
|
home = io.open(home_path, encoding="utf-8").read()
|
|
if not LANDING_RE.search(home):
|
|
print(f" [{lang}] could not find the homepage 'Latest news' block")
|
|
return 0
|
|
home = LANDING_RE.sub(lambda m: m.group(1) + block + m.group(3), home, count=1)
|
|
io.open(home_path, "w", encoding="utf-8", newline="").write(home)
|
|
print(f" [{lang}] homepage 'Latest news' <- {len(cards)} cards from the News hub")
|
|
return len(cards)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("Syncing homepage 'Latest news' from each News hub:")
|
|
total = sum(sync_lang(l) for l in LANGS)
|
|
print(f"Done ({total} cards written).")
|