-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extensible dimension calculators #193
Conversation
Fix max widths config value or glide width param not being respected in some cases Fix floating numbers for width and height values for Glide endpoint, they are not rounded integers Add additional tests for dimension calculator and GraphQL
Clean up tests and output assets and content in tmp directory
…ges into feature/167
…ges into feature/167
…gh Breakpoint anyway
…ges into feature/167
…o just `params` for simplicity
…nal asset As there can be custom dimension calculators, the dimensions on <img> tag will be custom. Add more tests for dimension calculator.
…ges into feature/167
…` in `Breakpoint` Cache calls in `breakpoints()` and `sources()`
…ges into feature/167
Was not very descriptive, was it?
…ges into feature/167
public function __set($name, $value): void | ||
{ | ||
throw new Exception(sprintf('Cannot modify property %s', $name)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Read only properties in classes are available only starting with PHP 8.1. As we are exposing Breakpoint
and Source
classes now for DimensionCalculator, as such need to be aware what methods and properties are available.
} | ||
|
||
return "(min-width: {$this->value}{$this->unit})"; | ||
} | ||
$formats = collect(['avif', 'webp', 'original']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So far this is how addon has worked: if you provided a JPG/PNG/WEBP etc. as source asset, then the default "srcSet" would Glide manipulate to the same format as the original asset was. This is default Glide behavior if you do not specify a format.
Responsive images addon config has option to toggle webp
and avif
formats, and technically you can change default quality amount for each format too.
The original
format has been introduced here, and here's few key notes as to why:
- We have to deal with source image being any possible image format that Glide/Intervention supports, as such we would have to add format toggles for each image format. Having just one
original
seems simpler. Nowadays we really only care forwebp
andavif
as their support becomes more robust as time goes. - This
original
format cannot be exchanged to justjpg
because in situations where source asset is a transparent image and that transparency needs to be maintained. Both WEBP and AVIF support transparency. If we force JPG, then transparency will become borked.
For now original
is not publicly available to devs through config or params. But if you really want to disable original sources, then you can through DimensionCalculator
. If we are introducing breaking changes, we could add original
image format to the config too, but I decided against it for now as this PR is becoming too big and would be out of scope technically, trying to remain lean here.
public function toArray(): array | ||
{ | ||
return [ | ||
'asset' => $this->asset, | ||
'label' => $this->label, | ||
'value' => $this->value, | ||
'media' => $this->getMediaString(), | ||
'minWidth' => $this->minWidth, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
value
in my opinion felt too vague as property name, so I have renamed it to minWidth
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
// Check if DimensionCalculator is instance of ResponsiveDimensionCalculator | ||
// as ratio is only property applicable only for this DimensionCalculator | ||
if (app(DimensionCalculator::class) instanceof ResponsiveDimensionCalculator) { | ||
$data['ratio'] = app(DimensionCalculator::class)->breakpointRatio($this->asset, $this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For legacy purposes, ratio
seems only relevant if you are using the original ResponsiveDimensionCalculator
.
'type' => GraphQL::int(), | ||
'description' => 'The min-width of this breakpoint.', | ||
], | ||
'unit' => [ | ||
'widthUnit' => [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Opinionated change, I just think this is more descriptive.
@@ -32,5 +32,10 @@ public function handle(): string | |||
return $this->imageUrl(); | |||
} | |||
|
|||
public function getParams(): array |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I needed something publicly accessible for params for tests.
public function getMimeType(): string|null | ||
{ | ||
$mimeTypesBySetFormat = [ | ||
'webp' => 'image/webp', | ||
'avif' => 'image/avif', | ||
]; | ||
|
||
if (isset($mimeTypesBySetFormat[$this->format])) { | ||
return $mimeTypesBySetFormat[$this->format]; | ||
} | ||
|
||
return $this->breakpoint->asset->mimeType(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This actually benefits for the original
format, as previously the <source>
tag for it did not contain mimetype at all, and browser has more difficult time without a mimetype specified. For example, if source asset was AVIF image, then original
srcset could be unnecessarily loaded by the browser and may make the image broken, as AVIF image may not be supported by some browsers. I don't think browsers can guess mimetype from the provided URLs that Glide URL generator gives.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome!
Described in #167, this allows developers to bind their own customized DimensionCalculator if they have different needs.
This required to move a few things around, as some things were tied to "ratios". Breakpoints have been separted of their
srcSets
, and I have introduced separateSource
to handle it instead (it representsI introduced an object class
Dimensions
to better contain width and height, as having an array was a bit ugly for my liking.If developers want to customize dimension calculations, they need to implement DimensionsCalculator interface with following three methods:
calculateForBreakpoint
for calculating multiple dimensions for breakpoint srcsetscalculateForImgTag
is specifically targeted for width and height in<img>
tagcalculateForPlaceholder
for blurry placeholderAll of these receive
Breakpoint
/Source
objects, so developers should have plentiful freedom when it comes to calculating dimensions, as from there you can access breakpoint params and original asset.Here is how developers can bind their implementation in AppServiceProvider, example:
The original dimension calculator has remained unchanged. I do not currently have an idea how to solve #167 width calculations elegantly, so this is up to the individual developer, now they have the freedom to do so. Or we can improve this in a later update.
Additional side-quests:
<img>
tagsrc
will now go through Glide instead of pointing to original asset file, due to DimensionCalculators ability to return specific widths and heights for<img>
tagmedia
attributes won't be outputted at allBreaking changes:
TODO:
DimensionCalculator
methods arguments can be simplified to onlyBreakpoint
(as it already containsasset
property forAsset
)