• Stars
    star
    897
  • Rank 50,907 (Top 2 %)
  • Language
    TypeScript
  • Created over 9 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

πŸ“‹ Simple copying on the web, with maximum browser compatibility. (You probably don't need this anymore!)

Logo for clipboard-polyfill: an icon of a clipboard fading into a drafting paper grid.

clipboard-polyfill

⚠️ You don't need clipboard-polyfill to copy text! ⚠️

Note: As of 2020, you can use navigator.clipboard.writeText(...) in the stable versions of all major browsers. This library will only be useful to you if you want to:

  • target older browsers (see below for compatibility) for text copy,
  • copy text/html in Firefox,
  • use the ClipboardItem API in Firefox, or
  • polyfill the API shape in a non-browser environment (e.g. in jsdom).

See the Compatibility section below for more details.


Summary

Makes copying on the web as easy as:

clipboard.writeText("hello world");

This library is a ponyfill/polyfill for the modern Promise-based asynchronous clipboard API.

Usage

If you use npm, install:

npm install clipboard-polyfill

Sample app that copies text to the clipboard:

import * as clipboard from "clipboard-polyfill";

function handler() {
  clipboard.writeText("This text is plain.").then(
    () => { console.log("success!"); },
    () => { console.log("error!"); }
  );
}

window.addEventListener("DOMContentLoaded", function () {
  const button = document.body.appendChild(document.createElement("button"));
  button.textContent = "Copy";
  button.addEventListener("click", handler);
});

Notes:

  • You need to call a clipboard operation in response to a user gesture (e.g. the event handler for a button click).
    • Some browsers may only allow one clipboard operation per gesture.

async/await syntax

import * as clipboard from "clipboard-polyfill";

async function handler() {
  console.log("Previous clipboard text:", await clipboard.readText());

  await clipboard.writeText("This text is plain.");
}

window.addEventListener("DOMContentLoaded", function () {
  const button = document.body.appendChild(document.createElement("button"));
  button.textContent = "Copy";
  button.addEventListener("click", handler);
});

More MIME types (data types)

import * as clipboard from "clipboard-polyfill";

async function handler() {
  console.log("Previous clipboard contents:", await clipboard.read());

  const item = new clipboard.ClipboardItem({
    "text/html": new Blob(
      ["<i>Markup</i> <b>text</b>. Paste me into a rich text editor."],
      { type: "text/html" }
    ),
    "text/plain": new Blob(
      ["Fallback markup text. Paste me into a rich text editor."],
      { type: "text/plain" }
    ),
  });
  await clipboard.write([item]);
}

window.addEventListener("DOMContentLoaded", function () {
  const button = document.body.appendChild(document.createElement("button"));
  button.textContent = "Copy";
  button.addEventListener("click", handler);
});

Check the Clipboard API specification for more details.

Notes:

  • You'll need to use async functions for the await syntax.
  • Currently, text/plain and text/html are the only data types that can be written to the clipboard across most browsers.
  • If you try to copy unsupported data types, they may be silently dropped (e.g. Safari 13.1) or the call may throw an error (e.g. Chrome 83). In general, it is not possible to tell when data types are dropped.
  • In some current browsers, read() may only return a subset of supported data types, even if the clipboard contains more data types. There is no way to tell if there were more data types.

overwrite-globals version

If you want the library to overwrite the global clipboard API with its implementations, import clipboard-polyfill/overwrite-globals. This will turn the library from a ponyfill into a proper polyfill, so you can write code as if the async clipboard API were already implemented in your browser:

import "clipboard-polyfill/overwrite-globals";

async function handler() {
  const item = new window.ClipboardItem({
    "text/html": new Blob(
      ["<i>Markup</i> <b>text</b>. Paste me into a rich text editor."],
      { type: "text/html" }
    ),
    "text/plain": new Blob(
      ["Fallback markup text. Paste me into a rich text editor."],
      { type: "text/plain" }
    ),
  });

  navigator.clipboard.write([item]);
}

window.addEventListener("DOMContentLoaded", function () {
  const button = document.body.appendChild(document.createElement("button"));
  button.textContent = "Copy";
  button.addEventListener("click", handler);
});

This approach is not recommended, because it may break any other code that interacts with the clipboard API globals, and may be incompatible with future browser implementations.

Flat-file version with Promise included

If you need to grab a version that "just works", download clipboard-polyfill.window-var.promise.es5.js and include it using a <script> tag:

<script src="./clipboard-polyfill.window-var.promise.es5.js"></script>
<button onclick="copy()">Copy text!</button>
<script>
  // `clipboard` is defined on the global `window` object.
  function copy() {
    clipboard.writeText("hello world!");
  }
</script>

Bundling / tree shaking / minification / CommonJS

Thanks to the conveniences of the modern JS ecosystem, we do not provide tree shaken, minified, or CommonJS builds anymore. To get such builds without losing compatibility, pass clipboard-polyfill builds through esbuild. For example:

mkdir temp && cd temp && npm install clipboard-polyfill esbuild

# Minify the ES6 build:
echo 'export * from "clipboard-polyfill";' | npx esbuild --format=esm --target=es6 --bundle --minify

# Include just the `writeText()` export and minify:
echo 'export { writeText } from "clipboard-polyfill";' | npx esbuild --format=esm --target=es6 --bundle --minify

# Minify an ES5 build:
cat node_modules/clipboard-polyfill/dist/es5/window-var/clipboard-polyfill.window-var.promise.es5.js | npx esbuild --format=esm --target=es5 --bundle --minify

# Get a CommonJS build:
echo 'export * from "clipboard-polyfill";' | npx esbuild --format=cjs --target=es6 --bundle

Why clipboard-polyfill?

Browsers have implemented several clipboard APIs over time, and writing to the clipboard without triggering bugs in various old and current browsers is fairly tricky. In every browser that supports copying to the clipboard in some way, clipboard-polyfill attempts to act as close as possible to the async clipboard API. (See above for disclaimers and limitations.)

See this presentation for for a longer history of clipboard access on the web.

Compatibility

  • β˜‘οΈ: Browser has native async clipboard support.
  • βœ…: clipboard-polyfill adds support.
  • ❌: Support is not possible.
  • Bold browser names indicate the latest functionality changes for stable versions of modern browsers.

Write support by earliest browser version:

Browser writeText() write() (HTML) write() (other formats)
Safari 13.1 β˜‘οΈ β˜‘οΈ β˜‘οΈ (image/uri-list, image/png)
Chrome 86ᡃ / Edge 86 β˜‘οΈ β˜‘οΈ β˜‘οΈ (image/png)
Chrome 76ᡃ / Edge 79 β˜‘οΈ βœ… β˜‘οΈ (image/png)
Chrome 66ᡃ / Firefox 63 β˜‘οΈ βœ… ❌
Safari 10 / Chrome 42ᡃ / Edgeᡈ / Firefox 41 βœ… βœ…α΅‡ ❌
IE 9 βœ…αΆœ ❌ ❌

Read support:

Browser readText() read() (HTML) read() (other formats)
Safari 13.1 β˜‘οΈ β˜‘οΈ β˜‘οΈ (image/uri-list, image/png)
Chrome 76 ᡃ / Edge 79 β˜‘οΈ ❌ β˜‘οΈ (image/png)
Chrome 66ᡃ β˜‘οΈ ❌ ❌
IE 9 βœ…αΆœ ❌ ❌
Firefox ❌ ❌ ❌
  • ᡃ Also includes versions of Edge, Opera, Brave, Vivaldi, etc. based on the corresponding version of Chrome.
  • ᡇ HTML did not work properly on mobile Safari in the first few releases of version 10.
  • ᢜ In Internet Explorer, you will need to polyfill window.Promise if you want the library to work.
  • ᡈ In older versions of Edge (Spartan):
    • It may not be possible to tell if a copy operation succeeded (Edge Bug #14110451, Edge Bug #14080262). clipboard-polyfill will always report success in this case.
    • Only the last data type you specify is copied to the clipboard (Edge Bug #14080506). Consider placing the most important data type last in the object that you pass to the ClipboardItem constructor.
    • The text/html data type is not written using the expected CF_HTML format. clipboard-polyfill does not try to work around this, since 1) it would require fragile browser version sniffing, 2) users of Edge are not generally stuck on version < 17, and 3) the failure mode for other browsers would be that invalid clipboard HTML is copied. (Edge Bug #14372529, #73)

clipboard-polyfill uses a variety of heuristics to work around compatibility bugs. Please let us know if you are running into compatibility issues with any of the browsers listed above.

History

Browser history

Browser First version supporting
navigator.clipboard.writeText(...)
Release Date
Chrome 66+ April 2018
Firefox 53+ October 2018
Edge 79+ (first Chromium-based release) January 2020
Safari 13.1+ March 2020

Project history

This project dates from a time when clipboard access in JS was barely becoming possible, and ergonomic clipboard API efforts were stalling. (See this presentation for a bit more context.) Fortunately, an ergonomic API with the same functionality is now available in all modern browsers since 2020:

  • 2015: Browsers start supporting the defunct document.execCommand("copy") call (with many, many issues).
  • 2015: Started this project as clipboard.js (half a year before @zenorocha picked the same name πŸ˜›).
  • 2016: Renewed discussions about an async clipboard API (e.g. proposal doc, crbug.com/593475).
  • 2017: Renamed this project to clipboard-polyfill to reflect a v2 API overhaul aligned with the draft spec.
  • 2018: Browsers start supporting navigator.clipboard.writeText().
  • 2020: Browsers start supporting navigator.clipboard.write() (including text/html support).

Thanks to Gary Kacmarcik, Hallvord Steen, and others for helping to bring the async clipboard API to life!

This is way too complicated!

If you only need to copy text in modern browsers, consider using navigator.clipboard.writeText() directly: https://caniuse.com/mdn-api_clipboard_writetext

If you need copy text in older browsers as well, you could also try this gist for a simple hacky solution.

More Repositories

1

folderify

πŸ“ Generate pixel-perfect macOS folder icons in the native style.
Rust
1,142
star
2

crypto.graphics

crypto.graphics
HTML
24
star
3

chrome-devices-in-new-tab

πŸ“± Changes the new tab page in Chrome to be a list of tabs open on your other devices. Now with dark mode!
CSS
12
star
4

web-worker-compat

11
star
5

md2html

Yet another Markdown-to-HTML conversion tool
Shell
8
star
6

MagicWorker.js

πŸ’» Web workers in file:// pages for *all* browsers.
JavaScript
8
star
7

browser-security-reading-list

πŸ”’ Documents covering web security concepts, specifications, and findings.
8
star
8

barely-a-dev-server

A teeny-tiny alternative to bundlers that does just what you need (and nothing more), using `esbuild`.
JavaScript
6
star
9

inception-font

πŸ“ Font based inspired by the maze lettering used in some trailers and posters for the 2010 movie "Inception" by Christopher Nolan. (Using Inkscape and FontForge.)
CSS
6
star
10

main-branch

A tool to replace the main branch for your repository on GitHub safely and easily.
TypeScript
5
star
11

scripts

Some of my scripts.
Shell
5
star
12

ugly-http-extension

JavaScript
5
star
13

backup-airtable.py

Back up data from Airtable to JSON files.
Python
5
star
14

emoji2cat

😼
5
star
15

offline-bootstrap

Easy HTML5 Offline Caching
HTML
5
star
16

CubeExplorerVersion225

source code of Cube Explorer v2.25, Delphi
Component Pascal
4
star
17

servecert

πŸŒβ†”οΈπŸ”’ A small local HTTPS proxy using mkcert certificates. Please use with care.
Go
4
star
18

presentation-mode

Brings back presentation mode on OSX.
JavaScript
4
star
19

dance-hacking

Audio manipulation code to recast songs into beat patterns for different types of dance.
Python
4
star
20

unutil.h

A file to go alongside util.h - A collaboration between @lgarron and @bgwines
C
4
star
21

mak

`make`, but `mak` it shorter.
Rust
4
star
22

bpm-tap

A simple BPM calculation tool.
TypeScript
3
star
23

ios-lockscreensaver

πŸ’» My personal adaptations of the only OSX screensaver I actually like (iOS screensaver by bodysoulspirit).
3
star
24

bun-audit

A stopgap for the missing `bun audit` command.
Makefile
2
star
25

ksolve-js-svg

ksolve definition parser, state simulator, and SVG drawing, in JS.
JavaScript
2
star
26

cubing-rust-wasm

Learning to publish Rust for the web.
JavaScript
2
star
27

alg.cubing.net-stats

TypeScript
2
star
28

homebrew-lgarron

My personal Homebrew tap.
Ruby
2
star
29

unsafe-browser-aes

TypeScript
2
star
30

ios-background

iOS column background
2
star
31

webauthn-json-example

TypeScript
2
star
32

crypto-class

Materials from teaching cryptography to high school students at Stanford (SPCS, formerly EPGY).
TeX
2
star
33

minimal-html-style

✨ An HTML style snippet that looks nice on all devices while being as small as possible.
HTML
2
star
34

octocats

Octocats by lgarron, a lΓ‘ Octodex.
2
star
35

shuang-chen-projects

This is a repository for several cube projects created by Shuang Chen.
Java
2
star
36

parcel-library-template

Don't use this. Use `esbuild`.
TypeScript
2
star
37

dotfiles

πŸ“„ My dotfiles, with machine-specific subsets handled using `make` and `stow`.
Shell
2
star
38

Makefile-scripts

πŸ› πŸ“œ Generate and maintain a `Makefile` based on scripts in `package.json`.
Makefile
2
star
39

color-chrome-theme

A Chrome theme with a familiar color scheme.
Makefile
2
star
40

hash-oll

An OLL naming scheme.
TypeScript
1
star
41

parcel-issue-6284

TypeScript
1
star
42

publish-playlist

Easily publish an iTunes playlist to the internet using Dropbox.
Shell
1
star
43

snowpack-url-folders

HTML
1
star
44

lockscreen-algsheets

TypeScript
1
star
45

random-dance-moves

Random social dance move generator, in the style of Richard Powers move descriptions.
JavaScript
1
star
46

lgarron.github.io

Github page
HTML
1
star
47

project-euler

7 years later.
Mathematica
1
star
48

parcel-6192

TypeScript
1
star
49

scrambler-interface

Interface for tnoodle and Mark 2 to share.
1
star
50

OrdinalArithmetic

Ordinal Arithmetic Package for Mathematica
1
star
51

refcon

Origami construction program.
Java
1
star
52

math

Math.
1
star
53

lgsound2png

Command-line tool for generating waveforms from sound files without libraries
C
1
star
54

u2f-api-polyfill.d.ts

TypeScript definitions for `u2f-api-polyfill` package.
1
star
55

heise-sim-keylayout

Keyboard layout for typing Rubik's Cube algorithms (move sequences)
1
star
56

worker-execution-origin

JavaScript
1
star
57

webauthn-user-journeys

Test yourself some WebAuthn!
HTML
1
star
58

make_carpet_mod

Automatically assemble gnembon_mc's carpet_mod.
Makefile
1
star
59

map-log-zoom

JavaScript
1
star
60

clapperboard

🎬
TypeScript
1
star
61

wca_ical

WCA feed parser > iCal for viewing in calendar clients.
PHP
1
star
62

lgarron.sty

My custom LaTeX commands
1
star
63

hs-ma-dict

Haskell-Mathematica Dictionary
1
star
64

g4gx-lgarron

Extremely rough source code for my talk at G4GX. (Atlanta, March 30, 2012)
1
star
65

speedsolving.com-logo

Source files for the speedsolving.com logo and banner.
1
star
66

git-cloud

Keep your .git folder outside of Dropbox, but the working directories in it.
Shell
1
star
67

serendipity-logo

Serendipity logo.
1
star
68

random-uint-below.js

🎲 An unbiased way to pick random integers in Javascript. Uses `crypto.getRandomValues()`.
TypeScript
1
star
69

speedlife.games

speedlife
TypeScript
1
star
70

QML

Haskell
1
star
71

https-test-server

Python
1
star
72

web-worker-test

JavaScript
1
star
73

pink-chrome-theme

Want a pink Chrome theme? This one's for you!
1
star
74

pizza

A repository to demonstrate an issue with the `go vet` `-unusedresult ` feature.
Go
1
star
75

copy-text-as-html

Coded in literally under 6 minutes. Caveat emptor. πŸ˜›
Makefile
1
star
76

sq1.js

Javascript port of Walter Souza's Square-1 solver/MRSS scrambler. (Also see Mark 2: https://github.com/lgarron/mark2 )
JavaScript
1
star
77

watermelon-clarity-chrome-theme

Bold innovation in color design.
1
star
78

youtube-backup

Simple script to backup the YouTube videos of a user.
JavaScript
1
star
79

cross-step

Crosss-Step Waltz Variations with Richard Powers and Angela Amarillas
HTML
1
star
80

midi-cubing

HTML
1
star
81

readme-cli-help

Maintain the output of a help command in your `README` file.
TypeScript
1
star
82

hardware

Useful hardware for computing electronics and more, ready for any occasion.
1
star
83

ts-project-template

My TypeScript project template.
Makefile
1
star
84

pet-the-kitties

😸 A revolutionary new app that emulates the experience of petting cats. Best on touch screens.
JavaScript
1
star
85

git-freeze

❄️ Freeze and πŸ”₯ thaw.
Shell
1
star
86

web-worker-primes

Simple web worker example.
JavaScript
1
star