From bfe8e09ba61c21d94dbfee5b92ad1b0708a9f605 Mon Sep 17 00:00:00 2001 From: Princesseuh Date: Tue, 10 Oct 2023 12:18:41 +0200 Subject: [PATCH] fix(assets): Don't include asked width in srcset request --- .changeset/smooth-goats-agree.md | 14 ++++++------- packages/astro/src/assets/services/service.ts | 20 +++++++++++++------ packages/astro/src/assets/services/sharp.ts | 4 ++-- packages/astro/src/assets/services/squoosh.ts | 4 ++-- 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/.changeset/smooth-goats-agree.md b/.changeset/smooth-goats-agree.md index 13e65d6a7..efa7b8434 100644 --- a/.changeset/smooth-goats-agree.md +++ b/.changeset/smooth-goats-agree.md @@ -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"; --- -My cool image +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 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 `` 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"; --- - + ``` The above code will generate the following: @@ -48,4 +46,4 @@ The above code will generate the following: ``` -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. diff --git a/packages/astro/src/assets/services/service.ts b/packages/astro/src/assets/services/service.ts index f3738e20e..9812c95c3 100644 --- a/packages/astro/src/assets/services/service.ts +++ b/packages/astro/src/assets/services/service.ts @@ -45,7 +45,10 @@ interface SharedServiceProps = Record */ getURL: (options: ImageTransform, imageConfig: ImageConfig) => string | Promise; /** - * 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 = { 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 = { 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 = { }, }; - // 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 = { 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 = { }, }; - // 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); diff --git a/packages/astro/src/assets/services/sharp.ts b/packages/astro/src/assets/services/sharp.ts index b7e856d85..215299138 100644 --- a/packages/astro/src/assets/services/sharp.ts +++ b/packages/astro/src/assets/services/sharp.ts @@ -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) { diff --git a/packages/astro/src/assets/services/squoosh.ts b/packages/astro/src/assets/services/squoosh.ts index 32aee874d..5be5d4077 100644 --- a/packages/astro/src/assets/services/squoosh.ts +++ b/packages/astro/src/assets/services/squoosh.ts @@ -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), }); }