Skip to content

Conversation

@GeezerPelletier
Copy link
Contributor

Summary

Adds a new image-alt preflight audit check that analyzes image alt text for accessibility and SEO issues.

See: https://jira.corp.adobe.com/browse/SITES-39442

Features:

  • Extracts images from scraped HTML pages using cheerio
  • Detects three types of alt text issues:
    • missing-alt (High SEO impact): Images without any alt attribute
    • empty-alt (Low impact): Empty alt attributes flagged for review (may be valid for decorative images)
    • low-quality-alt (Moderate impact): Generic/placeholder alt text (e.g., "image", "photo", "DSC0001", "IMG_001")
  • Integrates with Mystique for AI-powered alt text suggestions in the suggest step
  • Filters out invalid images (no src) and small data URIs (tracking pixels/tiny icons)
  • Includes timing/profiling data for performance monitoring

Files changed:
src/preflight/image-alt.js - New handler with comprehensive JSDoc documentation
src/preflight/handler.js - Registered new check (AUDIT_IMAGE_ALT, AVAILABLE_CHECKS, PREFLIGHT_HANDLERS)
test/audits/preflight-image-alt.test.js - 20 tests covering all functionality

Test plan

[x] 20 unit tests passing
[x] Code coverage: 100% statements, 97.91% branches, 100% functions, 100% lines
[x] Tests cover: missing/empty/low-quality detection, valid alt handling, image filtering, Mystique integration, error handling, timing data

@@ -0,0 +1,461 @@
/*
* Copyright 2025 Adobe. All rights reserved.
Copy link

@atopper atopper Jan 21, 2026

Choose a reason for hiding this comment

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

2026
Another case below too.

if (!altText || altText.length < 5) {
return true;
}
return LOW_QUALITY_ALT_PATTERNS.some((pattern) => pattern.test(altText.trim()));
Copy link

Choose a reason for hiding this comment

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

Maybe add a check for it being too long? Quick AI response:
alt text can be too long, which frustrates screen reader users as some cut off around 125 characters, making short, concise descriptions (under 100-125 characters) best for simple images, while complex images with data need a separate "long description" linked in the alt text. The goal is to convey the image's purpose and content succinctly without being overly wordy or cutting off vital info, aiming for 2-3 clear sentences or under 100-150 characters for most cases.

'empty-alt': 'If this is a decorative image, empty alt is correct. Otherwise, add descriptive alt text',
'low-quality-alt': 'Replace generic alt text with a meaningful description of the image content',
};
return recommendations[type] || 'Review and improve image alt text';
Copy link

@atopper atopper Jan 21, 2026

Choose a reason for hiding this comment

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

Can we provide AI generated suggestions for text to use?
ie alt="Developer named Guy typing at computer. You can tell he is a runner."

return {
type: 'empty-alt',
issue: 'Image has empty alt attribute (decorative image)',
seoImpact: 'Low',
Copy link

Choose a reason for hiding this comment

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

Thinking of localization. I guess the client can map empty-alt to localizable strings and ignore the 'issue' text altogether. Does that make sense?

issue: issue.issue,
seoImpact: issue.seoImpact,
seoRecommendation: getRecommendation(issue.type),
});
Copy link

Choose a reason for hiding this comment

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

Does the repo use the 'spread' operator at all?

    grouped[issue.type].push({
      ...issue,
      seoRecommendation: getRecommendation(issue.type),
    });

@@ -0,0 +1,461 @@
/*
* Copyright 2025 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
Copy link

Choose a reason for hiding this comment

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

Repo doesn't use typescript? That's too bad!

* Used to register and identify this check in the preflight system.
* @constant {string}
*/
export const PREFLIGHT_IMAGE_ALT = 'image-alt';
Copy link

@atopper atopper Jan 21, 2026

Choose a reason for hiding this comment

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

Can this be used throughout the code instead of hardcoded 'image-alt' strings?
Also add array of types?

const imageAltType = {
  MISSING_ALT: 'missing-alt',
  EMPTY_ALT: 'empty-alt',
  LOW_QUALITY_ALT: 'low-quality-alt',

Then use imageAltType.MISSING_ALT. That allows you to loop like on line 254-273.

check: 'low-quality-alt',
issue: grouped['low-quality-alt'],
});
}
Copy link

Choose a reason for hiding this comment

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

Can these checks and pushes be in a loop of defined property names? (See comment on line 59).

/^dsc\d+$/i, // Camera default names like DSC0001
/^img_\d+$/i, // IMG_0001 patterns
/^screen\s*shot/i,
];
Copy link

Choose a reason for hiding this comment

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

Interesting. Good list.
I wonder if AI could determine if other strings are rubbish (i.e. "Put image here")

Comment on lines +14 to +15
* @module preflight/image-alt
* @description Preflight audit check handler for analyzing image alt text accessibility and SEO.

Choose a reason for hiding this comment

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

Looks like AI noise here. Not sure if the provides any benefit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants