mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-21 03:09:08 -05:00
fix: keep bold labels in nested profile blocks
The nested list structure stays, so each label renders bold instead of showing its asterisks. The platform details block becomes a list as well: its labels were paragraphs followed by items with no blank line between them. validate_site now reports any asterisks that reach a rendered page outside code, which runs in the deploy and in pipeline step 8b.
This commit is contained in:
1 parent
f8fc9a672e
commit
721622c2ea
5 files changed
+63
-9
No files matched your search
@@ -3021,11 +3021,12 @@ def _render_platform_details(profile: dict) -> list[str]:
|
||||
lines.extend(['???+ info "Platform details"', ""])
|
||||
for pk, pv in platform_details.items():
|
||||
if isinstance(pv, dict):
|
||||
lines.append(f" **{pk}:**")
|
||||
lines.extend([f" - **{pk}:**", ""])
|
||||
for sk, sv in pv.items():
|
||||
lines.append(f" - {sk}: {_detail_value(profile, sk, sv)}")
|
||||
lines.append(f" - {sk}: {_detail_value(profile, sk, sv)}")
|
||||
lines.append("")
|
||||
else:
|
||||
lines.append(f" **{pk}:** {_detail_value(profile, pk, pv)}")
|
||||
lines.append(f" - **{pk}:** {_detail_value(profile, pk, pv)}")
|
||||
lines.append("")
|
||||
|
||||
return lines
|
||||
|
||||
@@ -197,11 +197,11 @@ def _render_yaml_value(lines: list[str], val: object, indent: int = 4) -> None:
|
||||
if isinstance(val, dict):
|
||||
for k, v in val.items():
|
||||
if isinstance(v, (dict, list)) and v:
|
||||
lines.append(f"{pad}- {_field_label(k)}:")
|
||||
lines.append(f"{pad}- **{_field_label(k)}:**")
|
||||
lines.append("")
|
||||
_render_yaml_value(lines, v, indent + 4)
|
||||
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:
|
||||
|
||||
@@ -32,6 +32,11 @@ class Page:
|
||||
links: list[str] = field(default_factory=list)
|
||||
missing_alt: list[str] = field(default_factory=list)
|
||||
jsonld: list[str] = field(default_factory=list)
|
||||
unrendered: list[str] = field(default_factory=list)
|
||||
|
||||
|
||||
# Text inside these is shown as written, so markup there is not a leftover.
|
||||
_LITERAL_TAGS = frozenset({"pre", "code", "script", "style", "textarea"})
|
||||
|
||||
|
||||
class _PageParser(HTMLParser):
|
||||
@@ -42,9 +47,12 @@ class _PageParser(HTMLParser):
|
||||
self._title_parts: list[str] = []
|
||||
self._jsonld_depth = 0
|
||||
self._jsonld_parts: list[str] = []
|
||||
self._literal_depth = 0
|
||||
|
||||
def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
|
||||
data = dict(attrs)
|
||||
if tag in _LITERAL_TAGS:
|
||||
self._literal_depth += 1
|
||||
if tag == "html":
|
||||
self.page.lang = data.get("lang", "")
|
||||
elif tag == "title":
|
||||
@@ -73,6 +81,8 @@ class _PageParser(HTMLParser):
|
||||
self.page.canonical.append(data.get("href", ""))
|
||||
|
||||
def handle_endtag(self, tag: str) -> None:
|
||||
if tag in _LITERAL_TAGS and self._literal_depth:
|
||||
self._literal_depth -= 1
|
||||
if tag == "title":
|
||||
self._title_depth -= 1
|
||||
elif tag == "script" and self._jsonld_depth:
|
||||
@@ -85,6 +95,8 @@ class _PageParser(HTMLParser):
|
||||
self._title_parts.append(data)
|
||||
if self._jsonld_depth:
|
||||
self._jsonld_parts.append(data)
|
||||
if not self._literal_depth and "**" in data:
|
||||
self.page.unrendered.append(data.strip()[:60])
|
||||
|
||||
def close(self) -> None:
|
||||
super().close()
|
||||
@@ -192,6 +204,10 @@ def _check_pages(
|
||||
report(path, f"duplicate IDs: {duplicate_ids[:5]}")
|
||||
if page.missing_alt:
|
||||
report(path, f"images missing alt: {page.missing_alt[:5]}")
|
||||
if page.unrendered:
|
||||
# Bold that reached the reader as asterisks: a block indented
|
||||
# one level too deep is read as code (the clownmdemu analysis).
|
||||
report(path, f"markdown left unrendered: {page.unrendered[:3]}")
|
||||
|
||||
if not is_404 and len(page.jsonld) != 1:
|
||||
report(path, f"expected one JSON-LD block, got {len(page.jsonld)}")
|
||||
|
||||
@@ -858,9 +858,24 @@ class NestedProfileBlocksRenderAsLists(unittest.TestCase):
|
||||
"tmss": {"supported": True}})
|
||||
self.assertNotIn("<pre>", html)
|
||||
self.assertNotIn("**", html)
|
||||
self.assertIn("external required: no", html)
|
||||
self.assertIn("<strong>external required:</strong> no", html)
|
||||
self.assertIn("<code>a.c:1</code>", html)
|
||||
|
||||
def test_platform_details_are_a_list(self):
|
||||
import generate_site
|
||||
|
||||
lines = generate_site._render_platform_details(
|
||||
{"platform_details": {"megacd": {"root": "x"}, "note": "y"}}
|
||||
)
|
||||
lines[0] = lines[0].replace("???+", "!!!")
|
||||
try:
|
||||
import markdown
|
||||
except ImportError:
|
||||
self.skipTest("markdown is not installed")
|
||||
html = markdown.markdown("\n".join(lines), extensions=["admonition"])
|
||||
self.assertIn("<li>root: x</li>", html)
|
||||
self.assertNotIn("**", html)
|
||||
|
||||
def test_a_list_under_a_key_is_a_sublist(self):
|
||||
html = self._html({"roms": [{"name": "a.bin", "size": 2}, "b.bin"]})
|
||||
self.assertNotIn("<pre>", html)
|
||||
|
||||
@@ -100,9 +100,9 @@ class PlatformDetails(unittest.TestCase):
|
||||
"root": "<system_dir>/x",
|
||||
}}}
|
||||
)
|
||||
self.assertIn(" - extensions_tried: .bin, .zip", lines)
|
||||
self.assertIn(" - hle_available: no", lines)
|
||||
self.assertIn(" - root: <system_dir>/x", lines)
|
||||
self.assertIn(" - extensions_tried: .bin, .zip", lines)
|
||||
self.assertIn(" - hle_available: no", lines)
|
||||
self.assertIn(" - root: <system_dir>/x", lines)
|
||||
|
||||
|
||||
class RenderedSiteValidation(unittest.TestCase):
|
||||
@@ -165,6 +165,28 @@ class RenderedSiteValidation(unittest.TestCase):
|
||||
|
||||
|
||||
|
||||
class UnrenderedMarkdown(unittest.TestCase):
|
||||
"""The clownmdemu analysis block reached readers as "- **bios_hle:**
|
||||
True": a list indented one level too deep, read as code."""
|
||||
|
||||
setUp = RenderedSiteValidation.setUp
|
||||
tearDown = RenderedSiteValidation.tearDown
|
||||
|
||||
def test_asterisks_in_prose_fail_and_in_code_pass(self):
|
||||
(self.site / "index.html").write_text(
|
||||
_page("Home", "Unique home description.", "<p>- **bios_hle:** True</p>"),
|
||||
encoding="utf-8",
|
||||
)
|
||||
issues = validate_site(self.site, self.config)
|
||||
self.assertTrue(any("markdown left unrendered" in issue for issue in issues))
|
||||
(self.site / "index.html").write_text(
|
||||
_page("Home", "Unique home description.",
|
||||
"<pre><code>a = 2 ** 8</code></pre><code>**/*.py</code>"),
|
||||
encoding="utf-8",
|
||||
)
|
||||
self.assertEqual(validate_site(self.site, self.config), [])
|
||||
|
||||
|
||||
class EveryTestDependencyIsInstalledInCi(unittest.TestCase):
|
||||
"""The markdown rendering test skipped on every CI run: the test job
|
||||
installed pyyaml and jsonschema only. A test that skips where it is
|
||||
|
||||
Reference in new issue
Block a user