This repository has been archived on 2025-12-24. You can view files and clone it, but cannot push or open issues or pull requests.
site-template/packages/imagetoolsOSR/plugin/hooks/load.js
2025-03-07 14:59:06 +01:00

152 lines
3.9 KiB
JavaScript

// @ts-check
import path from "node:path";
import objectHash from "object-hash";
import { store } from "../index.js";
import { getCachedBuffer } from "../utils/cache.js";
import { getSrcPath } from "../../api/utils/getSrcPath.js";
import { getAssetPath, getConfigOptions } from "../utils/shared.js";
import { sharp, supportedImageTypes } from "../../utils/runtimeChecks.js";
const { getLoadedImage, getTransformedImage } = await import("../utils/imagetools.js")
export default async function load(id) {
try {
var fileURL = new URL(`file://${id}`);
} catch (error) {
return null;
}
const { search, searchParams } = fileURL;
id = id.replace(search, "");
const ext = path.extname(id).slice(1);
if (!supportedImageTypes.includes(ext)) return null;
const { default: astroViteConfigs } = await import(
// @ts-ignore
"../../astroViteConfigs.js"
);
const { environment, projectBase, assetFileNames } = astroViteConfigs;
const src = await getSrcPath(id);
const rootRelativePosixSrc = path.posix.normalize(
path.relative("", src).split(path.sep).join(path.posix.sep)
);
const getHash = (width) =>
objectHash(
{ width, options, rootRelativePosixSrc },
// @ts-ignore
{ algorithm: "sha256" }
);
const base =
typeof arguments[1] === "string"
? arguments[1]
: path.basename(src, path.extname(src));
const config = Object.fromEntries(searchParams);
const { image: loadedImage, width: imageWidth } =
store.get(src) || store.set(src, await getLoadedImage(src, ext)).get(src);
const { type, widths, options, extension, raw, inline } = getConfigOptions(
config,
ext,
imageWidth
);
if (raw) {
const testConfig = { ...config }
delete testConfig.raw
delete testConfig.inline
delete testConfig.base64
if (Object.keys(testConfig).length > 0) {
throw new Error(
"If raw is set, no other options can be set except inline and base64"
);
}
}
if (inline) {
if (widths.length > 1) {
throw new Error(
`The base64 or inline parameter can't be used with multiple widths`
);
}
const [width] = widths
const hash = getHash(width)
if (store.has(hash)) {
return `export default "${store.get(hash)}"`;
} else {
const config = { width, ...options };
const { image, buffer } = raw
? {
image: sharp ? loadedImage : null,
buffer: !sharp ? loadedImage.data : null,
}
: await getTransformedImage({
src,
image: loadedImage,
config,
type,
});
const dataUri = `data:${type};base64,${(
buffer || (await getCachedBuffer(hash, image))
).toString("base64")}`
store.set(hash, dataUri)
return `export default "${dataUri}"`;
}
} else {
const sources = await Promise.all(
widths.map(async (width) => {
const hash = getHash(width)
const assetPath = getAssetPath(
base,
assetFileNames,
extension,
width,
hash
)
if (!store.has(assetPath)) {
const config = { width, ...options }
const { image, buffer } = raw
? {
image: sharp && loadedImage,
buffer: !sharp && loadedImage.data,
}
: await getTransformedImage({
src,
image: loadedImage,
config,
type,
});
const imageObject = { hash, type, image, buffer }
store.set(assetPath, imageObject)
}
const modulePath =
environment === "dev" ? assetPath : projectBase + assetPath
return { width, modulePath }
})
)
const srcset =
sources.length > 1
? sources
.map(({ width, modulePath }) => `${modulePath} ${width}w`)
.join(", ")
: sources[0].modulePath
return `export default "${srcset}"`
}
}