mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 06:06:37 +03:00
Fix browser script serving: run build after skill sync, serve via /js/
The skill sync wipes .claude/skills/ and re-copies from dist, deleting the generated browser script. Moved build-browser-detector.js to run AFTER the sync. Dev server's /js/* route now falls through to .claude/skills/critique/scripts/ for built artifacts. All fixture HTML references use /js/detect-antipatterns-browser.js (clean URL). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
fbfe525f4f
commit
d8803c8151
@@ -202,6 +202,6 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -370,6 +370,6 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -312,6 +312,6 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -317,6 +317,6 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -315,6 +315,6 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -373,6 +373,6 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -194,6 +194,6 @@
|
||||
<script>
|
||||
lucide.createIcons();
|
||||
</script>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -431,6 +431,6 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -236,6 +236,6 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -202,6 +202,6 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -200,6 +200,6 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+7
-7
@@ -322,13 +322,6 @@ async function build() {
|
||||
// Build CSS with Tailwind CLI (handles @theme directive)
|
||||
buildTailwindCSS();
|
||||
|
||||
// Generate browser anti-pattern detector from core module
|
||||
try {
|
||||
execSync('node scripts/build-browser-detector.js', { cwd: ROOT_DIR, stdio: 'inherit' });
|
||||
} catch (error) {
|
||||
console.error('Failed to build browser detector:', error.message);
|
||||
}
|
||||
|
||||
// Bundle HTML, JS, and compiled CSS with Bun
|
||||
await buildStaticSite();
|
||||
|
||||
@@ -395,6 +388,13 @@ async function build() {
|
||||
|
||||
console.log(`📋 Synced to .claude/: skills`);
|
||||
|
||||
// Generate browser anti-pattern detector (after skill sync so it doesn't get overwritten)
|
||||
try {
|
||||
execSync('node scripts/build-browser-detector.js', { cwd: ROOT_DIR, stdio: 'inherit' });
|
||||
} catch (error) {
|
||||
console.error('Failed to build browser detector:', error.message);
|
||||
}
|
||||
|
||||
console.log('\n✨ Build complete!');
|
||||
}
|
||||
|
||||
|
||||
+8
-20
@@ -19,19 +19,6 @@ const server = serve({
|
||||
"/cheatsheet": cheatsheet,
|
||||
"/gallery": gallery,
|
||||
|
||||
// Built skill scripts (.claude/skills/)
|
||||
"/.claude/skills/*": async (req) => {
|
||||
const url = new URL(req.url);
|
||||
if (url.pathname.includes('..')) return new Response("Bad Request", { status: 400 });
|
||||
const filePath = `.${url.pathname}`;
|
||||
const assetFile = file(filePath);
|
||||
if (await assetFile.exists()) {
|
||||
return new Response(assetFile, {
|
||||
headers: { "Content-Type": "application/javascript", "X-Content-Type-Options": "nosniff" }
|
||||
});
|
||||
}
|
||||
return new Response("Not Found", { status: 404 });
|
||||
},
|
||||
// Static assets - all public subdirectories
|
||||
"/assets/*": async (req) => {
|
||||
const url = new URL(req.url);
|
||||
@@ -60,13 +47,14 @@ const server = serve({
|
||||
"/js/*": async (req) => {
|
||||
const url = new URL(req.url);
|
||||
if (url.pathname.includes('..')) return new Response("Bad Request", { status: 400 });
|
||||
const filePath = `./public${url.pathname}`;
|
||||
const assetFile = file(filePath);
|
||||
if (await assetFile.exists()) {
|
||||
return new Response(assetFile, {
|
||||
headers: { "Content-Type": "application/javascript", "X-Content-Type-Options": "nosniff", "X-Frame-Options": "DENY" }
|
||||
});
|
||||
}
|
||||
// Check public/js/ first, then fall back to built artifacts
|
||||
const headers = { "Content-Type": "application/javascript", "X-Content-Type-Options": "nosniff", "X-Frame-Options": "DENY" };
|
||||
const publicFile = file(`./public${url.pathname}`);
|
||||
if (await publicFile.exists()) return new Response(publicFile, { headers });
|
||||
// Built browser detector served at /js/detect-antipatterns-browser.js
|
||||
const basename = url.pathname.split('/').pop();
|
||||
const builtFile = file(`./.claude/skills/critique/scripts/${basename}`);
|
||||
if (await builtFile.exists()) return new Response(builtFile, { headers });
|
||||
return new Response("Not Found", { status: 404 });
|
||||
},
|
||||
// Test fixtures (for browser visual testing)
|
||||
|
||||
@@ -38,8 +38,13 @@ describeIf('browser script parity with CLI', () => {
|
||||
let filePath;
|
||||
if (req.url.startsWith('/fixtures/')) {
|
||||
filePath = path.join(${JSON.stringify(path.join(import.meta.dir))}, req.url);
|
||||
} else if (req.url.startsWith('/.claude/')) {
|
||||
filePath = path.join(${JSON.stringify(path.join(import.meta.dir, '..'))}, req.url);
|
||||
} else if (req.url.startsWith('/js/')) {
|
||||
// Check public/js/ first, then built artifacts
|
||||
const basename = req.url.split('/').pop();
|
||||
filePath = path.join(${JSON.stringify(path.join(import.meta.dir, '..', 'public'))}, req.url);
|
||||
if (!fs.existsSync(filePath)) {
|
||||
filePath = path.join(${JSON.stringify(path.join(import.meta.dir, '..', '.claude', 'skills', 'critique', 'scripts'))}, basename);
|
||||
}
|
||||
} else {
|
||||
res.writeHead(404); res.end(); return;
|
||||
}
|
||||
|
||||
+1
-1
@@ -75,6 +75,6 @@
|
||||
<p>Purple-to-indigo gradient</p>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+1
-1
@@ -44,6 +44,6 @@
|
||||
<h3 style="color: rgb(220, 38, 38); font-size: 1.5rem;">Red heading — not AI purple</h3>
|
||||
<h3 style="color: rgb(180, 83, 9); font-size: 1.5rem;">Amber heading — distinctive</h3>
|
||||
</div>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+1
-1
@@ -132,6 +132,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+1
-1
@@ -237,6 +237,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+1
-1
@@ -108,6 +108,6 @@
|
||||
<strong>Warning:</strong> Your trial expires in 3 days. <a href="#" style="color: #d97706;">Upgrade now</a>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+1
-1
@@ -43,6 +43,6 @@
|
||||
<p style="font-size: 0.875rem; color: #6b7280;">Uniform 1px border — should NOT flag.</p>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+1
-1
@@ -8,4 +8,4 @@
|
||||
<p style="font-size: 15px; color: #6b7280;">Card description with close font sizes.</p>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
|
||||
+1
-1
@@ -131,6 +131,6 @@
|
||||
<p style="font-size: 0.8125rem; color: #9ca3af;">Inline dark card with side-tab.</p>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+1
-1
@@ -79,6 +79,6 @@
|
||||
<p style="font-size: 0.875rem; color: #94a3b8; margin-top: 0.25rem;">Shadow only. Clean.</p>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+1
-1
@@ -34,6 +34,6 @@
|
||||
|
||||
<h3>A Subheading</h3>
|
||||
<p>Can you tell this is a subheading? Exactly.</p>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+1
-1
@@ -40,6 +40,6 @@
|
||||
<h3>Strong Size Hierarchy</h3>
|
||||
<p>Sizes range from 12px to 48px — a 4:1 ratio with clear visual steps.</p>
|
||||
<p class="caption">Caption text is clearly distinct from body.</p>
|
||||
<script src="/.claude/skills/critique/scripts/detect-antipatterns-browser.js"></script>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user