diff --git a/packages/imagetools/plugin/hooks/load.js b/packages/imagetools/plugin/hooks/load.js index 635f788..f09d5b7 100644 --- a/packages/imagetools/plugin/hooks/load.js +++ b/packages/imagetools/plugin/hooks/load.js @@ -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 diff --git a/packages/imagetools_3/api/utils/getImage.js b/packages/imagetools_3/api/utils/getImage.js index a51b367..c857a87 100644 --- a/packages/imagetools_3/api/utils/getImage.js +++ b/packages/imagetools_3/api/utils/getImage.js @@ -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; } } diff --git a/packages/imagetools_3/api/utils/getProcessedImage.js b/packages/imagetools_3/api/utils/getProcessedImage.js index 4cc14cd..08a86b3 100644 --- a/packages/imagetools_3/api/utils/getProcessedImage.js +++ b/packages/imagetools_3/api/utils/getProcessedImage.js @@ -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, diff --git a/packages/imagetools_3/api/utils/getSrcPath.js b/packages/imagetools_3/api/utils/getSrcPath.js index 3a7a7da..5c9c5af 100644 --- a/packages/imagetools_3/api/utils/getSrcPath.js +++ b/packages/imagetools_3/api/utils/getSrcPath.js @@ -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; } diff --git a/packages/imagetools_3/api/utils/getSrcset.js b/packages/imagetools_3/api/utils/getSrcset.js index 14b3bf5..75f411d 100644 --- a/packages/imagetools_3/api/utils/getSrcset.js +++ b/packages/imagetools_3/api/utils/getSrcset.js @@ -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; } diff --git a/packages/imagetools_3/api/utils/throwErrorIfUnsupported.js b/packages/imagetools_3/api/utils/throwErrorIfUnsupported.js index 581ca16..5ef7e73 100644 --- a/packages/imagetools_3/api/utils/throwErrorIfUnsupported.js +++ b/packages/imagetools_3/api/utils/throwErrorIfUnsupported.js @@ -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`); } diff --git a/packages/imagetools_3/astro-imagetools.config.mjs b/packages/imagetools_3/astro-imagetools.config.mjs new file mode 100644 index 0000000..f1d3193 --- /dev/null +++ b/packages/imagetools_3/astro-imagetools.config.mjs @@ -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, + } + } +}); \ No newline at end of file diff --git a/packages/imagetools_3/astroViteConfigs.js b/packages/imagetools_3/astroViteConfigs.js index 2f7b5cc..af59ac4 100644 --- a/packages/imagetools_3/astroViteConfigs.js +++ b/packages/imagetools_3/astroViteConfigs.js @@ -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]" diff --git a/packages/imagetools_3/integration/utils/saveAndCopyAsset.js b/packages/imagetools_3/integration/utils/saveAndCopyAsset.js index 8ab63ca..f075377 100644 --- a/packages/imagetools_3/integration/utils/saveAndCopyAsset.js +++ b/packages/imagetools_3/integration/utils/saveAndCopyAsset.js @@ -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()); diff --git a/packages/imagetools_3/package.json b/packages/imagetools_3/package.json index d452f47..5919f56 100644 --- a/packages/imagetools_3/package.json +++ b/packages/imagetools_3/package.json @@ -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", diff --git a/packages/imagetools_3/public/images/default.png b/packages/imagetools_3/public/images/default.png new file mode 100644 index 0000000..48180db Binary files /dev/null and b/packages/imagetools_3/public/images/default.png differ diff --git a/packages/imagetools_3/tests/commons.js b/packages/imagetools_3/tests/commons.js index 5561298..6cf469d 100644 --- a/packages/imagetools_3/tests/commons.js +++ b/packages/imagetools_3/tests/commons.js @@ -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 }); } } diff --git a/packages/imagetools_3/tests/image.js b/packages/imagetools_3/tests/image.js new file mode 100644 index 0000000..47ccf8b --- /dev/null +++ b/packages/imagetools_3/tests/image.js @@ -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); +}); diff --git a/packages/imagetools_3/vitest.config.ts b/packages/imagetools_3/vitest.config.ts index 295c03c..58258f2 100644 --- a/packages/imagetools_3/vitest.config.ts +++ b/packages/imagetools_3/vitest.config.ts @@ -4,5 +4,5 @@ export default defineConfig({ test: { include: ["tests/**/*.js"], }, - root: ".", + root: ".", });