@bernierllc/validators-image-asset
v0.3.2
Published
Image asset validation for the BernierLLC validators ecosystem - validates alt text, formats, sizes, and optimization
Readme
@bernierllc/validators-image-asset
Image asset validation for the BernierLLC validators ecosystem - validates accessibility, performance, and optimization.
Installation
npm install @bernierllc/validators-image-assetFeatures
- Accessibility: Validates alt text presence for screen readers
- Performance: Checks file sizes and image dimensions
- Optimization: Recommends modern formats (WebP, AVIF) and responsive images
- Responsive: Validates srcset usage for large images
- Type-Safe: Full TypeScript support with detailed interfaces
Usage
Basic Validation
import { validateImageAsset } from '@bernierllc/validators-image-asset';
const imageData = {
src: 'example.jpg',
alt: 'A beautiful sunset',
format: 'jpg',
size: 150000, // bytes
width: 1920,
height: 1080
};
const problems = await validateImageAsset(imageData);
problems.forEach(problem => {
console.log(`${problem.severity}: ${problem.message}`);
if (problem.suggestion) {
console.log(` Suggestion: ${problem.suggestion}`);
}
});Using Individual Rules
import {
missingAltText,
inefficientFormat,
excessiveFileSize
} from '@bernierllc/validators-image-asset';
import { createRuleContext } from '@bernierllc/validators-core';
import { createSharedUtils } from '@bernierllc/validators-utils';
const imageData = {
src: 'example.png',
alt: 'Example image',
format: 'png',
size: 250000
};
const sharedUtils = createSharedUtils();
const context = createRuleContext('image-asset', imageData, sharedUtils);
// Run specific rule
const check = missingAltText.create(context);
check(imageData);
const problems = context.getProblems();Integration with Validator Runner
import { imageAssetValidator } from '@bernierllc/validators-image-asset';
import { createRuleContext } from '@bernierllc/validators-core';
import { createSharedUtils } from '@bernierllc/validators-utils';
const imageData = {
src: 'hero.webp',
alt: 'Hero image',
format: 'webp',
size: 180000,
width: 1920,
height: 1080,
srcset: 'hero-320w.webp 320w, hero-640w.webp 640w, hero.webp 1920w'
};
const sharedUtils = createSharedUtils();
const context = createRuleContext('image-asset', imageData, sharedUtils);
const problems = await imageAssetValidator.validate(imageData, context);API Reference
validateImageAsset(imageData, utils?)
Validates image assets for accessibility, performance, and optimization.
Parameters:
imageData: ImageAssetData- The image data to validateutils?: SharedUtils- Optional shared utilities (created automatically if not provided)
Returns: Promise<Problem[]> - Array of validation problems
ImageAssetData
interface ImageAssetData {
src: string; // Image source URL (required)
alt?: string; // Alt text for accessibility
title?: string; // Optional title attribute
format?: string; // Image format (jpg, png, webp, avif, svg, etc.)
size?: number; // File size in bytes
width?: number; // Image width in pixels
height?: number; // Image height in pixels
srcset?: string; // Responsive image srcset
}Validation Rules
1. Missing Alt Text (image-asset/missing-alt-text)
Severity: Error Description: All images must have descriptive alt text for accessibility
// ❌ Invalid - Missing alt text
const invalid = {
src: 'example.jpg'
};
// ✅ Valid - Has alt text
const valid = {
src: 'example.jpg',
alt: 'A beautiful mountain landscape'
};2. Inefficient Format (image-asset/inefficient-format)
Severity: Error (legacy formats), Warning (acceptable formats) Description: Images should use modern formats like WebP or AVIF
// ❌ Error - Legacy format
const legacy = {
src: 'example.bmp',
alt: 'Example',
format: 'bmp'
};
// ⚠️ Warning - Acceptable but not optimal
const acceptable = {
src: 'example.jpg',
alt: 'Example',
format: 'jpg'
};
// ✅ Valid - Modern format
const modern = {
src: 'example.webp',
alt: 'Example',
format: 'webp'
};Format Categories:
- Modern (no warning): WebP, AVIF, SVG
- Acceptable (warning): PNG, JPG, JPEG, GIF
- Legacy (error): BMP, TIFF, TIF
3. Excessive File Size (image-asset/excessive-file-size)
Severity: Error (>1MB), Warning (>500KB), Info (>200KB) Description: Image files should be compressed to reduce load time
// ❌ Error - Too large (>1MB)
const tooLarge = {
src: 'example.jpg',
alt: 'Example',
size: 1.5 * 1024 * 1024
};
// ⚠️ Warning - Large (>500KB)
const large = {
src: 'example.jpg',
alt: 'Example',
size: 600 * 1024
};
// ℹ️ Info - Could be optimized (>200KB)
const moderate = {
src: 'example.jpg',
alt: 'Example',
size: 250 * 1024
};
// ✅ Valid - Optimized (<200KB)
const optimized = {
src: 'example.webp',
alt: 'Example',
size: 150 * 1024
};Size Thresholds:
- Recommended: < 200KB
- Maximum: < 500KB
- Critical: < 1MB
4. Excessive Dimensions (image-asset/excessive-dimensions)
Severity: Error (>4096x2160), Warning (>2560x1440) Description: Image dimensions should match display requirements
// ❌ Error - Excessive dimensions
const excessive = {
src: 'example.jpg',
alt: 'Example',
width: 5000,
height: 3000
};
// ⚠️ Warning - Large dimensions
const large = {
src: 'example.jpg',
alt: 'Example',
width: 3000,
height: 1600
};
// ✅ Valid - Reasonable dimensions
const reasonable = {
src: 'example.jpg',
alt: 'Example',
width: 1920,
height: 1080
};Dimension Thresholds:
- Recommended: ≤ 2560x1440 (4K displays)
- Critical: ≤ 4096x2160
5. Missing Srcset (image-asset/missing-srcset)
Severity: Warning Description: Large images should provide multiple sizes via srcset
// ⚠️ Warning - Large image without srcset
const noSrcset = {
src: 'example.jpg',
alt: 'Example',
width: 1920,
height: 1080
};
// ✅ Valid - Has responsive srcset
const withSrcset = {
src: 'example.jpg',
alt: 'Example',
width: 1920,
height: 1080,
srcset: 'example-320w.jpg 320w, example-640w.jpg 640w, example.jpg 1920w',
sizes: '(max-width: 640px) 100vw, 640px'
};
// ✅ Valid - Small image doesn't need srcset
const smallImage = {
src: 'icon.png',
alt: 'Icon',
width: 64,
height: 64
};Thresholds:
- Width > 800px OR Height > 600px: srcset recommended
Examples
Optimal Web Image
const optimalImage = {
src: 'hero.webp',
alt: 'Hero section showing our product dashboard',
format: 'webp',
size: 180 * 1024, // 180KB
width: 1920,
height: 1080,
srcset: 'hero-320w.webp 320w, hero-640w.webp 640w, hero-1280w.webp 1280w, hero.webp 1920w',
sizes: '(max-width: 768px) 100vw, (max-width: 1200px) 80vw, 1200px'
};
const problems = await validateImageAsset(optimalImage);
// Result: [] (no problems)Email-Safe Image
const emailImage = {
src: 'newsletter-banner.jpg',
alt: 'Monthly newsletter banner',
format: 'jpg',
size: 120 * 1024, // 120KB
width: 600,
height: 200
};
const problems = await validateImageAsset(emailImage);
// Result: [{ severity: 'warning', message: '...not optimal format...' }]
// JPG acceptable for email compatibilityIcon/Thumbnail
const icon = {
src: 'user-avatar.webp',
alt: 'User profile picture',
format: 'webp',
size: 8 * 1024, // 8KB
width: 150,
height: 150
};
const problems = await validateImageAsset(icon);
// Result: [] (no problems - small images don't need srcset)Integration Status
- Logger: Not applicable (primitive validator)
- Docs-Suite: Ready - Markdown documentation with code examples
- NeverHub: Not applicable (primitive validator)
Best Practices
1. Always Provide Alt Text
// ❌ Bad
<img src="product.jpg" />
// ✅ Good
<img src="product.jpg" alt="Red running shoes with white soles" />2. Use Modern Formats with Fallbacks
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="Fallback for older browsers">
</picture>3. Implement Responsive Images
<img
src="large.jpg"
srcset="small.jpg 320w, medium.jpg 640w, large.jpg 1280w"
sizes="(max-width: 640px) 100vw, 50vw"
alt="Responsive image example"
/>4. Optimize File Sizes
- Use compression tools (ImageOptim, Squoosh, Sharp)
- Target < 200KB for web images
- Use progressive JPEG for large photos
- Consider lazy loading for below-fold images
5. Match Dimensions to Display
- Don't serve 4K images for mobile devices
- Use srcset to provide appropriate sizes
- Consider device pixel ratio (2x, 3x for retina)
Testing
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Run tests once (CI)
npm run test:runDevelopment
# Build the package
npm run build
# Watch mode for development
npm run dev
# Lint code
npm run lint
# Fix linting issues
npm run lint:fix
# Clean build artifacts
npm run cleanLicense
Copyright (c) 2025 Bernier LLC. All rights reserved.
See Also
- @bernierllc/validators-core - Core validation framework
- @bernierllc/validators-utils - Shared validation utilities
- @bernierllc/validators-a11y-contrast - Accessibility contrast validation
- @bernierllc/validators-web - Complete web page validation
