one
Version:
One is a React framework for web, iOS, and Android apps.
231 lines (230 loc) • 6.39 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all) __defProp(target, name, {
get: all[name],
enumerable: true
});
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: () => from[key],
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var clipboard_exports = {};
__export(clipboard_exports, { Clipboard: () => Clipboard });
module.exports = __toCommonJS(clipboard_exports);
var import_validate = require("./validate.cjs");
function webClipboard() {
if (typeof navigator === "undefined") return void 0;
return navigator.clipboard ?? void 0;
}
function getString(options) {
(0, import_validate.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) {
(0, import_validate.assertSetStringText)(text);
(0, import_validate.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) {
(0, import_validate.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) {
(0, import_validate.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) {
(0, import_validate.assertSetUrl)(url);
return Promise.resolve();
}
async function hasUrl() {
return false;
}
const inert = { remove: () => {} };
function addListener(_listener) {
(0, import_validate.assertListener)(_listener);
return inert;
}
const Clipboard = Object.freeze({
getString,
setString,
hasString,
getImage,
setImage,
hasImage,
getUrl,
setUrl,
hasUrl,
addListener
});