Files
pbakaus_impeccable/extension/popup/popup.js
T
Paul BakausandClaude Opus 4.6 e961d56252 Add Chrome DevTools extension for anti-pattern detection
Adds a Manifest V3 Chrome extension that injects the detector when
DevTools opens, with a dedicated panel for browsing findings, a toolbar
popup for quick scan/toggle, and per-rule settings synced via
chrome.storage. Categorizes anti-patterns into AI slop vs quality
issues with visual differentiation (sparkle prefix, panel grouping).
Overlay labels are polished with flush positioning, cycling for
multi-finding elements, and synchronized hover darkening.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 15:18:36 -07:00

68 lines
2.3 KiB
JavaScript

/**
* Impeccable DevTools Extension - Popup
*
* Quick controls: scan, toggle overlays, and see finding count.
*/
const countNumber = document.getElementById('count-number');
const countLabel = document.getElementById('count-label');
const btnScan = document.getElementById('btn-scan');
const btnToggle = document.getElementById('btn-toggle');
let overlaysVisible = true;
async function getActiveTabId() {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
return tab?.id;
}
function updateFromState(state) {
if (!state) return;
const count = state.findings?.reduce((sum, f) => sum + f.findings.length, 0) || 0;
countNumber.textContent = String(count);
countNumber.classList.toggle('has-findings', count > 0);
countLabel.textContent = count === 1 ? 'anti-pattern' : 'anti-patterns';
overlaysVisible = state.overlaysVisible !== false;
btnToggle.textContent = overlaysVisible ? 'Hide overlays' : 'Show overlays';
}
async function loadState() {
const tabId = await getActiveTabId();
if (!tabId) return;
chrome.runtime.sendMessage({ action: 'get-state', tabId }, updateFromState);
}
// Listen for real-time updates from service worker
chrome.runtime.onMessage.addListener((msg) => {
if (msg.action === 'findings-updated') {
const count = msg.findings?.reduce((sum, f) => sum + f.findings.length, 0) || 0;
countNumber.textContent = String(count);
countNumber.classList.toggle('has-findings', count > 0);
countLabel.textContent = count === 1 ? 'anti-pattern' : 'anti-patterns';
btnScan.textContent = 'Scan page';
btnScan.disabled = false;
}
if (msg.action === 'overlays-toggled-broadcast') {
overlaysVisible = msg.visible;
btnToggle.textContent = overlaysVisible ? 'Hide overlays' : 'Show overlays';
}
});
btnScan.addEventListener('click', async () => {
const tabId = await getActiveTabId();
if (!tabId) return;
btnScan.textContent = 'Scanning...';
btnScan.disabled = true;
chrome.runtime.sendMessage({ action: 'scan', tabId });
});
btnToggle.addEventListener('click', async () => {
const tabId = await getActiveTabId();
if (!tabId) return;
chrome.runtime.sendMessage({ action: 'toggle-overlays', tabId });
overlaysVisible = !overlaysVisible;
btnToggle.textContent = overlaysVisible ? 'Hide overlays' : 'Show overlays';
});
loadState();