clipboard-polyfill

A ponyfill for the async Clipboard API, giving reliable copy/paste of text and rich content across old and modern browsers.

Library
npm
v4.1.1
926stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
41/100Fair
Development Activity0
Maintenance20
Community56
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
73/100Good
Architecture78
Code Quality72
Innovation58
Learning Curve85

clipboard-polyfill makes reading from and writing to the system clipboard as simple as calling clipboard.writeText(...) or clipboard.readText(), backed by a Promise-based API that mirrors the W3C asynchronous Clipboard specification. Where a browser already implements navigator.clipboard natively, the library defers to it; where it doesn’t (or where a browser’s implementation has known bugs, such as text/html support in older Firefox), it falls back to a layered set of strategies built on document.execCommand('copy'), temporary DOM selections, and shadow DOM tricks worked out through years of cross-browser experimentation.

Beyond plain text, it implements a ClipboardItem polyfill so callers can write multiple MIME types (e.g. text/html alongside a text/plain fallback) in one call, matching the shape of the native API closely enough that code written against it keeps working as browsers catch up. An overwrite-globals entry point lets consumers who want a true polyfill (rather than a ponyfill) replace navigator.clipboard directly, at the cost of some global-mutation risk the maintainers are upfront about in the docs.

What You Get

  • A drop-in writeText()/readText() pair that mirrors the native async Clipboard API’s Promise-based signature
  • ClipboardItem and write()/read() support for copying multiple MIME types (e.g. text/html plus a text/plain fallback) in one call
  • Automatic fallback through execCommand('copy'), temporary DOM selections, and shadow DOM when a browser has no native clipboard support
  • An overwrite-globals entry point for consumers who want the library to patch navigator.clipboard directly instead of being called as a standalone module
  • ES5 and ES6 builds, including a flat window-var build with a bundled Promise polyfill for legacy environments (e.g. IE9)

Common Use Cases

  • Adding a reliable “Copy to clipboard” button in a web app that still needs to support older browser versions
  • Copying both a plain-text fallback and formatted text/html content in one operation for pasting into rich-text editors
  • Polyfilling navigator.clipboard in a non-browser DOM environment such as jsdom-based tests
  • Supporting clipboard read/write on legacy Edge/IE deployments where the native async Clipboard API never shipped

Under The Hood

Architecture The library is organized as a thin public surface (src/clipboard-polyfill/entries/es6/clipboard-polyfill.es6.ts) that re-exports a small set of implementation modules: implementations/text.ts and implementations/blob.ts hold the public writeText/readText/write/read functions, ClipboardItem/ClipboardItemPolyfill.ts implements the ClipboardItem constructor, and strategies/dom.ts and strategies/internet-explorer.ts hold the browser-specific fallback mechanics (temporary DOM selection, shadow DOM, execCommand, and legacy IE clipboard access). Each public function first checks for originalNavigatorClipboardWriteText/ReadText captured in builtins/builtin-globals.ts and only falls through to the DOM-based strategies when the native API is absent or throws, giving a clear layered-fallback data flow rather than a monolithic implementation. A separate overwrite-globals entry point composes the same core functions but assigns them onto window.navigator.clipboard, isolating the riskier global-patching behavior from the default ponyfill import.

Tech Stack Written in TypeScript targeting es5+dom lib types with strictNullChecks enabled, built and tested with Bun (bun run script/build.ts, bun test) rather than Node, and bundled via esbuild for consumers who want tree-shaken or CommonJS output. Linting and formatting run through Biome (biome.json disables a handful of default rules like noExplicitAny and noDelete to accommodate the low-level DOM/Promise-polyfill code). The project ships both ES6 and ES5 (with an included lightweight Promise polyfill) build targets, and a small demo app under src/demo/ built with the same esbuild pipeline.

Code Quality Tests are colocated with implementation files as *.test.ts (e.g. text.modern-browser.test.ts, text.execCommand-fallback.test.ts, text.blank-document.test.ts), run via Bun’s test runner, and CI (.github/workflows/) runs make lint, make test-bun, and a mock-test pass that exercises fallback code paths (missing Promise, older browser API shapes) under src/mock-test/. Naming is consistent and the fallback strategies are commented with citations to specific upstream browser bugs (e.g. old Edge CF_HTML issues), which is unusually thorough for a small utility library, though some older files retain var-based ES5-style code left over from the library’s long history rather than being modernized to const/let throughout.

API Design The public API is deliberately minimal and mirrors the native navigator.clipboard shape (writeText, readText, write, read, ClipboardItem) so that call sites need no polyfill-specific knowledge — code written against the native API mostly works unchanged. Getting started requires a single import and no configuration; the README documents async/await usage, multi-MIME-type writes, and the overwrite-globals alternative import path clearly, along with an explicit compatibility matrix per browser version so consumers know exactly what is and isn’t polyfilled.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search