fix: squoosh not working on Windows in certain situations (#7826)

This commit is contained in:
Erika 2023-07-26 21:38:37 +02:00 committed by GitHub
parent 54fb03b444
commit 31c4031ba7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 36 additions and 42 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Fix `astro:assets` not working on Windows in build when using Squoosh

View file

@ -7,7 +7,6 @@ import {
parseQuality,
type BaseServiceTransform,
type LocalImageService,
type LocalImageTransform,
} from './service.js';
import { processBuffer } from './vendor/squoosh/image-pool.js';
import type { Operation } from './vendor/squoosh/image.js';
@ -30,15 +29,8 @@ const qualityTable: Record<
// Squoosh's PNG encoder does not support a quality setting, so we can skip that here
};
async function getRotationForEXIF(
transform: LocalImageTransform,
inputBuffer: Buffer
): Promise<Operation | undefined> {
// check EXIF orientation data and rotate the image if needed
const filePath = transform.src.slice('/@fs'.length);
const filePathURL = new URL('.' + filePath, 'file:');
const meta = await imageMetadata(filePathURL, inputBuffer);
async function getRotationForEXIF(inputBuffer: Buffer): Promise<Operation | undefined> {
const meta = await imageMetadata(inputBuffer);
if (!meta) return undefined;
// EXIF orientations are a bit hard to read, but the numbers are actually standard. See https://exiftool.org/TagNames/EXIF.html for a list.
@ -71,7 +63,7 @@ const service: LocalImageService = {
const operations: Operation[] = [];
const rotation = await getRotationForEXIF(transform, inputBuffer);
const rotation = await getRotationForEXIF(inputBuffer);
if (rotation) {
operations.push(rotation);

View file

@ -17,7 +17,7 @@ declare global {
}
/**
* Type returned by ESM imports of images and direct calls to imageMetadata
* Type returned by ESM imports of images
*/
export interface ImageMetadata {
src: string;

View file

@ -1,4 +1,4 @@
import fs from 'node:fs';
import fs from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { prependForwardSlash, slash } from '../../core/path.js';
@ -15,34 +15,46 @@ export async function emitESMImage(
}
const url = pathToFileURL(id);
const meta = await imageMetadata(url);
if (!meta) {
let fileData: Buffer;
try {
fileData = await fs.readFile(url);
} catch (err) {
return undefined;
}
const fileMetadata = await imageMetadata(fileData);
if (!fileMetadata) {
return undefined;
}
const emittedImage: ImageMetadata = {
src: '',
...fileMetadata,
};
// Build
if (!watchMode) {
const pathname = decodeURI(url.pathname);
const filename = path.basename(pathname, path.extname(pathname) + `.${meta.format}`);
const filename = path.basename(pathname, path.extname(pathname) + `.${fileMetadata.format}`);
const handle = fileEmitter({
name: filename,
source: await fs.promises.readFile(url),
source: await fs.readFile(url),
type: 'asset',
});
meta.src = `__ASTRO_ASSET_IMAGE__${handle}__`;
emittedImage.src = `__ASTRO_ASSET_IMAGE__${handle}__`;
} else {
// Pass the original file information through query params so we don't have to load the file twice
url.searchParams.append('origWidth', meta.width.toString());
url.searchParams.append('origHeight', meta.height.toString());
url.searchParams.append('origFormat', meta.format);
url.searchParams.append('origWidth', fileMetadata.width.toString());
url.searchParams.append('origHeight', fileMetadata.height.toString());
url.searchParams.append('origFormat', fileMetadata.format);
meta.src = `/@fs` + prependForwardSlash(fileURLToNormalizedPath(url));
emittedImage.src = `/@fs` + prependForwardSlash(fileURLToNormalizedPath(url));
}
return meta;
return emittedImage;
}
function fileURLToNormalizedPath(filePath: URL): string {

View file

@ -1,22 +1,8 @@
import fs from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import type { ImageInputFormat, ImageMetadata } from '../types.js';
import imageSize from '../vendor/image-size/index.js';
export async function imageMetadata(
src: URL | string,
data?: Buffer
): Promise<ImageMetadata | undefined> {
let file = data;
if (!file) {
try {
file = await fs.readFile(src);
} catch (e) {
return undefined;
}
}
const { width, height, type, orientation } = imageSize(file);
export async function imageMetadata(data: Buffer): Promise<Omit<ImageMetadata, 'src'> | undefined> {
const { width, height, type, orientation } = imageSize(data);
const isPortrait = (orientation || 0) >= 5;
if (!width || !height || !type) {
@ -24,7 +10,6 @@ export async function imageMetadata(
}
return {
src: fileURLToPath(src),
width: isPortrait ? height : width,
height: isPortrait ? width : height,
format: type as ImageInputFormat,

View file

@ -1,4 +1,4 @@
import { APIRoute } from "../../../../../src/@types/astro";
import type { APIRoute } from "../../../../../src/@types/astro";
export const get = (async ({ params, request }) => {
const url = new URL(request.url);