-
Notifications
You must be signed in to change notification settings - Fork 3k
/
Copy pathindex.js
117 lines (104 loc) · 3.85 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// on Web/desktop this import will be replaced with `react-native-web`
import {Clipboard} from 'react-native-web';
import lodashGet from 'lodash/get';
import CONST from '../../CONST';
import * as Browser from '../Browser';
const canSetHtml = () => lodashGet(navigator, 'clipboard.write');
/**
* Deprecated method to write the content as HTML to clipboard.
* @param {String} html HTML representation
* @param {String} text Plain text representation
*/
function setHTMLSync(html, text) {
const node = document.createElement('span');
node.textContent = html;
node.style.all = 'unset';
node.style.opacity = '0';
node.style.position = 'absolute';
node.style.whiteSpace = 'pre-wrap';
node.style.userSelect = 'text';
node.addEventListener('copy', (e) => {
e.stopPropagation();
e.preventDefault();
e.clipboardData.clearData();
e.clipboardData.setData('text/html', html);
e.clipboardData.setData('text/plain', text);
});
document.body.appendChild(node);
const selection = window.getSelection();
const firstAnchorChild = selection.anchorNode && selection.anchorNode.firstChild;
const isComposer = firstAnchorChild instanceof HTMLTextAreaElement;
let originalSelection = null;
if (isComposer) {
originalSelection = {
start: firstAnchorChild.selectionStart,
end: firstAnchorChild.selectionEnd,
direction: firstAnchorChild.selectionDirection,
};
} else {
originalSelection = {
anchorNode: selection.anchorNode,
anchorOffset: selection.anchorOffset,
focusNode: selection.focusNode,
focusOffset: selection.focusOffset,
};
}
selection.removeAllRanges();
const range = document.createRange();
range.selectNodeContents(node);
selection.addRange(range);
try {
document.execCommand('copy');
} catch (e) {
// The 'copy' command can throw a SecurityError exception, we ignore this exception on purpose.
// See https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#the-copy-command for more details.
}
selection.removeAllRanges();
if (isComposer) {
firstAnchorChild.setSelectionRange(originalSelection.start, originalSelection.end, originalSelection.direction);
} else {
selection.setBaseAndExtent(originalSelection.anchorNode, originalSelection.anchorOffset, originalSelection.focusNode, originalSelection.focusOffset);
}
document.body.removeChild(node);
}
/**
* Writes the content as HTML if the web client supports it.
* @param {String} html HTML representation
* @param {String} text Plain text representation
*/
const setHtml = (html, text) => {
if (!html || !text) {
return;
}
if (!canSetHtml()) {
throw new Error('clipboard.write is not supported on this platform, thus HTML cannot be copied.');
}
if (CONST.BROWSER.SAFARI === Browser.getBrowser()) {
// Safari sanitize "text/html" data before writing to the pasteboard when using Clipboard API,
// whitespaces in the start of line are stripped away. We use the deprecated method to copy
// contents as HTML and keep whitespaces in the start of line on Safari.
// See https://webkit.org/blog/10855/async-clipboard-api/ for more details.
setHTMLSync(html, text);
} else {
navigator.clipboard.write([
// eslint-disable-next-line no-undef
new ClipboardItem({
'text/html': new Blob([html], {type: 'text/html'}),
'text/plain': new Blob([text], {type: 'text/plain'}),
}),
]);
}
};
/**
* Sets a string on the Clipboard object via react-native-web
*
* @param {String} text
*/
const setString = (text) => {
Clipboard.setString(text);
};
export default {
setString,
canSetHtml,
setHtml,
};