fix: settle the round 3 site packages together

This commit is contained in:
Abdessamad Derraz committed 2026-10-23 11:12:12 +02:00
1 parent d168ceb8a8
commit f0e7d87def
10 files changed
+44 -11

No files matched your search

+1 -1
View File
@@ -3207,7 +3207,7 @@ SAFE_LINK = "[Is it safe?](../index.md#is-it-safe)"
# Under "From your computer": a device with no network installs from the ZIP
# (`--from-pack`). The id is the one wiki/installer.md gives its section.
OFFLINE_LINE = ("No internet on the device? "
"[Install from the ZIP](../wiki/installer.md#without-a-network).")
"[Install from the ZIP](../wiki/installer.md#without-a-network-offline-install).")
# Shown in the "On the device" tab of a guide that has no `terminal:` of its own.
DEVICE_TERMINAL_FALLBACK = "Or fill the folder from your computer, with the ZIP."
+3 -3
View File
@@ -319,9 +319,9 @@ OG_DIR = Path(__file__).resolve().parent.parent / "docs_assets" / "og"
def og_image(rel: str, level: str) -> str:
"""The sharing card's address: the page's own when it has one, else
its section's."""
own = re.fullmatch(r"platforms/([a-z0-9_-]+)\.md", rel)
if own and own[1] != "index" and (OG_DIR / "platforms" / f"{own[1]}.png").is_file():
return f"{SITE_URL}assets/og/platforms/{own[1]}.png"
own = re.fullmatch(r"(platforms|systems)/([a-z0-9_-]+)\.mdx?", rel)
if own and own[2] != "index" and (OG_DIR / own[1] / f"{own[2]}.png").is_file():
return f"{SITE_URL}assets/og/{own[1]}/{own[2]}.png"
return f"{SITE_URL}assets/og/{og_section(rel, level)}.png"
+3
View File
@@ -88,6 +88,8 @@ class TablesStackWhenBuilt(unittest.TestCase):
"reference": {"labels": ["A", "B", "C"], "rows": 5, "action": False, "level": "reference"},
# Four columns do not fit a phone column, on any page (round 3).
"wide": {"labels": ["File", "Region", "Required", "Hash"], "rows": 105, "action": False, "level": "reference"},
# A hash never breaks: three columns with one overflow a phone (NetherSX2).
"hashes": {"labels": ["File", "Required", "Hash"], "rows": 40, "action": False, "level": "reference"},
}
script = (
f"import {{ stackKind }} from {json.dumps(PLUGIN.as_uri())};"
@@ -101,6 +103,7 @@ class TablesStackWhenBuilt(unittest.TestCase):
self.assertEqual(json.loads(result.stdout), {
"zip-header": "true", "action": "true", "pair": "kv",
"short-start": "true", "long-setup": None, "reference": None, "wide": "true",
"hashes": "true",
})
+14 -1
View File
@@ -45,6 +45,16 @@ _ELEMENT = re.compile(r"<[a-zA-Z][a-zA-Z0-9-]*[\s/>]")
_TAGS = re.compile(r"<[^>]+>")
_TABLE = re.compile(r"<table\b(?P<attrs>[^>]*)>(?P<body>.*?)</table>", re.S)
_CURRENT = re.compile(r'<a\b[^>]*aria-current="page"[^>]*>(?P<label>.*?)</a>', re.S)
_CURRENT_HREF = re.compile(r'<a\b(?=[^>]*aria-current="page")[^>]*href="(?P<href>[^"]*)"', re.S)
def _marked_parent(html: str, url: str) -> str | None:
"""The page a part page names as its parent. The sidebar marks that page
instead of the part, and the last crumb leads to it."""
found = _CURRENT_HREF.search(html.split('id="starlight__sidebar"', 1)[-1])
if found and found["href"].rstrip("/") != url.rstrip("/"):
return found["href"]
return None
_H1 = re.compile(r"<h1\b[^>]*>(?P<title>.*?)</h1>", re.S)
_HEADING = re.compile(r"<h(?P<level>[2-6])\b[^>]*>(?P<inner>.*?)</h(?P=level)>", re.S)
_CRUMBS = re.compile(r'<nav\b[^>]*aria-label="Breadcrumb"[^>]*>(?P<inner>.*?)</nav>', re.S)
@@ -128,6 +138,8 @@ class EveryBuiltPage(unittest.TestCase):
# A tab, or a group of the sidebar, opens on its overview.
if url in self.tab_roots or url in self.group_pages or not current or not title:
continue
if _marked_parent(html, url):
continue
with self.subTest(page=url):
self.assertEqual(_text(current["label"]), _text(title["title"]))
@@ -144,10 +156,11 @@ class EveryBuiltPage(unittest.TestCase):
crumbs = _CRUMBS.search(html)
if not crumbs:
continue
parent = _marked_parent(html, _url(path))
for href in _HREF.findall(crumbs["inner"]):
with self.subTest(page=_url(path), href=href):
self.assertTrue(href in self.tab_roots or href in self.group_pages
or "#" in href, href)
or "#" in href or href == parent, href)
def test_phone_tables_on_reader_pages_are_stacked(self):
"""A table of three columns or more, under RECORD_ROWS rows, on a
+4
View File
@@ -291,7 +291,11 @@ class PlatformShareCards(unittest.TestCase):
def test_other_pages_keep_their_section_card(self):
self.assertEqual(sitestarlight.og_image("platforms/index.md", "setup"),
f"{sitestarlight.SITE_URL}assets/og/setup.png")
# A manufacturer page has its own card since round 3 (6.6); one
# without a rendered card keeps its section's.
self.assertEqual(sitestarlight.og_image("systems/sony.md", "explore"),
f"{sitestarlight.SITE_URL}assets/og/systems/sony.png")
self.assertEqual(sitestarlight.og_image("systems/no-such-maker.md", "explore"),
f"{sitestarlight.SITE_URL}assets/og/explore.png")
+3 -3
View File
@@ -181,9 +181,9 @@ class OfflineLine(unittest.TestCase):
line = text.index("No internet on the device?")
self.assertLess(start, line)
self.assertLess(line, text.index("## On the device"))
self.assertIn("/retrobios/wiki/installer/#without-a-network", text)
self.assertIn("{ #without-a-network }", (REPO_ROOT / "wiki" / "installer.md").read_text(
encoding="utf-8"))
self.assertIn("/retrobios/wiki/installer/#without-a-network-offline-install", text)
self.assertIn("{ #without-a-network-offline-install }",
(REPO_ROOT / "wiki" / "installer.md").read_text(encoding="utf-8"))
class GetYourFilesListsEachSetupOnce(unittest.TestCase):
+6 -1
View File
@@ -51,8 +51,13 @@ def _moved_platform_pages() -> list[Path]:
folder = DOCS / "platforms"
if not folder.is_dir():
return []
# A guide page sits beside the setups (platforms/linux-handhelds) without
# being a list moved off one of them.
from siteguides import HANDHELD_GUIDE # noqa: PLC0415
guides = {Path(HANDHELD_GUIDE.path).stem} if HANDHELD_GUIDE else set()
return [path for path in sorted(folder.glob("*.md*"))
if path.stem not in platforms and path.stem != "index"]
if path.stem not in platforms and path.stem != "index" and path.stem not in guides]
class MetaFields(unittest.TestCase):
@@ -12,6 +12,9 @@
// - on a level 0 or 1 page (`level: start` or `setup`), a three-column table
// short enough to read as records (under RECORD_ROWS rows): one block per
// row. A longer one is a list scanned by column and keeps its scroll.
// - three columns or more where a column holds hashes: a hash cannot break,
// so the row is wider than a phone at any length (NetherSX2's File,
// Required, Hash summary measured 604 px in a 358 px column).
//
// A table of RECORD_ROWS rows or more gets its filter box here, above it.
// Written by site.ts once the page had painted, the box pushed the table
@@ -52,10 +55,13 @@ const holdsAction = (node) =>
(child.type === 'raw' && ACTION_CLASS.test(child.value ?? '')),
);
const HASH_HEADER = /^(hash|sha-?1|sha-?256|md5|crc-?32)$/i;
export const stackKind = ({ labels, rows, action, level }) => {
if (labels.length === 2) return 'kv';
if (labels.length >= WIDE_COLUMNS) return 'true';
if (action || DOWNLOAD_HEADER.test(labels.at(-1) ?? '')) return 'true';
if (labels.length > 2 && labels.some((label) => HASH_HEADER.test(label))) return 'true';
if (READER_LEVELS.has(level) && labels.length > 2 && rows < RECORD_ROWS) return 'true';
return null;
};
+3 -1
View File
@@ -317,7 +317,9 @@ const CATEGORY_WORDS: Record<string, string> = { bios: 'BIOS', game_data: 'game
// own page (systems/sony-playstation/) is part of its manufacturer's file
// (systems/sony.json), found by dropping words from the end of the slug.
const heldFile = async (item: Item): Promise<Held | undefined> => {
const slug = /^systems\/([^/]+)\//.exec(item.url)?.[1];
// Lookup urls are site-absolute (/retrobios/systems/...) since the API
// names every address from the site root.
const slug = /(?:^|\/)systems\/([^/]+)\//.exec(item.url)?.[1];
if (!slug || !item.sha1) return undefined;
const words = slug.split('-');
for (let size = words.length; size > 0; size -= 1) {
+1 -1
View File
@@ -343,7 +343,7 @@
}
@media (min-width: 50rem) {
/* The reason a file is listed reads as a sentence, not a word per line. */
.sl-markdown-content :is(td.rb-reason, td[data-label='Reason']) { min-width: 12rem; }
.sl-markdown-content :is(td.rb-reason, td[data-label='Reason'], td:has(> .rb-reason)) { min-width: 12rem; }
/* Get your files: every group table shares one set of columns. */
.sl-markdown-content :is(table.rb-packs, table:has(td[data-label='Runs on']):has(td[data-label='ZIP'])) {