diff --git a/app/templates/admin/components.html b/app/templates/admin/components.html
index fc889e87..b98bc6a3 100644
--- a/app/templates/admin/components.html
+++ b/app/templates/admin/components.html
@@ -2199,17 +2199,17 @@ goToPage(n) { if (n !== '...' && n >= 1 && n <= this.totalPages) { this.paginati
(Click Option 1 to see loading state)
-
diff --git a/scripts/validate_architecture.py b/scripts/validate_architecture.py
index 951c83bf..45d0cccd 100755
--- a/scripts/validate_architecture.py
+++ b/scripts/validate_architecture.py
@@ -1166,6 +1166,57 @@ class ArchitectureValidator:
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(
self, file_path: Path, content: str, lines: list[str], js_content: str
):
@@ -3029,6 +3080,9 @@ class ArchitectureValidator:
# TPL-011: Check for deprecated macros
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
if is_base_or_partial:
continue