Added
- New
thumbRatio()file method — generates a thumb with dimensions derived from an aspect ratio string (e.g.'16/9') or'intrinsic'. Accepts an optional array of thumb options (width,quality,format, etc.).cropdefaults totrue. Useful for overriding thesrcattribute in Imagex while keeping the ratio consistent with the rest of the image. - New
loadingoption with values'eager'or'lazy'(replacescritical) - Automatic
fetchpriority="high"whenloading: 'eager'(overridable viaattributes.img) - Default
decoding="async"attribute (overridable viaattributes.img) - Simplified flat attribute syntax — attributes are auto-converted to
sharedstructure - New
normalizeAttributesStructure()helper function - Cache invalidation when
srcsetconfig changes - Improved
compareFormatswith weighted multi-sample approach (samples first, middle, last srcset widths) - Per-image format comparison for art-directed images (each image is compared individually when using different source files)
- New helper functions:
getSampleElements()andcalculateWeightedFormatSize() - New method
getSmallestFormatForImage()with optional image and ratio parameters - New
compareFormatsWeightsglobal config option — controls how sampled file sizes are weighted whencompareFormatsis active. Presets:'mobile'(default, 50/30/20),'desktop'(20/30/50),'balanced'(34/33/33). Custom weights can be passed as an array (must sum to1.0) - New
resolveCompareFormatsWeights()helper for preset resolution and validation - Format comparison result is now cached per image — cache key is derived from file ID, last-modified timestamp, ratio, srcset preset, and active formats; auto-invalidates when a file is replaced or updated
cropis automatically set totruein srcset entries where the height is ratio-calculated andcropis not explicitly configured- Exception is now thrown when
thumbs.srcsetsis not configured inconfig.php - New
imagex-picture-jsonsnippet that returns a JSON structure instead of HTML — useful for headless CMS setups, API endpoints, and JavaScript-driven rendering (accepts the same options asimagex-picture) - New unit tests: 3 tests for
normalizeAttributesStructure(), 7 tests forresolveCompareFormatsWeights(), additional edge case tests for helper functions - New
coerceClassStyleToArrays()helper —classandstyleattributes now accept both strings and arrays; strings are automatically converted (class: 'foo bar'→['foo', 'bar']) - Early srcset preset validation in the
Imagexconstructor — missing format-specific presets (e.g.my-srcset-avif) are now detected immediately with a clear error message listing which presets are missing and which are available
Changed
-
BREAKING:
criticaloption renamed toloadingwith string values'eager'/'lazy'instead of boolean -
BREAKING:
srcsetNameoption renamed tosrcset -
BREAKING:
formatSizeHandlingoption renamed tocompareFormats -
BREAKING:
imgAttributes,pictureAttributes,sourcesAttributesmerged into singleattributesoption withimg,picture,sourceskeys -
BREAKING:
sourcesArtDirectedrenamed toartDirection -
classandstyleattributes now accept strings in addition to arrays — strings are silently converted (was a hard error before) -
BREAKING:
includeInitialFormatoption renamed toaddOriginalFormatAsSourcefor clarity — the new name makes explicit that a<source>element is added for the image's original format (e.g.jpeg,png) -
Improved error messages with available options when invalid values are passed
-
User-defined attributes always take precedence over Imagex-generated defaults for all attributes — including
src,srcset,width,height,loading,fetchpriority, anddecoding -
relativeUrlsnow also processes user-defined URL attributes (previously only applied to Imagex-generated URLs)
Fixed
- PHP 8.4 compatibility
Migration Guide
From 0.1.x to 0.2.0
1. Replace critical with loading
// Before
'critical' => true,
'critical' => false,
// After
'loading' => 'eager',
'loading' => 'lazy',2. Replace srcsetName with srcset
// Before
'srcsetName' => 'my-preset',
// After
'srcset' => 'my-preset',3. Replace formatSizeHandling with compareFormats
// Before
'formatSizeHandling' => true,
// After
'compareFormats' => true,4. Merge attribute options into attributes
// Before
'imgAttributes' => [
'shared' => ['alt' => 'text', 'sizes' => '100vw'],
'lazy' => ['class' => ['lazyload']],
],
'pictureAttributes' => [
'shared' => ['class' => ['my-picture']],
],
'sourcesAttributes' => [
'shared' => ['sizes' => '100vw'],
],
// After
'attributes' => [
'img' => [
'shared' => ['alt' => 'text', 'sizes' => '100vw'],
'lazy' => ['class' => ['lazyload']],
],
'picture' => [
'shared' => ['class' => ['my-picture']],
],
'sources' => [
'shared' => ['sizes' => '100vw'],
],
],
// Or use simplified flat syntax (auto-converted to 'shared')
'attributes' => [
'img' => ['alt' => 'text', 'sizes' => '100vw'],
'picture' => ['class' => ['my-picture']],
'sources' => ['sizes' => '100vw'],
],5. Rename sourcesArtDirected to artDirection
// Before
'sourcesArtDirected' => [
[
'media' => '(min-width: 800px)',
'ratio' => '21/9',
'image' => $wideImage,
],
],
// After
'artDirection' => [
[
'media' => '(min-width: 800px)',
'ratio' => '21/9',
'image' => $wideImage,
],
],6. Remove manual fetchpriority for eager images
fetchpriority="high" is now automatically set when loading: 'eager'. You can still override it:
'loading' => 'eager',
'attributes' => [
'img' => [
'fetchpriority' => 'low', // Override automatic 'high'
],
],7. Remove manual decoding if using default
decoding="async" is now set by default. You can still override it:
'attributes' => [
'img' => [
'decoding' => 'sync', // Override automatic 'async'
],
],8. class attribute — strings are now auto-converted
The class attribute accepts both strings and arrays. Strings are automatically split by whitespace, so no migration is required. Arrays are still recommended for conditional classes:
// Both work
'class' => 'my-image another-class',
'class' => ['my-image', 'another-class'],
// Arrays are still the better choice for conditional classes
'class' => [
'my-image',
$isActive ? 'is-active' : null, // null values are filtered out
],Full Changelog: 0.1.4...0.2.0