mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-18 17:33:30 -05:00
feat: link and list every file on site pages
This commit is contained in:
1 parent
bd6617cc6a
commit
43af290102
3 files changed
+89
-18
No files matched your search
@@ -684,3 +684,25 @@
|
||||
animation-iteration-count: 1 !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* A file card can be cited by URL: its link shows on hover, and the card a
|
||||
link lands on is marked. */
|
||||
.rb-permalink {
|
||||
margin-left: 0.4rem;
|
||||
color: var(--md-default-fg-color--light, var(--rb-border));
|
||||
text-decoration: none;
|
||||
opacity: 0;
|
||||
transition: opacity 0.15s;
|
||||
}
|
||||
.rb-file-entry:hover .rb-permalink,
|
||||
.rb-sys-file:hover .rb-permalink,
|
||||
.rb-permalink:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
.rb-file-entry:target,
|
||||
.rb-sys-file:target {
|
||||
outline: 2px solid var(--md-accent-fg-color, var(--rb-border));
|
||||
outline-offset: 2px;
|
||||
scroll-margin-top: 4rem;
|
||||
}
|
||||
|
||||
+42
-18
@@ -1776,8 +1776,11 @@ def _system_file_card(f: dict, consumers: FileConsumers) -> list[str]:
|
||||
sha1_short = sha1_full[:12] if sha1_full != "unknown" else "-"
|
||||
md5_short = md5_full[:12] if md5_full != "unknown" else "-"
|
||||
|
||||
lines = ['<div class="rb-sys-file" markdown>', ""]
|
||||
lines.append(f'**`{name}`** <span class="rb-badge rb-badge-muted">{size}</span>')
|
||||
anchor = f"sha1-{sha1_full[:12]}" if sha1_full != "unknown" else ""
|
||||
id_attr = f' id="{anchor}"' if anchor else ""
|
||||
lines = [f'<div class="rb-sys-file"{id_attr} markdown>', ""]
|
||||
permalink = f' <a class="rb-permalink" href="#{anchor}" title="Link to this file">#</a>' if anchor else ""
|
||||
lines.append(f'**`{name}`** <span class="rb-badge rb-badge-muted">{size}</span>{permalink}')
|
||||
lines.append("")
|
||||
if "/.variants/" in f.get("path", ""):
|
||||
lines.append(f"- Stored as: `{f['path'].rsplit('/', 1)[-1]}`")
|
||||
@@ -2040,9 +2043,12 @@ def _render_emulator_file(
|
||||
consumers: FileConsumers | None,
|
||||
files: list,
|
||||
_file_available,
|
||||
anchor: str = "",
|
||||
) -> list[str]:
|
||||
"""Render one row of an emulator profile's file table.
|
||||
|
||||
`anchor` is the card's id on the page, so one file can be cited by URL.
|
||||
|
||||
Split out of generate_emulator_page, where it was a 228-line loop body
|
||||
carrying most of that function's branching: thirty-odd optional fields,
|
||||
each with its own badge, hash line or note.
|
||||
@@ -2091,11 +2097,13 @@ def _render_emulator_file(
|
||||
border_cls = (
|
||||
"rb-file-entry-required" if required else "rb-file-entry-optional"
|
||||
)
|
||||
id_attr = f' id="{anchor}"' if anchor else ""
|
||||
lines.append(
|
||||
f'<div class="rb-file-entry {border_cls}" markdown>'
|
||||
f'<div class="rb-file-entry {border_cls}"{id_attr} markdown>'
|
||||
)
|
||||
lines.append("")
|
||||
lines.append(f"**`{fname}`** {badge_str}")
|
||||
permalink = f' <a class="rb-permalink" href="#{anchor}" title="Link to this file">#</a>' if anchor else ""
|
||||
lines.append(f"**`{fname}`** {badge_str}{permalink}")
|
||||
if desc:
|
||||
lines.append(f"<br>{_escape_tags(str(desc))}")
|
||||
lines.append("")
|
||||
@@ -2103,6 +2111,12 @@ def _render_emulator_file(
|
||||
details = []
|
||||
if fpath and fpath != fname:
|
||||
details.append(f"Path: `{fpath}`")
|
||||
standalone_path = f.get("standalone_path", "")
|
||||
if standalone_path and standalone_path != fpath:
|
||||
# The standalone build reads it elsewhere: MesenCE's dsp1.rom goes
|
||||
# under Firmware/, and a page naming only the core's path sent its
|
||||
# users to the wrong folder.
|
||||
details.append(f"Standalone path: `{standalone_path}`")
|
||||
if fsystem:
|
||||
details.append(f"System: {_system_link(fsystem, '../')}")
|
||||
if size:
|
||||
@@ -2178,22 +2192,25 @@ def _render_emulator_file(
|
||||
if fnote:
|
||||
lines.append(f"- {_escape_tags(str(fnote))}")
|
||||
if contents:
|
||||
lines.append(f"- Contents ({len(contents)} entries):")
|
||||
for c in contents[:10]:
|
||||
# Every member with the hashes the emulator checks: MAME and FBNeo
|
||||
# verify the members, never the archive, so a member's crc32 is the
|
||||
# value a reader compares a set against.
|
||||
lines.append(f"- Contents ({len(contents)} members):")
|
||||
for c in contents:
|
||||
if isinstance(c, dict):
|
||||
cname = c.get("name", "")
|
||||
cdesc = c.get("description", "")
|
||||
csize = c.get("size", "")
|
||||
parts = [f"`{cname}`"]
|
||||
if cdesc:
|
||||
parts.append(cdesc)
|
||||
if csize:
|
||||
parts.append(_fmt_size(csize))
|
||||
lines.append(f" - {' -'.join(parts)}")
|
||||
parts = []
|
||||
if c.get("description"):
|
||||
parts.append(_escape_tags(str(c["description"])))
|
||||
if c.get("size"):
|
||||
parts.append(_fmt_size(c["size"]))
|
||||
if c.get("crc32"):
|
||||
parts.append(f"CRC32 `{c['crc32']}`")
|
||||
if c.get("sha1"):
|
||||
parts.append(f"SHA1 `{c['sha1']}`")
|
||||
extra = f": {', '.join(parts)}" if parts else ""
|
||||
lines.append(f" - `{c.get('name', '')}`{extra}")
|
||||
else:
|
||||
lines.append(f" - {c}")
|
||||
if len(contents) > 10:
|
||||
lines.append(f" - ... and {len(contents) - 10} more")
|
||||
lines.append("")
|
||||
lines.append("</div>")
|
||||
lines.append("")
|
||||
@@ -2526,10 +2543,17 @@ def generate_emulator_page(
|
||||
lines.extend(_emulator_file_summary(files, _file_available))
|
||||
|
||||
# File table
|
||||
used: dict[str, int] = {}
|
||||
for f in files:
|
||||
base = "file-" + (
|
||||
re.sub(r"[^a-z0-9]+", "-", str(f.get("path") or f.get("name", "")).lower())
|
||||
.strip("-") or "entry"
|
||||
)
|
||||
used[base] = used.get(base, 0) + 1
|
||||
anchor = base if used[base] == 1 else f"{base}-{used[base]}"
|
||||
lines.extend(
|
||||
_render_emulator_file(
|
||||
f, profile, consumers, files, _file_available
|
||||
f, profile, consumers, files, _file_available, anchor
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -3598,5 +3598,30 @@ class GeneratedArtifactsMeetTheirSchemas(unittest.TestCase):
|
||||
self.assertEqual(proc.returncode, 0, proc.stdout + proc.stderr)
|
||||
|
||||
|
||||
|
||||
class AFileCardSaysAllItKnows(unittest.TestCase):
|
||||
"""Emulator pages cut a set at 10 members without their hashes, never
|
||||
showed standalone_path, and gave no file an anchor to link to."""
|
||||
|
||||
def test_members_standalone_path_and_anchor(self):
|
||||
from scripts.generate_site import _render_emulator_file
|
||||
|
||||
entry = {
|
||||
"name": "neogeo.zip", "path": "neogeo.zip", "category": "bios_zip",
|
||||
"standalone_path": "Firmware/neogeo.zip",
|
||||
"contents": [{"name": f"m{i}.bin", "size": 1024, "crc32": f"{i:08x}"}
|
||||
for i in range(12)],
|
||||
}
|
||||
text = "\n".join(_render_emulator_file(
|
||||
entry, {"files": [entry]}, None, [entry], lambda f: True, "file-neogeo-zip",
|
||||
))
|
||||
self.assertIn('id="file-neogeo-zip"', text)
|
||||
self.assertIn('href="#file-neogeo-zip"', text)
|
||||
self.assertIn("Standalone path: `Firmware/neogeo.zip`", text)
|
||||
self.assertIn("`m11.bin`", text)
|
||||
self.assertIn("CRC32 `0000000b`", text)
|
||||
self.assertNotIn("more", text)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user