feat: add extractImageFromClipboard utility with broad image/* MIME matching
This commit is contained in:
45
src/lib/clipboard-image.ts
Normal file
45
src/lib/clipboard-image.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* Extracts the first image File from a DataTransfer object.
|
||||||
|
*
|
||||||
|
* Resolution order (most → least reliable across browsers/OS):
|
||||||
|
* 1. clipboardData.files – browser-normalised FileList; Chrome/Linux/Mac/Safari
|
||||||
|
* all populate this for real paste events. Most reliable.
|
||||||
|
* 2. clipboardData.items – DataTransferItemList fallback for edge cases where
|
||||||
|
* files is empty but items contains a "file" kind entry.
|
||||||
|
*
|
||||||
|
* MIME matching: type.startsWith("image/") intentionally accepts any image
|
||||||
|
* subtype, including OS-specific variants like "image/x-png" on Linux that
|
||||||
|
* a strict allowlist (["image/png", ...]) would silently reject.
|
||||||
|
*
|
||||||
|
* The caller (onImageSelect / handleImageSelect) still runs validateImageFile
|
||||||
|
* which enforces the app's supported format allowlist — so we stay permissive
|
||||||
|
* here and strict at the validation boundary.
|
||||||
|
*/
|
||||||
|
export function extractImageFromClipboard(
|
||||||
|
clipboardData: DataTransfer | null | undefined,
|
||||||
|
): File | null {
|
||||||
|
if (!clipboardData) return null;
|
||||||
|
|
||||||
|
// ── 1. files array (primary) ──────────────────────────────────────────────
|
||||||
|
const { files } = clipboardData;
|
||||||
|
if (files?.length) {
|
||||||
|
for (let i = 0; i < files.length; i++) {
|
||||||
|
const file = files[i];
|
||||||
|
if (file.type.startsWith("image/")) return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 2. items fallback ─────────────────────────────────────────────────────
|
||||||
|
const { items } = clipboardData;
|
||||||
|
if (items?.length) {
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
const item = items[i];
|
||||||
|
if (item.kind === "file" && item.type.startsWith("image/")) {
|
||||||
|
const file = item.getAsFile();
|
||||||
|
if (file) return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user