img tools - cache
This commit is contained in:
parent
1217408a6e
commit
ac520a6e65
@ -19,12 +19,13 @@ export default async function load(id) {
|
||||
|
||||
|
||||
const { search, searchParams } = fileURL;
|
||||
|
||||
|
||||
id = id.replace(search, "");
|
||||
|
||||
|
||||
const ext = path.extname(id).slice(1);
|
||||
|
||||
|
||||
if (!supportedImageTypes.includes(ext)) return null;
|
||||
debugger
|
||||
|
||||
const { default: astroViteConfigs } = await import(
|
||||
// @ts-ignore
|
||||
|
||||
@ -33,6 +33,7 @@ export default async function ({
|
||||
transformConfigs,
|
||||
}) {
|
||||
try {
|
||||
|
||||
const args = Array.from(arguments);
|
||||
const hash = objectHash(args);
|
||||
|
||||
@ -41,11 +42,6 @@ export default async function ({
|
||||
return imagesData.get(hash);
|
||||
}
|
||||
|
||||
// Caching removed from this level to ensure proper Vite store population
|
||||
// Cache is now handled at the plugin level where it can properly manage the store
|
||||
|
||||
const start = performance.now();
|
||||
|
||||
const {
|
||||
path,
|
||||
base,
|
||||
@ -119,6 +115,8 @@ export default async function ({
|
||||
return returnObject;
|
||||
} catch (error) {
|
||||
console.error(`Error processing images:: ${src}`, error, error.stack);
|
||||
debugger
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
// @ts-check
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { extname, relative, resolve } from "node:path";
|
||||
import { fileURLToPath, URL } from "node:url";
|
||||
import { extname, relative, resolve, join } from "node:path";
|
||||
import fs from "node:fs/promises";
|
||||
import { existsSync } from "node:fs";
|
||||
|
||||
import { getSrcPath } from "./getSrcPath.js";
|
||||
import getResolvedSrc from "./getResolvedSrc.js";
|
||||
@ -16,7 +18,14 @@ export default async function getProcessedImage(
|
||||
transformConfigs,
|
||||
{ skipCache = false } = {}
|
||||
) {
|
||||
throwErrorIfUnsupported(src, extname(src).slice(1));
|
||||
const isRemote = src.startsWith("http");
|
||||
|
||||
const ext = isRemote
|
||||
? extname(new URL(src).pathname).slice(1)
|
||||
: extname(src).slice(1);
|
||||
|
||||
throwErrorIfUnsupported(src, ext);
|
||||
|
||||
let base;
|
||||
|
||||
if (src.match("(http://|https://|data:image/).*")) {
|
||||
@ -44,15 +53,14 @@ export default async function getProcessedImage(
|
||||
...rest
|
||||
} = transformConfigs;
|
||||
|
||||
const path = src.replace(/\\/g, `/`);
|
||||
let path = src.replace(/\\/g, `/`);
|
||||
|
||||
const { image, imageWidth, imageHeight, imageFormat } = await getImageDetails(
|
||||
await getSrcPath(src),
|
||||
width,
|
||||
height,
|
||||
aspect,
|
||||
skipCache
|
||||
);
|
||||
let imagePath = isRemote ? join(cwd, path) : await getSrcPath(src);
|
||||
|
||||
const imageBuffer = await fs.readFile(imagePath);
|
||||
|
||||
const { image, imageWidth, imageHeight, imageFormat } =
|
||||
await getImageDetails(imageBuffer, width, height, aspect, skipCache);
|
||||
|
||||
return {
|
||||
path,
|
||||
|
||||
@ -27,6 +27,10 @@ export async function getSrcPath(src) {
|
||||
const publicTest = publicPath.replace(paramPattern, "");
|
||||
if (fs.existsSync(publicTest)) return publicPath;
|
||||
|
||||
// @todo : remove this
|
||||
const cwdTest = path.join(process.cwd(), src);
|
||||
if (fs.existsSync(cwdTest)) return cwdTest;
|
||||
|
||||
// Fallback
|
||||
return src;
|
||||
}
|
||||
|
||||
@ -29,20 +29,19 @@ export default async function getSrcset(
|
||||
const [cleanSrc] = src.split("?");
|
||||
|
||||
const id = `${cleanSrc}?${params.slice(1)}`;
|
||||
|
||||
const fullPath = await getSrcPath(id);
|
||||
|
||||
const fullPath = await getSrcPath(cleanSrc);
|
||||
const { default: load } = await import("../../plugin/hooks/load.js");
|
||||
// @ts-ignore
|
||||
let srcset = null
|
||||
|
||||
try {
|
||||
|
||||
const loaded = await load(fullPath, base);
|
||||
if (loaded) {
|
||||
srcset = loaded.slice(16, -1);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error loading image ${fullPath}:`, error);
|
||||
console.error(`getSrcset::Error loading image ${fullPath}:`, error.message);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
import { supportedImageTypes } from "../../utils/runtimeChecks.js";
|
||||
|
||||
export default function throwErrorIfUnsupported(src, ext) {
|
||||
|
||||
if (!ext && typeof ext !== "string") {
|
||||
throw new Error(`Failed to load ${src}; Invalid image format`);
|
||||
}
|
||||
|
||||
20
packages/imagetools_3/astro-imagetools.config.mjs
Normal file
20
packages/imagetools_3/astro-imagetools.config.mjs
Normal file
@ -0,0 +1,20 @@
|
||||
import { defineConfig } from "imagetools/config"
|
||||
// https://astro-imagetools-docs.vercel.app/en/global-config-options/
|
||||
export default defineConfig({
|
||||
placeholder: "blurred",
|
||||
format: ["webp", "avif", "jpg"],
|
||||
fallbackFormat: "jpg",
|
||||
includeSourceFormat: false,
|
||||
cacheRoot:".test_cache2",
|
||||
formatOptions: {
|
||||
jpg: {
|
||||
quality: 80,
|
||||
},
|
||||
png: {
|
||||
quality: 80,
|
||||
},
|
||||
webp: {
|
||||
quality: 50,
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -2,10 +2,10 @@ export default {
|
||||
"environment": "build",
|
||||
"isSsrBuild": false,
|
||||
"projectBase": "",
|
||||
"publicDir": "C:\\Users\\zx\\Desktop\\polymech\\site2\\public\\",
|
||||
"rootDir": "C:\\Users\\zx\\Desktop\\polymech\\site2\\",
|
||||
"publicDir": "C:\\Users\\zx\\Desktop\\polymech\\site-min\\public\\",
|
||||
"rootDir": "C:\\Users\\zx\\Desktop\\polymech\\site-min\\",
|
||||
"mode": "production",
|
||||
"outDir": "C:\\Users\\zx\\Desktop\\polymech\\site2\\dist\\",
|
||||
"outDir": "C:\\Users\\zx\\Desktop\\polymech\\site-min\\dist\\",
|
||||
"assetsDir": "_astro",
|
||||
"sourcemap": false,
|
||||
"assetFileNames": "/_astro/[name]@[width].[hash][extname]"
|
||||
|
||||
@ -30,7 +30,6 @@ export async function saveAndCopyAsset(
|
||||
assetsDirExists = true;
|
||||
}
|
||||
|
||||
console.log(`cp ${src} ${dest}`);
|
||||
await fs.copyFile(src, dest).catch(async (error) => {
|
||||
if (error.code === "ENOENT") {
|
||||
const imageBuffer = buffer || (await image.toBuffer());
|
||||
|
||||
@ -14,7 +14,8 @@
|
||||
"scripts": {
|
||||
"test:watch": "vitest",
|
||||
"test": "vitest run",
|
||||
"test:src": "vitest run tests/src.js"
|
||||
"test:src": "vitest run tests/src.js",
|
||||
"test:image": "vitest run tests/image.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
BIN
packages/imagetools_3/public/images/default.png
Normal file
BIN
packages/imagetools_3/public/images/default.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
@ -1,36 +1,52 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { vi } from "vitest";
|
||||
|
||||
const testCachePath = path.join(process.cwd(), ".test_cache/");
|
||||
const testCachePath = path.join(process.cwd(), "test_cache/");
|
||||
|
||||
export const invalid_urls = ["https://example.com/non-existent-image.jpg"];
|
||||
|
||||
export const real_urls = [
|
||||
"https://picsum.photos/200/300",
|
||||
"https://fastly.picsum.photos/id/343/200/300.jpg?hmac=_7ttvLezG-XONDvp0ILwQCv50ivQa_oewm7m6xV2uZA",
|
||||
"https://assets.osr-plastic.org//products/sheetpress/cassandra-edczmax-rc2/media/gallery/latest_controller.jpg",
|
||||
"https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=800&h=400&fit=crop",
|
||||
"https://assets.osr-plastic.org//products/sheetpress/cassandra-edczmax-rc2/media/samples/30mm.jpg",
|
||||
"https://assets.osr-plastic.org//products/sheetpress/cassandra-edczmax-rc2/media/samples/DSC05051.JPG",
|
||||
];
|
||||
|
||||
export const default_options = {
|
||||
format: ["webp", "avif", "jpg"],
|
||||
formatOptions: {
|
||||
jpg: {
|
||||
quality: 80,
|
||||
},
|
||||
png: {
|
||||
quality: 80,
|
||||
},
|
||||
webp: {
|
||||
quality: 50,
|
||||
},
|
||||
},
|
||||
placeholder: "blurred",
|
||||
includeSourceFormat: false,
|
||||
fallbackFormat: ["webp", "avif", "jpg"],
|
||||
// cacheRoot: testCachePath,
|
||||
sizes: (breakpoints) => {
|
||||
const maxWidth = breakpoints[breakpoints.length - 1];
|
||||
return `(min-width: ${maxWidth}px) ${maxWidth}px, 100vw`;
|
||||
},
|
||||
};
|
||||
|
||||
export function setup() {
|
||||
// Create a temporary cache directory for tests
|
||||
if (!fs.existsSync(testCachePath)) {
|
||||
fs.mkdirSync(testCachePath, { recursive: true });
|
||||
}
|
||||
|
||||
// Mock runtimeChecks to use the test cache path
|
||||
vi.mock("../utils/runtimeChecks.js", () => ({
|
||||
cwd: process.cwd(),
|
||||
fsCachePath: testCachePath,
|
||||
supportedImageTypes: [
|
||||
"avif",
|
||||
"jpeg",
|
||||
"jpg",
|
||||
"png",
|
||||
"webp",
|
||||
"heic",
|
||||
"heif",
|
||||
"tiff",
|
||||
"gif",
|
||||
],
|
||||
}));
|
||||
}
|
||||
|
||||
export function teardown() {
|
||||
// Clean up the temporary cache directory
|
||||
if (fs.existsSync(testCachePath)) {
|
||||
fs.rmSync(testCachePath, { recursive: true, force: true });
|
||||
// fs.rmSync(testCachePath, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
44
packages/imagetools_3/tests/image.js
Normal file
44
packages/imagetools_3/tests/image.js
Normal file
@ -0,0 +1,44 @@
|
||||
import { describe, it, expect, beforeAll, afterAll, vi, beforeEach } from "vitest";
|
||||
import getImage from "../api/utils/getImage.js";
|
||||
import {
|
||||
setup,
|
||||
teardown,
|
||||
invalid_urls,
|
||||
real_urls,
|
||||
default_options,
|
||||
} from "./commons.js";
|
||||
|
||||
describe("getImage", () => {
|
||||
beforeAll(() => setup());
|
||||
afterAll(teardown);
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it("should return a default image for invalid URLs", async () => {
|
||||
for (const src of invalid_urls) {
|
||||
const result = await getImage({
|
||||
src,
|
||||
...default_options,
|
||||
transformConfigs: {},
|
||||
});
|
||||
expect(result.images[0].sources[0].srcset).toContain("default");
|
||||
}
|
||||
}, 20000);
|
||||
|
||||
it("should process and return image data for valid URLs", async () => {
|
||||
|
||||
for (const src of real_urls) {
|
||||
const result = await getImage({
|
||||
src,
|
||||
...default_options,
|
||||
transformConfigs: {},
|
||||
});
|
||||
expect(result).toHaveProperty("uuid");
|
||||
expect(result).toHaveProperty("images");
|
||||
expect(Array.isArray(result.images)).toBe(true);
|
||||
expect(result.images.length).toBeGreaterThan(0);
|
||||
}
|
||||
}, 20000);
|
||||
});
|
||||
@ -4,5 +4,5 @@ export default defineConfig({
|
||||
test: {
|
||||
include: ["tests/**/*.js"],
|
||||
},
|
||||
root: ".",
|
||||
root: ".",
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user