diff options
| author | Dawid Rycerz <dawid@rycerz.xyz> | 2025-07-22 15:08:37 +0300 |
|---|---|---|
| committer | Dawid Rycerz <dawid@rycerz.xyz> | 2025-07-22 15:08:37 +0300 |
| commit | fcc2f4704e39b0e69b377cc138f75027721dac22 (patch) | |
| tree | 732fc94b354a26c08fba9cc9059f9c6c900182be /src/utils/images.ts | |
Initial template
Diffstat (limited to 'src/utils/images.ts')
| -rw-r--r-- | src/utils/images.ts | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/src/utils/images.ts b/src/utils/images.ts new file mode 100644 index 0000000..d6f14f0 --- /dev/null +++ b/src/utils/images.ts @@ -0,0 +1,111 @@ +import { isUnpicCompatible, unpicOptimizer, astroAssetsOptimizer } from './images-optimization'; +import type { ImageMetadata } from 'astro'; +import type { OpenGraph } from '@astrolib/seo'; + +const load = async function () { + let images: Record<string, () => Promise<unknown>> | undefined = undefined; + try { + images = import.meta.glob('~/assets/images/**/*.{jpeg,jpg,png,tiff,webp,gif,svg,JPEG,JPG,PNG,TIFF,WEBP,GIF,SVG}'); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } catch (error) { + // continue regardless of error + } + return images; +}; + +let _images: Record<string, () => Promise<unknown>> | undefined = undefined; + +/** */ +export const fetchLocalImages = async () => { + _images = _images || (await load()); + return _images; +}; + +/** */ +export const findImage = async ( + imagePath?: string | ImageMetadata | null +): Promise<string | ImageMetadata | undefined | null> => { + // Not string + if (typeof imagePath !== 'string') { + return imagePath; + } + + // Absolute paths + if (imagePath.startsWith('http://') || imagePath.startsWith('https://') || imagePath.startsWith('/')) { + return imagePath; + } + + // Relative paths or not "~/assets/" + if (!imagePath.startsWith('~/assets/images')) { + return imagePath; + } + + const images = await fetchLocalImages(); + const key = imagePath.replace('~/', '/src/'); + + return images && typeof images[key] === 'function' + ? ((await images[key]()) as { default: ImageMetadata })['default'] + : null; +}; + +/** */ +export const adaptOpenGraphImages = async ( + openGraph: OpenGraph = {}, + astroSite: URL | undefined = new URL('') +): Promise<OpenGraph> => { + if (!openGraph?.images?.length) { + return openGraph; + } + + const images = openGraph.images; + const defaultWidth = 1200; + const defaultHeight = 626; + + const adaptedImages = await Promise.all( + images.map(async (image) => { + if (image?.url) { + const resolvedImage = (await findImage(image.url)) as ImageMetadata | string | undefined; + if (!resolvedImage) { + return { + url: '', + }; + } + + 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 astroAssetsOptimizer(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)) : '', + width: 'width' in _image && typeof _image.width === 'number' ? _image.width : undefined, + height: 'height' in _image && typeof _image.height === 'number' ? _image.height : undefined, + }; + } + return { + url: '', + }; + } + + return { + url: '', + }; + }) + ); + + return { ...openGraph, ...(adaptedImages ? { images: adaptedImages } : {}) }; +}; |
