Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/pageScanner/checks/img-alt-empty-check.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ export default {
return true;
}

// Skip 1x1 tracking pixels (any src or base64)
if ( hasEmptyAlt && isTrackingPixel( node ) ) {
return true;
Comment on lines +28 to +29

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Limit tracking-pixel skip to img elements

The img_alt_empty selector also runs this check for input[type="image"][alt=""], so this new exception makes a 1×1 image submit button such as <input type="image" alt="" width="1" height="1"> pass. Unlike passive tracking pixels, image inputs are controls and still need a non-empty accessible name; the existing tests already expect empty-alt image inputs to be violations, but this dimension-based bypass now lets those violations through when the control is 1×1.

Useful? React with 👍 / 👎.

}

// Return false if alt is empty and none of the exceptions apply
return ! hasEmptyAlt;
},
Expand Down Expand Up @@ -78,6 +83,33 @@ function isInsideValidCaption( node ) {
return false;
}

/**
* Check if image is a 1x1 tracking pixel.
* Checks both HTML attributes and computed natural dimensions.
* @param {HTMLElement} node - The node to check
* @return {boolean} True if image is a 1x1 tracking pixel
*/
function isTrackingPixel( node ) {
// Check HTML width/height attributes
const widthAttr = node.getAttribute( 'width' );
const heightAttr = node.getAttribute( 'height' );
if ( widthAttr === '1' && heightAttr === '1' ) {
return true;
}

// Check computed natural dimensions (e.g. for base64 or loaded images without explicit attributes)
if (
typeof node.naturalWidth === 'number' &&
typeof node.naturalHeight === 'number' &&
node.naturalWidth === 1 &&
node.naturalHeight === 1
) {
return true;
}

return false;
}

/**
* Check if image should be ignored due to plugin-specific cases
* @param {HTMLElement} node - The node to check
Expand Down
22 changes: 22 additions & 0 deletions tests/jest/rules/imgAltEmpty.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,28 @@ describe( 'Image Alt Empty Validation', () => {
html: '<img src="smiley.jpg" alt="" class="wp-smiley">',
shouldPass: true,
},

// Tracking pixel (1x1) edge cases
{
name: 'should pass for 1x1 tracking pixel with empty alt (gif)',
html: '<img src="track.gif" alt="" width="1" height="1">',
shouldPass: true,
},
{
name: 'should pass for 1x1 tracking pixel with empty alt (arbitrary src)',
html: '<img src="https://example.com/whatever.png" alt="" width="1" height="1">',
shouldPass: true,
},
{
name: 'should fail for 2x1 image with empty alt (not a tracking pixel)',
html: '<img src="tiny.png" alt="" width="2" height="1">',
shouldPass: false,
},
{
name: 'should fail for img with empty alt and no dimension attributes (cannot confirm tracking pixel without dimensions)',
html: '<img src="maybe-tracker.gif" alt="">',
shouldPass: false,
},
];

testCases.forEach( ( testCase ) => {
Expand Down