fix(assets): Don't include asked width in srcset request

This commit is contained in:
Princesseuh 2023-10-10 12:18:41 +02:00
parent fc86fdf0c3
commit bfe8e09ba6
No known key found for this signature in database
GPG key ID: 105BBD6D57F2B0C0
4 changed files with 24 additions and 18 deletions

View file

@ -6,7 +6,9 @@ Add support for generating multiple widths when using the Image component and a
## `srcset` support
The current usage is as follow:
Two new properties have been added to `Image` and `getImage`: `densities` and `widths`.
These props can be used to generate a `srcset` attribute with multiple sources. For example:
```astro
---
@ -14,17 +16,13 @@ import { Image } from "astro";
import myImage from "./my-image.jpg";
---
<Image src={myImage} densities={[2, 3]} alt="My cool image" />
<Image src={myImage} width={myImage.width / 2} densities={[2]} alt="My cool image" />
```
Alternatively to `densities`, `widths` can be used for specific widths. In both cases, according images and the following code will be generated:
```html
<img src="..." srcset="... 2x, ... 3x" alt="My cool image" />
```
(if `widths` is used the descriptor will be `w` instead of `x`)
## Picture component
The `Picture` component can be used to generate a `<picture>` element with multiple sources. It can be used as follow:
@ -35,7 +33,7 @@ import { Picture } from "astro:assets";
import myImage from "./my-image.jpg";
---
<Picture src={myImage} formats=["avif", "webp"] alt="My super image in multiple formats!" />
<Picture src={myImage} formats={["avif", "webp"]} alt="My super image in multiple formats!" />
```
The above code will generate the following:
@ -48,4 +46,4 @@ The above code will generate the following:
</picture>
```
The `Picture` component takes all the same props as the `Image` component, including `densities` and `widths`.
The `Picture` component takes all the same props as the `Image` component, including the new `densities` and `widths` properties.

View file

@ -45,7 +45,10 @@ interface SharedServiceProps<T extends Record<string, any> = Record<string, any>
*/
getURL: (options: ImageTransform, imageConfig: ImageConfig<T>) => string | Promise<string>;
/**
* TODO: Document
* Generate additional `srcset` values for the image.
*
* While in most cases this is exclusively used for `srcset`, it can also be used in a more generic way to generate
* multiple variants of the same image. For instance, you can use this to generate multiple aspect ratios or multiple formats.
*/
getSrcSet?: (
options: ImageTransform,
@ -226,8 +229,9 @@ export const baseService: Omit<LocalImageService, 'transform'> = {
const aspectRatio = targetWidth / targetHeight;
const imageWidth = isESMImportedImage(options.src) ? options.src.width : options.width;
const maxWidth = options.width ?? imageWidth ?? Infinity;
const maxWidth = imageWidth ?? Infinity;
// REFACTOR: Could we merge these two blocks?
if (densities) {
const densityValues = densities.map((density) => {
if (typeof density === 'number') {
@ -244,9 +248,12 @@ export const baseService: Omit<LocalImageService, 'transform'> = {
densityWidths.forEach((width, index) => {
const maxTargetWidth = Math.min(width, maxWidth);
// If the user passed dimensions, we don't want to add it to the srcset
const { width: transformWidth, height: transformHeight, ...rest } = options;
const srcSetValue = {
transform: {
...options,
...rest,
},
descriptor: `${densityValues[index]}x`,
attributes: {
@ -254,7 +261,7 @@ export const baseService: Omit<LocalImageService, 'transform'> = {
},
};
// Only set width and height if they are different from the original image
// Only set width and height if they are different from the original image, to avoid duplicated final images
if (maxTargetWidth !== imageWidth) {
srcSetValue.transform.width = maxTargetWidth;
srcSetValue.transform.height = Math.round(maxTargetWidth / aspectRatio);
@ -270,9 +277,11 @@ export const baseService: Omit<LocalImageService, 'transform'> = {
widths.forEach((width) => {
const maxTargetWidth = Math.min(width, maxWidth);
const { width: transformWidth, height: transformHeight, ...rest } = options;
const srcSetValue = {
transform: {
...options,
...rest,
},
descriptor: `${width}w`,
attributes: {
@ -280,7 +289,6 @@ export const baseService: Omit<LocalImageService, 'transform'> = {
},
};
// Only set width and height if they are different from the original image
if (maxTargetWidth !== imageWidth) {
srcSetValue.transform.width = maxTargetWidth;
srcSetValue.transform.height = Math.round(maxTargetWidth / aspectRatio);

View file

@ -50,9 +50,9 @@ const sharpService: LocalImageService = {
// Never resize using both width and height at the same time, prioritizing width.
if (transform.height && !transform.width) {
result.resize({ height: transform.height });
result.resize({ height: Math.round(transform.height) });
} else if (transform.width) {
result.resize({ width: transform.width });
result.resize({ width: Math.round(transform.width) });
}
if (transform.format) {

View file

@ -77,12 +77,12 @@ const service: LocalImageService = {
if (transform.height && !transform.width) {
operations.push({
type: 'resize',
height: transform.height,
height: Math.round(transform.height),
});
} else if (transform.width) {
operations.push({
type: 'resize',
width: transform.width,
width: Math.round(transform.width),
});
}