diff --git a/.changeset/easy-dingos-retire.md b/.changeset/easy-dingos-retire.md new file mode 100644 index 000000000000..a56e55d1843a --- /dev/null +++ b/.changeset/easy-dingos-retire.md @@ -0,0 +1,6 @@ +--- +'astro': patch +'@astrojs/netlify': patch +--- + +Fixes a bug where remote image dimensions were not validated during static builds on Netlify. diff --git a/packages/astro/src/assets/internal.ts b/packages/astro/src/assets/internal.ts index 0b2bdfb5b729..f8798ad50cfe 100644 --- a/packages/astro/src/assets/internal.ts +++ b/packages/astro/src/assets/internal.ts @@ -22,6 +22,7 @@ import { isESMImportedImage, isRemoteImage, resolveSrc } from './utils/imageKind import { inferRemoteSize } from './utils/remoteProbe.js'; import { createPlaceholderURL, stringifyPlaceholderURL } from './utils/url.js'; +export { verifyOptions } from './services/service.js'; export const cssFitValues = ['fill', 'contain', 'cover', 'scale-down']; export async function getConfiguredImageService(): Promise { diff --git a/packages/integrations/netlify/src/image-service.ts b/packages/integrations/netlify/src/image-service.ts index 91c3596ad25c..f8e93a05abdc 100644 --- a/packages/integrations/netlify/src/image-service.ts +++ b/packages/integrations/netlify/src/image-service.ts @@ -1,5 +1,6 @@ import type { ExternalImageService } from 'astro'; import { baseService } from 'astro/assets'; +import { verifyOptions } from '../../../astro/dist/assets/internal.js'; import { isESMImportedImage } from 'astro/assets/utils'; import { AstroError } from 'astro/errors'; @@ -51,6 +52,8 @@ const service: ExternalImageService = { getHTMLAttributes: baseService.getHTMLAttributes, getSrcSet: baseService.getSrcSet, validateOptions(options) { + verifyOptions(options); + if (options.format && !SUPPORTED_FORMATS.includes(options.format)) { throw new AstroError( `Unsupported image format "${options.format}"`, diff --git a/packages/integrations/netlify/test/static/fixtures/image-missing-dimension/astro.config.mjs b/packages/integrations/netlify/test/static/fixtures/image-missing-dimension/astro.config.mjs new file mode 100644 index 000000000000..6f09867119ee --- /dev/null +++ b/packages/integrations/netlify/test/static/fixtures/image-missing-dimension/astro.config.mjs @@ -0,0 +1,12 @@ +import { defineConfig } from 'astro/config'; +import netlify from '@astrojs/netlify'; + +export default defineConfig({ + adapter: netlify(), + output: 'static', + image: { + service: { + entrypoint: 'astro/assets/services/sharp' + } + } +}); diff --git a/packages/integrations/netlify/test/static/fixtures/image-missing-dimension/package.json b/packages/integrations/netlify/test/static/fixtures/image-missing-dimension/package.json new file mode 100644 index 000000000000..98054c7d11bd --- /dev/null +++ b/packages/integrations/netlify/test/static/fixtures/image-missing-dimension/package.json @@ -0,0 +1,9 @@ +{ + "name": "image-missing-dimention", + "type": "module", + "private": true, + "dependencies": { + "astro": "workspace:*", + "@astrojs/netlify": "workspace:*" + } +} diff --git a/packages/integrations/netlify/test/static/fixtures/image-missing-dimension/src/pages/index.astro b/packages/integrations/netlify/test/static/fixtures/image-missing-dimension/src/pages/index.astro new file mode 100644 index 000000000000..9402dbf6da2d --- /dev/null +++ b/packages/integrations/netlify/test/static/fixtures/image-missing-dimension/src/pages/index.astro @@ -0,0 +1,8 @@ +--- +import { Image } from 'astro:assets'; +--- + +Astro diff --git a/packages/integrations/netlify/test/static/image-missing-dimension.test.js b/packages/integrations/netlify/test/static/image-missing-dimension.test.js new file mode 100644 index 000000000000..92415f07be9e --- /dev/null +++ b/packages/integrations/netlify/test/static/image-missing-dimension.test.js @@ -0,0 +1,23 @@ +import * as assert from 'node:assert/strict'; +import { describe, it } from 'node:test'; +import { loadFixture } from '../../../../astro/test/test-utils.js'; + +describe('Image validation when is not size specification in netlify.', () => { + it('throw on missing dimension in static build', async () => { + const fixture = await loadFixture({ + root: new URL('./fixtures/image-missing-dimension/', import.meta.url) + }); + + try{ + await fixture.build(); + assert.fail(); + } catch (e) { + // check the error image about missing image dimension + assert.match( + e.name, + /MissingImageDimension/, + `Build failed but not with the expected "MissingImageDimension"` + ) + } + }) +}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d2e1713967fa..1db0b03c1ec1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1887,6 +1887,8 @@ importers: specifier: workspace:* version: link:../../.. + packages/astro/test/fixtures/actions-middleware-context: {} + packages/astro/test/fixtures/alias: dependencies: '@astrojs/svelte': @@ -5870,6 +5872,15 @@ importers: specifier: workspace:* version: link:../../../../../astro + packages/integrations/netlify/test/static/fixtures/image-missing-dimension: + dependencies: + '@astrojs/netlify': + specifier: workspace:* + version: link:../../../.. + astro: + specifier: workspace:* + version: link:../../../../../../astro + packages/integrations/netlify/test/static/fixtures/redirects: dependencies: '@astrojs/netlify':