From 3f9569274675dfa9fa798e6efb1bd551f5082c21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Kucharczyk?= Date: Sat, 13 Jun 2026 19:42:07 +0200 Subject: [PATCH] Navbar returns a Safe node; drop redundant filter_presets mark_safe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Navbar is static chrome (a few reverse() URLs in otherwise-fixed markup), so it now returns a single Safe node wrapping that markup instead of a mark_safe string — consistent with "trusted HTML is a Safe node," and a full element tree would be ~80 lines of nesting for no gain (it owns no component JS). Page() interpolates it via str() exactly as before. filter_presets.list_presets returned HttpResponse(mark_safe(...)); HttpResponse never escapes its body, so the mark_safe was pure noise — dropped. The mark_safe calls that remain are all load-bearing and not tree children: the node engine itself (core: how a node emits its SafeString), the script-tag / scripts= string helpers, and Page()'s final document string. Full suite green (445). Co-Authored-By: Claude Opus 4.8 --- common/layout.py | 12 +++++++++--- games/views/filter_presets.py | 3 +-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/common/layout.py b/common/layout.py index b4dadb3..acc96ec 100644 --- a/common/layout.py +++ b/common/layout.py @@ -186,10 +186,16 @@ def _main_script(mastered: bool) -> str: return _MAIN_SCRIPT_A + ("true" if mastered else "false") + _MAIN_SCRIPT_B -def Navbar(*, today_played: str, last_7_played: str, current_year: int) -> SafeText: - """Top navigation bar.""" +def Navbar(*, today_played: str, last_7_played: str, current_year: int) -> "Node": + """Top navigation bar. + + Static chrome, so it's a single ``Safe`` node wrapping its markup rather + than a hand-built element tree — trusted HTML belongs in a ``Safe`` node, + not a ``mark_safe`` string.""" + from common.components import Safe + logo = static("icons/schedule.png") - return mark_safe(f"""