"""File cards and install boxes read at a glance (density round, 2026-10-27). A system page wrote every setup's install command for each console, twice: 12 long lines for the PSP. A file card showed four full hashes, the collection path and the catalogue records before the next file. Now a box shows one command for the setup picked, and a card shows the name, the size, the download, a short SHA1, the setups and the emulators. The rest sits in closed folds, every fact still on the page. """ from __future__ import annotations import re import sys import types import unittest from html.parser import HTMLParser from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(REPO_ROOT / "scripts")) import generate_site as gs # noqa: E402 import sitemarkup as markup # noqa: E402 from cross_reference import FileConsumers # noqa: E402 DIST = REPO_ROOT / "website" / "dist" SITE_TS = REPO_ROOT / "website" / "src" / "scripts" / "site.ts" SHA1 = "30a33f3651f8e1b0967a5dfe6ff714baebcce41a" MD5 = "866855cc330b9b95cc69135fb7b41d38" CRC32 = "7b57fa78" SHA256 = "3ab7fcf6956d0281ada94d501fc6d1cfa8fc034f139e25fed6c829f723d92a95" class _Visible(HTMLParser): """Words shown before any fold is opened: text outside closed details (their summary counts), hidden elements, scripts and styles.""" VOID = {"br", "img", "input", "wbr", "hr", "meta", "link", "source"} def __init__(self) -> None: super().__init__(convert_charrefs=True) self.stack: list[tuple[str, object]] = [] self.hidden = 0 self.words: list[str] = [] def handle_starttag(self, tag: str, attrs: list) -> None: if tag in self.VOID: return names = dict(attrs) if tag == "summary" and self.stack and self.stack[-1] == ("details", True): self.hidden -= 1 self.stack.append((tag, "shown")) return hides = tag in ("script", "style") or "hidden" in names or ( tag == "details" and "open" not in names) self.hidden += hides self.stack.append((tag, hides)) def handle_endtag(self, tag: str) -> None: while self.stack: name, hides = self.stack.pop() if hides == "shown": self.hidden += 1 elif hides: self.hidden -= 1 if name == tag: break def handle_data(self, data: str) -> None: if not self.hidden: self.words += data.split() def visible_words(html_text: str) -> list[str]: parser = _Visible() parser.feed(html_text) return parser.words def _main(page: str) -> str: text = (DIST / page / "index.html").read_text(encoding="utf-8") return text[text.index("")] def _card_consumers(sha1: str) -> types.SimpleNamespace: return types.SimpleNamespace( platforms={sha1: {"batocera", "retroarch"}}, emulators={sha1: {"ppsspp"}}, platform_systems={sha1: {"batocera": {"sony-psp"}, "retroarch": {"sony-psp"}}}, platform_destinations={sha1: {"batocera": {"psp/ppge_atlas.zim"}, "retroarch": {"PPSSPP/ppge_atlas.zim"}}}, installed={sha1: {"knulli": {"PPSSPP/ppge_atlas.zim"}}}, emulator_entries={}, emulator_files={}, ) def _card() -> dict: return {"name": "ppge_atlas.zim", "sha1": SHA1, "md5": MD5, "crc32": CRC32, "sha256": SHA256, "size": 666539, "path": "bios/Sony/PlayStation Portable/ppge_atlas.zim", "provenance": {"tosec": {"name": "ppge_atlas (PPSSPP).zim"}}} class ASystemCardShowsTheAnswerFirst(unittest.TestCase): def setUp(self) -> None: self.lines = gs._system_file_card(_card(), _card_consumers(SHA1)) self.text = "\n".join(self.lines) self.fold = self.text[self.text.index("")] self.shown = self.text.replace(self.fold, "") def test_the_open_part(self) -> None: for fact in ("ppge_atlas.zim", ">650.9 KB<", ">Download", "
On the setup's list
", "
Packed for its emulators by
", "
Emulators
", f'
SHA1
{SHA1[:12]}
'): self.assertIn(fact, self.shown) def test_every_hash_whole_in_one_fold_with_the_rest(self) -> None: for label, value in (("SHA1", SHA1), ("MD5", MD5), ("CRC32", CRC32), ("SHA256", SHA256)): self.assertIn(f'
{label}
{value}
', self.fold) shown = " ".join(visible_words(self.text)) for value in (MD5, CRC32, SHA256, SHA1): self.assertNotIn(value, shown) self.assertIn("
Collection path
", self.fold) self.assertIn("
Catalogued
", self.fold) self.assertEqual(self.text.count("Hashes, collection path and catalogues", self.fold) def test_the_fold_is_out_of_the_search(self) -> None: self.assertTrue(self.fold.startswith("
\n")) def test_no_fact_is_lost(self) -> None: # The yardstick list a page is cut by holds every fact: the # Starlight card holds each of its values. with markup.using("mkdocs"): yardstick = "\n".join(gs._system_file_card(_card(), _card_consumers(SHA1))) for label, values in re.findall(r"(?m)^- ([^:]+): (.*)$", yardstick): self.assertIn(f"
{label}
", self.text) for value in re.findall(r"[0-9a-f]{8,64}|`[^`]+`", values): self.assertIn(value.strip("`"), self.text, label) def test_a_card_reads_in_few_words(self) -> None: # Measured on this card: 31 words open, 40 before the round. self.assertLessEqual(len(visible_words(self.text)), min(40, int(31 * 1.05))) class AnEmulatorCardFoldsItsHashes(unittest.TestCase): def setUp(self) -> None: entry = {"name": "scph5501.bin", "md5": "490f666e1afb15b7362b406ed1cea246", "sha1": "b05def971d8ec59f346f2d9ac21fb742e3eb6917", "size": 524288, "required": True, "note": "Read at boot.", "priority": 5, "validation": ["md5"], "source_ref": "src/core/bios.cpp:47"} profile = {"emulator": "DuckStation", "files": [entry], "systems": ["sony-playstation"]} self.text = "\n".join(gs._render_emulator_file( entry, profile, None, profile["files"], lambda _f: True, anchor="file-scph5501-bin")) self.fold = self.text[self.text.index("")] self.shown = self.text.replace(self.fold, "") def test_a_short_hash_open_and_every_hash_folded(self) -> None: # On the size's line. self.assertIn('- Size: 512.0 KB, SHA1 b05def971d8e', self.shown) self.assertIn('490f666e1afb15b7362b406ed1cea246', self.fold) self.assertNotIn("490f666e1afb15b7362b406ed1cea246", self.shown) def test_notes_open_the_rest_folded(self) -> None: self.assertIn("Read at boot.", self.shown) for fact in ("Priority: 5", "Validation: md5", "Source:"): self.assertIn(fact, self.fold) self.assertNotIn(fact, self.shown) self.assertIn("Hashes, priority, validation and more", self.fold) def test_the_markdown_yardstick_is_unchanged(self) -> None: with markup.using("mkdocs"): entry = {"name": "a.bin", "md5": "b" * 32, "size": 4} text = "\n".join(gs._render_emulator_file( entry, {"files": [entry]}, None, [entry], lambda _f: True)) self.assertNotIn(" None: self.text = "\n".join(gs._console_install_block("PlayStation Portable", PAIRS)) def test_one_command_per_tab_for_the_setup_picked(self) -> None: tabs = self.text[self.text.index("")] self.assertEqual(re.findall(r' None: select = re.search(r"", self.text).group(1) options = re.findall(r'