@atlaskit/editor-plugin-highlight
Version:
Highlight plugin for @atlaskit/editor-core
106 lines (102 loc) • 4.14 kB
JavaScript
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import { entireSelectionContainsMark } from '@atlaskit/editor-common/mark';
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
/**
* Value returned by `getActiveColor` when the selection spans more than one
* distinct highlight (background) color. Callers can compare against this to
* detect a multi-color selection.
*/
export var MULTIPLE_HIGHLIGHT_COLORS_SELECTED = 'multiple';
var getAllUniqueBackgroundColorMarksInRange = function getAllUniqueBackgroundColorMarksInRange(from, to, tr) {
var doc = tr.doc;
var backgroundColor = doc.type.schema.marks.backgroundColor;
var colorMarks = [];
var colorSet = new Set();
doc.nodesBetween(from, to, function (node) {
if (node.isLeaf) {
var mark = backgroundColor.isInSet(node.marks);
if (mark && !colorSet.has(mark.attrs.color)) {
colorMarks.push(mark);
colorSet.add(mark.attrs.color);
}
}
});
return colorMarks;
};
var getAllUniqueBackgroundColorMarksInCellSelection = function getAllUniqueBackgroundColorMarksInCellSelection(selection, tr) {
var colorMarks = [];
var colorSet = new Set();
selection.forEachCell(function (cell, cellPos) {
var from = cellPos;
var to = cellPos + cell.nodeSize;
var marks = getAllUniqueBackgroundColorMarksInRange(from, to, tr);
marks.forEach(function (mark) {
if (!colorSet.has(mark.attrs.color)) {
colorMarks.push(mark);
colorSet.add(mark.attrs.color);
}
});
});
return colorMarks;
};
// For Cell Selections - find first instance of a backgroundColor mark
// if all cells entirely contain this mark, set the color.
// If the selection contains multiple colors, return null
var getColorFromCellSelection = function getColorFromCellSelection(selection, tr) {
var marks = getAllUniqueBackgroundColorMarksInCellSelection(selection, tr);
if (marks.length > 1) {
return MULTIPLE_HIGHLIGHT_COLORS_SELECTED;
}
var firstColorMark = marks.at(0);
if (!firstColorMark) {
return null;
}
var foundUncolouredNode = false;
selection.forEachCell(function (cell, cellPos) {
if (foundUncolouredNode) {
return;
}
var from = cellPos;
var to = cellPos + cell.nodeSize;
if (!entireSelectionContainsMark(firstColorMark, tr.doc, from, to)) {
foundUncolouredNode = true;
}
});
return foundUncolouredNode ? null : firstColorMark.attrs.color;
};
// All other selections - find the first instance of a backgroundColor mark
// if selection entirely contains this mark, set the color.
// If the selection contains multiple colors, return null
var getColorFromRange = function getColorFromRange(from, to, tr) {
var marks = getAllUniqueBackgroundColorMarksInRange(from, to, tr);
if (marks.length > 1) {
return MULTIPLE_HIGHLIGHT_COLORS_SELECTED;
}
var firstColorMark = marks.at(0);
if (firstColorMark && entireSelectionContainsMark(firstColorMark, tr.doc, from, to)) {
return firstColorMark.attrs.color;
}
return null;
};
// For Cursor selections - set color if it is found in the storedMarks or $cursor.marks
var getColorFromCursor = function getColorFromCursor(selection, tr) {
var _mark$attrs$color;
if (!selection.$cursor) {
return null;
}
var mark = tr.doc.type.schema.marks.backgroundColor.isInSet([].concat(_toConsumableArray(tr.storedMarks ? tr.storedMarks : []), _toConsumableArray(selection.$cursor.marks())));
return (_mark$attrs$color = mark === null || mark === void 0 ? void 0 : mark.attrs.color) !== null && _mark$attrs$color !== void 0 ? _mark$attrs$color : null;
};
export var getActiveColor = function getActiveColor(tr) {
var selection = tr.selection;
var color = null;
if (selection instanceof CellSelection) {
color = getColorFromCellSelection(selection, tr);
} else if (selection instanceof TextSelection && selection.$cursor) {
color = getColorFromCursor(selection, tr);
} else {
color = getColorFromRange(selection.from, selection.to, tr);
}
return color;
};