@atlaskit/editor-plugin-card
Version:
Card plugin for @atlaskit/editor-core
118 lines (115 loc) • 3.26 kB
JavaScript
import { appearanceForNodeType } from '../../pm-plugins/utils';
import { EVENT_SUBJECT } from './types';
export function isDatasourceNode(node) {
return 'datasource' in node.attrs && !!node.attrs.datasource;
}
/**
* Determine if a node is considered to be a link
*/
export const isLinkNode = node => {
if (isDatasourceNode(node)) {
return false;
}
if (!!appearanceForNodeType(node.type)) {
return true;
}
return hasLinkMark(node);
};
export function getNodeSubject(node) {
if (isDatasourceNode(node)) {
return EVENT_SUBJECT.DATASOURCE;
}
if (isLinkNode(node)) {
return EVENT_SUBJECT.LINK;
}
return null;
}
/**
* Analytics appearance for link object
*/
export function appearanceForLink(node) {
const appearance = appearanceForNodeType(node.type);
if (appearance) {
return appearance;
}
return 'url';
}
const getLinkMark = node => {
if (node.marks) {
for (let i = 0; i < node.marks.length; i++) {
const mark = node.marks[i];
if (mark.type.name === 'link') {
return mark;
}
}
}
};
const hasLinkMark = node => {
return !!getLinkMark(node);
};
export function getUrl(node) {
var _node$attrs$url, _node$attrs, _getLinkMark, _getLinkMark$attrs;
return (_node$attrs$url = (_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.url) !== null && _node$attrs$url !== void 0 ? _node$attrs$url : (_getLinkMark = getLinkMark(node)) === null || _getLinkMark === void 0 ? void 0 : (_getLinkMark$attrs = _getLinkMark.attrs) === null || _getLinkMark$attrs === void 0 ? void 0 : _getLinkMark$attrs.href;
}
export const getNodeContext = (doc, pos) => {
const $pos = doc.resolve(pos);
const maxDepth = 3;
for (let i = 0; i <= maxDepth; i++) {
const node = $pos.node($pos.depth - i);
if (node && node.type.name !== 'paragraph') {
return node.type.name;
}
}
return 'unknown';
};
export const findAtPositions = (tr, positions) => {
const entities = [];
for (let i = 0; i < positions.length; i++) {
const pos = positions[i];
const node = tr.doc.nodeAt(pos);
if (!node) {
continue;
}
const nodeContext = getNodeContext(tr.doc, pos);
entities.push({
pos,
node,
nodeContext
});
}
return entities;
};
export const findInNodeRange = (doc, from, to, predicate) => {
const entities = [];
doc.nodesBetween(from, to, (node, pos) => {
if (predicate(node)) {
const entirelyInRange = pos >= from && pos + node.nodeSize <= to;
if (entirelyInRange) {
const nodeContext = getNodeContext(doc, pos);
entities.push({
pos,
node,
nodeContext
});
}
}
});
return entities;
};
/**
* Returns whether or not two sets of links appear to likely be the same set of links
* That they are in the same order and that both their hrefs and appearances match
*/
export const areSameNodes = (setA, setB) => {
if (setA.length !== setB.length) {
return false;
}
for (let i = 0; i < setA.length; i++) {
const a = setA[i];
const b = setB[i];
if (getUrl(a.node) !== getUrl(b.node) || appearanceForLink(a.node) !== appearanceForLink(b.node)) {
return false;
}
}
return true;
};