From 25d4edeadc76352b62811f799a498d36d8334b7f Mon Sep 17 00:00:00 2001 From: Ivan Despot <66276597+g-despot@users.noreply.github.com> Date: Thu, 30 Jul 2026 17:40:25 +0200 Subject: [PATCH] Exempt hidden analytics beacons from the alt-text check The indexability suite already exempted the analytics beacon by hostname ("static.scarf.sh"). That predicate went stale when the pixel moved to our own CNAME (pixel.weaviate.cloud), so test_images_have_alt_text started failing on /weaviate/concepts/data-import, /cloud/quickstart and /cloud/manage-clusters/create. Repair the exemption structurally instead of by hostname: skip images hidden from both rendering and the accessibility tree (inline display:none or visibility:hidden, aria-hidden="true") and 1x1 tracking pixels. Alt text is meaningless on an image no reader, screen reader or crawler can reach, and the rule survives the next domain move. The scarf.sh case is kept. Content images missing alt text are still caught. Also mark the beacon itself as decorative in scarf.js with alt="" and aria-hidden="true", which is the correct markup for a hidden pixel. --- src/scripts/scarf.js | 5 +++++ tests/test_docs_indexability.py | 35 ++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/scripts/scarf.js b/src/scripts/scarf.js index 6e0d0384..af63b293 100644 --- a/src/scripts/scarf.js +++ b/src/scripts/scarf.js @@ -5,6 +5,11 @@ const scarfScript = { src: "https://pixel.weaviate.cloud/a.png?x-pxid=a41b0758-a3a9-4874-a880-8b5d5a363d40", referrerPolicy: "no-referrer-when-downgrade", style: "display: none;", + // Decorative, hidden analytics beacon: empty alt plus aria-hidden keeps it + // out of the accessibility tree instead of leaving assistive technology to + // announce an image with no alt attribute. + alt: "", + "aria-hidden": "true", }, }; diff --git a/tests/test_docs_indexability.py b/tests/test_docs_indexability.py index 56b3af6c..63afde1b 100644 --- a/tests/test_docs_indexability.py +++ b/tests/test_docs_indexability.py @@ -251,7 +251,17 @@ def _is_decorative_image(img) -> bool: # Skip language/site logo SVGs (e.g., /img/site/logo-py.svg) if src.endswith(".svg") and "/img/site/" in src: return True - # Skip analytics tracking pixels (e.g., Scarf) + # Skip images that carry no content by construction: analytics beacons, + # spacers, and anything hidden from both rendering and the accessibility + # tree. Such an image conveys nothing to a reader, a screen reader, or a + # crawler, so requiring alt text on it is meaningless. This is matched + # structurally rather than by hostname on purpose: the previous + # "static.scarf.sh" check went stale the moment the beacon moved to our own + # CNAME, and any hostname list will go stale again on the next move. + if _is_hidden_non_content(img): + return True + # Retained for the Scarf-hosted pixel, in case it is ever embedded without + # the hidden styling that the structural check above relies on. if "static.scarf.sh" in src: return True # Skip very small images (likely icons) @@ -262,6 +272,29 @@ def _is_decorative_image(img) -> bool: return False +def _is_hidden_non_content(img) -> bool: + """Check if an image is hidden from users and from the accessibility tree. + + Covers the ways a non-content image announces itself: + - inline `display: none` / `visibility: hidden` (removed from the render + tree, and therefore from the accessibility tree) + - `aria-hidden="true"` (explicitly withheld from assistive technology) + - 1x1 dimensions (a tracking pixel or a spacer) + """ + style = (img.get("style") or "").lower().replace(" ", "") + if "display:none" in style or "visibility:hidden" in style: + return True + + if str(img.get("aria-hidden", "")).lower() == "true": + return True + + dims = (img.get("width"), img.get("height")) + if all(d is not None and str(d).strip().isdigit() and int(d) <= 1 for d in dims): + return True + + return False + + @pytest.mark.indexability @pytest.mark.parametrize("path", ALL_PATHS) def test_llm_notice_present(path):