Complete catalog standardization: generations, banners, and Fakemon roster tag.
Adds standardize-vault-pages pipeline, exports intentional empty generations, and refreshes the 396-hack catalog with full banner coverage, status classification, and Fakemon generation tags.
This commit is contained in:
+50
-2
@@ -20,7 +20,50 @@ import enrich_vault as E
|
||||
|
||||
FACTS_GLOB = os.path.join(E.SCRAPE, "web_facts*.json")
|
||||
SCALAR_FIELDS = ["tagline", "developer", "version", "status", "release_date",
|
||||
"base", "platform", "generation", "homepage"]
|
||||
"base", "platform", "generation", "homepage", "source", "fakemon",
|
||||
"banner"]
|
||||
LIST_FIELDS = ["generations"]
|
||||
|
||||
|
||||
def normalize_link_fact(link):
|
||||
if isinstance(link, str):
|
||||
return "Link", link
|
||||
if isinstance(link, dict) and link.get("url"):
|
||||
return link.get("label") or "Link", link["url"]
|
||||
return None
|
||||
|
||||
|
||||
def merge_links_section(body, links):
|
||||
normalized = [x for x in (normalize_link_fact(link) for link in links) if x]
|
||||
if not normalized:
|
||||
return body
|
||||
existing = ""
|
||||
match = re.search(r"(?ms)^## Links\s*\n(.*?)(?=^## |\n\[\[Index|\Z)", body)
|
||||
if match:
|
||||
existing = match.group(1).strip()
|
||||
pairs = []
|
||||
for line in existing.splitlines():
|
||||
url_match = re.search(r"(https?://\S+)", line)
|
||||
if not url_match:
|
||||
continue
|
||||
label_match = re.match(r"^\s*-\s*([^:]+):", line)
|
||||
pairs.append(((label_match.group(1).strip() if label_match else "Link"), url_match.group(1).rstrip(".,)")))
|
||||
pairs.extend(normalized)
|
||||
seen = set()
|
||||
lines = []
|
||||
for label, url in pairs:
|
||||
if url in seen:
|
||||
continue
|
||||
seen.add(url)
|
||||
lines.append(f"- {label}: {url}")
|
||||
return set_section(body, "Links", "\n".join(lines))
|
||||
|
||||
|
||||
def facts_sort_key(path: str) -> int:
|
||||
match = re.search(r"web_facts(\d*)\.json$", os.path.basename(path))
|
||||
if not match or not match.group(1):
|
||||
return 0
|
||||
return int(match.group(1))
|
||||
|
||||
|
||||
def set_section(body, heading, content):
|
||||
@@ -57,6 +100,9 @@ def apply_one(stem, facts):
|
||||
for k in SCALAR_FIELDS:
|
||||
if facts.get(k):
|
||||
fm[k] = facts[k]
|
||||
for k in LIST_FIELDS:
|
||||
if k in facts:
|
||||
fm[k] = facts[k]
|
||||
if facts.get("type"):
|
||||
fm["type"] = facts["type"]
|
||||
fm["tags"] = E.derive_tags(fm)
|
||||
@@ -77,6 +123,8 @@ def apply_one(stem, facts):
|
||||
body = set_section(body, "Features", feats)
|
||||
if facts.get("notability"):
|
||||
body = set_section(body, "Why it stands out", facts["notability"].strip())
|
||||
if facts.get("links"):
|
||||
body = merge_links_section(body, facts["links"])
|
||||
|
||||
return f"---\n{E.emit_fm(fm)}\n---\n{body}", "ok"
|
||||
|
||||
@@ -84,7 +132,7 @@ def apply_one(stem, facts):
|
||||
def main():
|
||||
apply = "--apply" in sys.argv
|
||||
facts = {}
|
||||
for fp in sorted(glob.glob(FACTS_GLOB)):
|
||||
for fp in sorted(glob.glob(FACTS_GLOB), key=facts_sort_key):
|
||||
facts.update(json.load(open(fp, encoding="utf-8")))
|
||||
ok = miss = 0
|
||||
for stem, f in facts.items():
|
||||
|
||||
Reference in New Issue
Block a user