Extension Detection Rules (from content.ts)

Section 1 — Below Size Thresholds

These <img> tags are smaller than the 50×50px / 1,000px² minimum. Extension should NOT show the button.

#1 — <img> 16×16
16 < 50 min side → skip
Should Ignore
tiny image
#2 — <img> 24×24
24 < 50 min side → skip
Should Ignore
small image
#3 — <img> 48×48
48 < 50 min side → skip
Should Ignore
almost big enough
#4 — <img> 50×50 (exact threshold)
50 = 50 min side, area 2500 > 1000 → passes (barely)
Edge — Exactly at Threshold
threshold test
#5 — <img> 120×8 (extreme aspect ratio)
8 < 50 min side → skip. Also ratio 15 > 10.
Should Ignore
thin strip
#6 — <img> 500×10 (wide banner strip)
10 < 50 min side → skip. Ratio 50 > 10.
Should Ignore
banner strip

Section 2 — URL Keyword Filtering

These images are large enough to detect, but their URLs contain blocked keywords. Extension should skip them.

#7 — URL contains "icon" (200×200)
URL match: 'icon' → skip despite valid size
Should Ignore
photo
#8 — URL contains "favicon" (200×200)
URL match: 'favicon' → skip
Should Ignore
photo
#9 — URL contains "logo" (200×200)
URL match: 'logo' → skip
Should Ignore
photo
#10 — URL contains "sprite" (200×200)
URL match: 'sprite' → skip
Should Ignore
photo
#11 — URL contains "avatar" (200×200)
URL match: 'avatar' → skip
Should Ignore
photo
#12 — URL contains "badge" (200×200)
URL match: 'badge' → skip
Should Ignore
photo
#13 — Clean URL, no keywords (200×200)
No blocked keywords in URL → should detect
Should Detect (control)
photo

Section 3 — Alt Text Filtering (Size-Dependent)

Alt text keywords only filter images with area < 10,000px². Large images with the same alt text should still be detected.

#14 — alt="icon" on 80×80 (area 6,400)
6,400 < 10,000 + alt matches 'icon' → skip
Should Ignore
icon
#15 — alt="company logo" on 90×90 (area 8,100)
8,100 < 10,000 + alt matches 'logo' → skip
Should Ignore
company logo
#16 — alt="icon" on 200×200 (area 40,000)
40,000 ≥ 10,000 → alt text filter does NOT apply. Should detect.
Should Detect
icon
#17 — alt="logo" on 300×200 (area 60,000)
60,000 ≥ 10,000 → alt text filter does NOT apply. Should detect.
Should Detect
logo

Section 4 — Navigation & Sidebar Context

Images inside nav, sidebar, menu-bar, or role="navigation" containers are skipped regardless of size.

#18 — 200×150 inside role="navigation"
Parent has role="navigation" → skip
Should Ignore
#19 — 200×150 inside class="sidebar"
Parent class matches /sidebar/ → skip
Should Ignore
#20 — 200×150 inside id="app-bar"
Parent id matches /app-bar/ → skip
Should Ignore
App Bar app bar image

Section 5 — CSS Visibility Edge Cases

The extension skips display:none, visibility:hidden, and opacity:0. But partial opacity, transforms, z-index, and overflow clipping are NOT filtered.

#21 — display:none (300×200)
display:none → skip. Image invisible.
Should Ignore
hidden (image is here but display:none)
#22 — visibility:hidden (300×200)
visibility:hidden → skip. Space reserved but invisible.
Should Ignore
hidden (image is here but visibility:hidden)
#23 — opacity:0 (300×200)
opacity exactly '0' → skip.
Should Ignore
transparent (image is here but opacity:0)
#24 — opacity:0.15 (300×200)
opacity 0.15 ≠ '0' → passes visibility check. Barely visible.
Should Detect (but questionable UX)
faded
#25 — z-index:-1 behind text overlay (400×250)
z-index doesn't affect visibility checks. pointerenter may not fire if covered.
Should Detect (but hover may be blocked)
behind text
Text overlay covers image
#26 — transform:scale(0.3) on 400×300
Renders ~120×90. getBoundingClientRect returns scaled size. 120 > 50 → passes.
Edge — Passes size check but looks small
scaled
#27 — overflow:hidden clips 400×300 to 120×80 container
Image rect may still report full size or clipped size depending on browser.
Edge — Button may appear outside visible area
clipped

Section 6 — Inspirational Images (Happy Path)

Standard content images with clean URLs, no blocked keywords, well above size thresholds. Extension should always detect these.

#28 — Card thumbnail 300×200
Clean URL, 300×200 ≫ thresholds → detect
Should Detect
landscape photo
#29 — Medium photo 400×300
Clean URL, standard photo → detect
Should Detect
architecture
#30 — Large photo 600×400
Clean URL, large image → detect
Should Detect
nature
#31 — Responsive hero (100% width)
Width fills container, well above thresholds → detect
Should Detect
hero image

Section 7 — Lazy Loading & Dynamic Sources

Extension monitors data-src, data-lazy, and loading="lazy". These simulate common lazy-load patterns.

#32 — data-src (simulated lazy load)
Has data-src and src. Extension checks data-src first.
Should Detect
lazy loaded
#33 — loading="lazy" native (300×200)
Native lazy loading. Extension monitors img[loading].
Should Detect
native lazy

Section 8 — CSS Background Images

Extension extracts background-image from computed styles. These test whether that detection works on various container sizes.

#34 — background-image on 300×200 div
Div with background-image, 300×200 → should detect
Should Detect
#35 — background-image on 40×40 span
40 < 50 min side → skip even for bg images
Should Ignore

Section 9 — Blind Spots (Extension Cannot See These)

These element types are not targeted by the extension at all. No <img> or background-image = invisible to the extension. Confirm the button does NOT appear.

#36 — Inline <svg> 300×200
Extension only targets <img> and background-image. SVG elements ignored.
Blind Spot — Not Detected
Inline SVG
#37 — <canvas> 400×250
Canvas is not an <img>. Extension doesn't target canvas elements.
Blind Spot — Not Detected
#38 — <object> SVG 250×200
Object embeds are not scanned by the extension.
Blind Spot — Not Detected
#39 — CSS mask-image SVG on div 200×200
mask-image is not background-image. Not detected.
Blind Spot — Not Detected
#40 — <img> with SVG src (data URI) 300×200
getAllImagesFromPage skips data: URLs. Hover detection may still work since it's an <img>.
Edge / Blind Spot — Check if hover works on data URI img
data uri svg

Section 10 — Positioning Edge Cases

The extension uses position:fixed for the button and viewport intersection checks. These test tricky positioning scenarios.

#41 — position:absolute 300×200
Absolutely positioned but in viewport → detect. Button uses fixed coords.
Should Detect
absolute
#42 — mix-blend-mode:multiply 300×200
Blend modes don't affect visibility checks → detect
Should Detect
blended

Section 11 — Cropped, Clipped & Scaled-Down Images (Your Actual Bug)

This is the core problem. The extension uses getBoundingClientRect() which reports the element's layout box, not the visible clipped area. A 1200px image inside a 60px overflow:hidden container still reports rect.width = 1200 → passes the 50px check → button appears on what looks like a tiny icon. Similarly, object-fit, clip-path, and CSS scaling can cause mismatches between what's visible and what the extension measures.

#44 — 1200×800 inside 48×48 overflow:hidden (avatar crop)
getBoundingClientRect() → 1200×800 (full img box). Visible: 48×48. Bug: button shows on "icon".
Bug — Button likely appears (should not)
avatar crop
Looks like a 48px avatar, but img element is 1200×800
#45 — 800×600 inside 64×64 overflow:hidden (thumbnail crop)
img rect = 800×600. Container shows 64×64. Button likely shows.
Bug — Button likely appears (should not)
thumbnail crop
64×64 visible, but img is 800×600
#46 — Negative margin + overflow:hidden (centered crop to 56×56)
Image offset with negative margins to center within small container. Common avatar pattern.
Bug — Button likely appears (should not)
centered crop
56px circle crop, img is 400×400 with negative margins
#47 — object-fit:cover on 48×48 <img> (natural: 1200×800)
img element is 48×48 via CSS. getBoundingClientRect() = 48×48. 48 < 50 → should skip. But test it.
Edge — Should ignore (48 < 50) but verify
avatar object-fit:cover, element is 48×48
#48 — object-fit:cover on 56×56 <img> (natural: 1200×800)
Element is 56×56. rect = 56×56, area 3136. Passes 50px + 1000 area checks. Button will show.
Edge — Button appears on small avatar (undesirable?)
avatar object-fit:cover, element is 56×56 — just above 50px threshold
#49 — object-fit:cover on 200×200 <img> (natural: 1200×800)
Element is 200×200. Large enough to be a real content image. Should detect.
Should Detect
cover photo
#50 — object-fit:contain on 60×60 <img> (natural: 800×400)
Image letterboxed inside 60×60 box. rect = 60×60, passes check. Visible image even smaller due to contain.
Edge — Button appears but image looks tiny
contained object-fit:contain, element is 60×60 but image letterboxed inside
#51 — clip-path: circle(30px) on 300×300 image
Image is 300×300 but clip-path shows only a 60px diameter circle. rect still = 300×300.
Bug — Button appears (visible area is only ~60px circle)
clipped Only a 60px circle visible, but rect reports 300×300
#52 — clip-path: inset(40%) on 400×300 image
Inset 40% from each edge → only 20% visible (80×60). rect still = 400×300.
Bug — Button appears (visible ~80×60)
inset clipped Inset 40% — tiny center visible, full rect reported
#53 — CSS width:52px height:auto (natural: 1200×800)
rect = 52×~35. Height 35 < 50 → should skip. But width passes. Test the interaction.
Edge — Should ignore (height < 50)
scaled down CSS scales 1200×800 to 52×~35
#54 — max-width:64px on 800×600 image
rect = 64×48. Height 48 < 50 → should skip.
Edge — Should ignore (height < 50)
max-width constrained max-width:64px, renders 64×48
#55 — transform:scale(0.1) on 600×400 (renders 60×40)
getBoundingClientRect() accounts for transforms → rect = 60×40. Height 40 < 50 → skip.
Edge — Should ignore (scaled height < 50)
scale transformed
transform:scale(0.1) — visually 60×40
#56 — Real-world profile card: 40×40 avatar via overflow:hidden
Simulates a typical social media profile card. Avatar container is 40×40, img is unconstrained.
Bug — Button shows over tiny avatar
profile
Jane Designer
@janedesigns
#57 — Real-world card grid: 80×80 thumbnails via overflow:hidden
Pinterest/Dribbble-style card. Container is 80×80, image is much larger.
Edge — Button shows on small thumbnail
card thumb
card thumb
card thumb
#58 — 1200×800 inside 400×250 overflow:hidden (large crop, should detect)
Container is 400×250 — a real content image size. Image overflows but visible area is large.
Should Detect (visible area is large enough)
large crop
#59 — Deeply nested overflow:hidden (outer 50×50, img 1000×1000)
Three levels of overflow:hidden containers. img rect may still report 1000×1000.
Bug — Button likely appears
deeply nested
Visible: ~50×50, img reports 1000×1000
#60 — Modern avatar: object-fit:cover + overflow:hidden parent (44×44)
img styled 44×44 with object-fit:cover inside overflow:hidden. rect = 44×44, below threshold.
Should Ignore (44 < 50)
avatar
Modern Avatar
object-fit:cover + overflow:hidden
#61 — Worst case: 2000×1500 unsized <img> in 32×32 overflow:hidden
No width/height on img element, no CSS sizing. Parent clips to 32×32. rect = 2000×1500. Button + mispositioned.
Bug — Button appears AND is likely positioned far outside visible area
worst case
32px visible, img is 2000×1500 with no CSS constraints
#43 — fixed 32×32 icon
fixed icon