From afc45af2022f7c43fbb6c5c04983695f3819e47e Mon Sep 17 00:00:00 2001
From: Erika <3019731+Princesseuh@users.noreply.github.com>
Date: Mon, 14 Aug 2023 15:29:42 +0200
Subject: [PATCH] feat(assets): Add support for passing non-awaited imports to
the Image component and `getImage` (#8066)
* feat(assets): Add support for passing non-awaited imports to the Image component and `getImage`
* test: add test
---
.changeset/odd-plants-tie.md | 5 ++++
packages/astro/client-base.d.ts | 4 ++-
packages/astro/src/assets/internal.ts | 25 +++++++++++++++----
packages/astro/src/assets/types.ts | 6 ++++-
packages/astro/test/core-image.test.js | 13 ++++++++++
.../core-image/src/pages/inlineImport.astro | 7 ++++++
6 files changed, 53 insertions(+), 7 deletions(-)
create mode 100644 .changeset/odd-plants-tie.md
create mode 100644 packages/astro/test/fixtures/core-image/src/pages/inlineImport.astro
diff --git a/.changeset/odd-plants-tie.md b/.changeset/odd-plants-tie.md
new file mode 100644
index 000000000..b57376dee
--- /dev/null
+++ b/.changeset/odd-plants-tie.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Add support for non-awaited imports to the Image component and `getImage`
diff --git a/packages/astro/client-base.d.ts b/packages/astro/client-base.d.ts
index c0203e0ef..3b0ee4901 100644
--- a/packages/astro/client-base.d.ts
+++ b/packages/astro/client-base.d.ts
@@ -48,7 +48,9 @@ declare module 'astro:assets' {
* This is functionally equivalent to using the `` component, as the component calls this function internally.
*/
getImage: (
- options: import('./dist/assets/types.js').ImageTransform
+ options:
+ | import('./dist/assets/types.js').ImageTransform
+ | import('./dist/assets/types.js').UnresolvedImageTransform
) => Promise;
getConfiguredImageService: typeof import('./dist/assets/index.js').getConfiguredImageService;
Image: typeof import('./components/Image.astro').default;
diff --git a/packages/astro/src/assets/internal.ts b/packages/astro/src/assets/internal.ts
index c56b5369c..06e4f8cc0 100644
--- a/packages/astro/src/assets/internal.ts
+++ b/packages/astro/src/assets/internal.ts
@@ -1,7 +1,12 @@
import type { AstroSettings } from '../@types/astro.js';
import { AstroError, AstroErrorData } from '../core/errors/index.js';
import { isLocalService, type ImageService } from './services/service.js';
-import type { GetImageResult, ImageMetadata, ImageTransform } from './types.js';
+import type {
+ GetImageResult,
+ ImageMetadata,
+ ImageTransform,
+ UnresolvedImageTransform,
+} from './types.js';
export function injectImageEndpoint(settings: AstroSettings) {
settings.injectedRoutes.push({
@@ -37,7 +42,7 @@ export async function getConfiguredImageService(): Promise {
}
export async function getImage(
- options: ImageTransform,
+ options: ImageTransform | UnresolvedImageTransform,
serviceConfig: Record
): Promise {
if (!options || typeof options !== 'object') {
@@ -48,9 +53,19 @@ export async function getImage(
}
const service = await getConfiguredImageService();
+
+ // If the user inlined an import, something fairly common especially in MDX, await it for them
+ const resolvedOptions: ImageTransform = {
+ ...options,
+ src:
+ typeof options.src === 'object' && 'then' in options.src
+ ? (await options.src).default
+ : options.src,
+ };
+
const validatedOptions = service.validateOptions
- ? await service.validateOptions(options, serviceConfig)
- : options;
+ ? await service.validateOptions(resolvedOptions, serviceConfig)
+ : resolvedOptions;
let imageURL = await service.getURL(validatedOptions, serviceConfig);
@@ -60,7 +75,7 @@ export async function getImage(
}
return {
- rawOptions: options,
+ rawOptions: resolvedOptions,
options: validatedOptions,
src: imageURL,
attributes:
diff --git a/packages/astro/src/assets/types.ts b/packages/astro/src/assets/types.ts
index 5632d7691..9c5990cb7 100644
--- a/packages/astro/src/assets/types.ts
+++ b/packages/astro/src/assets/types.ts
@@ -27,6 +27,10 @@ export interface ImageMetadata {
orientation?: number;
}
+export type UnresolvedImageTransform = Omit & {
+ src: Promise<{ default: ImageMetadata }>;
+};
+
/**
* Options accepted by the image transformation service.
*/
@@ -93,7 +97,7 @@ export type LocalImageProps = ImageSharedProps & {
*
* ```
*/
- src: ImageMetadata;
+ src: ImageMetadata | Promise<{ default: ImageMetadata }>;
/**
* Desired output format for the image. Defaults to `webp`.
*
diff --git a/packages/astro/test/core-image.test.js b/packages/astro/test/core-image.test.js
index 4d5f467bf..8c09de245 100644
--- a/packages/astro/test/core-image.test.js
+++ b/packages/astro/test/core-image.test.js
@@ -147,6 +147,19 @@ describe('astro:image', () => {
})
).to.be.true;
});
+
+ it('supports inlined imports', async () => {
+ let res = await fixture.fetch('/inlineImport');
+ let html = await res.text();
+ $ = cheerio.load(html);
+
+ let $img = $('img');
+ expect($img).to.have.a.lengthOf(1);
+
+ let src = $img.attr('src');
+ res = await fixture.fetch(src);
+ expect(res.status).to.equal(200);
+ });
});
describe('vite-isms', () => {
diff --git a/packages/astro/test/fixtures/core-image/src/pages/inlineImport.astro b/packages/astro/test/fixtures/core-image/src/pages/inlineImport.astro
new file mode 100644
index 000000000..323587993
--- /dev/null
+++ b/packages/astro/test/fixtures/core-image/src/pages/inlineImport.astro
@@ -0,0 +1,7 @@
+---
+import { getImage } from "astro:assets";
+
+const optimizedImage = await getImage({src: import('../assets/penguin1.jpg')})
+---
+
+