feat: download button on every file card

The Apple II page named its start files with no visible way to get one: the download sat after the collection path, fourth of a card's facts. Each card now carries a Download button in its title, each start-line name links to its card, and a card held on another part page is reached by its permanent link.
This commit is contained in:
Abdessamad Derraz committed 2026-10-26 21:01:49 +01:00
1 parent 0c77ef074e
commit b24fc06e51
6 files changed
+133 -26

No files matched your search

+7 -6
View File
@@ -100,17 +100,17 @@ class TheConsoleBiosComesFirst(unittest.TestCase):
def test_the_section_opens_on_the_bios_by_region(self):
lines = gs._start_with(self.files, self.required_only())
self.assertEqual(lines[0], "**Start with** the BIOS for the region of your games:")
self.assertIn("- **North America**: `scph5501.bin`", lines)
self.assertIn("- **Japan**: `scph5500.bin`", lines)
self.assertLess(lines.index("- **North America**: `scph5501.bin`"),
lines.index("- **Japan**: `scph5500.bin`"))
self.assertIn("- **North America**: [`scph5501.bin`](#sha1-444444444444)", lines)
self.assertIn("- **Japan**: [`scph5500.bin`](#sha1-555555555555)", lines)
self.assertLess(lines.index("- **North America**: [`scph5501.bin`](#sha1-444444444444)"),
lines.index("- **Japan**: [`scph5500.bin`](#sha1-555555555555)"))
def test_regions_needing_the_same_file_share_a_line(self):
consumers = _consumers({"4" * 40: [
{"required": True, "region": ["north-america", "latin-america", "brazil"]}]})
lines = gs._start_with([_file("scph5501.bin", "4")], consumers)
# Brazil says nothing Latin America does not.
self.assertIn("- **North America, Latin America**: `scph5501.bin`", lines)
self.assertIn("- **North America, Latin America**: [`scph5501.bin`](#sha1-444444444444)", lines)
def test_a_long_list_names_the_first_and_counts_the_rest(self):
files = [_file(f"rom{i}.bin", "abcdefgh"[i]) for i in range(8)]
@@ -120,7 +120,8 @@ class TheConsoleBiosComesFirst(unittest.TestCase):
consumers.emulator_files = {"emu": [{"required": True}] * len(files)}
consumers.emulator_entries = {f["sha1"]: {"emu": i} for i, f in enumerate(files)}
self.assertEqual(gs._start_with(files, consumers)[0],
"**Start with**: `rom0.bin`, `rom1.bin`, `rom2.bin` and 5 more files. "
"**Start with**: [`rom0.bin`](#sha1-aaaaaaaaaaaa), [`rom1.bin`](#sha1-bbbbbbbbbbbb), "
"[`rom2.bin`](#sha1-cccccccccccc) and 5 more files. "
"They come first below.")
def test_no_required_file_no_line(self):
+7 -6
View File
@@ -80,18 +80,18 @@ class TheSectionStartsWithItsOwnConsole(unittest.TestCase):
def test_a_console_its_emulators_run_without_says_so(self) -> None:
self.assertEqual(gs._start_with(self.files, self.consumers, section=DS), [
"**No file needed** with emu-a or emu-b. For full accuracy: "
"`bios7.bin`, `bios9.bin`.", ""])
"[`bios7.bin`](#sha1-777777777777), [`bios9.bin`](#sha1-999999999999).", ""])
def test_the_dsi_section_names_its_file(self) -> None:
lines = gs._start_with(self.files, self.consumers, section=("Nintendo", "Nintendo DSi"))
self.assertEqual(lines, ["**Start with**: `dsi_bios7.bin`.", ""])
self.assertEqual(lines, ["**Start with**: [`dsi_bios7.bin`](#sha1-dddddddddddd).", ""])
def test_more_than_three_emulators_are_counted(self) -> None:
hle = {"required": False, "hle_fallback": True, "system": "nintendo-ds"}
consumers = _consumers({"7" * 40: [(f"emu-{n}", hle) for n in "abcd"]})
self.assertEqual(gs._start_with(self.files[:1], consumers, section=DS)[0],
"**No file needed**: none of its 4 emulators requires one. "
"For full accuracy: `NDS_Bios7.bin`.")
"For full accuracy: [`NDS_Bios7.bin`](#sha1-777777777777).")
def test_a_shipped_file_is_no_start(self) -> None:
consumers = _consumers({"7" * 40: [("emu-a", {"required": True, "bundled": True,
@@ -108,7 +108,7 @@ class TheNameSetupsWrite(unittest.TestCase):
destinations={"a" * 40: {"p1": {"gba_bios.bin"}, "p2": {"bios/gba_bios.bin"},
"p3": {"GBA_bios.rom"}}})
self.assertEqual(gs._start_with([f], consumers, section=("Nintendo", "Game Boy Advance")),
["**Start with**: `gba_bios.bin`.", ""])
["**Start with**: [`gba_bios.bin`](#sha1-aaaaaaaaaaaa).", ""])
def test_no_setup_then_the_emulators_name(self) -> None:
f = _file("x.rom", "b", "bios/Nintendo/Game Boy Advance/x.rom")
@@ -142,7 +142,7 @@ class ArcadeSetsAreNamedWhereverFiled(unittest.TestCase):
link = f"[`neogeo.zip`](/retrobios/files/?sha1={'2' * 40})"
self.assertEqual(lines[0], f"**Start with** {link}. Keep it zipped. "
"mame0, mame1 and mame2 read it.")
self.assertIn("Geolith reads `aes.zip` instead.", lines)
self.assertIn("Geolith reads [`aes.zip`](#sha1-111111111111) instead.", lines)
def test_another_consoles_file_or_an_emulators_folder_is_left_out(self) -> None:
text = "\n".join(gs._start_with([self.aes], self.consumers, section=("SNK", "Neo Geo")))
@@ -164,7 +164,8 @@ class ArcadeSetsAreNamedWhereverFiled(unittest.TestCase):
for i in range(8)]
consumers = _consumers({f["sha1"]: [("emu", {"required": True})] for f in files})
self.assertEqual(gs._start_with(files, consumers, first_below=False)[0],
"**Start with**: `rom0.bin`, `rom1.bin`, `rom2.bin` and 5 more files.")
"**Start with**: [`rom0.bin`](#sha1-aaaaaaaaaaaa), [`rom1.bin`](#sha1-bbbbbbbbbbbb), "
"[`rom2.bin`](#sha1-cccccccccccc) and 5 more files.")
class CardsSayWhichReleaseTheSetMatches(unittest.TestCase):
+8 -3
View File
@@ -29,6 +29,11 @@ DIST = REPO_ROOT / "website" / "dist"
CONTENT = REPO_ROOT / "website" / "src" / "content" / "docs"
def _unlinked(text: str) -> str:
"""A start line's wording: each file it names links to its card."""
return re.sub(r"\[(`[^`]*`)\]\([^)]*\)", r"\1", text)
def _file(name: str, char: str, path: str = "") -> dict:
return {"name": name, "sha1": char * 40, "md5": char * 32, "size": 4096,
"path": path or f"bios/Nintendo/Game Boy/{name}"}
@@ -73,7 +78,7 @@ class AFileFewRequireIsNoStartFile(unittest.TestCase):
consumers = _consumers({"1" * 40: [
("emux_gb", {"name": "dmg_boot.bin", "required": True}),
("gambatte", optional), ("mgba", optional), ("sameboy", optional)]})
line = gs._start_with([boot], consumers)[0]
line = _unlinked(gs._start_with([boot], consumers)[0])
self.assertTrue(line.startswith("**No file needed** with "), line)
self.assertRegex(line, r"Only \S.* requires `dmg_boot.bin`\.$")
@@ -82,7 +87,7 @@ class AFileFewRequireIsNoStartFile(unittest.TestCase):
required = {"name": "scph5501.bin", "required": True}
consumers = _consumers({"2" * 40: [
("a", required), ("b", required), ("c", {"required": False, "hle_fallback": True})]})
self.assertEqual(gs._start_with([bios], consumers)[0], "**Start with**: `scph5501.bin`.")
self.assertEqual(_unlinked(gs._start_with([bios], consumers)[0]), "**Start with**: `scph5501.bin`.")
def test_an_entry_read_for_a_system_with_no_section_is_dropped(self) -> None:
sample = _file("ym2608_adpcm_rom.bin", "3", "bios/Nintendo/NES/ym2608_adpcm_rom.bin")
@@ -131,7 +136,7 @@ class TheNeoGeoOpensOnItsSet(unittest.TestCase):
"5" * 40: [("ares", {"name": "neo-epo.sp1", "required": True,
"system": "snk-neogeo"})],
})
lines = gs._start_with([neogeo, epo], consumers, section=("SNK", "Neo Geo"))
lines = [_unlinked(line) for line in gs._start_with([neogeo, epo], consumers, section=("SNK", "Neo Geo"))]
self.assertTrue(lines[0].startswith("**Start with** `neogeo.zip`. Keep it zipped. "))
self.assertIn("ares reads `neo-epo.sp1` instead.", lines)
cards = gs._console_cards("SNK", [epo, neogeo], consumers, set(),
+50 -5
View File
@@ -52,11 +52,17 @@ def _consumers(reads: dict[str, list[tuple[str, dict]]]) -> types.SimpleNamespac
)
def _unlinked(text: str) -> str:
"""The wording of a start line: each file it names links to its card,
which EachFileDownloadsFromItsCard holds."""
return re.sub(r"\[(`[^`]*`)\]\([^)]*\)", r"\1", text)
def _page(stem: str) -> str:
path = SYSTEMS / f"{stem}.md"
if not path.is_file():
raise unittest.SkipTest(f"systems/{stem}.md not generated")
return path.read_text(encoding="utf-8")
return _unlinked(path.read_text(encoding="utf-8"))
def _start_line(text: str) -> str:
@@ -83,7 +89,7 @@ class AStartFileIsNoOnesExtra(unittest.TestCase):
"1" * 40: [(e, {"name": "naomi.zip", "required": True}) for e, _ in both + extra],
"2" * 40: both + extra,
})
self.assertEqual(gs._start_with([naomi, hod2], consumers),
self.assertEqual([_unlinked(line) for line in gs._start_with([naomi, hod2], consumers)],
["**Start with**: `naomi.zip`.", ""])
def test_the_naomi_page_opens_on_naomi_zip(self) -> None:
@@ -95,7 +101,7 @@ class AStartFileIsNoOnesExtra(unittest.TestCase):
"3" * 40: [(e, {"name": "bios7.bin", "required": True}) for e in ("a", "b")],
"4" * 40: [(e, {"name": "bios9.bin", "required": True}) for e in ("a", "b")],
})
self.assertEqual(gs._start_with([bios7, bios9], consumers)[0],
self.assertEqual(_unlinked(gs._start_with([bios7, bios9], consumers)[0]),
"**Start with**: `bios7.bin`, `bios9.bin`.")
def test_some_files_each_is_not_every_file_for_one(self) -> None:
@@ -121,7 +127,7 @@ class OtherNamesForOneSlotReadAsAlternatives(unittest.TestCase):
for e in ("mesen", "nestopia", "fceumm")],
"6" * 40: [("fbneo", {"name": "fdsbios.zip", "required": True})],
})
self.assertEqual(gs._start_with([disk, fds], consumers)[0],
self.assertEqual(_unlinked(gs._start_with([disk, fds], consumers)[0]),
"**Start with**: `disksys.rom`. FinalBurn Neo reads `fdsbios.zip` instead.")
def test_a_card_read_under_another_name_says_both(self) -> None:
@@ -131,7 +137,7 @@ class OtherNamesForOneSlotReadAsAlternatives(unittest.TestCase):
"7" * 40: [("c", {"name": "short.rom", "required": True})],
})
self.assertIn("reads `long name (1986).bin` (as `short.rom`) instead.",
gs._start_with([disk, card], consumers)[0])
_unlinked(gs._start_with([disk, card], consumers)[0]))
def test_a_regional_line_names_one_file_per_reader(self) -> None:
mega_cd = _page("sega").split("{ #mega-cd }", 1)[1].split("\n## ", 1)[0]
@@ -293,5 +299,44 @@ class OneLabelOnceOnABoardPage(unittest.TestCase):
[])
class EachFileDownloadsFromItsCard(unittest.TestCase):
"""The Apple II page named eight start files and gave no visible way to
get one: the download was a "(download)" after the collection path,
fourth of a card's facts."""
def test_the_card_title_holds_the_download(self) -> None:
from cross_reference import FileConsumers # noqa: PLC0415
f = _file("apple2-asoft-auto.rom", "3", "bios/Apple/Apple II/apple2-asoft-auto.rom")
title = next(line for line in gs._system_file_card(f, FileConsumers({"files": {}}))
if "rb-file-title" in line)
self.assertIn('class="rb-download" href="https://raw.githubusercontent.com/Abdess/'
'retrobios/main/bios/Apple/Apple%20II/apple2-asoft-auto.rom"', title)
self.assertIn('aria-label="Download apple2-asoft-auto.rom"', title)
facts = "\n".join(gs._system_file_card(f, FileConsumers({"files": {}})))
self.assertNotIn("(download)", facts)
def test_a_start_name_leads_to_its_card(self) -> None:
line = gs._link_held_names("- **Apple II**: `a.rom`, `b.rom`.",
{"a.rom": "a" * 40, "b.rom": "b" * 40}, {"a" * 40})
self.assertEqual(line, "- **Apple II**: [`a.rom`](#sha1-aaaaaaaaaaaa), `b.rom`.")
def test_a_card_on_another_part_is_reached_by_its_permalink(self) -> None:
full = next(iter(json.loads((REPO_ROOT / "database.json").read_text())["files"]))
here = f'[`x.rom`](#sha1-{full[:12]})'
away = gs._cards_elsewhere(here)
self.assertEqual(away, f"[`x.rom`](/retrobios/files/?sha1={full})")
held = here + f'\n<h3 id="sha1-{full[:12]}" class="rb-file-title">'
self.assertEqual(gs._cards_elsewhere(held), held)
def test_every_start_name_on_the_built_apple_page_links(self) -> None:
page = next(SYSTEMS.glob("apple.md*"), None)
if page is None:
self.skipTest("site not generated")
section = page.read_text(encoding="utf-8").split("## Apple II {", 1)[1]
start = section.split("<section", 1)[0]
self.assertIn("[`apple2-asoft-auto.rom`](#sha1-33a24f5489ba)", start)
if __name__ == "__main__":
unittest.main()