website: one picture viewer (assets/gallery.js) for app and dashboard pictures — declared data-gallery sets, a click on the big picture closes, JS-off still opens the file; site gate 20 + 4 decoys; demo-hp language read back (hu); R-908 (old Resend key in homelab-manifests history); 131 -> 132
gates / gates (push) Successful in 4m25s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
This commit is contained in:
2026-10-08 13:14:24 +02:00
parent 460135a15a
commit 79c53b5f1a
27 changed files with 711 additions and 734 deletions
+7
View File
@@ -1,3 +1,10 @@
## gates — site gate 20: the one picture viewer (2026-10-08)
- Every `data-gallery` opener must be an `<a href>` to an existing file under `website/assets/`; a page with openers must
load `/assets/gallery.js?v=N`, and a page that loads it must have openers; „Screenshot Gallery / Lightbox" (the old inline
viewer) may appear on no page. Four decoys: `site/viewer-opener-without-href`, `viewer-opener-missing-file`,
`viewer-openers-no-script`, `viewer-inline-copy-back`, each with its failure line (`must=`).
## gates — site gate 19: dashboard pictures in the page's own language (2026-10-08)
- `site_gates.py` gate 19: every `/assets/dashboard-*-(hu|en).webp` on a page must match the page's language set.
+30 -1
View File
@@ -29,6 +29,8 @@ Gates (all must pass; non-zero exit on any failure):
17. faq-ld — each FAQ page's FAQPage JSON-LD carries exactly its visible questions and answers
18. tail — nothing after </html> (a stray file-dump summary sat visible below technologiak.html)
19. dash-lang — a page shows dashboard pictures only in its own language (`dashboard-*-hu.webp` / `-en.webp`)
20. viewer — data-gallery openers are <a href> to existing assets; gallery.js (with ?v=) exactly where openers are;
no inline viewer copy
"""
import html as _html, io, json, os, re, sys, unicodedata
@@ -452,8 +454,35 @@ for p, s in pages.items():
fail("%s: a %s dashboard picture (%s) on a %s page — use the page's own language" % (p, m.group(1), m.group(0), want))
print(" dashboard pictures: %d references, each in its page's language" % _dash_n)
# gate 20: the one picture viewer (2026-10-08). A set is declared in the page: every opener is an <a href> to a file
# that exists under website/assets/, carrying data-gallery. A page with openers loads assets/gallery.js with a ?v=; a
# page that loads it has openers; the old inline viewer script appears on no page.
_OPENER_RE = re.compile(r"<(\w+)\b[^>]*\bdata-gallery=\"[^\"]*\"[^>]*>")
_GJS_RE = re.compile(r'<script defer src="/assets/gallery\.js(\?v=[0-9]+)?"></script>')
_open_n = 0
for p, s in pages.items():
openers = [m.group(0) for m in _OPENER_RE.finditer(s)]
_open_n += len(openers)
js = _GJS_RE.findall(s)
if openers and not js:
fail("%s: %d picture opener(s) (data-gallery) but no <script defer src=\"/assets/gallery.js?v=N\">" % (p, len(openers)))
if js and not js[0]:
fail("%s: assets/gallery.js loaded without ?v=" % p)
if js and not openers:
fail("%s: loads assets/gallery.js but declares no data-gallery picture" % p)
for o in openers:
m = re.match(r'<a\b[^>]*\bhref="(/assets/[^"]+)"', o)
if not m:
fail("%s: a data-gallery opener that is not an <a href=\"/assets/…\">: %s" % (p, o[:120]))
continue
if not os.path.exists(os.path.join(W, m.group(1).lstrip("/"))):
fail("%s: a data-gallery opener points at a missing file: %s" % (p, m.group(1)))
if "Screenshot Gallery / Lightbox" in s:
fail("%s: an inline copy of the picture viewer — it lives only in assets/gallery.js" % p)
print(" picture viewer: %d openers, every one a link to an existing file" % _open_n)
if fails:
print("\nSITE GATES FAILED: %d problem(s)" % len(fails))
sys.exit(1)
print("site gates OK — BOM, emoji=0, nav/footer per language, analytics, no CDN, no legacy tokens, no <style>, "
"cache-busted assets, twins + hreflang + globe, lang, same apps, no Hungarian in English, FAQ JSON-LD, clean tail, dashboard pictures per language")
"cache-busted assets, twins + hreflang + globe, lang, same apps, no Hungarian in English, FAQ JSON-LD, clean tail, dashboard pictures per language, one picture viewer")
+18 -1
View File
@@ -82,7 +82,7 @@ COVERS = {
"switch at the wrong twin, lang=\"hu\" on an English page, an app missing from one apps page, "
"ASCII-only Hungarian in English text and in a script message, a 'please', an English "
"retrieval promise the Hungarian does not make, a FAQ JSON-LD drifting from the visible "
"answer, text after </html>, and a Hungarian dashboard picture on an English page — each must convict WITH its own failure line"),
"answer, text after </html>, a Hungarian dashboard picture on an English page, and four picture-viewer faults (an opener without href, an opener to a missing file, openers with no gallery.js, the inline viewer put back) — each must convict WITH its own failure line"),
"script-tests": ("R-885: FIVE cases in scripts/test_script_tests_gate.py, run from here: a suite that PRINTS "
"OK and exits 1 (label without fact), a failing suite three levels deep (scope is a walk), "
"an empty scripts/ tree (checked nothing), the genuine article (must pass), the nested mark"),
@@ -544,6 +544,23 @@ decoy("site/leftover-text-switch", "site_gates.py",
decoy("site/dashboard-picture-wrong-language", "site_gates.py",
replace_in(_EN("index.html"), 'src="/assets/dashboard-start-en.webp"', 'src="/assets/dashboard-start-hu.webp"'),
must="en/index.html: a hu dashboard picture (/assets/dashboard-start-hu.webp) on a en page")
# the one picture viewer (2026-10-08): an opener without href, an opener to a missing file, openers with no script,
# and the old inline viewer put back
decoy("site/viewer-opener-without-href", "site_gates.py",
replace_in(_EN("apps.html"), '<a href="/assets/immich-screenshot-1.webp" data-gallery="immich" class="app-shot-link">',
'<a data-gallery="immich" class="app-shot-link">'),
must="en/apps.html: a data-gallery opener that is not an <a href=")
decoy("site/viewer-opener-missing-file", "site_gates.py",
replace_in(os.path.join(_WEB, "index.html"), '<a href="/assets/dashboard-apps-hu.webp" data-gallery="dashboard">',
'<a href="/assets/dashboard-apps-hu-old.webp" data-gallery="dashboard">'),
must="index.html: a data-gallery opener points at a missing file")
decoy("site/viewer-openers-no-script", "site_gates.py",
replace_in(_EN("technology.html"), ' <script defer src="/assets/gallery.js?v=1"></script>\n', ""),
must="en/technology.html: 2 picture opener(s) (data-gallery) but no")
decoy("site/viewer-inline-copy-back", "site_gates.py",
replace_in(os.path.join(_WEB, "alkalmazasok.html"), "</body>",
" <script>\n /**\n * Screenshot Gallery / Lightbox functionality\n */\n </script>\n</body>"),
must="alkalmazasok.html: an inline copy of the picture viewer")
decoy("site/lang-attr", "site_gates.py",
replace_in(_EN("backups.html"), '<html lang="en">', '<html lang="hu">'),
must="the English set needs lang='en'")