From eebebeb4a4e95fa580eea8d06d3576c02156de93 Mon Sep 17 00:00:00 2001 From: prototypa Date: Sun, 13 Oct 2024 06:50:21 -0400 Subject: [PATCH] Fix issue #515: Image optimization crash --- package-lock.json | 4 ++-- package.json | 2 +- src/utils/images-optimization.ts | 31 +++++++++++++++++++++++-------- src/utils/images.ts | 27 ++++++++++++++++++--------- 4 files changed, 44 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index c5f3b4fc0..4d1fa89f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@onwidget/astrowind", - "version": "1.0.0-beta.47", + "version": "1.0.0-beta.48", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@onwidget/astrowind", - "version": "1.0.0-beta.47", + "version": "1.0.0-beta.48", "dependencies": { "@astrojs/rss": "^4.0.8", "@astrojs/sitemap": "^3.2.0", diff --git a/package.json b/package.json index 7b626a2d5..089ed4150 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onwidget/astrowind", - "version": "1.0.0-beta.47", + "version": "1.0.0-beta.48", "description": "AstroWind: A free template using Astro 4.0 and Tailwind CSS. Astro starter theme.", "type": "module", "private": true, diff --git a/src/utils/images-optimization.ts b/src/utils/images-optimization.ts index 3f563b223..8eb75725b 100644 --- a/src/utils/images-optimization.ts +++ b/src/utils/images-optimization.ts @@ -22,13 +22,16 @@ export interface ImageProps extends Omit, 'src'> { widths?: number[] | null; aspectRatio?: string | number | null; objectPosition?: string; + + format?: string; } export type ImagesOptimizer = ( image: ImageMetadata | string, breakpoints: number[], width?: number, - height?: number + height?: number, + format?: string ) => Promise>; /* ******* */ @@ -209,17 +212,25 @@ const getBreakpoints = ({ }; /* ** */ -export const astroAsseetsOptimizer: ImagesOptimizer = async (image, breakpoints, _width, _height) => { +export const astroAsseetsOptimizer: ImagesOptimizer = async ( + image, + breakpoints, + _width, + _height, + format = undefined +) => { if (!image) { return []; } return Promise.all( breakpoints.map(async (w: number) => { - const url = (await getImage({ src: image, width: w, inferSize: true })).src; + const result = (await getImage({ src: image, width: w, inferSize: true, ...(format ? { format: format } : {}) })); + return { - src: url, - width: w, + src: result?.src, + width: result?.attributes?.width ?? w, + height: result?.attributes?.height }; }) ); @@ -230,7 +241,7 @@ export const isUnpicCompatible = (image: string) => { }; /* ** */ -export const unpicOptimizer: ImagesOptimizer = async (image, breakpoints, width, height) => { +export const unpicOptimizer: ImagesOptimizer = async (image, breakpoints, width, height, format = undefined) => { if (!image || typeof image !== 'string') { return []; } @@ -242,16 +253,19 @@ export const unpicOptimizer: ImagesOptimizer = async (image, breakpoints, width, return Promise.all( breakpoints.map(async (w: number) => { + const _height = width && height ? computeHeight(w, width / height) : height; const url = transformUrl({ url: image, width: w, - height: width && height ? computeHeight(w, width / height) : height, + height: _height, cdn: urlParsed.cdn, + ...(format ? { format: format } : {}), }) || image; return { src: String(url), width: w, + height: _height, }; }) ); @@ -270,6 +284,7 @@ export async function getImagesOptimized( widths, layout = 'constrained', style = '', + format, ...rest }: ImageProps, transform: ImagesOptimizer = () => Promise.resolve([]) @@ -312,7 +327,7 @@ export async function getImagesOptimized( let breakpoints = getBreakpoints({ width: width, breakpoints: widths, layout: layout }); breakpoints = [...new Set(breakpoints)].sort((a, b) => a - b); - const srcset = (await transform(image, breakpoints, Number(width) || undefined, Number(height) || undefined)) + const srcset = (await transform(image, breakpoints, Number(width) || undefined, Number(height) || undefined, format)) .map(({ src, width }) => `${src} ${width}w`) .join(', '); diff --git a/src/utils/images.ts b/src/utils/images.ts index 3570727f0..1edd3961f 100644 --- a/src/utils/images.ts +++ b/src/utils/images.ts @@ -1,4 +1,4 @@ -import { getImage } from 'astro:assets'; +import { isUnpicCompatible, unpicOptimizer, astroAsseetsOptimizer } from './images-optimization'; import type { ImageMetadata } from 'astro'; import type { OpenGraph } from '@astrolib/seo'; @@ -64,23 +64,32 @@ export const adaptOpenGraphImages = async ( const adaptedImages = await Promise.all( images.map(async (image) => { if (image?.url) { - const resolvedImage = (await findImage(image.url)) as ImageMetadata | undefined; + const resolvedImage = (await findImage(image.url)) as ImageMetadata | string | undefined; if (!resolvedImage) { return { url: '', }; } - const _image = await getImage({ - src: resolvedImage, - alt: 'Placeholder alt', - width: image?.width || defaultWidth, - height: image?.height || defaultHeight, - }); + let _image; + + if ( + typeof resolvedImage === 'string' && + (resolvedImage.startsWith('http://') || resolvedImage.startsWith('https://')) && + isUnpicCompatible(resolvedImage) + ) { + _image = (await unpicOptimizer(resolvedImage, [defaultWidth], defaultWidth, defaultHeight, 'jpg'))[0]; + } else if (resolvedImage) { + const dimensions = + typeof resolvedImage !== 'string' && resolvedImage?.width <= defaultWidth + ? [resolvedImage?.width, resolvedImage?.height] + : [defaultWidth, defaultHeight]; + _image = (await astroAsseetsOptimizer(resolvedImage, [dimensions[0]], dimensions[0], dimensions[1], 'jpg'))[0]; + } if (typeof _image === 'object') { return { - url: 'src' in _image && typeof _image.src === 'string' ? String(new URL(_image.src, astroSite)) : 'pepe', + url: 'src' in _image && typeof _image.src === 'string' ? String(new URL(_image.src, astroSite)) : '', width: 'width' in _image && typeof _image.width === 'number' ? _image.width : undefined, height: 'height' in _image && typeof _image.height === 'number' ? _image.height : undefined, };