mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-11 21:57:14 +03:00
Fix live detector empty state (#190)
* Fix live detector empty state * Fix live detector stale scan results
This commit is contained in:
@@ -1437,13 +1437,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1497,7 +1504,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -1565,7 +1572,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -1585,6 +1592,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1599,11 +1607,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -1618,10 +1626,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -4253,13 +4253,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4313,7 +4320,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -4381,7 +4388,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -4401,6 +4408,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4415,11 +4423,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -4434,10 +4442,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -6088,6 +6088,10 @@ void main() {
|
||||
let steerFocusRecoverTimer = null;
|
||||
const STEER_PAGE_FOCUS_PAUSE_MS = 500;
|
||||
let detectActive = false;
|
||||
let detectScanSeq = 0;
|
||||
let activeDetectScanId = null;
|
||||
let pendingDetectScanId = null;
|
||||
const DETECT_EMPTY_MESSAGE = 'No detector issues found.';
|
||||
const PICK_PREFS_KEY = 'impeccable-live-pick';
|
||||
const INTERACTION_PREFS_KEY = 'impeccable-live-interaction';
|
||||
const PLACEHOLDER_DEFAULT_HEIGHT = 80;
|
||||
@@ -7601,6 +7605,17 @@ void main() {
|
||||
let detectReady = false; // true once detect script posts 'impeccable-ready'
|
||||
let detectPendingScan = false; // scan requested before script was ready
|
||||
|
||||
function requestDetectScan() {
|
||||
const scanId = String(++detectScanSeq);
|
||||
activeDetectScanId = scanId;
|
||||
pendingDetectScanId = scanId;
|
||||
window.postMessage({
|
||||
source: 'impeccable-command',
|
||||
action: 'scan',
|
||||
config: { scanId },
|
||||
}, '*');
|
||||
}
|
||||
|
||||
function toggleDetect() {
|
||||
if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
|
||||
detectActive = !detectActive;
|
||||
@@ -7611,12 +7626,14 @@ void main() {
|
||||
detectPendingScan = true;
|
||||
loadDetectScript();
|
||||
} else if (detectReady) {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
} else {
|
||||
detectPendingScan = true;
|
||||
}
|
||||
} else {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'remove' }, '*');
|
||||
activeDetectScanId = null;
|
||||
pendingDetectScanId = null;
|
||||
detectCount = 0;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
@@ -7686,12 +7703,18 @@ void main() {
|
||||
detectReady = true;
|
||||
if (detectPendingScan && detectActive) {
|
||||
detectPendingScan = false;
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
}
|
||||
}
|
||||
// Scan results arrived
|
||||
if (e.data.source === 'impeccable-results') {
|
||||
if (!detectActive) return;
|
||||
if (activeDetectScanId && e.data.scanId !== activeDetectScanId) return;
|
||||
detectCount = e.data.count || 0;
|
||||
if (detectActive && pendingDetectScanId && detectCount === 0) {
|
||||
showToast(DETECT_EMPTY_MESSAGE, 3200);
|
||||
}
|
||||
pendingDetectScanId = null;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1437,13 +1437,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1497,7 +1504,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -1565,7 +1572,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -1585,6 +1592,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1599,11 +1607,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -1618,10 +1626,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -4253,13 +4253,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4313,7 +4320,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -4381,7 +4388,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -4401,6 +4408,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4415,11 +4423,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -4434,10 +4442,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -6088,6 +6088,10 @@ void main() {
|
||||
let steerFocusRecoverTimer = null;
|
||||
const STEER_PAGE_FOCUS_PAUSE_MS = 500;
|
||||
let detectActive = false;
|
||||
let detectScanSeq = 0;
|
||||
let activeDetectScanId = null;
|
||||
let pendingDetectScanId = null;
|
||||
const DETECT_EMPTY_MESSAGE = 'No detector issues found.';
|
||||
const PICK_PREFS_KEY = 'impeccable-live-pick';
|
||||
const INTERACTION_PREFS_KEY = 'impeccable-live-interaction';
|
||||
const PLACEHOLDER_DEFAULT_HEIGHT = 80;
|
||||
@@ -7601,6 +7605,17 @@ void main() {
|
||||
let detectReady = false; // true once detect script posts 'impeccable-ready'
|
||||
let detectPendingScan = false; // scan requested before script was ready
|
||||
|
||||
function requestDetectScan() {
|
||||
const scanId = String(++detectScanSeq);
|
||||
activeDetectScanId = scanId;
|
||||
pendingDetectScanId = scanId;
|
||||
window.postMessage({
|
||||
source: 'impeccable-command',
|
||||
action: 'scan',
|
||||
config: { scanId },
|
||||
}, '*');
|
||||
}
|
||||
|
||||
function toggleDetect() {
|
||||
if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
|
||||
detectActive = !detectActive;
|
||||
@@ -7611,12 +7626,14 @@ void main() {
|
||||
detectPendingScan = true;
|
||||
loadDetectScript();
|
||||
} else if (detectReady) {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
} else {
|
||||
detectPendingScan = true;
|
||||
}
|
||||
} else {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'remove' }, '*');
|
||||
activeDetectScanId = null;
|
||||
pendingDetectScanId = null;
|
||||
detectCount = 0;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
@@ -7686,12 +7703,18 @@ void main() {
|
||||
detectReady = true;
|
||||
if (detectPendingScan && detectActive) {
|
||||
detectPendingScan = false;
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
}
|
||||
}
|
||||
// Scan results arrived
|
||||
if (e.data.source === 'impeccable-results') {
|
||||
if (!detectActive) return;
|
||||
if (activeDetectScanId && e.data.scanId !== activeDetectScanId) return;
|
||||
detectCount = e.data.count || 0;
|
||||
if (detectActive && pendingDetectScanId && detectCount === 0) {
|
||||
showToast(DETECT_EMPTY_MESSAGE, 3200);
|
||||
}
|
||||
pendingDetectScanId = null;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1437,13 +1437,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1497,7 +1504,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -1565,7 +1572,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -1585,6 +1592,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1599,11 +1607,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -1618,10 +1626,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -4253,13 +4253,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4313,7 +4320,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -4381,7 +4388,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -4401,6 +4408,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4415,11 +4423,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -4434,10 +4442,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -6088,6 +6088,10 @@ void main() {
|
||||
let steerFocusRecoverTimer = null;
|
||||
const STEER_PAGE_FOCUS_PAUSE_MS = 500;
|
||||
let detectActive = false;
|
||||
let detectScanSeq = 0;
|
||||
let activeDetectScanId = null;
|
||||
let pendingDetectScanId = null;
|
||||
const DETECT_EMPTY_MESSAGE = 'No detector issues found.';
|
||||
const PICK_PREFS_KEY = 'impeccable-live-pick';
|
||||
const INTERACTION_PREFS_KEY = 'impeccable-live-interaction';
|
||||
const PLACEHOLDER_DEFAULT_HEIGHT = 80;
|
||||
@@ -7601,6 +7605,17 @@ void main() {
|
||||
let detectReady = false; // true once detect script posts 'impeccable-ready'
|
||||
let detectPendingScan = false; // scan requested before script was ready
|
||||
|
||||
function requestDetectScan() {
|
||||
const scanId = String(++detectScanSeq);
|
||||
activeDetectScanId = scanId;
|
||||
pendingDetectScanId = scanId;
|
||||
window.postMessage({
|
||||
source: 'impeccable-command',
|
||||
action: 'scan',
|
||||
config: { scanId },
|
||||
}, '*');
|
||||
}
|
||||
|
||||
function toggleDetect() {
|
||||
if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
|
||||
detectActive = !detectActive;
|
||||
@@ -7611,12 +7626,14 @@ void main() {
|
||||
detectPendingScan = true;
|
||||
loadDetectScript();
|
||||
} else if (detectReady) {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
} else {
|
||||
detectPendingScan = true;
|
||||
}
|
||||
} else {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'remove' }, '*');
|
||||
activeDetectScanId = null;
|
||||
pendingDetectScanId = null;
|
||||
detectCount = 0;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
@@ -7686,12 +7703,18 @@ void main() {
|
||||
detectReady = true;
|
||||
if (detectPendingScan && detectActive) {
|
||||
detectPendingScan = false;
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
}
|
||||
}
|
||||
// Scan results arrived
|
||||
if (e.data.source === 'impeccable-results') {
|
||||
if (!detectActive) return;
|
||||
if (activeDetectScanId && e.data.scanId !== activeDetectScanId) return;
|
||||
detectCount = e.data.count || 0;
|
||||
if (detectActive && pendingDetectScanId && detectCount === 0) {
|
||||
showToast(DETECT_EMPTY_MESSAGE, 3200);
|
||||
}
|
||||
pendingDetectScanId = null;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1437,13 +1437,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1497,7 +1504,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -1565,7 +1572,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -1585,6 +1592,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1599,11 +1607,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -1618,10 +1626,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -4253,13 +4253,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4313,7 +4320,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -4381,7 +4388,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -4401,6 +4408,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4415,11 +4423,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -4434,10 +4442,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -6088,6 +6088,10 @@ void main() {
|
||||
let steerFocusRecoverTimer = null;
|
||||
const STEER_PAGE_FOCUS_PAUSE_MS = 500;
|
||||
let detectActive = false;
|
||||
let detectScanSeq = 0;
|
||||
let activeDetectScanId = null;
|
||||
let pendingDetectScanId = null;
|
||||
const DETECT_EMPTY_MESSAGE = 'No detector issues found.';
|
||||
const PICK_PREFS_KEY = 'impeccable-live-pick';
|
||||
const INTERACTION_PREFS_KEY = 'impeccable-live-interaction';
|
||||
const PLACEHOLDER_DEFAULT_HEIGHT = 80;
|
||||
@@ -7601,6 +7605,17 @@ void main() {
|
||||
let detectReady = false; // true once detect script posts 'impeccable-ready'
|
||||
let detectPendingScan = false; // scan requested before script was ready
|
||||
|
||||
function requestDetectScan() {
|
||||
const scanId = String(++detectScanSeq);
|
||||
activeDetectScanId = scanId;
|
||||
pendingDetectScanId = scanId;
|
||||
window.postMessage({
|
||||
source: 'impeccable-command',
|
||||
action: 'scan',
|
||||
config: { scanId },
|
||||
}, '*');
|
||||
}
|
||||
|
||||
function toggleDetect() {
|
||||
if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
|
||||
detectActive = !detectActive;
|
||||
@@ -7611,12 +7626,14 @@ void main() {
|
||||
detectPendingScan = true;
|
||||
loadDetectScript();
|
||||
} else if (detectReady) {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
} else {
|
||||
detectPendingScan = true;
|
||||
}
|
||||
} else {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'remove' }, '*');
|
||||
activeDetectScanId = null;
|
||||
pendingDetectScanId = null;
|
||||
detectCount = 0;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
@@ -7686,12 +7703,18 @@ void main() {
|
||||
detectReady = true;
|
||||
if (detectPendingScan && detectActive) {
|
||||
detectPendingScan = false;
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
}
|
||||
}
|
||||
// Scan results arrived
|
||||
if (e.data.source === 'impeccable-results') {
|
||||
if (!detectActive) return;
|
||||
if (activeDetectScanId && e.data.scanId !== activeDetectScanId) return;
|
||||
detectCount = e.data.count || 0;
|
||||
if (detectActive && pendingDetectScanId && detectCount === 0) {
|
||||
showToast(DETECT_EMPTY_MESSAGE, 3200);
|
||||
}
|
||||
pendingDetectScanId = null;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1437,13 +1437,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1497,7 +1504,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -1565,7 +1572,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -1585,6 +1592,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1599,11 +1607,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -1618,10 +1626,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -4253,13 +4253,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4313,7 +4320,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -4381,7 +4388,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -4401,6 +4408,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4415,11 +4423,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -4434,10 +4442,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -6088,6 +6088,10 @@ void main() {
|
||||
let steerFocusRecoverTimer = null;
|
||||
const STEER_PAGE_FOCUS_PAUSE_MS = 500;
|
||||
let detectActive = false;
|
||||
let detectScanSeq = 0;
|
||||
let activeDetectScanId = null;
|
||||
let pendingDetectScanId = null;
|
||||
const DETECT_EMPTY_MESSAGE = 'No detector issues found.';
|
||||
const PICK_PREFS_KEY = 'impeccable-live-pick';
|
||||
const INTERACTION_PREFS_KEY = 'impeccable-live-interaction';
|
||||
const PLACEHOLDER_DEFAULT_HEIGHT = 80;
|
||||
@@ -7601,6 +7605,17 @@ void main() {
|
||||
let detectReady = false; // true once detect script posts 'impeccable-ready'
|
||||
let detectPendingScan = false; // scan requested before script was ready
|
||||
|
||||
function requestDetectScan() {
|
||||
const scanId = String(++detectScanSeq);
|
||||
activeDetectScanId = scanId;
|
||||
pendingDetectScanId = scanId;
|
||||
window.postMessage({
|
||||
source: 'impeccable-command',
|
||||
action: 'scan',
|
||||
config: { scanId },
|
||||
}, '*');
|
||||
}
|
||||
|
||||
function toggleDetect() {
|
||||
if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
|
||||
detectActive = !detectActive;
|
||||
@@ -7611,12 +7626,14 @@ void main() {
|
||||
detectPendingScan = true;
|
||||
loadDetectScript();
|
||||
} else if (detectReady) {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
} else {
|
||||
detectPendingScan = true;
|
||||
}
|
||||
} else {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'remove' }, '*');
|
||||
activeDetectScanId = null;
|
||||
pendingDetectScanId = null;
|
||||
detectCount = 0;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
@@ -7686,12 +7703,18 @@ void main() {
|
||||
detectReady = true;
|
||||
if (detectPendingScan && detectActive) {
|
||||
detectPendingScan = false;
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
}
|
||||
}
|
||||
// Scan results arrived
|
||||
if (e.data.source === 'impeccable-results') {
|
||||
if (!detectActive) return;
|
||||
if (activeDetectScanId && e.data.scanId !== activeDetectScanId) return;
|
||||
detectCount = e.data.count || 0;
|
||||
if (detectActive && pendingDetectScanId && detectCount === 0) {
|
||||
showToast(DETECT_EMPTY_MESSAGE, 3200);
|
||||
}
|
||||
pendingDetectScanId = null;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1437,13 +1437,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1497,7 +1504,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -1565,7 +1572,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -1585,6 +1592,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1599,11 +1607,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -1618,10 +1626,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -4253,13 +4253,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4313,7 +4320,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -4381,7 +4388,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -4401,6 +4408,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4415,11 +4423,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -4434,10 +4442,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -6088,6 +6088,10 @@ void main() {
|
||||
let steerFocusRecoverTimer = null;
|
||||
const STEER_PAGE_FOCUS_PAUSE_MS = 500;
|
||||
let detectActive = false;
|
||||
let detectScanSeq = 0;
|
||||
let activeDetectScanId = null;
|
||||
let pendingDetectScanId = null;
|
||||
const DETECT_EMPTY_MESSAGE = 'No detector issues found.';
|
||||
const PICK_PREFS_KEY = 'impeccable-live-pick';
|
||||
const INTERACTION_PREFS_KEY = 'impeccable-live-interaction';
|
||||
const PLACEHOLDER_DEFAULT_HEIGHT = 80;
|
||||
@@ -7601,6 +7605,17 @@ void main() {
|
||||
let detectReady = false; // true once detect script posts 'impeccable-ready'
|
||||
let detectPendingScan = false; // scan requested before script was ready
|
||||
|
||||
function requestDetectScan() {
|
||||
const scanId = String(++detectScanSeq);
|
||||
activeDetectScanId = scanId;
|
||||
pendingDetectScanId = scanId;
|
||||
window.postMessage({
|
||||
source: 'impeccable-command',
|
||||
action: 'scan',
|
||||
config: { scanId },
|
||||
}, '*');
|
||||
}
|
||||
|
||||
function toggleDetect() {
|
||||
if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
|
||||
detectActive = !detectActive;
|
||||
@@ -7611,12 +7626,14 @@ void main() {
|
||||
detectPendingScan = true;
|
||||
loadDetectScript();
|
||||
} else if (detectReady) {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
} else {
|
||||
detectPendingScan = true;
|
||||
}
|
||||
} else {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'remove' }, '*');
|
||||
activeDetectScanId = null;
|
||||
pendingDetectScanId = null;
|
||||
detectCount = 0;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
@@ -7686,12 +7703,18 @@ void main() {
|
||||
detectReady = true;
|
||||
if (detectPendingScan && detectActive) {
|
||||
detectPendingScan = false;
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
}
|
||||
}
|
||||
// Scan results arrived
|
||||
if (e.data.source === 'impeccable-results') {
|
||||
if (!detectActive) return;
|
||||
if (activeDetectScanId && e.data.scanId !== activeDetectScanId) return;
|
||||
detectCount = e.data.count || 0;
|
||||
if (detectActive && pendingDetectScanId && detectCount === 0) {
|
||||
showToast(DETECT_EMPTY_MESSAGE, 3200);
|
||||
}
|
||||
pendingDetectScanId = null;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1437,13 +1437,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1497,7 +1504,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -1565,7 +1572,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -1585,6 +1592,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1599,11 +1607,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -1618,10 +1626,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -4253,13 +4253,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4313,7 +4320,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -4381,7 +4388,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -4401,6 +4408,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4415,11 +4423,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -4434,10 +4442,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -6088,6 +6088,10 @@ void main() {
|
||||
let steerFocusRecoverTimer = null;
|
||||
const STEER_PAGE_FOCUS_PAUSE_MS = 500;
|
||||
let detectActive = false;
|
||||
let detectScanSeq = 0;
|
||||
let activeDetectScanId = null;
|
||||
let pendingDetectScanId = null;
|
||||
const DETECT_EMPTY_MESSAGE = 'No detector issues found.';
|
||||
const PICK_PREFS_KEY = 'impeccable-live-pick';
|
||||
const INTERACTION_PREFS_KEY = 'impeccable-live-interaction';
|
||||
const PLACEHOLDER_DEFAULT_HEIGHT = 80;
|
||||
@@ -7601,6 +7605,17 @@ void main() {
|
||||
let detectReady = false; // true once detect script posts 'impeccable-ready'
|
||||
let detectPendingScan = false; // scan requested before script was ready
|
||||
|
||||
function requestDetectScan() {
|
||||
const scanId = String(++detectScanSeq);
|
||||
activeDetectScanId = scanId;
|
||||
pendingDetectScanId = scanId;
|
||||
window.postMessage({
|
||||
source: 'impeccable-command',
|
||||
action: 'scan',
|
||||
config: { scanId },
|
||||
}, '*');
|
||||
}
|
||||
|
||||
function toggleDetect() {
|
||||
if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
|
||||
detectActive = !detectActive;
|
||||
@@ -7611,12 +7626,14 @@ void main() {
|
||||
detectPendingScan = true;
|
||||
loadDetectScript();
|
||||
} else if (detectReady) {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
} else {
|
||||
detectPendingScan = true;
|
||||
}
|
||||
} else {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'remove' }, '*');
|
||||
activeDetectScanId = null;
|
||||
pendingDetectScanId = null;
|
||||
detectCount = 0;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
@@ -7686,12 +7703,18 @@ void main() {
|
||||
detectReady = true;
|
||||
if (detectPendingScan && detectActive) {
|
||||
detectPendingScan = false;
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
}
|
||||
}
|
||||
// Scan results arrived
|
||||
if (e.data.source === 'impeccable-results') {
|
||||
if (!detectActive) return;
|
||||
if (activeDetectScanId && e.data.scanId !== activeDetectScanId) return;
|
||||
detectCount = e.data.count || 0;
|
||||
if (detectActive && pendingDetectScanId && detectCount === 0) {
|
||||
showToast(DETECT_EMPTY_MESSAGE, 3200);
|
||||
}
|
||||
pendingDetectScanId = null;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1437,13 +1437,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1497,7 +1504,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -1565,7 +1572,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -1585,6 +1592,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1599,11 +1607,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -1618,10 +1626,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -4253,13 +4253,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4313,7 +4320,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -4381,7 +4388,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -4401,6 +4408,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4415,11 +4423,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -4434,10 +4442,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -6088,6 +6088,10 @@ void main() {
|
||||
let steerFocusRecoverTimer = null;
|
||||
const STEER_PAGE_FOCUS_PAUSE_MS = 500;
|
||||
let detectActive = false;
|
||||
let detectScanSeq = 0;
|
||||
let activeDetectScanId = null;
|
||||
let pendingDetectScanId = null;
|
||||
const DETECT_EMPTY_MESSAGE = 'No detector issues found.';
|
||||
const PICK_PREFS_KEY = 'impeccable-live-pick';
|
||||
const INTERACTION_PREFS_KEY = 'impeccable-live-interaction';
|
||||
const PLACEHOLDER_DEFAULT_HEIGHT = 80;
|
||||
@@ -7601,6 +7605,17 @@ void main() {
|
||||
let detectReady = false; // true once detect script posts 'impeccable-ready'
|
||||
let detectPendingScan = false; // scan requested before script was ready
|
||||
|
||||
function requestDetectScan() {
|
||||
const scanId = String(++detectScanSeq);
|
||||
activeDetectScanId = scanId;
|
||||
pendingDetectScanId = scanId;
|
||||
window.postMessage({
|
||||
source: 'impeccable-command',
|
||||
action: 'scan',
|
||||
config: { scanId },
|
||||
}, '*');
|
||||
}
|
||||
|
||||
function toggleDetect() {
|
||||
if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
|
||||
detectActive = !detectActive;
|
||||
@@ -7611,12 +7626,14 @@ void main() {
|
||||
detectPendingScan = true;
|
||||
loadDetectScript();
|
||||
} else if (detectReady) {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
} else {
|
||||
detectPendingScan = true;
|
||||
}
|
||||
} else {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'remove' }, '*');
|
||||
activeDetectScanId = null;
|
||||
pendingDetectScanId = null;
|
||||
detectCount = 0;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
@@ -7686,12 +7703,18 @@ void main() {
|
||||
detectReady = true;
|
||||
if (detectPendingScan && detectActive) {
|
||||
detectPendingScan = false;
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
}
|
||||
}
|
||||
// Scan results arrived
|
||||
if (e.data.source === 'impeccable-results') {
|
||||
if (!detectActive) return;
|
||||
if (activeDetectScanId && e.data.scanId !== activeDetectScanId) return;
|
||||
detectCount = e.data.count || 0;
|
||||
if (detectActive && pendingDetectScanId && detectCount === 0) {
|
||||
showToast(DETECT_EMPTY_MESSAGE, 3200);
|
||||
}
|
||||
pendingDetectScanId = null;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1437,13 +1437,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1497,7 +1504,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -1565,7 +1572,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -1585,6 +1592,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1599,11 +1607,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -1618,10 +1626,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -4253,13 +4253,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4313,7 +4320,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -4381,7 +4388,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -4401,6 +4408,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4415,11 +4423,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -4434,10 +4442,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -6088,6 +6088,10 @@ void main() {
|
||||
let steerFocusRecoverTimer = null;
|
||||
const STEER_PAGE_FOCUS_PAUSE_MS = 500;
|
||||
let detectActive = false;
|
||||
let detectScanSeq = 0;
|
||||
let activeDetectScanId = null;
|
||||
let pendingDetectScanId = null;
|
||||
const DETECT_EMPTY_MESSAGE = 'No detector issues found.';
|
||||
const PICK_PREFS_KEY = 'impeccable-live-pick';
|
||||
const INTERACTION_PREFS_KEY = 'impeccable-live-interaction';
|
||||
const PLACEHOLDER_DEFAULT_HEIGHT = 80;
|
||||
@@ -7601,6 +7605,17 @@ void main() {
|
||||
let detectReady = false; // true once detect script posts 'impeccable-ready'
|
||||
let detectPendingScan = false; // scan requested before script was ready
|
||||
|
||||
function requestDetectScan() {
|
||||
const scanId = String(++detectScanSeq);
|
||||
activeDetectScanId = scanId;
|
||||
pendingDetectScanId = scanId;
|
||||
window.postMessage({
|
||||
source: 'impeccable-command',
|
||||
action: 'scan',
|
||||
config: { scanId },
|
||||
}, '*');
|
||||
}
|
||||
|
||||
function toggleDetect() {
|
||||
if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
|
||||
detectActive = !detectActive;
|
||||
@@ -7611,12 +7626,14 @@ void main() {
|
||||
detectPendingScan = true;
|
||||
loadDetectScript();
|
||||
} else if (detectReady) {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
} else {
|
||||
detectPendingScan = true;
|
||||
}
|
||||
} else {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'remove' }, '*');
|
||||
activeDetectScanId = null;
|
||||
pendingDetectScanId = null;
|
||||
detectCount = 0;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
@@ -7686,12 +7703,18 @@ void main() {
|
||||
detectReady = true;
|
||||
if (detectPendingScan && detectActive) {
|
||||
detectPendingScan = false;
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
}
|
||||
}
|
||||
// Scan results arrived
|
||||
if (e.data.source === 'impeccable-results') {
|
||||
if (!detectActive) return;
|
||||
if (activeDetectScanId && e.data.scanId !== activeDetectScanId) return;
|
||||
detectCount = e.data.count || 0;
|
||||
if (detectActive && pendingDetectScanId && detectCount === 0) {
|
||||
showToast(DETECT_EMPTY_MESSAGE, 3200);
|
||||
}
|
||||
pendingDetectScanId = null;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1437,13 +1437,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1497,7 +1504,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -1565,7 +1572,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -1585,6 +1592,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1599,11 +1607,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -1618,10 +1626,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -4253,13 +4253,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4313,7 +4320,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -4381,7 +4388,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -4401,6 +4408,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4415,11 +4423,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -4434,10 +4442,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -6088,6 +6088,10 @@ void main() {
|
||||
let steerFocusRecoverTimer = null;
|
||||
const STEER_PAGE_FOCUS_PAUSE_MS = 500;
|
||||
let detectActive = false;
|
||||
let detectScanSeq = 0;
|
||||
let activeDetectScanId = null;
|
||||
let pendingDetectScanId = null;
|
||||
const DETECT_EMPTY_MESSAGE = 'No detector issues found.';
|
||||
const PICK_PREFS_KEY = 'impeccable-live-pick';
|
||||
const INTERACTION_PREFS_KEY = 'impeccable-live-interaction';
|
||||
const PLACEHOLDER_DEFAULT_HEIGHT = 80;
|
||||
@@ -7601,6 +7605,17 @@ void main() {
|
||||
let detectReady = false; // true once detect script posts 'impeccable-ready'
|
||||
let detectPendingScan = false; // scan requested before script was ready
|
||||
|
||||
function requestDetectScan() {
|
||||
const scanId = String(++detectScanSeq);
|
||||
activeDetectScanId = scanId;
|
||||
pendingDetectScanId = scanId;
|
||||
window.postMessage({
|
||||
source: 'impeccable-command',
|
||||
action: 'scan',
|
||||
config: { scanId },
|
||||
}, '*');
|
||||
}
|
||||
|
||||
function toggleDetect() {
|
||||
if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
|
||||
detectActive = !detectActive;
|
||||
@@ -7611,12 +7626,14 @@ void main() {
|
||||
detectPendingScan = true;
|
||||
loadDetectScript();
|
||||
} else if (detectReady) {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
} else {
|
||||
detectPendingScan = true;
|
||||
}
|
||||
} else {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'remove' }, '*');
|
||||
activeDetectScanId = null;
|
||||
pendingDetectScanId = null;
|
||||
detectCount = 0;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
@@ -7686,12 +7703,18 @@ void main() {
|
||||
detectReady = true;
|
||||
if (detectPendingScan && detectActive) {
|
||||
detectPendingScan = false;
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
}
|
||||
}
|
||||
// Scan results arrived
|
||||
if (e.data.source === 'impeccable-results') {
|
||||
if (!detectActive) return;
|
||||
if (activeDetectScanId && e.data.scanId !== activeDetectScanId) return;
|
||||
detectCount = e.data.count || 0;
|
||||
if (detectActive && pendingDetectScanId && detectCount === 0) {
|
||||
showToast(DETECT_EMPTY_MESSAGE, 3200);
|
||||
}
|
||||
pendingDetectScanId = null;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1437,13 +1437,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1497,7 +1504,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -1565,7 +1572,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -1585,6 +1592,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1599,11 +1607,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -1618,10 +1626,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -4253,13 +4253,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4313,7 +4320,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -4381,7 +4388,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -4401,6 +4408,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4415,11 +4423,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -4434,10 +4442,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -6088,6 +6088,10 @@ void main() {
|
||||
let steerFocusRecoverTimer = null;
|
||||
const STEER_PAGE_FOCUS_PAUSE_MS = 500;
|
||||
let detectActive = false;
|
||||
let detectScanSeq = 0;
|
||||
let activeDetectScanId = null;
|
||||
let pendingDetectScanId = null;
|
||||
const DETECT_EMPTY_MESSAGE = 'No detector issues found.';
|
||||
const PICK_PREFS_KEY = 'impeccable-live-pick';
|
||||
const INTERACTION_PREFS_KEY = 'impeccable-live-interaction';
|
||||
const PLACEHOLDER_DEFAULT_HEIGHT = 80;
|
||||
@@ -7601,6 +7605,17 @@ void main() {
|
||||
let detectReady = false; // true once detect script posts 'impeccable-ready'
|
||||
let detectPendingScan = false; // scan requested before script was ready
|
||||
|
||||
function requestDetectScan() {
|
||||
const scanId = String(++detectScanSeq);
|
||||
activeDetectScanId = scanId;
|
||||
pendingDetectScanId = scanId;
|
||||
window.postMessage({
|
||||
source: 'impeccable-command',
|
||||
action: 'scan',
|
||||
config: { scanId },
|
||||
}, '*');
|
||||
}
|
||||
|
||||
function toggleDetect() {
|
||||
if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
|
||||
detectActive = !detectActive;
|
||||
@@ -7611,12 +7626,14 @@ void main() {
|
||||
detectPendingScan = true;
|
||||
loadDetectScript();
|
||||
} else if (detectReady) {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
} else {
|
||||
detectPendingScan = true;
|
||||
}
|
||||
} else {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'remove' }, '*');
|
||||
activeDetectScanId = null;
|
||||
pendingDetectScanId = null;
|
||||
detectCount = 0;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
@@ -7686,12 +7703,18 @@ void main() {
|
||||
detectReady = true;
|
||||
if (detectPendingScan && detectActive) {
|
||||
detectPendingScan = false;
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
}
|
||||
}
|
||||
// Scan results arrived
|
||||
if (e.data.source === 'impeccable-results') {
|
||||
if (!detectActive) return;
|
||||
if (activeDetectScanId && e.data.scanId !== activeDetectScanId) return;
|
||||
detectCount = e.data.count || 0;
|
||||
if (detectActive && pendingDetectScanId && detectCount === 0) {
|
||||
showToast(DETECT_EMPTY_MESSAGE, 3200);
|
||||
}
|
||||
pendingDetectScanId = null;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1437,13 +1437,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1497,7 +1504,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -1565,7 +1572,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -1585,6 +1592,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1599,11 +1607,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -1618,10 +1626,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -4253,13 +4253,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4313,7 +4320,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -4381,7 +4388,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -4401,6 +4408,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4415,11 +4423,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -4434,10 +4442,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -6088,6 +6088,10 @@ void main() {
|
||||
let steerFocusRecoverTimer = null;
|
||||
const STEER_PAGE_FOCUS_PAUSE_MS = 500;
|
||||
let detectActive = false;
|
||||
let detectScanSeq = 0;
|
||||
let activeDetectScanId = null;
|
||||
let pendingDetectScanId = null;
|
||||
const DETECT_EMPTY_MESSAGE = 'No detector issues found.';
|
||||
const PICK_PREFS_KEY = 'impeccable-live-pick';
|
||||
const INTERACTION_PREFS_KEY = 'impeccable-live-interaction';
|
||||
const PLACEHOLDER_DEFAULT_HEIGHT = 80;
|
||||
@@ -7601,6 +7605,17 @@ void main() {
|
||||
let detectReady = false; // true once detect script posts 'impeccable-ready'
|
||||
let detectPendingScan = false; // scan requested before script was ready
|
||||
|
||||
function requestDetectScan() {
|
||||
const scanId = String(++detectScanSeq);
|
||||
activeDetectScanId = scanId;
|
||||
pendingDetectScanId = scanId;
|
||||
window.postMessage({
|
||||
source: 'impeccable-command',
|
||||
action: 'scan',
|
||||
config: { scanId },
|
||||
}, '*');
|
||||
}
|
||||
|
||||
function toggleDetect() {
|
||||
if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
|
||||
detectActive = !detectActive;
|
||||
@@ -7611,12 +7626,14 @@ void main() {
|
||||
detectPendingScan = true;
|
||||
loadDetectScript();
|
||||
} else if (detectReady) {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
} else {
|
||||
detectPendingScan = true;
|
||||
}
|
||||
} else {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'remove' }, '*');
|
||||
activeDetectScanId = null;
|
||||
pendingDetectScanId = null;
|
||||
detectCount = 0;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
@@ -7686,12 +7703,18 @@ void main() {
|
||||
detectReady = true;
|
||||
if (detectPendingScan && detectActive) {
|
||||
detectPendingScan = false;
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
}
|
||||
}
|
||||
// Scan results arrived
|
||||
if (e.data.source === 'impeccable-results') {
|
||||
if (!detectActive) return;
|
||||
if (activeDetectScanId && e.data.scanId !== activeDetectScanId) return;
|
||||
detectCount = e.data.count || 0;
|
||||
if (detectActive && pendingDetectScanId && detectCount === 0) {
|
||||
showToast(DETECT_EMPTY_MESSAGE, 3200);
|
||||
}
|
||||
pendingDetectScanId = null;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1437,13 +1437,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1497,7 +1504,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -1565,7 +1572,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -1585,6 +1592,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1599,11 +1607,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -1618,10 +1626,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -4253,13 +4253,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4313,7 +4320,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -4381,7 +4388,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -4401,6 +4408,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4415,11 +4423,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -4434,10 +4442,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -1437,13 +1437,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1497,7 +1504,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -1565,7 +1572,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -1585,6 +1592,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -1599,11 +1607,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -1618,10 +1626,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -4253,13 +4253,20 @@ if (IS_BROWSER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap) {
|
||||
function scanResultMeta(options = {}) {
|
||||
const scanId = options.scanId;
|
||||
if (typeof scanId !== 'string' && typeof scanId !== 'number') return {};
|
||||
return { scanId: String(scanId) };
|
||||
}
|
||||
|
||||
function postSerializedFindings(groupMap, options = {}) {
|
||||
if (!EXTENSION_MODE) return;
|
||||
const allFindings = browserFindingsFromMap(groupMap);
|
||||
window.postMessage({
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4313,7 +4320,7 @@ if (IS_BROWSER) {
|
||||
rememberVisualContrastAnalysis(result);
|
||||
const added = addVisualContrastResult(groupMap, result, { decorate: true });
|
||||
if (added) {
|
||||
postSerializedFindings(groupMap);
|
||||
postSerializedFindings(groupMap, options);
|
||||
window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-resolved', {
|
||||
detail: {
|
||||
selector: result.selector,
|
||||
@@ -4381,7 +4388,7 @@ if (IS_BROWSER) {
|
||||
overlayIndex = 0;
|
||||
}
|
||||
|
||||
function renderBrowserFindings(collected) {
|
||||
function renderBrowserFindings(collected, options = {}) {
|
||||
const { allFindings, pageLevelFindings } = collected;
|
||||
|
||||
for (const { el, findings } of allFindings) {
|
||||
@@ -4401,6 +4408,7 @@ if (IS_BROWSER) {
|
||||
source: 'impeccable-results',
|
||||
findings: serializeFindings(allFindings),
|
||||
count: allFindings.length,
|
||||
...scanResultMeta(options),
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -4415,11 +4423,11 @@ if (IS_BROWSER) {
|
||||
clearOverlays();
|
||||
const generation = scanGeneration;
|
||||
const collected = collectBrowserFindings();
|
||||
const allFindings = renderBrowserFindings(collected);
|
||||
const allFindings = renderBrowserFindings(collected, options);
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
addVisualContrastFindings(collected.groupMap, options, { decorate: true, generation })
|
||||
.then(() => {
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap);
|
||||
if (generation === scanGeneration) postSerializedFindings(collected.groupMap, options);
|
||||
})
|
||||
.catch(err => {
|
||||
reportVisualContrastError(err);
|
||||
@@ -4434,10 +4442,10 @@ if (IS_BROWSER) {
|
||||
if (shouldRunVisualContrast(options)) {
|
||||
const collected = await collectBrowserFindingsAsync(options, { generation, scheduleLazy: true });
|
||||
if (generation !== scanGeneration) return [];
|
||||
return renderBrowserFindings(collected);
|
||||
return renderBrowserFindings(collected, options);
|
||||
}
|
||||
lastVisualContrastAnalyses = [];
|
||||
return renderBrowserFindings(collectBrowserFindings());
|
||||
return renderBrowserFindings(collectBrowserFindings(), options);
|
||||
};
|
||||
|
||||
const detect = function(options = {}) {
|
||||
|
||||
@@ -6088,6 +6088,10 @@ void main() {
|
||||
let steerFocusRecoverTimer = null;
|
||||
const STEER_PAGE_FOCUS_PAUSE_MS = 500;
|
||||
let detectActive = false;
|
||||
let detectScanSeq = 0;
|
||||
let activeDetectScanId = null;
|
||||
let pendingDetectScanId = null;
|
||||
const DETECT_EMPTY_MESSAGE = 'No detector issues found.';
|
||||
const PICK_PREFS_KEY = 'impeccable-live-pick';
|
||||
const INTERACTION_PREFS_KEY = 'impeccable-live-interaction';
|
||||
const PLACEHOLDER_DEFAULT_HEIGHT = 80;
|
||||
@@ -7601,6 +7605,17 @@ void main() {
|
||||
let detectReady = false; // true once detect script posts 'impeccable-ready'
|
||||
let detectPendingScan = false; // scan requested before script was ready
|
||||
|
||||
function requestDetectScan() {
|
||||
const scanId = String(++detectScanSeq);
|
||||
activeDetectScanId = scanId;
|
||||
pendingDetectScanId = scanId;
|
||||
window.postMessage({
|
||||
source: 'impeccable-command',
|
||||
action: 'scan',
|
||||
config: { scanId },
|
||||
}, '*');
|
||||
}
|
||||
|
||||
function toggleDetect() {
|
||||
if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
|
||||
detectActive = !detectActive;
|
||||
@@ -7611,12 +7626,14 @@ void main() {
|
||||
detectPendingScan = true;
|
||||
loadDetectScript();
|
||||
} else if (detectReady) {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
} else {
|
||||
detectPendingScan = true;
|
||||
}
|
||||
} else {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'remove' }, '*');
|
||||
activeDetectScanId = null;
|
||||
pendingDetectScanId = null;
|
||||
detectCount = 0;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
@@ -7686,12 +7703,18 @@ void main() {
|
||||
detectReady = true;
|
||||
if (detectPendingScan && detectActive) {
|
||||
detectPendingScan = false;
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
}
|
||||
}
|
||||
// Scan results arrived
|
||||
if (e.data.source === 'impeccable-results') {
|
||||
if (!detectActive) return;
|
||||
if (activeDetectScanId && e.data.scanId !== activeDetectScanId) return;
|
||||
detectCount = e.data.count || 0;
|
||||
if (detectActive && pendingDetectScanId && detectCount === 0) {
|
||||
showToast(DETECT_EMPTY_MESSAGE, 3200);
|
||||
}
|
||||
pendingDetectScanId = null;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6088,6 +6088,10 @@ void main() {
|
||||
let steerFocusRecoverTimer = null;
|
||||
const STEER_PAGE_FOCUS_PAUSE_MS = 500;
|
||||
let detectActive = false;
|
||||
let detectScanSeq = 0;
|
||||
let activeDetectScanId = null;
|
||||
let pendingDetectScanId = null;
|
||||
const DETECT_EMPTY_MESSAGE = 'No detector issues found.';
|
||||
const PICK_PREFS_KEY = 'impeccable-live-pick';
|
||||
const INTERACTION_PREFS_KEY = 'impeccable-live-interaction';
|
||||
const PLACEHOLDER_DEFAULT_HEIGHT = 80;
|
||||
@@ -7601,6 +7605,17 @@ void main() {
|
||||
let detectReady = false; // true once detect script posts 'impeccable-ready'
|
||||
let detectPendingScan = false; // scan requested before script was ready
|
||||
|
||||
function requestDetectScan() {
|
||||
const scanId = String(++detectScanSeq);
|
||||
activeDetectScanId = scanId;
|
||||
pendingDetectScanId = scanId;
|
||||
window.postMessage({
|
||||
source: 'impeccable-command',
|
||||
action: 'scan',
|
||||
config: { scanId },
|
||||
}, '*');
|
||||
}
|
||||
|
||||
function toggleDetect() {
|
||||
if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
|
||||
detectActive = !detectActive;
|
||||
@@ -7611,12 +7626,14 @@ void main() {
|
||||
detectPendingScan = true;
|
||||
loadDetectScript();
|
||||
} else if (detectReady) {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
} else {
|
||||
detectPendingScan = true;
|
||||
}
|
||||
} else {
|
||||
window.postMessage({ source: 'impeccable-command', action: 'remove' }, '*');
|
||||
activeDetectScanId = null;
|
||||
pendingDetectScanId = null;
|
||||
detectCount = 0;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
@@ -7686,12 +7703,18 @@ void main() {
|
||||
detectReady = true;
|
||||
if (detectPendingScan && detectActive) {
|
||||
detectPendingScan = false;
|
||||
window.postMessage({ source: 'impeccable-command', action: 'scan' }, '*');
|
||||
requestDetectScan();
|
||||
}
|
||||
}
|
||||
// Scan results arrived
|
||||
if (e.data.source === 'impeccable-results') {
|
||||
if (!detectActive) return;
|
||||
if (activeDetectScanId && e.data.scanId !== activeDetectScanId) return;
|
||||
detectCount = e.data.count || 0;
|
||||
if (detectActive && pendingDetectScanId && detectCount === 0) {
|
||||
showToast(DETECT_EMPTY_MESSAGE, 3200);
|
||||
}
|
||||
pendingDetectScanId = null;
|
||||
updateGlobalBarState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,6 +577,61 @@ describe('detectUrl — browser-only fixtures', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('extension mode echoes scan ids on result messages', async () => {
|
||||
const puppeteer = await import('puppeteer');
|
||||
const browser = await puppeteer.default.launch({
|
||||
headless: true,
|
||||
args: process.env.CI ? ['--no-sandbox', '--disable-setuid-sandbox'] : [],
|
||||
});
|
||||
try {
|
||||
const page = await browser.newPage();
|
||||
await page.setViewport({ width: 1280, height: 800 });
|
||||
await page.goto(`${baseUrl}/fixtures/antipatterns/should-pass.html`, { waitUntil: 'load' });
|
||||
const browserScript = fs.readFileSync(path.join(ROOT, 'cli/engine/detect-antipatterns-browser.js'), 'utf-8');
|
||||
await page.evaluate(() => {
|
||||
document.documentElement.dataset.impeccableExtension = 'true';
|
||||
window.__impeccableMessages = [];
|
||||
window.addEventListener('message', event => {
|
||||
if (event.source !== window || !event.data?.source?.startsWith('impeccable-')) return;
|
||||
window.__impeccableMessages.push(event.data);
|
||||
});
|
||||
});
|
||||
await page.evaluate(browserScript);
|
||||
const result = await page.evaluate(async () => {
|
||||
window.postMessage({
|
||||
source: 'impeccable-command',
|
||||
action: 'scan',
|
||||
config: { scanId: 'scan-2' },
|
||||
}, '*');
|
||||
const deadline = Date.now() + 1000;
|
||||
while (
|
||||
Date.now() < deadline &&
|
||||
!window.__impeccableMessages.some(message =>
|
||||
message.source === 'impeccable-results' &&
|
||||
message.scanId === 'scan-2'
|
||||
)
|
||||
) {
|
||||
await new Promise(resolve => setTimeout(resolve, 25));
|
||||
}
|
||||
const resultMessage = window.__impeccableMessages.find(message =>
|
||||
message.source === 'impeccable-results' &&
|
||||
message.scanId === 'scan-2'
|
||||
);
|
||||
return {
|
||||
ready: window.__impeccableMessages.some(message => message.source === 'impeccable-ready'),
|
||||
scanId: resultMessage?.scanId || null,
|
||||
count: resultMessage?.count ?? null,
|
||||
};
|
||||
});
|
||||
assert.equal(result.ready, true, `expected extension ready message, got: ${JSON.stringify(result)}`);
|
||||
assert.equal(result.scanId, 'scan-2', `expected scan id echo in results, got: ${JSON.stringify(result)}`);
|
||||
assert.equal(result.count, 0, `expected clean fixture to have no findings, got: ${JSON.stringify(result)}`);
|
||||
await page.close();
|
||||
} finally {
|
||||
await browser.close().catch(() => {});
|
||||
}
|
||||
});
|
||||
|
||||
it('browser API: impeccableDetect is pure, impeccableScan decorates', async () => {
|
||||
const puppeteer = await import('puppeteer');
|
||||
const browser = await puppeteer.default.launch({
|
||||
|
||||
@@ -292,6 +292,34 @@ describe('live-browser.js regression guards', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('detect mode shows an empty result toast once per requested scan', () => {
|
||||
assert.match(
|
||||
SOURCE,
|
||||
/const DETECT_EMPTY_MESSAGE = 'No detector issues found\.';/,
|
||||
'live detector zero result copy should live in one named constant',
|
||||
);
|
||||
assert.match(
|
||||
SOURCE,
|
||||
/function requestDetectScan\(\)[\s\S]{0,240}?const scanId = String\(\+\+detectScanSeq\);[\s\S]{0,80}?activeDetectScanId = scanId;[\s\S]{0,160}?config: \{ scanId \}/,
|
||||
'Detect scans must send a fresh scan id to the detector',
|
||||
);
|
||||
assert.match(
|
||||
SOURCE,
|
||||
/if \(!detectActive\) return;[\s\S]{0,80}?if \(activeDetectScanId && e\.data\.scanId !== activeDetectScanId\) return;/,
|
||||
'live detector results must ignore inactive and stale scan ids',
|
||||
);
|
||||
assert.match(
|
||||
SOURCE,
|
||||
/if \(detectActive && pendingDetectScanId && detectCount === 0\) \{[\s\S]{0,80}?showToast\(DETECT_EMPTY_MESSAGE, 3200\);[\s\S]{0,120}?pendingDetectScanId = null;/,
|
||||
'a matching zero result scan must use the existing toast UI and clear the pending scan id',
|
||||
);
|
||||
assert.match(
|
||||
SOURCE,
|
||||
/window\.postMessage\(\{ source: 'impeccable-command', action: 'remove' \}, '\*'\);[\s\S]{0,80}?activeDetectScanId = null;[\s\S]{0,80}?pendingDetectScanId = null;/,
|
||||
'turning Detect off must clear scan ids',
|
||||
);
|
||||
});
|
||||
|
||||
it('insert mode UI and generate payload guards', () => {
|
||||
assert.match(SOURCE, /function toggleInsert\(\)/, 'global bar must expose insert toggle');
|
||||
assert.match(SOURCE, /PREFIX \+ '-insert-toggle'/, 'insert toggle needs stable id');
|
||||
|
||||
Reference in New Issue
Block a user