From dd766eb976694928fded9cd7187df26b1b20a5c3 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Sun, 13 Sep 2026 15:57:19 -0400 Subject: [PATCH] =?UTF-8?q?fix:=20the=20favicon=20and=20nav=20brand=20mark?= =?UTF-8?q?=20rendered=20blank=20=E2=80=94=20"--"=20inside=20an=20XML=20co?= =?UTF-8?q?mment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 7ca6ee0's favicon.svg had a comment naming the `--fc-chrome-rgb` custom property. `--` is illegal inside an XML comment, so the file is not well-formed XML, and a browser renders an SVG-as-image only if it parses. It fails without any error, just a blank image. Because TopNav's brand glyph is the same file, the tab icon and the nav mark both went missing on the #251 deploy. logo.svg parses and was unaffected. The comment now names the property without the hyphens, and says why it has to. tests/test_public_svgs.py parses every SVG under frontend/public. It includes a vacuity guard (the directory really contains the two known files) and a positive control (the exact defect raises ParseError), so the check can actually fail. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01SHQB1YukL3VyvMK8rcbmV9 --- frontend/public/favicon.svg | 5 ++++- tests/test_public_svgs.py | 40 +++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 tests/test_public_svgs.py diff --git a/frontend/public/favicon.svg b/frontend/public/favicon.svg index 9cb1c69..d2d1914 100644 --- a/frontend/public/favicon.svg +++ b/frontend/public/favicon.svg @@ -15,7 +15,10 @@ Colours are theme tokens (frontend/src/theme/fabled-tokens.js): obsidian plate, accent gold. The plate is kept here (unlike logo.svg) so the tab icon is self-contained against any browser chrome; on the nav it is - invisible because it matches --fc-chrome-rgb exactly. --> + invisible because it matches the fc-chrome-rgb custom property exactly. + No double hyphen may appear inside this comment: XML forbids it, and a + browser refuses to render an SVG that does not parse (it happened once — + tests/test_public_svgs.py). --> diff --git a/tests/test_public_svgs.py b/tests/test_public_svgs.py new file mode 100644 index 0000000..7e1ff87 --- /dev/null +++ b/tests/test_public_svgs.py @@ -0,0 +1,40 @@ +"""Every SVG the browser loads from `frontend/public/` must parse as XML. + +A browser renders an SVG used as an image only if it is well-formed XML, and +when it is not, nothing reports it: no console error in most browsers, no +failed build, no failed request — the icon is simply blank. `favicon.svg` +shipped that way (merge #251) because its comment contained a CSS custom +property name, and `--` is illegal inside an XML comment. Both the tab icon and +the nav brand mark went missing, and only a person looking at the page noticed. +""" +from __future__ import annotations + +import xml.etree.ElementTree as ET +from pathlib import Path + +import pytest + +PUBLIC = Path(__file__).resolve().parent.parent / "frontend" / "public" +SVGS = sorted(PUBLIC.rglob("*.svg")) + + +def test_the_public_dir_has_svgs_to_check(): + """Guards the guard: a moved directory would otherwise pass vacuously.""" + assert {p.name for p in SVGS} >= {"favicon.svg", "logo.svg"} + + +@pytest.mark.parametrize("svg", SVGS, ids=lambda p: p.name) +def test_svg_is_well_formed_xml(svg): + root = ET.parse(svg).getroot() + assert root.tag == "{http://www.w3.org/2000/svg}svg" + + +def test_the_parser_rejects_the_shape_that_broke_the_favicon(): + """Positive control: the exact defect must fail this parser, or the + parametrized test above proves nothing.""" + broken = ( + '' + "" + ) + with pytest.raises(ET.ParseError): + ET.fromstring(broken)