@atlaskit/editor-plugin-text-formatting
Version:
Text-formatting plugin for @atlaskit/editor-core
114 lines (110 loc) • 4.33 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.nextToggleMark = exports.nextApplyMarkOnRange = void 0;
var _mark = require("@atlaskit/editor-common/mark");
var _state = require("@atlaskit/editor-prosemirror/state");
var _cellSelection = require("@atlaskit/editor-tables/cell-selection");
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
/**
* A custom version of the ProseMirror toggleMark, where we only toggle marks
* on text nodes in the selection rather than all inline nodes.
* @param markType
* @param attrs
*/
var nextToggleMark = exports.nextToggleMark = function nextToggleMark(markType, api, attrs) {
return function (_ref) {
var tr = _ref.tr;
var mark = markType.create(attrs);
// For cursor selections we can use the default behaviour.
if (tr.selection instanceof _state.TextSelection && tr.selection.$cursor) {
if (mark.isInSet(tr.storedMarks || tr.selection.$cursor.marks())) {
tr.removeStoredMark(mark);
} else {
tr.addStoredMark(mark);
}
return tr;
}
return nextToggleMarkInRange(mark, api)({
tr: tr
});
};
};
var nextToggleMarkInRange = function nextToggleMarkInRange(mark, api) {
return function (_ref2) {
var tr = _ref2.tr;
if (tr.selection instanceof _cellSelection.CellSelection) {
var removeMark = true;
var cells = [];
tr.selection.forEachCell(function (cell, cellPos) {
cells.push({
node: cell,
pos: cellPos
});
var from = cellPos;
var to = cellPos + cell.nodeSize;
removeMark && (removeMark = (0, _mark.entireSelectionContainsMark)(mark, tr.doc, from, to));
});
for (var i = cells.length - 1; i >= 0; i--) {
var cell = cells[i];
var from = cell.pos;
var to = from + cell.node.nodeSize;
nextApplyMarkOnRange(from, to, removeMark, mark, tr, api);
}
} else {
var _tr$selection = tr.selection,
$from = _tr$selection.$from,
$to = _tr$selection.$to;
// We decide to remove the mark only if the entire selection contains the mark
// Examples with *bold* text
// Scenario 1: Selection contains both bold and non-bold text -> bold entire selection
// Scenario 2: Selection contains only bold text -> un-bold entire selection
// Scenario 3: Selection contains no bold text -> bold entire selection
var _removeMark = (0, _mark.entireSelectionContainsMark)(mark, tr.doc, $from.pos, $to.pos);
nextApplyMarkOnRange($from.pos, $to.pos, _removeMark, mark, tr, api);
}
if (tr.docChanged) {
return tr;
}
return null;
};
};
var nextApplyMarkOnRange = exports.nextApplyMarkOnRange = function nextApplyMarkOnRange(from, to, removeMark, mark, tr, api) {
var schema = tr.doc.type.schema;
var code = schema.marks.code;
if (mark.type === code) {
var _api$base;
api === null || api === void 0 || (_api$base = api.base) === null || _api$base === void 0 || (_api$base = _api$base.actions) === null || _api$base === void 0 || _api$base.resolveMarks(from, to, tr);
}
/**
* We should refactor this so text formatting doesn't reference plugins it doesn't know about.
*/
tr.doc.nodesBetween(tr.mapping.map(from), tr.mapping.map(to), function (node, pos) {
if ((0, _platformFeatureFlags.fg)('editor_inline_comments_on_inline_nodes')) {
if (!node.isText) {
var isAllowedInlineNode = ['emoji', 'status', 'date', 'mention', 'inlineCard'].includes(node.type.name);
if (!isAllowedInlineNode) {
return true;
}
}
} else {
if (!node.isText) {
return true;
}
}
// This is an issue when the user selects some text.
// We need to check if the current node position is less than the range selection from.
// If it’s true, that means we should apply the mark using the range selection,
// not the current node position.
var nodeBetweenFrom = Math.max(pos, tr.mapping.map(from));
var nodeBetweenTo = Math.min(pos + node.nodeSize, tr.mapping.map(to));
if (removeMark) {
tr.removeMark(nodeBetweenFrom, nodeBetweenTo, mark);
} else {
tr.addMark(nodeBetweenFrom, nodeBetweenTo, mark);
}
return true;
});
return tr;
};