UNPKG

14.1 kBSource Map (JSON)View Raw
1{"version":3,"file":"clipboard-polyfill.promise.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","DT","type","value","indexOf","m","this","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