From 7876dc09e95b8bdde10d9174556878e3a7db3fdc Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Fri, 6 Nov 2026 08:21:30 +0100 Subject: [PATCH] fix: send moved part cards to the emulator index Adding one entry to mame.yml moves 938 cards from one part page to the next, and a published emulators/mame-files-1/#file-... address landed on a page without the card. A part page now sends a file- id it does not hold to the emulator page, whose card index row opens the part that holds it. --- tests/test_site_exports.py | 25 +++++++++++++++++++++++++ website/src/scripts/site.ts | 13 +++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/tests/test_site_exports.py b/tests/test_site_exports.py index 5455a422b..4d230afc9 100644 --- a/tests/test_site_exports.py +++ b/tests/test_site_exports.py @@ -866,6 +866,31 @@ class AWantedDumpIsFoundByItsHash(unittest.TestCase): self.assertIn('retired_files.load(_REPO_ROOT / "retired.json"), wanted)', source) +class AMovedPartCardReachesItsPage(unittest.TestCase): + """One entry added to mame.yml moved 938 of its 1,585 cards from one + part page to another, and emulators/mame-files-1/#file-mackbd-m0110a-zip + led to a page without the card: part pages have no card index, and + site.js redirected only sha1- ids.""" + + def test_a_part_page_sends_a_missing_card_to_the_emulator_page(self): + import re as _re # noqa: PLC0415 + + import generate_site # noqa: PLC0415 + + script = (Path(__file__).resolve().parents[1] / "website" / "src" / "scripts" + / "site.ts").read_text(encoding="utf-8") + body = script.split("const followMovedCard = () => {", 1)[1].split("\n};", 1)[0] + pattern = _re.search(r"const part = /(.+?)/\.exec\(location\.pathname\)", body).group(1) + files = [{"name": f"f{i}.bin", "path": f"f{i}.bin", "required": True} for i in range(600)] + stem = generate_site.emulator_parts("mame", files)[1][0] + found = _re.search(pattern.replace("\\/", "/"), f"/retrobios/emulators/{stem}/") + self.assertEqual(found.group(1), "mame") + self.assertIn("emulators/${part[1]}/#", body) + self.assertIn("id.startsWith('file-')", body) + # The emulator page holds the index whose row leads to the card. + self.assertIn("closest('.rb-card-index tr')", body) + + class AFileHasAnAddressByContent(unittest.TestCase): """mt32_control.rom moved from the Commodore page to the Roland page and every link to its card broke: the anchor was content-based, the page diff --git a/website/src/scripts/site.ts b/website/src/scripts/site.ts index 263309d34..daeb78f28 100644 --- a/website/src/scripts/site.ts +++ b/website/src/scripts/site.ts @@ -814,7 +814,10 @@ const resolveFileAddress = () => { // A file card moved to another page keeps its address: an id of the form // sha1-<12 hex> that this page does not hold is looked up by content, and -// an emulator card listed in the table of a split page opens its page. +// an emulator card listed in the table of a split page opens its page. A +// part of a split emulator page (emulators/mame-files-1/) sends a card id +// it no longer holds to that table: an entry added to the profile moves +// hundreds of cards from one part to the next. const followMovedCard = () => { const id = decodeURIComponent(location.hash.slice(1)); if (!id) return; @@ -824,8 +827,14 @@ const followMovedCard = () => { location.replace(link.href); return; } + if (target) return; const match = /^sha1-([0-9a-f]{12})$/.exec(id); - if (match && !target) location.replace(new URL(`files/?sha1=${match[1]}`, siteRoot())); + if (match) { + location.replace(new URL(`files/?sha1=${match[1]}`, siteRoot())); + return; + } + const part = /\/emulators\/(.+)-files-\d+\/?$/.exec(location.pathname); + if (part && id.startsWith('file-')) location.replace(new URL(`emulators/${part[1]}/#${encodeURIComponent(id)}`, siteRoot())); }; // A link to a card folded in a table row (emulators with many entries)