summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/tasty-oranges-bathe.md5
-rw-r--r--packages/astro/components/Image.astro4
-rw-r--r--packages/astro/components/Picture.astro21
-rw-r--r--packages/astro/src/assets/internal.ts2
-rw-r--r--packages/astro/src/assets/services/service.ts12
-rw-r--r--packages/astro/src/assets/types.ts15
-rw-r--r--packages/astro/test/core-image.test.js3
-rw-r--r--packages/astro/test/fixtures/core-image/src/pages/picturecomponent.astro2
8 files changed, 44 insertions, 20 deletions
diff --git a/.changeset/tasty-oranges-bathe.md b/.changeset/tasty-oranges-bathe.md
new file mode 100644
index 000000000..b155cd4d8
--- /dev/null
+++ b/.changeset/tasty-oranges-bathe.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Fix `sizes` attribute not being present on `source` elements when using it on the Picture component
diff --git a/packages/astro/components/Image.astro b/packages/astro/components/Image.astro
index a11efd4f9..9c4fcf7e9 100644
--- a/packages/astro/components/Image.astro
+++ b/packages/astro/components/Image.astro
@@ -1,6 +1,7 @@
---
import { getImage, type LocalImageProps, type RemoteImageProps } from 'astro:assets';
import { AstroError, AstroErrorData } from '../dist/core/errors/index.js';
+import type { HTMLAttributes } from '../types';
// The TypeScript diagnostic for JSX props uses the last member of the union to suggest props, so it would be better for
// LocalImageProps to be last. Unfortunately, when we do this the error messages that remote images get are complete nonsense
@@ -24,8 +25,7 @@ if (typeof props.height === 'string') {
const image = await getImage(props);
-const additionalAttributes: Record<string, any> = {};
-
+const additionalAttributes: HTMLAttributes<'img'> = {};
if (image.srcSet.values.length > 0) {
additionalAttributes.srcset = image.srcSet.attribute;
}
diff --git a/packages/astro/components/Picture.astro b/packages/astro/components/Picture.astro
index f6c7686e8..d4327840a 100644
--- a/packages/astro/components/Picture.astro
+++ b/packages/astro/components/Picture.astro
@@ -49,9 +49,16 @@ const fallbackImage = await getImage({
densities: props.densities,
});
-const additionalAttributes: Record<string, any> = {};
+const imgAdditionalAttributes: HTMLAttributes<'img'> = {};
+const sourceAdditionaAttributes: HTMLAttributes<'source'> = {};
+
+// Propagate the `sizes` attribute to the `source` elements
+if (props.sizes) {
+ sourceAdditionaAttributes.sizes = props.sizes;
+}
+
if (fallbackImage.srcSet.values.length > 0) {
- additionalAttributes.srcset = fallbackImage.srcSet.attribute;
+ imgAdditionalAttributes.srcset = fallbackImage.srcSet.attribute;
}
---
@@ -62,8 +69,14 @@ if (fallbackImage.srcSet.values.length > 0) {
props.densities || (!props.densities && !props.widths)
? `${image.src}${image.srcSet.values.length > 0 ? ', ' + image.srcSet.attribute : ''}`
: image.srcSet.attribute;
- return <source srcset={srcsetAttribute} type={'image/' + image.options.format} />;
+ return (
+ <source
+ srcset={srcsetAttribute}
+ type={'image/' + image.options.format}
+ {...sourceAdditionaAttributes}
+ />
+ );
})
}
- <img src={fallbackImage.src} {...additionalAttributes} {...fallbackImage.attributes} />
+ <img src={fallbackImage.src} {...imgAdditionalAttributes} {...fallbackImage.attributes} />
</picture>
diff --git a/packages/astro/src/assets/internal.ts b/packages/astro/src/assets/internal.ts
index f7df11f69..1c26ac6b5 100644
--- a/packages/astro/src/assets/internal.ts
+++ b/packages/astro/src/assets/internal.ts
@@ -102,6 +102,7 @@ export async function getImage(
let imageURL = await service.getURL(validatedOptions, imageConfig);
let srcSets: SrcSetValue[] = await Promise.all(
srcSetTransforms.map(async (srcSet) => ({
+ transform: srcSet.transform,
url: await service.getURL(srcSet.transform, imageConfig),
descriptor: srcSet.descriptor,
attributes: srcSet.attributes,
@@ -115,6 +116,7 @@ export async function getImage(
) {
imageURL = globalThis.astroAsset.addStaticImage(validatedOptions);
srcSets = srcSetTransforms.map((srcSet) => ({
+ transform: srcSet.transform,
url: globalThis.astroAsset.addStaticImage!(srcSet.transform),
descriptor: srcSet.descriptor,
attributes: srcSet.attributes,
diff --git a/packages/astro/src/assets/services/service.ts b/packages/astro/src/assets/services/service.ts
index 7d2f6afb9..8d77442c7 100644
--- a/packages/astro/src/assets/services/service.ts
+++ b/packages/astro/src/assets/services/service.ts
@@ -3,7 +3,7 @@ import { AstroError, AstroErrorData } from '../../core/errors/index.js';
import { isRemotePath, joinPaths } from '../../core/path.js';
import { DEFAULT_OUTPUT_FORMAT, VALID_SUPPORTED_FORMATS } from '../consts.js';
import { isESMImportedImage, isRemoteAllowed } from '../internal.js';
-import type { ImageOutputFormat, ImageTransform } from '../types.js';
+import type { ImageOutputFormat, ImageTransform, UnresolvedSrcSetValue } from '../types.js';
export type ImageService = LocalImageService | ExternalImageService;
@@ -28,12 +28,6 @@ type ImageConfig<T> = Omit<AstroConfig['image'], 'service'> & {
service: { entrypoint: string; config: T };
};
-type SrcSetValue = {
- transform: ImageTransform;
- descriptor?: string;
- attributes?: Record<string, any>;
-};
-
interface SharedServiceProps<T extends Record<string, any> = Record<string, any>> {
/**
* Return the URL to the endpoint or URL your images are generated from.
@@ -53,7 +47,7 @@ interface SharedServiceProps<T extends Record<string, any> = Record<string, any>
getSrcSet?: (
options: ImageTransform,
imageConfig: ImageConfig<T>
- ) => SrcSetValue[] | Promise<SrcSetValue[]>;
+ ) => UnresolvedSrcSetValue[] | Promise<UnresolvedSrcSetValue[]>;
/**
* Return any additional HTML attributes separate from `src` that your service requires to show the image properly.
*
@@ -233,7 +227,7 @@ export const baseService: Omit<LocalImageService, 'transform'> = {
};
},
getSrcSet(options) {
- const srcSet: SrcSetValue[] = [];
+ const srcSet: UnresolvedSrcSetValue[] = [];
const { targetWidth } = getTargetDimensions(options);
const { widths, densities } = options;
const targetFormat = options.format ?? DEFAULT_OUTPUT_FORMAT;
diff --git a/packages/astro/src/assets/types.ts b/packages/astro/src/assets/types.ts
index ec7393e50..c11f58b25 100644
--- a/packages/astro/src/assets/types.ts
+++ b/packages/astro/src/assets/types.ts
@@ -33,11 +33,18 @@ export interface ImageMetadata {
orientation?: number;
}
-export interface SrcSetValue {
- url: string;
+/**
+ * A yet to be completed with an url `SrcSetValue`. Other hooks will only see a resolved value, where the URL of the image has been added.
+ */
+export type UnresolvedSrcSetValue = {
+ transform: ImageTransform;
descriptor?: string;
- attributes?: Record<string, string>;
-}
+ attributes?: Record<string, any>;
+};
+
+export type SrcSetValue = UnresolvedSrcSetValue & {
+ url: string;
+};
/**
* A yet to be resolved image transform. Used by `getImage`
diff --git a/packages/astro/test/core-image.test.js b/packages/astro/test/core-image.test.js
index ade979918..fb7c7c828 100644
--- a/packages/astro/test/core-image.test.js
+++ b/packages/astro/test/core-image.test.js
@@ -222,6 +222,9 @@ describe('astro:image', () => {
expect($img).to.have.a.lengthOf(1);
expect($picture).to.have.a.lengthOf(1);
expect($source).to.have.a.lengthOf(1);
+ expect($source.attr('sizes')).to.equal(
+ '(max-width: 448px) 400px, (max-width: 810px) 750px, 1050px'
+ );
const srcset2 = parseSrcset($source.attr('srcset'));
expect(srcset2.every((src) => src.url.startsWith('/_image'))).to.equal(true);
diff --git a/packages/astro/test/fixtures/core-image/src/pages/picturecomponent.astro b/packages/astro/test/fixtures/core-image/src/pages/picturecomponent.astro
index 713990d86..2fcf4e06c 100644
--- a/packages/astro/test/fixtures/core-image/src/pages/picturecomponent.astro
+++ b/packages/astro/test/fixtures/core-image/src/pages/picturecomponent.astro
@@ -8,7 +8,7 @@ import myImage from "../assets/penguin1.jpg";
</div>
<div id="picture-widths">
-<Picture src={myImage} width={Math.round(myImage.width / 2)} alt="A penguin" widths={[myImage.width]} />
+<Picture src={myImage} width={Math.round(myImage.width / 2)} alt="A penguin" widths={[myImage.width]} sizes="(max-width: 448px) 400px, (max-width: 810px) 750px, 1050px" />
</div>
<div id="picture-fallback">