fix:imagetools
This commit is contained in:
parent
0f6bcc4267
commit
a64acb9f71
File diff suppressed because one or more lines are too long
8
package-lock.json
generated
8
package-lock.json
generated
@ -67,6 +67,7 @@
|
||||
"sharp": "^0.29.3",
|
||||
"showdown": "^2.1.0",
|
||||
"tailwindcss": "^4.0.7",
|
||||
"ts-retry": "^6.0.0",
|
||||
"type-fest": "^4.34.1",
|
||||
"vite": "^6.1.1",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
@ -15132,6 +15133,12 @@
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-retry": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-retry/-/ts-retry-6.0.0.tgz",
|
||||
"integrity": "sha512-WsVRE/P+VNYbiQC3E6TeIXBRCQj7vzjN4MlXd84AC88K7WwuWShN7A3Q/QSV/yd1hjO8qn2Cevdqny2HMwKUaA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tsconfck": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.5.tgz",
|
||||
@ -16759,6 +16766,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@astropub/codecs": "0.4.4",
|
||||
"@polymech/fs": "file:../../../polymech-mono/packages/fs",
|
||||
"file-type": "17.1.1",
|
||||
"find-cache-dir": "3.3.2",
|
||||
"find-up": "^6.3.0",
|
||||
|
||||
@ -3,6 +3,9 @@
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./src/index.js"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "astro dev --mode dev --host=0.0.0.0 --o-images=medium",
|
||||
"start": "astro dev",
|
||||
@ -77,6 +80,7 @@
|
||||
"sharp": "^0.29.3",
|
||||
"showdown": "^2.1.0",
|
||||
"tailwindcss": "^4.0.7",
|
||||
"ts-retry": "^6.0.0",
|
||||
"type-fest": "^4.34.1",
|
||||
"vite": "^6.1.1",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
|
||||
@ -4,12 +4,7 @@ import objectHash from "object-hash";
|
||||
import getImageSources from "./getImageSources.js";
|
||||
import getProcessedImage from "./getProcessedImage.js";
|
||||
import getArtDirectedImages from "./getArtDirectedImages.js";
|
||||
import pMap from "p-map";
|
||||
|
||||
const imagesData = new Map();
|
||||
|
||||
const delay = (ms = 100) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
export default async function ({
|
||||
src,
|
||||
type,
|
||||
@ -23,29 +18,26 @@ export default async function ({
|
||||
artDirectives,
|
||||
transformConfigs,
|
||||
}) {
|
||||
try {
|
||||
const args = Array.from(arguments);
|
||||
|
||||
const hash = objectHash(args);
|
||||
|
||||
if (imagesData.has(hash)) {
|
||||
return imagesData.get(hash);
|
||||
}
|
||||
// const start = performance.now();
|
||||
const { path, base, rest, image, imageWidth, imageHeight, imageFormat } =
|
||||
await getProcessedImage(src, transformConfigs);
|
||||
|
||||
await delay();
|
||||
src = path;
|
||||
|
||||
rest.aspect = `${imageWidth / imageHeight}`;
|
||||
|
||||
if (!fallbackFormat) {
|
||||
fallbackFormat = imageFormat;
|
||||
}
|
||||
|
||||
// Fetch both image sources and art-directed images
|
||||
const [mainImage, artDirectedImages] = await pMap(
|
||||
[
|
||||
async () =>
|
||||
await getImageSources(
|
||||
const [mainImage, artDirectedImages] = await Promise.all([
|
||||
getImageSources(
|
||||
src,
|
||||
base,
|
||||
image,
|
||||
@ -60,8 +52,7 @@ export default async function ({
|
||||
includeSourceFormat,
|
||||
rest
|
||||
),
|
||||
async () => {
|
||||
return await getArtDirectedImages(
|
||||
getArtDirectedImages(
|
||||
artDirectives,
|
||||
placeholder,
|
||||
format,
|
||||
@ -71,28 +62,18 @@ export default async function ({
|
||||
includeSourceFormat,
|
||||
formatOptions,
|
||||
rest
|
||||
);
|
||||
},
|
||||
],
|
||||
async (task) => await task(),
|
||||
{ concurrency: 1 }
|
||||
);
|
||||
),
|
||||
]);
|
||||
|
||||
const images = [...artDirectedImages, mainImage];
|
||||
|
||||
// Ensure artDirectedImages is an array
|
||||
const images = Array.isArray(artDirectedImages) ? [...artDirectedImages, mainImage] : [mainImage];
|
||||
const uuid = crypto.randomBytes(4).toString("hex").toUpperCase();
|
||||
|
||||
const returnObject = {
|
||||
uuid,
|
||||
images,
|
||||
};
|
||||
|
||||
imagesData.set(hash, returnObject);
|
||||
//const end = performance.now();
|
||||
//console.log( `Responsive Image sets generated for ${type} at ${args[0].src} in ${end - start}ms`);
|
||||
imagesData.set(hash, returnObject)
|
||||
return returnObject;
|
||||
} catch (error) {
|
||||
console.error("Error processing images:", error);
|
||||
debugger
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -3,8 +3,9 @@ import getSrcset from "./getSrcset.js";
|
||||
import getConfigOptions from "./getConfigOptions.js";
|
||||
import getFallbackImage from "./getFallbackImage.js";
|
||||
import pMap from "p-map";
|
||||
import { DEFAULT_IO_DELAY } from "../../constants.js";
|
||||
|
||||
function delay(ms = 150) {
|
||||
function delay(ms = DEFAULT_IO_DELAY) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
|
||||
@ -6,28 +6,32 @@ import { getSrcPath } from "./getSrcPath.js";
|
||||
import getResolvedSrc from "./getResolvedSrc.js";
|
||||
import { cwd, sharp } from "../../utils/runtimeChecks.js";
|
||||
import throwErrorIfUnsupported from "./throwErrorIfUnsupported.js";
|
||||
import { retryAsync } from "ts-retry";
|
||||
import { DEFAULT_IO_DELAY } from "../../constants.js";
|
||||
|
||||
const { getImageDetails } = await (sharp
|
||||
? import("./imagetools.js")
|
||||
: import("./codecs.js"));
|
||||
|
||||
export default async function getProcessedImage(src, transformConfigs) {
|
||||
throwErrorIfUnsupported(src, extname(src).slice(1));
|
||||
|
||||
export async function _getProcessedImage(src, transformConfigs) {
|
||||
throwErrorIfUnsupported(src, extname(src).slice(1));
|
||||
let base;
|
||||
|
||||
if (src.match("(http://|https://|data:image/).*")) {
|
||||
({ src, base } = await getResolvedSrc(src))
|
||||
({ src, base } = await getResolvedSrc(src));
|
||||
} else {
|
||||
const {
|
||||
default: { isSsrBuild },
|
||||
} = await import("../../astroViteConfigs.js")
|
||||
} = await import("../../astroViteConfigs.js");
|
||||
|
||||
if (isSsrBuild) {
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const assetPath = resolve(filename, "../../client") + src
|
||||
const filename = fileURLToPath(import.meta.url);
|
||||
const assetPath = resolve(filename, "../../client") + src;
|
||||
src = "/" + relative(cwd, assetPath);
|
||||
}
|
||||
}
|
||||
|
||||
const {
|
||||
w,
|
||||
h,
|
||||
@ -57,3 +61,8 @@ export default async function getProcessedImage(src, transformConfigs) {
|
||||
imageFormat,
|
||||
};
|
||||
}
|
||||
|
||||
export default async function getProcessedImage(src, transformConfigs) {
|
||||
//@todo : hiccups in vips/sharp
|
||||
return retryAsync(() => _getProcessedImage(src, transformConfigs), { delay: DEFAULT_IO_DELAY, maxTry: 3 })
|
||||
}
|
||||
@ -13,9 +13,7 @@ const { fileTypeFromBuffer } = await import("file-type");
|
||||
|
||||
export default async function getResolvedSrc(src) {
|
||||
const token = crypto.createHash("md5").update(src).digest("hex");
|
||||
|
||||
let filepath = fsCachePath + token;
|
||||
|
||||
const fileExists = (() => {
|
||||
for (const type of supportedImageTypes) {
|
||||
const fileExists = fs.existsSync(filepath + `.${type}`);
|
||||
@ -28,18 +26,14 @@ export default async function getResolvedSrc(src) {
|
||||
}
|
||||
})();
|
||||
|
||||
try {
|
||||
if (!fileExists) {
|
||||
const buffer = Buffer.from(await (await fetch(src)).arrayBuffer());
|
||||
|
||||
const { ext } = (await fileTypeFromBuffer(buffer)) || {};
|
||||
|
||||
throwErrorIfUnsupported(src, ext);
|
||||
|
||||
filepath += `.${ext}`;
|
||||
|
||||
fs.writeFileSync(filepath, buffer);
|
||||
}
|
||||
|
||||
const base = /^https?:/.test(src)
|
||||
? parse(new URL(src).pathname).name
|
||||
: undefined;
|
||||
@ -47,4 +41,8 @@ export default async function getResolvedSrc(src) {
|
||||
src = join("/", relative(cwd, filepath));
|
||||
|
||||
return { src, base };
|
||||
} catch (e) {
|
||||
console.error(`Error while resolving src: ${src} : ${e.message}`)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
1
packages/imagetools/constants.js
Normal file
1
packages/imagetools/constants.js
Normal file
@ -0,0 +1 @@
|
||||
export const DEFAULT_IO_DELAY = 350;
|
||||
@ -5,6 +5,7 @@ import { posix as path, resolve } from "node:path"
|
||||
import { saveAndCopyAsset } from "./utils/saveAndCopyAsset.js"
|
||||
import vitePluginAstroImageTools, { store } from "../plugin/index.js"
|
||||
import pMap from "p-map"
|
||||
import { DEFAULT_IO_DELAY } from "../constants.js"
|
||||
|
||||
const filename = fileURLToPath(import.meta.url);
|
||||
const astroViteConfigsPath = resolve(filename, "../../astroViteConfigs.js");
|
||||
@ -60,7 +61,7 @@ export default {
|
||||
assetPaths,
|
||||
async ([assetPath, { hash, image, buffer }]) => {
|
||||
// delay, otherwise unknown errors occur (sharp/vips)
|
||||
await new Promise((resolve) => setTimeout(resolve, 150));
|
||||
await new Promise((resolve) => setTimeout(resolve, DEFAULT_IO_DELAY));
|
||||
try {
|
||||
await saveAndCopyAsset(
|
||||
hash,
|
||||
|
||||
@ -36,7 +36,7 @@ export const PRODUCTS_TARGET = (lang) => `./content/${lang}/products`
|
||||
|
||||
// Product assets
|
||||
|
||||
export const ASSETS_LOCALE = true
|
||||
export const ASSETS_LOCAL = false
|
||||
|
||||
// OSRL - Language
|
||||
export const IS_DEV = true
|
||||
|
||||
@ -14,7 +14,7 @@ import { sync as mv } from '@polymech/fs/move'
|
||||
import { logger } from '@/base/index.js'
|
||||
|
||||
import { removeArrayValues, removeArrays, removeBufferValues, removeEmptyObjects } from '@/base/objects.js'
|
||||
import { ITEM_ASSET_URL, PRODUCT_CONFIG, PRODUCT_ROOT, DEFAULT_IMAGE_URL, ASSETS_LOCALE } from '../app/config.js'
|
||||
import { ITEM_ASSET_URL, PRODUCT_CONFIG, PRODUCT_ROOT, DEFAULT_IMAGE_URL, ASSETS_LOCAL } from '../app/config.js'
|
||||
import { GalleryImage, MetaJSON } from './images.js'
|
||||
|
||||
import { validateFilename, sanitizeFilename } from "@polymech/fs/utils"
|
||||
@ -138,7 +138,7 @@ export const gallery = async (
|
||||
))
|
||||
}
|
||||
|
||||
if (!ASSETS_LOCALE) {
|
||||
if (!ASSETS_LOCAL) {
|
||||
galleryFiles = await pMap(galleryFiles, async (f) => (await default_filter(assetUrl(f))) ? f : null, { concurrency: 5 })
|
||||
galleryFiles = galleryFiles.filter((f) => f !== null)
|
||||
galleryFiles = default_sort(galleryFiles)
|
||||
@ -181,7 +181,7 @@ export const gallery = async (
|
||||
delete imageMeta.exif.icc
|
||||
delete imageMeta.exif.xmp
|
||||
delete imageMeta.exif.iptc
|
||||
const src = ASSETS_LOCALE ? filePath : await image_url(assetUrl(file))
|
||||
const src = ASSETS_LOCAL ? filePath : await image_url(assetUrl(file))
|
||||
const ret: GalleryImage =
|
||||
{
|
||||
name: path.parse(file).name,
|
||||
|
||||
Reference in New Issue
Block a user