@atlaskit/editor-common
Version:
A package that contains common classes and components for editor and renderer
180 lines (179 loc) • 5.97 kB
JavaScript
// Ignored via go/ees005
// eslint-disable-next-line import/no-namespace
import * as clipboard from 'clipboard-polyfill';
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
import { ACTION, 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 = () =>
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-explicit-any
window.clipboardData && typeof window.clipboardData.setData === 'function';
const isExtensionNode = node => {
if (node === 'extension' || node === 'bodiedExtension' || node === 'inlineExtension' || node === 'multiBodiedExtension') {
return true;
}
return false;
};
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 {
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-explicit-any
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 (!!document && typeof document === 'object') {
try {
// ED-17083 extension copy seems have issue with ClipboardItem API
// Hence of use of this polyfill
copyHTMLToClipboardPolyfill(elementToCopy, plainTextToCopy);
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
}
}
};
// At the time of development, Firefox doesn't support ClipboardItem API
// Hence of use of this polyfill
export const copyHTMLToClipboardPolyfill = async (elementToCopy, plainTextToCopy) => {
const dt = new clipboard.ClipboardItem({
'text/html': new Blob([elementToCopy.innerHTML], {
type: 'text/html'
}),
'text/plain': new Blob([plainTextToCopy || elementToCopy.innerText], {
type: 'text/plain'
})
});
await 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) {
var _attributes;
const {
actionSubjectId: selectionActionSubjectId
} = selectionAnalyticsPayload;
const node = (_attributes = selectionAnalyticsPayload.attributes) === null || _attributes === void 0 ? void 0 : _attributes.node;
const content = [];
let extensionType;
let extensionKey;
switch (selectionActionSubjectId) {
case ACTION_SUBJECT_ID.NODE:
if (node) {
content.push(node);
if (isExtensionNode(node)) {
extensionType = selection.node.attrs.extensionType;
extensionKey = selection.node.attrs.extensionKey;
}
}
break;
case ACTION_SUBJECT_ID.RANGE:
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
content.push(...selectionAnalyticsPayload.attributes.nodes);
break;
case ACTION_SUBJECT_ID.ALL:
content.push('all');
break;
case ACTION_SUBJECT_ID.CELL:
{
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const {
selectedCells
} = selectionAnalyticsPayload.attributes;
content.push(...Array(selectedCells).fill('tableCell'));
break;
}
}
if (isExtensionNode(node)) {
return {
eventType: EVENT_TYPE.TRACK,
action,
actionSubject: ACTION_SUBJECT.DOCUMENT,
attributes: {
content,
extensionKey,
extensionType
}
};
}
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']
}
};
}
};
export const getNodeCopiedAnalyticsPayload = (node, inputMethod) => {
const nodeType = node.type.name;
let extensionType;
let extensionKey;
if (isExtensionNode(nodeType)) {
extensionType = node.attrs.extensionType;
extensionKey = node.attrs.extensionKey;
}
const payload = {
eventType: EVENT_TYPE.TRACK,
action: ACTION.COPIED,
actionSubject: ACTION_SUBJECT.DOCUMENT,
attributes: {
content: [nodeType],
inputMethod,
nodeType,
...(extensionType ? {
extensionType
} : {}),
...(extensionKey ? {
extensionKey
} : {})
}
};
return payload;
};