From 529feb7ed4079a8a83ac88e9d96361d2ec7cdbdc Mon Sep 17 00:00:00 2001 From: Samir Boulahtit Date: Fri, 2 Jan 2026 22:49:34 +0100 Subject: [PATCH] feat: add architecture rule TPL-015 for page_header macro API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Detects deprecated buttons=[] parameter usage in page_header macro. Correct API: - Single button: action_label, action_icon, action_onclick - Multiple buttons: use page_header_flex with {% call %} 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .architecture-rules/frontend.yaml | 33 +++++++++++++++++++++++++++++ scripts/validate_architecture.py | 35 +++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/.architecture-rules/frontend.yaml b/.architecture-rules/frontend.yaml index ab912b25..3d26158d 100644 --- a/.architecture-rules/frontend.yaml +++ b/.architecture-rules/frontend.yaml @@ -561,6 +561,39 @@ template_rules: exceptions: - "shared/macros/pagination.html" + - id: "TPL-015" + name: "Use correct page_header macro API" + severity: "error" + description: | + The page_header macro does not accept a buttons=[] parameter. + Use action_label/action_onclick for a single action button, + or use page_header_flex with {% call %} for multiple buttons. + + OLD (deprecated - will break): + {{ page_header('Title', buttons=[ + {'text': 'Add', 'icon': 'plus', 'click': 'doSomething()'} + ]) }} + + NEW (single action button): + {{ page_header('Title', action_label='Add', action_icon='plus', action_onclick='doSomething()') }} + + NEW (multiple buttons - use page_header_flex): + {% call page_header_flex(title='Title') %} + + + {% endcall %} + + Parameters for page_header: + - title, subtitle + - action_label, action_url, action_icon, action_onclick + - back_url, back_label + pattern: + file_pattern: "app/templates/**/*.html" + anti_patterns: + - "page_header\\s*\\([^)]*buttons\\s*=" + exceptions: + - "shared/macros/headers.html" + - id: "TPL-014" name: "Use new modal_simple macro API with call block" severity: "error" diff --git a/scripts/validate_architecture.py b/scripts/validate_architecture.py index 92a34c4d..3bf43e62 100755 --- a/scripts/validate_architecture.py +++ b/scripts/validate_architecture.py @@ -1306,6 +1306,38 @@ class ArchitectureValidator: ) break # Only report once per line + def _check_page_header_macro_api( + self, file_path: Path, content: str, lines: list[str] + ): + """ + TPL-015: Check for old page_header macro API. + + The page_header macro does not accept a buttons=[] parameter. + Use action_label/action_onclick for single button, or page_header_flex for multiple. + + OLD (deprecated): {{ page_header('Title', buttons=[...]) }} + NEW (correct): {{ page_header('Title', action_label='Add', action_onclick='...') }} + """ + # Skip the macro definition file + if "shared/macros/headers.html" in str(file_path): + return + + if "noqa: tpl-015" in content.lower(): + return + + for i, line in enumerate(lines, 1): + if re.search(r"page_header\s*\([^)]*buttons\s*=", line): + self._add_violation( + rule_id="TPL-015", + rule_name="Use correct page_header macro API", + severity=Severity.ERROR, + file_path=file_path, + line_number=i, + message="page_header does not accept 'buttons' parameter", + context=line.strip()[:80], + suggestion="Use action_label/action_onclick, or page_header_flex with {% call %}", + ) + def _check_alpine_template_vars( self, file_path: Path, content: str, lines: list[str], js_content: str ): @@ -3286,6 +3318,9 @@ class ArchitectureValidator: # TPL-014: Check for old modal_simple macro API self._check_modal_simple_macro_api(file_path, content, lines) + # TPL-015: Check for old page_header macro API + self._check_page_header_macro_api(file_path, content, lines) + # Skip base/partials for TPL-001 check if is_base_or_partial: continue