@mirawision/copily
v1.0.0
Published
A comprehensive clipboard manipulation library for TypeScript, providing functionalities for copying/pasting text, HTML, JSON, images, files, and smart content detection.
Readme
Copily — Clipboard Tools
A lightweight, TypeScript-first clipboard library. Copy and paste text, HTML, JSON, images, and files. Intercept copy/paste events and perform smart clipboard detection.
Features
- Basic Copy & Paste: Text, HTML, JSON, images, and files
- Smart Detection: Detect OTP, URL, email, JSON, HTML, image, and file
- Copy Interception: Intercept and modify copy events
- Paste Interception: Intercept and override paste behavior
- Smart Paste Listener: Listen to paste events with smart detection
- Security: HTML sanitization and secure-context checks
- Fallbacks: Legacy support via
document.execCommand
Installation
npm install @mirawision/copilyQuick Start
// Root import (all core + advanced)
import { copyText, pasteText, pasteSmart } from '@mirawision/copily';
await copyText('Hello Copily!');
const results = await pasteSmart();// Subpath imports (tree-shakable)
import { copyText, pasteHTML } from '@mirawision/copily/core';
import { pasteSmart, interceptPaste } from '@mirawision/copily/advanced';API Reference
Basic Copy & Paste
copyText(text: string): Promise<void>
Copies plain text to clipboard.
await copyText('Hello World!');pasteText(): Promise<string>
Reads plain text from clipboard.
const text = await pasteText();
console.log(text); // "Hello World!"copyHTML(html: string): Promise<void>
Copies HTML content with fallback plain text.
await copyHTML('<p>Hello <strong>World</strong>!</p>');pasteHTML(): Promise<string>
Reads HTML content from clipboard.
const html = await pasteHTML();
console.log(html); // "<p>Hello <strong>World</strong>!</p>"copyJSON(obj: object): Promise<void>
Serializes object to JSON and copies to clipboard.
await copyJSON({ name: 'John', age: 30 });pasteJSON(): Promise<object>
Parses clipboard content as JSON.
const data = await pasteJSON();
console.log(data); // { name: 'John', age: 30 }Files & Images
copyImage(image: Blob | HTMLImageElement | string): Promise<void>
Copies image to clipboard from blob, element, or URL.
// From blob
const imageBlob = new Blob(['image data'], { type: 'image/png' });
await copyImage(imageBlob);
// From URL
await copyImage('https://example.com/image.jpg');
// From HTML element
const img = document.querySelector('img');
await copyImage(img);pasteImage(): Promise<Blob | null>
Reads image from clipboard.
const imageBlob = await pasteImage();
if (imageBlob) {
const url = URL.createObjectURL(imageBlob);
// Use the image URL
}copyFile(file: File | Blob): Promise<void>
Copies file to clipboard.
const file = new File(['file content'], 'document.txt', { type: 'text/plain' });
await copyFile(file);pasteFile(): Promise<File | null>
Reads file from clipboard.
const file = await pasteFile();
if (file) {
console.log(file.name); // "clipboard-file"
}Smart Detection
pasteSmart(): Promise<ClipboardSmartResult[]>
Intelligently detects clipboard content and returns structured results.
const results = await pasteSmart();
// Results can include:
// { type: 'otp', value: '123456' }
// { type: 'url', value: 'https://example.com' }
// { type: 'email', value: '[email protected]' }
// { type: 'json', value: { name: 'John' } }
// { type: 'html', value: '<p>content</p>' }
// { type: 'text', value: 'plain text' }
// { type: 'image', blob: Blob }
// { type: 'file', file: File }Clipboard Event Utilities
interceptCopy(handler: CopyInterceptHandler): () => void
Intercepts copy events on the page.
const cleanup = interceptCopy(({ event, selection, target }) => {
// Block copying from private elements
if (target?.classList.contains('private')) {
return { prevent: true };
}
// Add attribution
return {
overrideText: `${selection}\n\nCopied from mysite.com`,
overrideHTML: `${selection}<br><br><em>Copied from mysite.com</em>`
};
});
// Cleanup when done
cleanup();interceptPaste(handler: PasteInterceptHandler): () => void
Intercepts paste events on the page with optional overrides.
const cleanup = interceptPaste(({ event, plainText, html, target }) => {
// Force plain text only
return { overrideText: plainText };
// Or block entirely: return { prevent: true };
// Or inject HTML into contenteditable: return { overrideHTML: '<strong>Pasted</strong>' };
});
cleanup();listenCopy(callback: (params: { event: ClipboardEvent; selection: string; target: HTMLElement | null }) => void): () => void
Listens to copy events and provides selection details.
const cleanup = listenCopy(({ event, selection, target }) => {
if (!selection) return;
console.log('Copied:', selection);
});
cleanup();listenPaste(callback: (data: ClipboardSmartResult[]) => void): () => void
Listens to paste events with smart detection.
const cleanup = listenPaste((results) => {
results.forEach(result => {
switch (result.type) {
case 'otp':
console.log('OTP detected:', result.value);
break;
case 'url':
console.log('URL detected:', result.value);
break;
case 'email':
console.log('Email detected:', result.value);
break;
}
});
});
// Cleanup when done
cleanup();Extras & Fallbacks
clearClipboard(): Promise<void>
Clears clipboard content.
await clearClipboard();fallbackCopyText(text: string): void
Legacy copy using document.execCommand.
try {
await copyText('Hello');
} catch {
fallbackCopyText('Hello');
}Error Handling
The library provides specific error types for different scenarios:
import {
ClipboardError,
ClipboardPermissionError,
ClipboardUnsupportedError,
ClipboardFormatError
} from '@mirawision/copily';
try {
await copyText('Hello');
} catch (error) {
if (error instanceof ClipboardPermissionError) {
// Handle permission denied
} else if (error instanceof ClipboardUnsupportedError) {
// Handle unsupported browser
} else if (error instanceof ClipboardFormatError) {
// Handle format errors
}
}Security & Permissions
Secure Context & Permissions
- The Clipboard API requires HTTPS. Operations will fail with a
ClipboardPermissionErrorif not secure. - Permission prompts are handled by the browser. Catch errors to provide UX fallbacks.
HTML Sanitization
HTML content is automatically sanitized to prevent XSS:
// This will be sanitized automatically
await copyHTML('<script>alert("xss")</script><p>Safe content</p>');
// Result: <p>Safe content</p>Browser Support
- Modern Browsers: Full support with Clipboard API
- Older Browsers: Fallback support with
document.execCommand - Mobile: Limited support (varies by platform)
Use Cases
Copy with Attribution
interceptCopy(({ selection }) => ({
overrideText: `${selection}\n\nCopied from mysite.com`,
overrideHTML: `${selection}<br><br><em>Copied from mysite.com</em>`
}));OTP Code Detection
listenPaste((results) => {
const otp = results.find(r => r.type === 'otp');
if (otp) {
// Auto-fill OTP input
document.getElementById('otp-input').value = otp.value;
}
});Rich Text Copy
// Use HTML + styles when needed
await copyHTML('<span style="font-weight:700;color:#f00;font-size:18px">Important notice</span>');Image Processing
const imageBlob = await pasteImage();
if (imageBlob) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const img = new Image();
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
// Process the image
};
img.src = URL.createObjectURL(imageBlob);
}Contributing
Contributions are always welcome! Feel free to open issues or submit pull requests.
License
This project is licensed under the MIT License.
