@atlaskit/editor-common
Version:
A package that contains common classes and components for editor and renderer
106 lines (105 loc) • 3.81 kB
JavaScript
import * as clipboard from 'clipboard-polyfill';
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
import { ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '../analytics';
import { getAllSelectionAnalyticsPayload, getCellSelectionAnalyticsPayload, getNodeSelectionAnalyticsPayload, getRangeSelectionAnalyticsPayload } from '../selection';
const isClipboardApiSupported = () => !!navigator.clipboard && typeof navigator.clipboard.writeText === 'function';
const isIEClipboardApiSupported = () => window.clipboardData && typeof window.clipboardData.setData === 'function';
export const copyToClipboard = async textToCopy => {
if (isClipboardApiSupported()) {
try {
await navigator.clipboard.writeText(textToCopy);
} catch (error) {
throw new Error('Clipboard api is not supported');
}
} else if (isIEClipboardApiSupported()) {
try {
await window.clipboardData.setData('text', textToCopy);
} catch (error) {
throw new Error('IE clipboard api is not supported');
}
} else {
throw new Error('Clipboard api is not supported');
}
};
export const copyHTMLToClipboard = async (elementToCopy, plainTextToCopy) => {
// @ts-ignore
if (isClipboardApiSupported() && typeof ClipboardItem !== 'undefined') {
try {
const data = new ClipboardItem({
'text/plain': new Blob([plainTextToCopy || elementToCopy.innerText], {
type: 'text/plain'
}),
'text/html': new Blob([elementToCopy.innerHTML], {
type: 'text/html'
})
});
// @ts-ignore
await navigator.clipboard.write([data]);
} catch (error) {
throw new Error('Clipboard api is not supported');
}
} else if (typeof document !== undefined) {
// ED-17083 extension copy seems have issue with ClipboardItem API
// Hence of use of this polyfill
copyHTMLToClipboardPolyfill(elementToCopy, plainTextToCopy);
}
};
// At the time of development, Firefox doesn't support ClipboardItem API
// Hence of use of this polyfill
export const copyHTMLToClipboardPolyfill = (elementToCopy, plainTextToCopy) => {
const Clipboard = clipboard;
const dt = new Clipboard.DT();
dt.setData('text/plain', plainTextToCopy || elementToCopy.innerText);
dt.setData('text/html', elementToCopy.innerHTML);
Clipboard.write(dt);
};
export const getAnalyticsPayload = (state, action) => {
const {
selection,
doc
} = state;
const selectionAnalyticsPayload = getNodeSelectionAnalyticsPayload(selection) || getRangeSelectionAnalyticsPayload(selection, doc) || getAllSelectionAnalyticsPayload(selection) || getCellSelectionAnalyticsPayload(state);
if (selectionAnalyticsPayload) {
const {
actionSubjectId: selectionActionSubjectId
} = selectionAnalyticsPayload;
let content = [];
switch (selectionActionSubjectId) {
case ACTION_SUBJECT_ID.NODE:
content.push(selectionAnalyticsPayload.attributes.node);
break;
case ACTION_SUBJECT_ID.RANGE:
content.push(...selectionAnalyticsPayload.attributes.nodes);
break;
case ACTION_SUBJECT_ID.ALL:
content.push('all');
break;
case ACTION_SUBJECT_ID.CELL:
{
const {
selectedCells
} = selectionAnalyticsPayload.attributes;
content.push(...Array(selectedCells).fill('tableCell'));
break;
}
}
return {
eventType: EVENT_TYPE.TRACK,
action,
actionSubject: ACTION_SUBJECT.DOCUMENT,
attributes: {
content
}
};
}
if (selection instanceof TextSelection && selection.$cursor) {
return {
eventType: EVENT_TYPE.TRACK,
action,
actionSubject: ACTION_SUBJECT.DOCUMENT,
attributes: {
content: ['caret']
}
};
}
};