UNPKG

14.5 kBSource Map (JSON)View Raw
1{"version":3,"file":"clipboard-polyfill.esm.js","sources":["../DT.ts","../clipboard-polyfill.ts"],"sourcesContent":["const dataTypes = [\n \"text/plain\",\n \"text/html\",\n];\n\n// TODO: Dedup with main file?\nfunction warnOrLog() {\n // tslint:disable-next-line: no-console\n (console.warn || console.log).call(arguments);\n} // IE9 workaround (can't bind console functions).\nconst warn = warnOrLog.bind(console, \"[clipboard-polyfill]\");\nlet showWarnings = true;\nexport function suppressDTWarnings() {\n showWarnings = false;\n}\n\nexport class DT {\n private m: {[key: string]: string} = {};\n\n public setData(type: string, value: string): void {\n if (showWarnings && dataTypes.indexOf(type) === -1) {\n warn(\"Unknown data type: \" + type, \"Call clipboard.suppressWarnings() \" +\n \"to suppress this warning.\");\n }\n\n this.m[type] = value;\n }\n\n public getData(type: string): string | undefined {\n return this.m[type];\n }\n\n // TODO: Provide an iterator consistent with DataTransfer.\n public forEach(f: (value: string, key: string) => void): void {\n // tslint:disable-next-line: forin\n for (const k in this.m) {\n f(this.m[k], k);\n }\n }\n}\n","import {DT, suppressDTWarnings} from \"./DT\";\n\n// Debug log strings should be short, since they are compiled into the production build.\n// TODO: Compile debug logging code out of production builds?\n// tslint:disable-next-line: no-empty\nlet debugLog: (s: string) => void = (s: string) => {};\nlet showWarnings = true;\n// Workaround for:\n// - IE9 (can't bind console functions directly), and\n// - Edge Issue #14495220 (referencing `console` without F12 Developer Tools can cause an exception)\nfunction warnOrLog() {\n // tslint:disable-next-line: no-console\n (console.warn || console.log).apply(console, arguments);\n}\nconst warn = warnOrLog.bind(\"[clipboard-polyfill]\");\n\nconst TEXT_PLAIN = \"text/plain\";\n\nexport {DT};\n\nexport function setDebugLog(f: (s: string) => void): void {\n debugLog = f;\n}\n\nexport function suppressWarnings() {\n showWarnings = false;\n suppressDTWarnings();\n}\n\nexport async function write(data: DT): Promise<void> {\n if (showWarnings && !data.getData(TEXT_PLAIN)) {\n warn(\"clipboard.write() was called without a \" +\n \"`text/plain` data type. On some platforms, this may result in an \" +\n \"empty clipboard. Call clipboard.suppressWarnings() \" +\n \"to suppress this warning.\");\n }\n\n // Internet Explorer\n if (seemToBeInIE()) {\n if (writeIE(data)) {\n return;\n } else {\n throw new Error(\"Copying failed, possibly because the user rejected it.\");\n }\n }\n\n if (execCopy(data)) {\n debugLog(\"regular execCopy worked\");\n return;\n }\n\n // Success detection on Edge is not possible, due to bugs in all 4\n // detection mechanisms we could try to use. Assume success.\n if (navigator.userAgent.indexOf(\"Edge\") > -1) {\n debugLog(\"UA \\\"Edge\\\" => assuming success\");\n return;\n }\n\n // Fallback 1 for desktop Safari.\n if (copyUsingTempSelection(document.body, data)) {\n debugLog(\"copyUsingTempSelection worked\");\n return;\n }\n\n // Fallback 2 for desktop Safari.\n if (copyUsingTempElem(data)) {\n debugLog(\"copyUsingTempElem worked\");\n return;\n }\n\n // Fallback for iOS Safari.\n const text = data.getData(TEXT_PLAIN);\n if (text !== undefined && copyTextUsingDOM(text)) {\n debugLog(\"copyTextUsingDOM worked\");\n return;\n }\n\n throw new Error(\"Copy command failed.\");\n}\n\nexport async function writeText(s: string): Promise<void> {\n if (navigator.clipboard && navigator.clipboard.writeText) {\n debugLog(\"Using `navigator.clipboard.writeText()`.\");\n return navigator.clipboard.writeText(s);\n }\n return write(DTFromText(s));\n}\n\nexport async function read(): Promise<DT> {\n return DTFromText(await readText());\n}\n\nexport async function readText(): Promise<string> {\n if (navigator.clipboard && navigator.clipboard.readText) {\n debugLog(\"Using `navigator.clipboard.readText()`.\");\n return navigator.clipboard.readText();\n }\n if (seemToBeInIE()) {\n debugLog(\"Reading text using IE strategy.\");\n return readIE();\n }\n throw new Error(\"Read is not supported in your browser.\");\n}\n\nlet useStarShown = false;\nfunction useStar(): void {\n if (useStarShown) {\n return;\n }\n if (showWarnings) {\n warn(\"The deprecated default object of `clipboard-polyfill` was called. Please switch to `import * as clipboard from \\\"clipboard-polyfill\\\"` and see https://github.com/lgarron/clipboard-polyfill/issues/101 for more info.\");\n }\n useStarShown = true;\n}\n\nconst ClipboardPolyfillDefault = {\n DT,\n setDebugLog(f: (s: string) => void): void {\n useStar();\n return setDebugLog(f);\n },\n suppressWarnings() {\n useStar();\n return suppressWarnings();\n },\n async write(data: DT): Promise<void> {\n useStar();\n return write(data);\n },\n async writeText(s: string): Promise<void> {\n useStar();\n return writeText(s);\n },\n async read(): Promise<DT> {\n useStar();\n return read();\n },\n async readText(): Promise<string> {\n useStar();\n return readText();\n },\n};\n\nexport default ClipboardPolyfillDefault;\n\n/******** Implementations ********/\n\nclass FallbackTracker {\n public success: boolean = false;\n}\n\nfunction copyListener(tracker: FallbackTracker, data: DT, e: ClipboardEvent): void {\n debugLog(\"listener called\");\n tracker.success = true;\n data.forEach((value: string, key: string) => {\n const clipboardData = e.clipboardData!;\n clipboardData.setData(key, value);\n if (key === TEXT_PLAIN && clipboardData.getData(key) !== value) {\n debugLog(\"setting text/plain failed\");\n tracker.success = false;\n }\n });\n e.preventDefault();\n}\n\nfunction execCopy(data: DT): boolean {\n const tracker = new FallbackTracker();\n const listener = copyListener.bind(this, tracker, data);\n\n document.addEventListener(\"copy\", listener);\n try {\n // We ignore the return value, since FallbackTracker tells us whether the\n // listener was called. It seems that checking the return value here gives\n // us no extra information in any browser.\n document.execCommand(\"copy\");\n } finally {\n document.removeEventListener(\"copy\", listener);\n }\n return tracker.success;\n}\n\n// Temporarily select a DOM element, so that `execCommand()` is not rejected.\nfunction copyUsingTempSelection(e: HTMLElement, data: DT): boolean {\n selectionSet(e);\n const success = execCopy(data);\n selectionClear();\n return success;\n}\n\n// Create a temporary DOM element to select, so that `execCommand()` is not\n// rejected.\nfunction copyUsingTempElem(data: DT): boolean {\n const tempElem = document.createElement(\"div\");\n // Setting an individual property does not support `!important`, so we set the\n // whole style instead of just the `-webkit-user-select` property.\n tempElem.setAttribute(\"style\", \"-webkit-user-select: text !important\");\n // Place some text in the elem so that Safari has something to select.\n tempElem.textContent = \"temporary element\";\n document.body.appendChild(tempElem);\n\n const success = copyUsingTempSelection(tempElem, data);\n\n document.body.removeChild(tempElem);\n return success;\n}\n\n// Uses shadow DOM.\nfunction copyTextUsingDOM(str: string): boolean {\n debugLog(\"copyTextUsingDOM\");\n\n const tempElem = document.createElement(\"div\");\n // Setting an individual property does not support `!important`, so we set the\n // whole style instead of just the `-webkit-user-select` property.\n tempElem.setAttribute(\"style\", \"-webkit-user-select: text !important\");\n // Use shadow DOM if available.\n let spanParent: Node = tempElem;\n if (tempElem.attachShadow) {\n debugLog(\"Using shadow DOM.\");\n spanParent = tempElem.attachShadow({mode: \"open\"});\n }\n\n const span = document.createElement(\"span\");\n span.innerText = str;\n\n spanParent.appendChild(span);\n document.body.appendChild(tempElem);\n selectionSet(span);\n\n const result = document.execCommand(\"copy\");\n\n selectionClear();\n document.body.removeChild(tempElem);\n\n return result;\n}\n\n/******** Selection ********/\n\nfunction selectionSet(elem: Element): void {\n const sel = document.getSelection();\n if (sel) {\n const range = document.createRange();\n range.selectNodeContents(elem);\n sel.removeAllRanges();\n sel.addRange(range);\n }\n}\n\nfunction selectionClear(): void {\n const sel = document.getSelection();\n if (sel) {\n sel.removeAllRanges();\n }\n}\n\n/******** Convenience ********/\n\nfunction DTFromText(s: string): DT {\n const dt = new DT();\n dt.setData(TEXT_PLAIN, s);\n return dt;\n}\n\n/******** Internet Explorer ********/\n\ninterface IEWindow extends Window {\n clipboardData: {\n setData: (key: string, value: string) => boolean;\n // Always results in a string: https://msdn.microsoft.com/en-us/library/ms536436(v=vs.85).aspx\n getData: (key: string) => string;\n };\n}\n\nfunction seemToBeInIE(): boolean {\n return typeof ClipboardEvent === \"undefined\" &&\n typeof (window as IEWindow).clipboardData !== \"undefined\" &&\n typeof (window as IEWindow).clipboardData.setData !== \"undefined\";\n}\n\nfunction writeIE(data: DT): boolean {\n // IE supports text or URL, but not HTML: https://msdn.microsoft.com/en-us/library/ms536744(v=vs.85).aspx\n // TODO: Write URLs to `text/uri-list`? https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Recommended_drag_types\n const text = data.getData(TEXT_PLAIN);\n if (text !== undefined) {\n return (window as IEWindow).clipboardData.setData(\"Text\", text);\n }\n\n throw new Error((\"No `text/plain` value was specified.\"));\n}\n\n// Returns \"\" if the read failed, e.g. because the user rejected the permission.\nasync function readIE(): Promise<string> {\n const text = (window as IEWindow).clipboardData.getData(\"Text\");\n if (text === \"\") {\n throw new Error(\"Empty clipboard or could not read plain text from clipboard\");\n }\n return text;\n}\n"],"names":["dataTypes","warn","console","log","call","arguments","bind","showWarnings","this","DT","type","value","indexOf","m","f","k","debugLog","s","apply","TEXT_PLAIN","setDebugLog","suppressWarnings","write","data","getData","seemToBeInIE","text","undefined","window","clipboardData","setData","Error","writeIE","execCopy","navigator","userAgent","copyUsingTempSelection","document","body","tempElem","createElement","setAttribute","textContent","appendChild","success","removeChild","copyUsingTempElem","str","spanParent","attachShadow","mode","span","innerText","selectionSet","result","execCommand","selectionClear","copyTextUsingDOM","writeText","clipboard","DTFromText","read","_a","readText","_b","readIE","useStarShown","useStar","ClipboardPolyfillDefault","tracker","FallbackTracker","listener","e","forEach","key","preventDefault","addEventListener","removeEventListener","elem","sel","getSelection","range","createRange","selectNodeContents","removeAllRanges","addRange","dt","ClipboardEvent"],"mappings":"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"}
\No newline at end of file