fix: show every field of structured profile blocks

The analysis and firmware blocks printed their source_ref as plain code,
dropped any list or map inside a list item (cemu's firmware title
contents), cut values at 200 characters and let a folded note's second
line leave its admonition. Citations are now pinned links and every
value is shown on its own line.
This commit is contained in:
Abdessamad Derraz committed 2026-10-21 05:09:56 +02:00
1 parent 76b41741ec
commit 90e54dcb43
3 files changed
+89 -15

No files matched your search

+19 -1
View File
@@ -3055,6 +3055,22 @@ def _plain_value(value: object) -> str:
return _escape_tags(str(value))
def _structured_field_text(profile: dict) -> Callable[[object, object], str]:
"""Scalars of a structured block, citations linked at the profile's pin.
The file entries and platform details linked their source_ref, and the
analysis and firmware blocks printed 186 of them as plain code.
"""
def text(key: object, value: object) -> str:
if key == "source_ref" and isinstance(value, str):
return _source_ref_markdown(profile, value)
if isinstance(value, str):
return link_prose_citations(profile, _field_text(key, value))
return _field_text(key, value)
return text
def _render_structured_blocks(profile: dict) -> list[str]:
"""Every remaining structured field, as a collapsible section."""
lines: list[str] = []
@@ -3090,7 +3106,8 @@ def _render_structured_blocks(profile: dict) -> list[str]:
lines.append(f'???+ abstract "{label}"')
lines.append("")
start = len(lines)
_render_yaml_value(lines, val, indent=4)
_render_yaml_value(lines, val, indent=4,
field_text=_structured_field_text(profile))
lines[start:] = [_escape_tags(line) for line in lines[start:]]
lines.append("")
@@ -5168,6 +5185,7 @@ from sitesources import ( # noqa: E402,F401
from siterender import ( # noqa: E402,F401
_by_mode,
_count,
_field_text,
_render_yaml_value,
_slugify_anchor,
_system_page_map,
+28 -14
View File
@@ -8,6 +8,7 @@ import sys
import urllib.error
import urllib.parse
import urllib.request
from collections.abc import Callable
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path
@@ -212,9 +213,10 @@ def _field_text(key: object, value: object) -> str:
elif value is None:
text = "none"
else:
text = str(value)
if len(text) > 200:
text = text[:200] + "..."
# One line: a folded note's second line started at column 0 and
# left the admonition it was written in. Never cut: 34 notes lost
# their end, and a cut citation links to another line.
text = " ".join(str(value).split())
return f"`{text}`" if key == "source_ref" else text
@@ -223,12 +225,19 @@ def _field_label(key: object) -> str:
return str(key).replace("_", " ")
def _render_yaml_value(lines: list[str], val: object, indent: int = 4) -> None:
FieldText = Callable[[object, object], str]
def _render_yaml_value(
lines: list[str], val: object, indent: int = 4,
field_text: FieldText = _field_text,
) -> None:
"""Render any YAML value as a nested markdown list.
Every level is a list item and its children a sublist four spaces in.
A key written as a paragraph with its children indented below it read as
an indented code block: the clownmdemu page showed the raw asterisks.
``field_text`` renders each scalar, so a page can link a source_ref.
"""
pad = " " * indent
if isinstance(val, dict):
@@ -236,27 +245,32 @@ def _render_yaml_value(lines: list[str], val: object, indent: int = 4) -> None:
if isinstance(v, (dict, list)) and v:
lines.append(f"{pad}- **{_field_label(k)}:**")
lines.append("")
_render_yaml_value(lines, v, indent + 4)
_render_yaml_value(lines, v, indent + 4, field_text)
else:
lines.append(f"{pad}- **{_field_label(k)}:** {_field_text(k, v)}")
lines.append(f"{pad}- **{_field_label(k)}:** {field_text(k, v)}")
lines.append("")
elif isinstance(val, list):
for item in val:
if isinstance(item, dict):
parts = [
f"{_field_label(ik)}: {_field_text(ik, iv)}"
for ik, iv in item.items()
if not isinstance(iv, (dict, list))
]
lines.append(f"{pad}- {', '.join(parts)}")
# Scalars on the item's line, lists and maps as its children:
# cemu's firmware titles lost the files each title carries.
scalars = {ik: iv for ik, iv in item.items()
if not (isinstance(iv, (dict, list)) and iv)}
nested = {ik: iv for ik, iv in item.items() if ik not in scalars}
parts = [f"{_field_label(ik)}: {field_text(ik, iv)}"
for ik, iv in scalars.items()]
lines.append(f"{pad}- {', '.join(parts)}".rstrip())
if nested:
lines.append("")
_render_yaml_value(lines, nested, indent + 4, field_text)
else:
lines.append(f"{pad}- {_field_text(None, item)}")
lines.append(f"{pad}- {field_text(None, item)}")
lines.append("")
elif isinstance(val, str) and "\n" in val:
for line in val.split("\n"):
lines.append(f"{pad}{line}")
else:
lines.append(f"{pad}{_field_text(None, val)}")
lines.append(f"{pad}{field_text(None, val)}")
def _platform_link(name: str, display: str, prefix: str = "") -> str:
+42
View File
@@ -139,5 +139,47 @@ class BundledFilesAreNotToSource(unittest.TestCase):
'<span class="rb-badge rb-badge-danger">1</span> |', page)
class StructuredBlocks(unittest.TestCase):
PIN = "1e0de94dc7e669c0925a22c0fccf6cdc837af0a0"
def profile(self, block: str, value: object) -> dict:
return {"source": "https://github.com/libretro/blastem",
"source_commit": self.PIN, block: value}
def render(self, profile: dict) -> str:
import generate_site
return "\n".join(generate_site._render_structured_blocks(profile))
def test_a_source_ref_in_a_block_is_a_pinned_link(self):
"""186 citations in analysis and firmware blocks were plain code."""
page = self.render(self.profile("analysis", {"tmss": {
"source_ref": "libblastem.c:355-359"}}))
self.assertIn(
f"[`libblastem.c:355-359`](https://github.com/libretro/blastem/blob/"
f"{self.PIN}/libblastem.c#L355-L359)", page)
def test_a_list_inside_a_list_item_is_shown(self):
"""cemu's firmware titles lost the files each title carries."""
page = self.render(self.profile("firmware_titles", [
{"id": "0005001b-10042400", "name": "Shared fonts",
"content": ["CafeCn.ttf", "CafeKr.ttf"]}]))
self.assertIn(" - id: 0005001b-10042400, name: Shared fonts\n", page)
self.assertIn(" - **content:**", page)
self.assertIn(" - CafeKr.ttf", page)
def test_a_folded_note_stays_inside_its_block(self):
page = self.render(self.profile("analysis", {"tmss": {
"note": "The core points\nsystem/tmss_path at the system directory."}}))
self.assertIn("- **note:** The core points system/tmss_path at the", page)
body = page.split("\n")[1:]
self.assertEqual([line for line in body if line and not line.startswith(" ")], [])
def test_a_long_note_is_not_cut(self):
note = "word " * 80 + "end."
page = self.render(self.profile("analysis", {"x": {"note": note}}))
self.assertIn("end.", page)
if __name__ == "__main__":
unittest.main()