feat: describe emulator pages in structured data

This commit is contained in:
Abdessamad Derraz committed 2026-10-17 23:52:50 +02:00
1 parent 43af290102
commit 0a2907bd5f
2 files changed
+70

No files matched your search

+50
View File
@@ -1209,6 +1209,54 @@ def _page_description(markdown: str, relative: Path, title: str) -> str:
return f"{title}: RetroBIOS source-traced retrogaming firmware reference."
# Structured data a page generator knows beyond its text, by page path
# relative to docs/: read by decorate_markdown_pages.
PAGE_DATA: dict[str, dict] = {}
def emulator_structured_data(profile: dict) -> dict:
"""What an emulator page states, for a reader of its JSON-LD.
The block said only the page name: a crawler could not learn which files
the core loads, their hashes, the source read or when.
"""
data: dict = {}
source = profile.get("source")
if isinstance(source, dict):
source = next(iter(source.values()), "")
commit = profile.get("source_commit")
if isinstance(commit, dict):
commit = next(iter(commit.values()), "")
if source:
about = {
"@type": "SoftwareSourceCode",
"name": str(profile.get("emulator", "")),
"codeRepository": str(source),
}
if commit:
about["version"] = str(commit)
data["about"] = about
if profile.get("profiled_date"):
data["dateModified"] = str(profile["profiled_date"])
parts = []
for f in profile.get("files") or []:
if not isinstance(f, dict) or not f.get("name"):
continue
identifiers = []
for field in ("sha1", "sha256", "md5", "crc32"):
values = f.get(field)
for value in values if isinstance(values, list) else [values]:
if value:
identifiers.append(f"{field}:{str(value).lower()}")
part = {"@type": "CreativeWork", "name": str(f.get("path") or f["name"])}
if identifiers:
part["identifier"] = identifiers
parts.append(part)
if parts:
data["hasPart"] = parts
return data
def decorate_markdown_pages(docs: Path) -> None:
"""Add per-page descriptions and machine-readable structured data."""
for path in sorted(docs.rglob("*.md")):
@@ -1244,6 +1292,7 @@ def decorate_markdown_pages(docs: Path) -> None:
"name": SITE_NAME,
"url": SITE_URL,
},
**PAGE_DATA.get(relative.as_posix(), {}),
}
structured_json = json.dumps(
structured, ensure_ascii=False, separators=(",", ":")
@@ -3849,6 +3898,7 @@ def main():
}
for name, profile in public_profiles.items():
page = generate_emulator_page(name, profile, db, consumers, suppl_names)
PAGE_DATA[f"emulators/{name}.md"] = emulator_structured_data(profile)
write_if_changed(str(docs / "emulators" / f"{name}.md"), page)
# Generate cross-reference page
+20
View File
@@ -3623,5 +3623,25 @@ class AFileCardSaysAllItKnows(unittest.TestCase):
self.assertNotIn("more", text)
class EmulatorPagesStateTheirDataForMachines(unittest.TestCase):
"""Every emulator page's JSON-LD differed only by name and url."""
def test_source_pin_date_and_files(self):
from scripts.generate_site import emulator_structured_data
data = emulator_structured_data({
"emulator": "DuckStation", "source": "https://github.com/stenzek/duckstation",
"source_commit": "4122fed9", "profiled_date": "2026-03-23",
"files": [{"name": "scph5501.bin", "md5": "490F666E", "sha1": ["a" * 40]},
{"name": "free.bin"}],
})
self.assertEqual(data["about"]["codeRepository"], "https://github.com/stenzek/duckstation")
self.assertEqual(data["about"]["version"], "4122fed9")
self.assertEqual(data["dateModified"], "2026-03-23")
self.assertEqual(data["hasPart"][0]["identifier"], ["sha1:" + "a" * 40, "md5:490f666e"])
self.assertNotIn("identifier", data["hasPart"][1])
if __name__ == "__main__":
unittest.main()