UNPKG

one

Version:

One is a React framework for web, iOS, and Android apps.

212 lines (209 loc) • 5.51 kB
import { assertGetImageOptions, assertGetStringOptions, assertListener, assertSetImage, assertSetStringOptions, assertSetStringText, assertSetUrl } from "./validate.mjs"; function webClipboard() { if (typeof navigator === "undefined") return void 0; return navigator.clipboard ?? void 0; } function getString(options) { assertGetStringOptions(options, "getString"); return readString(options); } async function readString(options) { const clipboard = webClipboard(); if (!clipboard) return ""; if (options?.preferredFormat === "html" && typeof clipboard.read === "function") { try { for (const item of await clipboard.read()) { if (item.types.includes("text/html")) { const blob = await item.getType("text/html"); return await blob.text(); } } } catch {} } if (!clipboard.readText) return ""; try { return await clipboard.readText(); } catch { return ""; } } function setString(text, options) { assertSetStringText(text); assertSetStringOptions(options, "setString"); return writeText(text, options?.inputFormat === "html"); } async function writeText(text, html) { const clipboard = webClipboard(); if (!clipboard) return false; if (html && typeof clipboard.write === "function" && typeof ClipboardItem !== "undefined") { try { await clipboard.write([new ClipboardItem({ "text/html": new Blob([text], { type: "text/html" }), "text/plain": new Blob([text], { type: "text/plain" }) })]); return true; } catch {} } if (!clipboard.writeText) return false; try { await clipboard.writeText(text); return true; } catch { return false; } } async function hasString() { return (await getString()).length > 0; } function stripDataUriPrefix(base64Image) { const comma = base64Image.indexOf(","); if (base64Image.startsWith("data:") && comma !== -1) { return base64Image.slice(comma + 1); } return base64Image; } function sniffMimeType(bytes) { if (bytes.length >= 3 && bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) { return "image/jpeg"; } return "image/png"; } function decodeBase64(base64Image) { try { const binary = atob(stripDataUriPrefix(base64Image)); const bytes = new Uint8Array(binary.length); for (let index = 0; index < binary.length; index++) { bytes[index] = binary.charCodeAt(index); } return bytes; } catch { return null; } } async function convertImage(blob, format, jpegQuality) { try { const bitmap = await createImageBitmap(blob); const width = bitmap.width; const height = bitmap.height; const mime = format === "jpeg" ? "image/jpeg" : "image/png"; if (format === "png" && blob.type === "image/png" || format === "jpeg" && blob.type === "image/jpeg") { bitmap.close(); const buffer = await blob.arrayBuffer(); let binary = ""; const bytes = new Uint8Array(buffer); for (let index = 0; index < bytes.length; index++) { binary += String.fromCharCode(bytes[index]); } return { dataUrl: `data:${mime};base64,${btoa(binary)}`, width, height }; } const canvas = document.createElement("canvas"); canvas.width = width; canvas.height = height; const context = canvas.getContext("2d"); if (!context) { bitmap.close(); return null; } context.drawImage(bitmap, 0, 0); bitmap.close(); const dataUrl = canvas.toDataURL(mime, jpegQuality); return { dataUrl, width, height }; } catch { return null; } } function getImage(options) { assertGetImageOptions(options); return readImage(options); } async function readImage(options) { const clipboard = webClipboard(); if (!clipboard || typeof clipboard.read !== "function") return null; try { for (const item of await clipboard.read()) { const type = item.types.find((entry) => entry.startsWith("image/")); if (!type) continue; const blob = await item.getType(type); const converted = await convertImage(blob, options.format, options.jpegQuality ?? 1); if (converted) { return { data: converted.dataUrl, size: { width: converted.width, height: converted.height } }; } } } catch { return null; } return null; } function setImage(base64Image) { assertSetImage(base64Image); return writeImage(base64Image); } async function writeImage(base64Image) { const clipboard = webClipboard(); if (!clipboard || typeof clipboard.write !== "function" || typeof ClipboardItem === "undefined") { return; } const bytes = decodeBase64(base64Image); if (!bytes) return; const mime = sniffMimeType(bytes); const copy = new Uint8Array(bytes.length); copy.set(bytes); try { await clipboard.write([new ClipboardItem({ [mime]: new Blob([copy.buffer], { type: mime }) })]); } catch {} } async function hasImage() { const clipboard = webClipboard(); if (!clipboard || typeof clipboard.read !== "function") return false; try { for (const item of await clipboard.read()) { if (item.types.some((entry) => entry.startsWith("image/"))) return true; } } catch { return false; } return false; } function getUrl() { return Promise.resolve(null); } function setUrl(url) { assertSetUrl(url); return Promise.resolve(); } async function hasUrl() { return false; } const inert = { remove: () => {} }; function addListener(_listener) { assertListener(_listener); return inert; } const Clipboard = Object.freeze({ getString, setString, hasString, getImage, setImage, hasImage, getUrl, setUrl, hasUrl, addListener }); export { Clipboard }; //# sourceMappingURL=index.mjs.map