ngx-editor
Version:
Rich Text Editor for angular using ProseMirror
134 lines (123 loc) • 4.3 kB
JavaScript
import { InputRule } from 'prosemirror-inputrules';
const isMarkActive = (state, type) => {
const { from, $from, to, empty } = state.selection;
if (empty) {
return !!type.isInSet(state.storedMarks || $from.marks());
}
else {
return state.doc.rangeHasMark(from, to, type);
}
};
const getSelectionMarks = (state) => {
let marks = [];
const { selection: { from, to, empty, $from }, storedMarks } = state;
if (empty) {
marks = storedMarks || $from.marks();
}
else {
state.doc.nodesBetween(from, to, node => {
marks = [...marks, ...node.marks];
});
}
return marks;
};
const isLinkActive = (state) => {
const { schema, selection: { anchor, head, from } } = state;
if (!schema.marks.link) {
return false;
}
const isForwardSelection = anchor === from;
const linkMarks = getSelectionMarks(state).filter(mark => mark.type === schema.marks.link);
if (!linkMarks.length) {
return false;
}
const selectionHasOnlyMarks = isForwardSelection ?
(state.doc.rangeHasMark(anchor, anchor + 1, schema.marks.link) &&
state.doc.rangeHasMark(head - 1, head, schema.marks.link)) : (state.doc.rangeHasMark(anchor - 1, anchor, schema.marks.link) &&
state.doc.rangeHasMark(head, head + 1, schema.marks.link));
if (linkMarks.length === 1 && selectionHasOnlyMarks) {
return true;
}
return false;
};
const findNodeType = (type, $from) => {
for (let i = $from.depth; i > 0; i--) {
if ($from.node(i).type === type) {
return $from.node(i).type;
}
}
return null;
};
const isNodeActive = (state, type, attrs = {}) => {
const { selection } = state;
const { $from, to } = selection;
const node = findNodeType(type, $from);
if (!Object.entries(attrs).length || !node) {
return !!node;
}
return to <= $from.end() && $from.parent.hasMarkup(type, attrs);
};
const calculateTooltipPos = (view) => {
const { state: { selection } } = view;
const { from, to } = selection;
// These are in screen coordinates
const start = view.coordsAtPos(from);
const end = view.coordsAtPos(to);
// The box in which the tooltip is positioned, to use as base
const box = view.dom.getBoundingClientRect();
// Find a center-ish x position from the selection endpoints (when
// crossing lines, end may be more to the left)
const left = Math.max((start.left + end.left) / 2, start.left + 3);
return {
left: left - box.left,
bottom: box.bottom - start.top
};
};
const getSelectionNodes = (state) => {
const nodes = [];
const { selection: { from, to } } = state;
state.doc.nodesBetween(from, to, node => {
nodes.push(node);
});
return nodes;
};
// Ref: https://github.com/ProseMirror/prosemirror-commands/blob/master/src/commands.js
const markApplies = (doc, ranges, type) => {
for (const range of ranges) {
const { $from, $to } = range;
let canApply = $from.depth === 0 ? doc.type.allowsMarkType(type) : false;
doc.nodesBetween($from.pos, $to.pos, (node) => {
if (canApply) {
return false;
}
canApply = node.inlineContent && node.type.allowsMarkType(type);
return true;
});
if (canApply) {
return true;
}
}
return false;
};
const markInputRule = (regexp, markType, attrs) => {
return new InputRule(regexp, (state, match, start, end) => {
const tr = state.tr;
if (match[2]) {
const textStart = start + match[0].indexOf(match[2]);
const textEnd = textStart + match[2].length;
if (textEnd < end) {
tr.delete(textEnd, end);
}
if (textStart > start) {
tr.delete(start, textStart);
}
end = start + match[2].length;
}
return tr.addMark(start, end, markType.create(attrs));
});
};
/**
* Generated bundle index. Do not edit.
*/
export { calculateTooltipPos, getSelectionMarks, getSelectionNodes, isLinkActive, isMarkActive, isNodeActive, markApplies, markInputRule };
//# sourceMappingURL=ngx-editor-helpers.mjs.map