From 062335dbf7300ad5370e29ebcf7a05d5a4703a1c Mon Sep 17 00:00:00 2001
From: Matthew Phillips <matthew@skypack.dev>
Date: Fri, 7 Oct 2022 17:08:15 -0400
Subject: [PATCH] Fix remote images in SSG mode (#5021)

---
 .changeset/sixty-actors-look.md               |  5 ++++
 packages/integrations/image/src/build/ssg.ts  |  7 ++++--
 .../get-image-remote/astro.config.mjs         |  8 ++++++
 .../fixtures/get-image-remote/package.json    | 10 ++++++++
 .../get-image-remote/src/pages/index.astro    | 25 +++++++++++++++++++
 .../integrations/image/test/get-image.test.js | 17 +++++++++++++
 pnpm-lock.yaml                                | 10 ++++++++
 7 files changed, 80 insertions(+), 2 deletions(-)
 create mode 100644 .changeset/sixty-actors-look.md
 create mode 100644 packages/integrations/image/test/fixtures/get-image-remote/astro.config.mjs
 create mode 100644 packages/integrations/image/test/fixtures/get-image-remote/package.json
 create mode 100644 packages/integrations/image/test/fixtures/get-image-remote/src/pages/index.astro
 create mode 100644 packages/integrations/image/test/get-image.test.js

diff --git a/.changeset/sixty-actors-look.md b/.changeset/sixty-actors-look.md
new file mode 100644
index 0000000000..fe6c1adb6c
--- /dev/null
+++ b/.changeset/sixty-actors-look.md
@@ -0,0 +1,5 @@
+---
+'@astrojs/image': patch
+---
+
+Fix remote images in SSG mode
diff --git a/packages/integrations/image/src/build/ssg.ts b/packages/integrations/image/src/build/ssg.ts
index ba920b4f97..4e017bbb4f 100644
--- a/packages/integrations/image/src/build/ssg.ts
+++ b/packages/integrations/image/src/build/ssg.ts
@@ -164,12 +164,13 @@ export async function ssgBuild({
 		for (const [filename, transform] of transforms) {
 			timeStart = performance.now();
 			let outputFile: string;
+			let outputFileURL: URL;
 
 			if (isRemoteImage(src)) {
-				const outputFileURL = new URL(path.join('./assets', path.basename(filename)), outDir);
+				outputFileURL = new URL(path.join('./assets', path.basename(filename)), outDir);
 				outputFile = fileURLToPath(outputFileURL);
 			} else {
-				const outputFileURL = new URL(path.join('./assets', filename), outDir);
+				outputFileURL = new URL(path.join('./assets', filename), outDir);
 				outputFile = fileURLToPath(outputFileURL);
 			}
 
@@ -193,6 +194,8 @@ export async function ssgBuild({
 				}
 			}
 
+			const outputFolder = new URL('./', outputFileURL);
+			await fs.mkdir(outputFolder, { recursive: true });
 			await fs.writeFile(outputFile, data);
 
 			const timeEnd = performance.now();
diff --git a/packages/integrations/image/test/fixtures/get-image-remote/astro.config.mjs b/packages/integrations/image/test/fixtures/get-image-remote/astro.config.mjs
new file mode 100644
index 0000000000..f00c6ebae7
--- /dev/null
+++ b/packages/integrations/image/test/fixtures/get-image-remote/astro.config.mjs
@@ -0,0 +1,8 @@
+import { defineConfig } from 'astro/config';
+import image from '@astrojs/image';
+
+// https://astro.build/config
+export default defineConfig({
+	site: 'http://localhost:3000',
+	integrations: [image({ logLevel: 'silent', serviceEntryPoint: '@astrojs/image/sharp' })]
+});
diff --git a/packages/integrations/image/test/fixtures/get-image-remote/package.json b/packages/integrations/image/test/fixtures/get-image-remote/package.json
new file mode 100644
index 0000000000..a5279e3122
--- /dev/null
+++ b/packages/integrations/image/test/fixtures/get-image-remote/package.json
@@ -0,0 +1,10 @@
+{
+  "name": "@test/image-get-image-remote",
+  "version": "0.0.0",
+  "private": true,
+  "dependencies": {
+    "@astrojs/image": "workspace:*",
+    "astro": "workspace:*",
+    "sharp": "^0.31.0"
+  }
+}
diff --git a/packages/integrations/image/test/fixtures/get-image-remote/src/pages/index.astro b/packages/integrations/image/test/fixtures/get-image-remote/src/pages/index.astro
new file mode 100644
index 0000000000..ff45cd498f
--- /dev/null
+++ b/packages/integrations/image/test/fixtures/get-image-remote/src/pages/index.astro
@@ -0,0 +1,25 @@
+---
+import { getImage } from "@astrojs/image";
+
+const i = {
+	src: "https://images.unsplash.com/photo-1664309570712-564c233f112b?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=200&q=80",
+	format: 'avif',
+	width: 200,
+	height: 300,
+}
+const image = await getImage(i as any);
+---
+
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
+		<meta name="viewport" content="width=device-width" />
+		<meta name="generator" content={Astro.generator} />
+		<title>Astro</title>
+	</head>
+	<body>
+		<h1>Astro</h1>
+		<img {...image} />
+	</body>
+</html>
diff --git a/packages/integrations/image/test/get-image.test.js b/packages/integrations/image/test/get-image.test.js
new file mode 100644
index 0000000000..6a4ddc816a
--- /dev/null
+++ b/packages/integrations/image/test/get-image.test.js
@@ -0,0 +1,17 @@
+import { expect } from 'chai';
+import { loadFixture } from './test-utils.js';
+
+describe('getImage', function () {
+	/** @type {import('../../../astro/test/test-utils').Fixture} */
+	let fixture;
+
+	before(async () => {
+		fixture = await loadFixture({ root: './fixtures/get-image-remote/' });
+		await fixture.build();
+	});
+
+	it('Remote images works', async () => {
+		const assets = await fixture.readdir('/assets')
+		expect(assets).to.have.a.lengthOf(1);
+	});
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1c0d473b84..04f1ca855a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -2603,6 +2603,16 @@ importers:
       astro: link:../../../../../astro
       sharp: 0.31.1
 
+  packages/integrations/image/test/fixtures/get-image-remote:
+    specifiers:
+      '@astrojs/image': workspace:*
+      astro: workspace:*
+      sharp: ^0.31.0
+    dependencies:
+      '@astrojs/image': link:../../..
+      astro: link:../../../../../astro
+      sharp: 0.31.1
+
   packages/integrations/image/test/fixtures/no-alt-text-image:
     specifiers:
       '@astrojs/image': workspace:*