feat(lint): add template_literal_selector rule (#107)

Detects querySelector/querySelectorAll calls that use template literal
variables (e.g. `${compId}`) inside script tags. The HTML bundler's
cheerio/css-what parser crashes on these during compilation, causing
silent fallback to raw HTML without runtime injection.

Severity: error (breaks bundling)
Fix: replace template literal with hardcoded composition ID string
This commit is contained in:
Vance Ingalls
2026-03-27 17:42:28 -07:00
committed by GitHub
parent 476c20747d
commit f0a8644208
2 changed files with 77 additions and 0 deletions
@@ -502,6 +502,26 @@ export function lintHyperframeHtml(
}
}
// ── Template literal variables in querySelector (breaks cheerio bundler) ──
for (const script of scripts) {
const templateLiteralSelectorPattern =
/(?:querySelector|querySelectorAll)\s*\(\s*`[^`]*\$\{[^}]+\}[^`]*`\s*\)/g;
let tlMatch: RegExpExecArray | null;
while ((tlMatch = templateLiteralSelectorPattern.exec(script.content)) !== null) {
pushFinding({
code: "template_literal_selector",
severity: "error",
message:
"querySelector uses a template literal variable (e.g. `${compId}`). " +
"The HTML bundler's CSS parser crashes on these. Use a hardcoded string instead.",
file: filePath,
fixHint:
"Replace the template literal variable with a hardcoded string. The bundler's CSS parser cannot handle interpolated variables in script content.",
snippet: truncateSnippet(tlMatch[0]),
});
}
}
const errorCount = findings.filter((finding) => finding.severity === "error").length;
const warningCount = findings.length - errorCount;