fix: use correct block name in messages template + add TPL-008 rule
- Fix messages.html: change {% block page_scripts %} to {% block extra_scripts %}
(page_scripts doesn't exist in admin/base.html, causing JS not to load)
- Add TPL-008 architecture rule to catch invalid template block names
This prevents silent failures where content in undefined blocks is ignored
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -243,6 +243,35 @@ template_rules:
|
|||||||
file_pattern: "app/templates/**/*.html"
|
file_pattern: "app/templates/**/*.html"
|
||||||
recommended_pattern: '<template x-if="items.length === 0">No items</template>'
|
recommended_pattern: '<template x-if="items.length === 0">No items</template>'
|
||||||
|
|
||||||
|
- id: "TPL-008"
|
||||||
|
name: "Use valid block names from base templates"
|
||||||
|
severity: "error"
|
||||||
|
description: |
|
||||||
|
Templates must use block names that exist in their base template.
|
||||||
|
Using undefined blocks silently fails (content is not rendered).
|
||||||
|
|
||||||
|
Admin base blocks: title, extra_head, alpine_data, content, extra_scripts
|
||||||
|
Vendor base blocks: title, extra_head, alpine_data, content, extra_scripts
|
||||||
|
Shop base blocks: title, description, extra_head, alpine_data, content, extra_scripts
|
||||||
|
|
||||||
|
WRONG: {% block page_scripts %}...{% endblock %} (undefined)
|
||||||
|
RIGHT: {% block extra_scripts %}...{% endblock %}
|
||||||
|
pattern:
|
||||||
|
file_pattern: "app/templates/admin/**/*.html"
|
||||||
|
valid_blocks:
|
||||||
|
- "title"
|
||||||
|
- "extra_head"
|
||||||
|
- "alpine_data"
|
||||||
|
- "content"
|
||||||
|
- "extra_scripts"
|
||||||
|
forbidden_patterns:
|
||||||
|
- "{% block page_scripts %}"
|
||||||
|
- "{% block scripts %}"
|
||||||
|
- "{% block js %}"
|
||||||
|
- "{% block footer_scripts %}"
|
||||||
|
exceptions:
|
||||||
|
- "base.html"
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# FRONTEND COMPONENT RULES
|
# FRONTEND COMPONENT RULES
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|||||||
@@ -331,6 +331,6 @@
|
|||||||
{% endcall %}
|
{% endcall %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block page_scripts %}
|
{% block extra_scripts %}
|
||||||
<script src="{{ url_for('static', path='admin/js/messages.js') }}"></script>
|
<script src="{{ url_for('static', path='admin/js/messages.js') }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -812,6 +812,10 @@ class ArchitectureValidator:
|
|||||||
# TPL-007: Check empty state implementation
|
# TPL-007: Check empty state implementation
|
||||||
self._check_template_empty_state(file_path, content, lines)
|
self._check_template_empty_state(file_path, content, lines)
|
||||||
|
|
||||||
|
# TPL-008: Check for invalid block names
|
||||||
|
if is_admin:
|
||||||
|
self._check_valid_block_names(file_path, content, lines)
|
||||||
|
|
||||||
if is_base_or_partial:
|
if is_base_or_partial:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -1053,6 +1057,50 @@ class ArchitectureValidator:
|
|||||||
suggestion='Add <template x-if="items.length === 0">No items found</template>',
|
suggestion='Add <template x-if="items.length === 0">No items found</template>',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _check_valid_block_names(
|
||||||
|
self, file_path: Path, content: str, lines: list[str]
|
||||||
|
):
|
||||||
|
"""TPL-008: Check that templates use valid block names from base template"""
|
||||||
|
if "noqa: tpl-008" in content.lower():
|
||||||
|
return
|
||||||
|
|
||||||
|
# Skip base templates
|
||||||
|
if file_path.name == "base.html":
|
||||||
|
return
|
||||||
|
|
||||||
|
# Valid admin template blocks
|
||||||
|
valid_blocks = {"title", "extra_head", "alpine_data", "content", "extra_scripts"}
|
||||||
|
|
||||||
|
# Common invalid block names that developers might mistakenly use
|
||||||
|
invalid_blocks = {
|
||||||
|
"page_scripts": "extra_scripts",
|
||||||
|
"scripts": "extra_scripts",
|
||||||
|
"js": "extra_scripts",
|
||||||
|
"footer_scripts": "extra_scripts",
|
||||||
|
"head": "extra_head",
|
||||||
|
"body": "content",
|
||||||
|
"main": "content",
|
||||||
|
}
|
||||||
|
|
||||||
|
import re
|
||||||
|
block_pattern = re.compile(r"{%\s*block\s+(\w+)\s*%}")
|
||||||
|
|
||||||
|
for i, line in enumerate(lines, 1):
|
||||||
|
match = block_pattern.search(line)
|
||||||
|
if match:
|
||||||
|
block_name = match.group(1)
|
||||||
|
if block_name in invalid_blocks:
|
||||||
|
self._add_violation(
|
||||||
|
rule_id="TPL-008",
|
||||||
|
rule_name="Use valid block names from base templates",
|
||||||
|
severity=Severity.ERROR,
|
||||||
|
file_path=file_path,
|
||||||
|
line_number=i,
|
||||||
|
message=f"Invalid block name '{block_name}' - this block doesn't exist in admin/base.html",
|
||||||
|
context=line.strip(),
|
||||||
|
suggestion=f"Use '{{% block {invalid_blocks[block_name]} %}}' instead",
|
||||||
|
)
|
||||||
|
|
||||||
def _check_pagination_macro_usage(
|
def _check_pagination_macro_usage(
|
||||||
self, file_path: Path, content: str, lines: list[str]
|
self, file_path: Path, content: str, lines: list[str]
|
||||||
):
|
):
|
||||||
|
|||||||
Reference in New Issue
Block a user