fix: components page copyCode Alpine error and add TPL-012 rule
- Fixed copyCode template literal by using single quotes for outer attribute - Added TPL-012 architecture rule to detect double quotes inside multi-line copyCode template literals that break HTML attribute parsing - Pattern: @click="copyCode(`...`)" with inner double quotes breaks parsing - Solution: Use @click='copyCode(`...`)' with single quotes for outer attribute 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2199,17 +2199,17 @@ goToPage(n) { if (n !== '...' && n >= 1 && n <= this.totalPages) { this.paginati
|
|||||||
<span class="text-xs text-gray-500">(Click Option 1 to see loading state)</span>
|
<span class="text-xs text-gray-500">(Click Option 1 to see loading state)</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button @click="copyCode(`{% raw %}{% from 'shared/macros/dropdowns.html' import action_dropdown, dropdown_item %}
|
<button @click='copyCode(`{% raw %}{% from "shared/macros/dropdowns.html" import action_dropdown, dropdown_item %}
|
||||||
{% call action_dropdown(
|
{% call action_dropdown(
|
||||||
label='Run Scan',
|
label="Run Scan",
|
||||||
loading_label='Scanning...',
|
loading_label="Scanning...",
|
||||||
open_var='scanDropdownOpen',
|
open_var="scanDropdownOpen",
|
||||||
loading_var='scanning',
|
loading_var="scanning",
|
||||||
icon='search'
|
icon="search"
|
||||||
) %}
|
) %}
|
||||||
{{ dropdown_item('Run All', "runScan('all'); scanDropdownOpen = false") }}
|
{{ dropdown_item("Run All", "runScan(\"all\"); scanDropdownOpen = false") }}
|
||||||
{{ dropdown_item('Run Selected', "runScan('selected'); scanDropdownOpen = false") }}
|
{{ dropdown_item("Run Selected", "runScan(\"selected\"); scanDropdownOpen = false") }}
|
||||||
{% endcall %}{% endraw %}`)" class="text-sm text-purple-600 hover:text-purple-700 dark:text-purple-400 flex items-center">
|
{% endcall %}{% endraw %}`)' class="text-sm text-purple-600 hover:text-purple-700 dark:text-purple-400 flex items-center">
|
||||||
<span x-html="$icon('duplicate', 'w-4 h-4 mr-1')"></span>
|
<span x-html="$icon('duplicate', 'w-4 h-4 mr-1')"></span>
|
||||||
Copy Code
|
Copy Code
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -1166,6 +1166,57 @@ class ArchitectureValidator:
|
|||||||
suggestion=f"Use '{info['replacement']}' macro instead",
|
suggestion=f"Use '{info['replacement']}' macro instead",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _check_escaped_quotes_in_alpine(
|
||||||
|
self, file_path: Path, content: str, lines: list[str]
|
||||||
|
):
|
||||||
|
"""TPL-012: Check for problematic quotes in Alpine copyCode template literals.
|
||||||
|
|
||||||
|
When using copyCode() with a multi-line template literal, double quotes
|
||||||
|
inside the template will prematurely end the outer @click="..." attribute.
|
||||||
|
|
||||||
|
Bad: @click="copyCode(`{{ func("arg") }}`)" # inner " ends the attribute
|
||||||
|
Good: @click='copyCode(`{{ func("arg") }}`)' # single quotes for outer
|
||||||
|
"""
|
||||||
|
if "noqa: tpl-012" in content.lower():
|
||||||
|
return
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
# Track multi-line copyCode template literals with double-quoted outer attribute
|
||||||
|
in_copycode_template = False
|
||||||
|
copycode_start_line = 0
|
||||||
|
|
||||||
|
for i, line in enumerate(lines, 1):
|
||||||
|
if "noqa: tpl-012" in line.lower():
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Check for start of copyCode with double-quoted attribute and template literal
|
||||||
|
# Pattern: @click="copyCode(` where the backtick doesn't close on same line
|
||||||
|
if '@click="copyCode(`' in line and '`)' not in line:
|
||||||
|
in_copycode_template = True
|
||||||
|
copycode_start_line = i
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Check for end of copyCode template (backtick followed by )" or )')
|
||||||
|
if in_copycode_template:
|
||||||
|
if '`)"' in line or "`)'" in line:
|
||||||
|
in_copycode_template = False
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Check for double quotes that would break the outer attribute
|
||||||
|
# These appear in Jinja template code like {{ func("arg") }}
|
||||||
|
if re.search(r'\(\s*"[^"]*"\s*[,)]', line):
|
||||||
|
self._add_violation(
|
||||||
|
rule_id="TPL-012",
|
||||||
|
rule_name="Double quotes in copyCode template literal",
|
||||||
|
severity=Severity.ERROR,
|
||||||
|
file_path=file_path,
|
||||||
|
line_number=i,
|
||||||
|
message="Double quotes inside multi-line copyCode template literal will break HTML attribute parsing",
|
||||||
|
context=line.strip()[:80],
|
||||||
|
suggestion="Change outer attribute to single quotes: @click='copyCode(`...`)'",
|
||||||
|
)
|
||||||
|
|
||||||
def _check_alpine_template_vars(
|
def _check_alpine_template_vars(
|
||||||
self, file_path: Path, content: str, lines: list[str], js_content: str
|
self, file_path: Path, content: str, lines: list[str], js_content: str
|
||||||
):
|
):
|
||||||
@@ -3029,6 +3080,9 @@ class ArchitectureValidator:
|
|||||||
# TPL-011: Check for deprecated macros
|
# TPL-011: Check for deprecated macros
|
||||||
self._check_deprecated_macros(file_path, content, lines)
|
self._check_deprecated_macros(file_path, content, lines)
|
||||||
|
|
||||||
|
# TPL-012: Check for escaped quotes in Alpine template literals
|
||||||
|
self._check_escaped_quotes_in_alpine(file_path, content, lines)
|
||||||
|
|
||||||
# Skip base/partials for TPL-001 check
|
# Skip base/partials for TPL-001 check
|
||||||
if is_base_or_partial:
|
if is_base_or_partial:
|
||||||
continue
|
continue
|
||||||
|
|||||||
Reference in New Issue
Block a user