class ClipboardItemImpl { constructor(items, options = {}) { this.items = items; this.options = options; } get presentationStyle() { return this.options.presentationStyle; } get types() { return Object.keys(this.items); } getType(type) { return this.items[type]; } } function blobToStr(blob) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.addEventListener("load", () => { const { result } = reader; if (typeof result === "string") { resolve(result); } else { reject("Cannot read Blob as String"); } }); reader.addEventListener("error", () => { reject("Cannot read Blob"); }); reader.readAsText(blob); }); } async function stringify(item) { const strItem = {}; for (const type of item.types) { strItem[type] = await blobToStr(item.getType(type)); } return strItem; } async function write(items) { if (!items[0].getType("text/plain")) { throw new Error( `Calling clipboard.write() without a "text/plain" type may result in an empty clipboard on some platforms.` ); } const strItem = await stringify(items[0]); const stubContainer = document.createElement("div"); const shadowContainer = stubContainer.attachShadow({ mode: "open" }); const stub = document.createElement("span"); stub.innerText = strItem["text/plain"]; shadowContainer.appendChild(stub); document.body.appendChild(stubContainer); const selection = document.getSelection(); const range = document.createRange(); range.selectNodeContents(stub); selection.removeAllRanges(); selection.addRange(range); const onCopy = (ev) => { for (const type in strItem) { ev.clipboardData.setData(type, strItem[type]); } ev.preventDefault(); }; document.addEventListener("copy", onCopy); let result; try { result = document.execCommand("copy"); } finally { document.removeEventListener("copy", onCopy); } selection.removeAllRanges(); document.body.removeChild(stubContainer); return result; } /** * Only attempt to polyfill browsers that partially implement * the Clipboard API (aka. Firefox with `clipboard.write()` and * `ClipboardItem` behind a feature flag) * * Spec: https://w3c.github.io/clipboard-apis/ */ if (window.navigator.clipboard) { if (!window.navigator.clipboard.write) { window.navigator.clipboard.write = write.bind(window); } if (!window.ClipboardItem) { window.ClipboardItem = ClipboardItemImpl; } }