Fix exclusion grouping duplicate images together

Exclusions were keyed only by content identifier (src / role-img
label), so multiple identical images (or repeated icons) shared one
key and excluding one silently excluded all of them. Each occurrence
now gets a per-run instance number appended to the identifier, so
duplicates can be excluded individually while staying stable across
reloads.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Sascha 2026-07-13 11:29:32 +02:00
parent 1cef0eddca
commit c6a92ea26c
4 changed files with 29 additions and 9 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -80,13 +80,24 @@
return null;
}
function isExcluded(img, exclusions) {
const id = imageIdentifier(img);
// Mehrere Bilder können dieselbe imageIdentifier() haben (z.B. dasselbe Icon
// mehrfach auf der Seite). Ohne Zusatz würde ein Ausschluss dann alle gleich
// aussehenden Bilder treffen. Der Zähler hängt daher pro Lauf eine laufende
// Nummer an, sodass jedes Vorkommen einzeln aus-/eingeschlossen werden kann
// stabil über Neuladen, solange Reihenfolge und Anzahl der Duplikate gleich bleiben.
function instanceIdentifier(img, occurrenceCounts) {
const base = imageIdentifier(img);
if (base === null) return null;
const n = occurrenceCounts.get(base) || 0;
occurrenceCounts.set(base, n + 1);
return `${base}#${n}`;
}
function isExcluded(id, exclusions) {
return id !== null && exclusions.includes(id);
}
function toggleExclusion(img) {
const id = imageIdentifier(img);
function toggleExclusion(id) {
if (id === null) return;
const exclusions = loadExclusions();
const idx = exclusions.indexOf(id);
@ -288,6 +299,7 @@
function run() {
removePreviousRun();
const exclusions = loadExclusions();
const occurrenceCounts = new Map();
const stats = { ok: 0, error: 0, warning: 0, excluded: 0, total: 0 };
// Fehlerhafte Verwendung von alt auf Nicht-<img>-Elementen
@ -302,14 +314,15 @@
deepQueryAll('img, [role="img"]', document, (img) => {
stats.total += 1;
const id = instanceIdentifier(img, occurrenceCounts);
if (isExcluded(img, exclusions)) {
if (isExcluded(id, exclusions)) {
stats.excluded += 1;
createLabel(img, 'excluded', ['Ausgeschlossen (manuell als dekorativ markiert)'], {
icon: '⦸',
position: 'absolute',
onClick: () => {
toggleExclusion(img);
toggleExclusion(id);
run();
}
});
@ -358,7 +371,7 @@
icon: kind === 'success' ? '✔' : kind === 'error' ? '✖' : '⚠️',
position: 'absolute',
onClick: () => {
toggleExclusion(img);
toggleExclusion(id);
run();
}
});

View File

@ -36,5 +36,12 @@
<p>8. Bild mit potenziell gefährlichem alt-Text (XSS-Test):</p>
<img src="https://via.placeholder.com/100x80/000000/ffffff?text=8" alt="&lt;img src=x onerror=alert('XSS')&gt;">
<p>9a. Dasselbe Bild dreimal ohne alt (Duplikat-Test nur dieses eine ausschließen):</p>
<img src="https://via.placeholder.com/100x80/999999/ffffff?text=9">
<p>9b. Zweites Vorkommen desselben Bildes:</p>
<img src="https://via.placeholder.com/100x80/999999/ffffff?text=9">
<p>9c. Drittes Vorkommen desselben Bildes:</p>
<img src="https://via.placeholder.com/100x80/999999/ffffff?text=9">
</body>
</html>