From 1e96968744c0971619617f5be1de494dc8c79d8d Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Thu, 5 Nov 2026 12:24:18 +0100 Subject: [PATCH] fix: record list parts by their front matter --- scripts/generate_site.py | 10 +- scripts/sitestarlight.py | 5 +- tests/test_site_r2_nav.py | 5 + website/src/data/published-parts.json | 260 +++++++++++++++++++++++++- 4 files changed, 272 insertions(+), 8 deletions(-) diff --git a/scripts/generate_site.py b/scripts/generate_site.py index e76d55ada..3ca81db28 100644 --- a/scripts/generate_site.py +++ b/scripts/generate_site.py @@ -3357,6 +3357,8 @@ def _published_parts() -> dict[str, str]: def _parent_page(link: str) -> str: """The page a `parent:` link names (/platforms/batocera/), under docs/.""" path, _, fragment = link.partition("#") + # Written with the site's base (/retrobios/emulators/x/) or without it. + path = path.removeprefix(sitestarlight.BASE.rstrip("/")) stem = path.strip("/") or "index" return f"{stem}.md" + (f"#{fragment}" if fragment else "") @@ -3374,13 +3376,11 @@ def record_parts(docs: Path, present: set[str], published: dict[str, str]) -> di if not page.is_file(): page = page.with_suffix(".mdx") try: - with page.open(encoding="utf-8") as handle: - head = handle.read(2048) + parent = _front_matter(page.read_text(encoding="utf-8")).get("parent") except OSError: continue - link = re.search(r"^parent:\n(?: .*\n)*? link: (\"[^\"\n]*\")", head, re.M) - if link and rel not in found: - found[rel] = _parent_page(json.loads(link[1])) + if isinstance(parent, dict) and parent.get("link") and rel not in found: + found[rel] = _parent_page(str(parent["link"])) return dict(sorted(found.items())) diff --git a/scripts/sitestarlight.py b/scripts/sitestarlight.py index dad8fa63f..bf532b9f5 100644 --- a/scripts/sitestarlight.py +++ b/scripts/sitestarlight.py @@ -819,12 +819,13 @@ def redirects(profiles: dict, present: set[str], that is already a page's address, is left out. Addresses are written under the site root, without its base. ``moved`` adds pages that moved by generation, old page to new page, the new one with an optional - #fragment.""" + #fragment. A page MOVED_PAGES names keeps that target over the part + record: cross-reference-minui is answered on MinUI's own page.""" def address(rel: str) -> str: page, _, fragment = rel.partition("#") return "/" + page_url(page)[len(BASE):] + (f"#{fragment}" if fragment else "") - out = {address(old): address(new) for old, new in {**MOVED_PAGES, **(moved or {})}.items() + out = {address(old): address(new) for old, new in {**(moved or {}), **MOVED_PAGES}.items() if old not in present and new.partition("#")[0] in present} pages = {rel.casefold() for rel in present} claims: dict[str, set[str]] = {} diff --git a/tests/test_site_r2_nav.py b/tests/test_site_r2_nav.py index a0175dcc1..4f90adb2e 100644 --- a/tests/test_site_r2_nav.py +++ b/tests/test_site_r2_nav.py @@ -291,6 +291,11 @@ class Redirects(unittest.TestCase): published = generate_site.record_parts( docs, {"gaps-files-to-source-7.md", "gaps.md"}, kept) self.assertEqual(published, {"gaps-files-to-source-7.md": "gaps.md", **kept}) + # An emulator part names its parent with the site's base. + self.assertEqual(generate_site._parent_page("/retrobios/emulators/amiberry/"), + "emulators/amiberry.md") + self.assertEqual(generate_site._parent_page("/platforms/b/#atari-st"), + "platforms/b.md#atari-st") # The next run made six parts. self.assertEqual( sitestarlight.redirects({}, {"gaps.md", "platforms/b.md"}, published), diff --git a/website/src/data/published-parts.json b/website/src/data/published-parts.json index 7c119e52a..3521fb626 100644 --- a/website/src/data/published-parts.json +++ b/website/src/data/published-parts.json @@ -1,4 +1,62 @@ { + "cross-reference-amberelec.md": "cross-reference.md", + "cross-reference-batocera.md": "cross-reference.md", + "cross-reference-emudeck.md": "cross-reference.md", + "cross-reference-emuelec.md": "cross-reference.md", + "cross-reference-knulli.md": "cross-reference.md", + "cross-reference-lakka.md": "cross-reference.md", + "cross-reference-minui.md": "cross-reference.md", + "cross-reference-myminui.md": "cross-reference.md", + "cross-reference-nextui.md": "cross-reference.md", + "cross-reference-recalbox.md": "cross-reference.md", + "cross-reference-retroarch.md": "cross-reference.md", + "cross-reference-retrobat.md": "cross-reference.md", + "cross-reference-retrodeck.md": "cross-reference.md", + "cross-reference-retropie.md": "cross-reference.md", + "cross-reference-rocknix.md": "cross-reference.md", + "cross-reference-romm.md": "cross-reference.md", + "emulators/amiberry-files-1.md": "emulators/amiberry.md", + "emulators/amiberry-files-2.md": "emulators/amiberry.md", + "emulators/data-dolphin-sys-2.md": "emulators/dolphin.md", + "emulators/data-dolphin-sys-3.md": "emulators/dolphin.md", + "emulators/data-dolphin-sys.md": "emulators/dolphin.md", + "emulators/mame-files-1.md": "emulators/mame.md", + "emulators/mame-files-10.md": "emulators/mame.md", + "emulators/mame-files-2.md": "emulators/mame.md", + "emulators/mame-files-3.md": "emulators/mame.md", + "emulators/mame-files-4.md": "emulators/mame.md", + "emulators/mame-files-5.md": "emulators/mame.md", + "emulators/mame-files-6.md": "emulators/mame.md", + "emulators/mame-files-7.md": "emulators/mame.md", + "emulators/mame-files-8.md": "emulators/mame.md", + "emulators/mame-files-9.md": "emulators/mame.md", + "emulators/vice-standalone-files-1.md": "emulators/vice-standalone.md", + "emulators/vice-standalone-files-2.md": "emulators/vice-standalone.md", + "gaps-files-to-source-2.md": "gaps.md", + "gaps-files-to-source-3.md": "gaps.md", + "gaps-files-to-source-4.md": "gaps.md", + "gaps-files-to-source-5.md": "gaps.md", + "gaps-files-to-source-6.md": "gaps.md", + "gaps-files-to-source-7.md": "gaps.md", + "gaps-files-to-source.md": "gaps.md", + "get/amberelec.md": "platforms/amberelec.md", + "get/batocera.md": "platforms/batocera.md", + "get/bizhawk.md": "platforms/bizhawk.md", + "get/emudeck.md": "platforms/emudeck.md", + "get/emuelec.md": "platforms/emuelec.md", + "get/knulli.md": "platforms/knulli.md", + "get/lakka.md": "platforms/lakka.md", + "get/minui.md": "platforms/minui.md", + "get/misterfpga.md": "platforms/misterfpga.md", + "get/myminui.md": "platforms/myminui.md", + "get/nextui.md": "platforms/nextui.md", + "get/recalbox.md": "platforms/recalbox.md", + "get/retroarch.md": "platforms/retroarch.md", + "get/retrobat.md": "platforms/retrobat.md", + "get/retrodeck.md": "platforms/retrodeck.md", + "get/retropie.md": "platforms/retropie.md", + "get/rocknix.md": "platforms/rocknix.md", + "get/romm.md": "platforms/romm.md", "platforms/batocera-acorn-bbc-micro.md": "platforms/batocera.md#acorn-bbc-micro", "platforms/batocera-apple-ii.md": "platforms/batocera.md#apple-ii", "platforms/batocera-apple-macintosh-ii.md": "platforms/batocera.md#apple-macintosh-ii", @@ -78,5 +136,205 @@ "platforms/retropie-snk-neogeo-cd.md": "platforms/retropie.md#snk-neogeo-cd", "platforms/retropie-sony-playstation-2.md": "platforms/retropie.md#sony-playstation-2", "platforms/retropie-sony-playstation.md": "platforms/retropie.md#sony-playstation", - "platforms/romm-sony-playstation-2.md": "platforms/romm.md#sony-playstation-2" + "platforms/romm-sony-playstation-2.md": "platforms/romm.md#sony-playstation-2", + "provenance-no-intro.md": "provenance.md", + "provenance-redump.md": "provenance.md", + "provenance-tosec.md": "provenance.md", + "systems/arcade-aamber-pegasus.md": "systems/arcade.md", + "systems/arcade-acclaim-zn-1.md": "systems/arcade.md", + "systems/arcade-allied-leisure-pinball.md": "systems/arcade.md", + "systems/arcade-american-laser-games-laserdisc.md": "systems/arcade.md", + "systems/arcade-andamiro-pump-it-up.md": "systems/arcade.md", + "systems/arcade-arcade-2.md": "systems/arcade.md", + "systems/arcade-arcade-3.md": "systems/arcade.md", + "systems/arcade-arcade-4.md": "systems/arcade.md", + "systems/arcade-arcade.md": "systems/arcade.md", + "systems/arcade-arcadia-systems-multi-select.md": "systems/arcade.md", + "systems/arcade-aristocrat-mk5.md": "systems/arcade.md", + "systems/arcade-aristocrat-mk6.md": "systems/arcade.md", + "systems/arcade-aristocrat-mk7.md": "systems/arcade.md", + "systems/arcade-atari-system-1.md": "systems/arcade.md", + "systems/arcade-atari-zn-1.md": "systems/arcade.md", + "systems/arcade-atlus-zn-1.md": "systems/arcade.md", + "systems/arcade-barcrest-mpu4.md": "systems/arcade.md", + "systems/arcade-brezzasoft-crystal-system.md": "systems/arcade.md", + "systems/arcade-capcom-zn-1.md": "systems/arcade.md", + "systems/arcade-capcom-zn-2.md": "systems/arcade.md", + "systems/arcade-cd-express-cubo-cd32.md": "systems/arcade.md", + "systems/arcade-century-cvs.md": "systems/arcade.md", + "systems/arcade-ces-galaxy-games.md": "systems/arcade.md", + "systems/arcade-data-east-deco-cassette-system.md": "systems/arcade.md", + "systems/arcade-efo-cedar-magnet-system.md": "systems/arcade.md", + "systems/arcade-eighting-zn-1.md": "systems/arcade.md", + "systems/arcade-exidy-max-a-flex.md": "systems/arcade.md", + "systems/arcade-game-plan-mpu-1.md": "systems/arcade.md", + "systems/arcade-gottlieb-system-1.md": "systems/arcade.md", + "systems/arcade-igs-polygame-master.md": "systems/arcade.md", + "systems/arcade-imax-macs.md": "systems/arcade.md", + "systems/arcade-incredible-technologies-eagle.md": "systems/arcade.md", + "systems/arcade-kaneko-super-nova-system.md": "systems/arcade.md", + "systems/arcade-konami-bubble-system.md": "systems/arcade.md", + "systems/arcade-konami-endeavour.md": "systems/arcade.md", + "systems/arcade-konami-gv.md": "systems/arcade.md", + "systems/arcade-konami-gx.md": "systems/arcade.md", + "systems/arcade-konami-python-2.md": "systems/arcade.md", + "systems/arcade-konami-python.md": "systems/arcade.md", + "systems/arcade-konami-system-573.md": "systems/arcade.md", + "systems/arcade-konami-twinkle.md": "systems/arcade.md", + "systems/arcade-konami-viper.md": "systems/arcade.md", + "systems/arcade-laserdisc-arcade-games.md": "systems/arcade.md", + "systems/arcade-mame-2.md": "systems/arcade.md", + "systems/arcade-mame-3.md": "systems/arcade.md", + "systems/arcade-mame-4.md": "systems/arcade.md", + "systems/arcade-mame-5.md": "systems/arcade.md", + "systems/arcade-mame-6.md": "systems/arcade.md", + "systems/arcade-mame-7.md": "systems/arcade.md", + "systems/arcade-mame-8.md": "systems/arcade.md", + "systems/arcade-mame.md": "systems/arcade.md", + "systems/arcade-midway-mcr.md": "systems/arcade.md", + "systems/arcade-namco-system-11.md": "systems/arcade.md", + "systems/arcade-namco-system-246.md": "systems/arcade.md", + "systems/arcade-namco-system-256.md": "systems/arcade.md", + "systems/arcade-nichibutsu-high-rate-dvd.md": "systems/arcade.md", + "systems/arcade-nintendo-aleck64.md": "systems/arcade.md", + "systems/arcade-nintendo-playchoice-10.md": "systems/arcade.md", + "systems/arcade-nintendo-super-system.md": "systems/arcade.md", + "systems/arcade-nmk16.md": "systems/arcade.md", + "systems/arcade-plug-and-play-tv-games.md": "systems/arcade.md", + "systems/arcade-recel-system-iii.md": "systems/arcade.md", + "systems/arcade-sammy-atomiswave.md": "systems/arcade.md", + "systems/arcade-sammy-medal-games.md": "systems/arcade.md", + "systems/arcade-sega-isg-selection-master.md": "systems/arcade.md", + "systems/arcade-sega-mega-play.md": "systems/arcade.md", + "systems/arcade-sega-mega-tech.md": "systems/arcade.md", + "systems/arcade-sega-model-2.md": "systems/arcade.md", + "systems/arcade-sega-naomi-2.md": "systems/arcade.md", + "systems/arcade-sega-naomi-gd-rom.md": "systems/arcade.md", + "systems/arcade-sega-naomi.md": "systems/arcade.md", + "systems/arcade-sega-shooting-zone.md": "systems/arcade.md", + "systems/arcade-sega-system-sp.md": "systems/arcade.md", + "systems/arcade-sielectronics-system-y2.md": "systems/arcade.md", + "systems/arcade-snk-hyper-neo-geo-64.md": "systems/arcade.md", + "systems/arcade-tab-austria-silverball.md": "systems/arcade.md", + "systems/arcade-taito-c-chip.md": "systems/arcade.md", + "systems/arcade-taito-fx-1.md": "systems/arcade.md", + "systems/arcade-taito-g-net.md": "systems/arcade.md", + "systems/arcade-taito-type-zero.md": "systems/arcade.md", + "systems/arcade-tecmo-tps.md": "systems/arcade.md", + "systems/arcade-tourvision.md": "systems/arcade.md", + "systems/arcade-video-system-zn-1.md": "systems/arcade.md", + "systems/arcade-virtuality-su2000.md": "systems/arcade.md", + "systems/arcade-visual-pinball-tables.md": "systems/arcade.md", + "systems/bungie-marathon-2.md": "systems/bungie.md", + "systems/bungie-marathon.md": "systems/bungie.md", + "systems/commodore-amiga-2.md": "systems/commodore.md", + "systems/commodore-amiga.md": "systems/commodore.md", + "systems/commodore-c128.md": "systems/commodore.md", + "systems/epic-megagames-jazz-jackrabbit-2-2.md": "systems/epic-megagames.md", + "systems/epic-megagames-jazz-jackrabbit-2.md": "systems/epic-megagames.md", + "systems/game-engines-c-dogs-sdl-10.md": "systems/game-engines.md", + "systems/game-engines-c-dogs-sdl-11.md": "systems/game-engines.md", + "systems/game-engines-c-dogs-sdl-12.md": "systems/game-engines.md", + "systems/game-engines-c-dogs-sdl-2.md": "systems/game-engines.md", + "systems/game-engines-c-dogs-sdl-3.md": "systems/game-engines.md", + "systems/game-engines-c-dogs-sdl-4.md": "systems/game-engines.md", + "systems/game-engines-c-dogs-sdl-5.md": "systems/game-engines.md", + "systems/game-engines-c-dogs-sdl-6.md": "systems/game-engines.md", + "systems/game-engines-c-dogs-sdl-7.md": "systems/game-engines.md", + "systems/game-engines-c-dogs-sdl-8.md": "systems/game-engines.md", + "systems/game-engines-c-dogs-sdl-9.md": "systems/game-engines.md", + "systems/game-engines-c-dogs-sdl.md": "systems/game-engines.md", + "systems/game-engines-hurrican-2.md": "systems/game-engines.md", + "systems/game-engines-hurrican-3.md": "systems/game-engines.md", + "systems/game-engines-hurrican-4.md": "systems/game-engines.md", + "systems/game-engines-hurrican.md": "systems/game-engines.md", + "systems/game-engines-hydra-castle-labyrinth-2.md": "systems/game-engines.md", + "systems/game-engines-hydra-castle-labyrinth-3.md": "systems/game-engines.md", + "systems/game-engines-hydra-castle-labyrinth.md": "systems/game-engines.md", + "systems/game-engines-ikemen-go.md": "systems/game-engines.md", + "systems/game-engines-theme-hospital-2.md": "systems/game-engines.md", + "systems/game-engines-theme-hospital.md": "systems/game-engines.md", + "systems/game-engines-thextech-10.md": "systems/game-engines.md", + "systems/game-engines-thextech-11.md": "systems/game-engines.md", + "systems/game-engines-thextech-2.md": "systems/game-engines.md", + "systems/game-engines-thextech-3.md": "systems/game-engines.md", + "systems/game-engines-thextech-4.md": "systems/game-engines.md", + "systems/game-engines-thextech-5.md": "systems/game-engines.md", + "systems/game-engines-thextech-6.md": "systems/game-engines.md", + "systems/game-engines-thextech-7.md": "systems/game-engines.md", + "systems/game-engines-thextech-8.md": "systems/game-engines.md", + "systems/game-engines-thextech-9.md": "systems/game-engines.md", + "systems/game-engines-thextech.md": "systems/game-engines.md", + "systems/magnavox-odyssey2-2.md": "systems/magnavox.md", + "systems/magnavox-odyssey2.md": "systems/magnavox.md", + "systems/microsoft-msx.md": "systems/microsoft.md", + "systems/nintendo-3ds.md": "systems/nintendo.md", + "systems/nintendo-game-boy.md": "systems/nintendo.md", + "systems/nintendo-gamecube.md": "systems/nintendo.md", + "systems/nintendo-nes.md": "systems/nintendo.md", + "systems/nintendo-nintendo-64dd.md": "systems/nintendo.md", + "systems/nintendo-nintendo-ds.md": "systems/nintendo.md", + "systems/nintendo-nintendo-dsi.md": "systems/nintendo.md", + "systems/nintendo-snes.md": "systems/nintendo.md", + "systems/nintendo-wii-u.md": "systems/nintendo.md", + "systems/other-altirra.md": "systems/other.md", + "systems/other-armsx2.md": "systems/other.md", + "systems/other-c64-emu.md": "systems/other.md", + "systems/other-clock-signal.md": "systems/other.md", + "systems/other-cxbx-reloaded.md": "systems/other.md", + "systems/other-eka2l1.md": "systems/other.md", + "systems/other-epsxe.md": "systems/other.md", + "systems/other-fbneo.md": "systems/other.md", + "systems/other-future-pinball-fploader.md": "systems/other.md", + "systems/other-gopher2600.md": "systems/other.md", + "systems/other-idtech4a.md": "systems/other.md", + "systems/other-ines.md": "systems/other.md", + "systems/other-mame-2.md": "systems/other.md", + "systems/other-mame-3.md": "systems/other.md", + "systems/other-mame-4.md": "systems/other.md", + "systems/other-mame-5.md": "systems/other.md", + "systems/other-mame.md": "systems/other.md", + "systems/other-mame4droid.md": "systems/other.md", + "systems/other-mariani.md": "systems/other.md", + "systems/other-mednafen.md": "systems/other.md", + "systems/other-msx-emu.md": "systems/other.md", + "systems/other-nethersx2.md": "systems/other.md", + "systems/other-nuance.md": "systems/other.md", + "systems/other-opentyrian.md": "systems/other.md", + "systems/other-pcem.md": "systems/other.md", + "systems/other-pom2.md": "systems/other.md", + "systems/other-project64-2.md": "systems/other.md", + "systems/other-project64-3.md": "systems/other.md", + "systems/other-project64.md": "systems/other.md", + "systems/other-shadps4.md": "systems/other.md", + "systems/other-skyline-2.md": "systems/other.md", + "systems/other-skyline.md": "systems/other.md", + "systems/other-syobonaction.md": "systems/other.md", + "systems/other-xm6typeg.md": "systems/other.md", + "systems/other-yaps2.md": "systems/other.md", + "systems/other-zesarux.md": "systems/other.md", + "systems/rpg-maker-easyrpg-2.md": "systems/rpg-maker.md", + "systems/rpg-maker-easyrpg-3.md": "systems/rpg-maker.md", + "systems/rpg-maker-easyrpg-4.md": "systems/rpg-maker.md", + "systems/rpg-maker-easyrpg-5.md": "systems/rpg-maker.md", + "systems/rpg-maker-easyrpg.md": "systems/rpg-maker.md", + "systems/rpg-maker-mkxp-z-2.md": "systems/rpg-maker.md", + "systems/rpg-maker-mkxp-z-3.md": "systems/rpg-maker.md", + "systems/rpg-maker-mkxp-z-4.md": "systems/rpg-maker.md", + "systems/rpg-maker-mkxp-z-5.md": "systems/rpg-maker.md", + "systems/rpg-maker-mkxp-z-6.md": "systems/rpg-maker.md", + "systems/rpg-maker-mkxp-z-7.md": "systems/rpg-maker.md", + "systems/rpg-maker-mkxp-z-8.md": "systems/rpg-maker.md", + "systems/rpg-maker-mkxp-z-9.md": "systems/rpg-maker.md", + "systems/rpg-maker-mkxp-z.md": "systems/rpg-maker.md", + "systems/sega-arcade.md": "systems/sega.md", + "systems/sega-mega-cd.md": "systems/sega.md", + "systems/sega-saturn.md": "systems/sega.md", + "systems/sony-playstation-2.md": "systems/sony.md", + "systems/sony-playstation-3.md": "systems/sony.md", + "systems/sony-playstation-4.md": "systems/sony.md", + "systems/sony-playstation-portable.md": "systems/sony.md", + "systems/sony-playstation-vita.md": "systems/sony.md", + "systems/sony-playstation.md": "systems/sony.md", + "systems/sony-pocketstation.md": "systems/sony.md" }