Browse Source

Skip remote URLs in thumbnail generation

feature/canvas-chatbot-copilot
yuanzoo 2 months ago
parent
commit
5a9b811d2a
  1. 14
      src/utils/__tests__/imageThumbnail.test.ts
  2. 43
      src/utils/imageThumbnail.ts

14
src/utils/__tests__/imageThumbnail.test.ts

@ -0,0 +1,14 @@
import { describe, expect, it } from "vitest";
import { generateThumbnail } from "../imageThumbnail";
describe("generateThumbnail", () => {
it("returns empty sources unchanged", async () => {
await expect(generateThumbnail("")).resolves.toBe("");
});
it("does not export remote image URLs through canvas", async () => {
const remoteUrl = "https://r2cdn.copilotbase.com/r2cdn2/generated.png";
await expect(generateThumbnail(remoteUrl)).resolves.toBe(remoteUrl);
});
});

43
src/utils/imageThumbnail.ts

@ -9,35 +9,40 @@ export async function generateThumbnail(
quality: number = 0.6 quality: number = 0.6
): Promise<string> { ): Promise<string> {
if (!base64DataUrl) return base64DataUrl; if (!base64DataUrl) return base64DataUrl;
if (!base64DataUrl.startsWith("data:image/")) return base64DataUrl;
return new Promise((resolve) => { return new Promise((resolve) => {
const img = new Image(); const img = new Image();
img.onload = () => { img.onload = () => {
const { naturalWidth: w, naturalHeight: h } = img; try {
const { naturalWidth: w, naturalHeight: h } = img;
// Skip if already small enough // Skip if already small enough
if (w <= maxDim && h <= maxDim) { if (w <= maxDim && h <= maxDim) {
resolve(base64DataUrl); resolve(base64DataUrl);
return; return;
} }
// Calculate scaled dimensions preserving aspect ratio // Calculate scaled dimensions preserving aspect ratio
const scale = Math.min(maxDim / w, maxDim / h); const scale = Math.min(maxDim / w, maxDim / h);
const newW = Math.round(w * scale); const newW = Math.round(w * scale);
const newH = Math.round(h * scale); const newH = Math.round(h * scale);
const canvas = document.createElement("canvas"); const canvas = document.createElement("canvas");
canvas.width = newW; canvas.width = newW;
canvas.height = newH; canvas.height = newH;
const ctx = canvas.getContext("2d"); const ctx = canvas.getContext("2d");
if (!ctx) { if (!ctx) {
resolve(base64DataUrl);
return;
}
ctx.drawImage(img, 0, 0, newW, newH);
resolve(canvas.toDataURL("image/jpeg", quality));
} catch {
resolve(base64DataUrl); resolve(base64DataUrl);
return;
} }
ctx.drawImage(img, 0, 0, newW, newH);
resolve(canvas.toDataURL("image/jpeg", quality));
}; };
img.onerror = () => resolve(base64DataUrl); img.onerror = () => resolve(base64DataUrl);
img.src = base64DataUrl; img.src = base64DataUrl;

Loading…
Cancel
Save