@atlaskit/editor-plugin-find-replace
Version:
find replace plugin for @atlaskit/editor-core
120 lines (116 loc) • 5.96 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
import { pluginFactory, stepHasSlice } from '@atlaskit/editor-common/utils';
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
import { initialState } from './main';
import { findReplacePluginKey } from './plugin-key';
import reducer from './reducer';
import { createDecorations, findClosestMatch, findDecorationFromMatch, findMatches, findSearchIndex, findUniqueItemsIn, getSelectionForMatch, isMatchAffectedByStep, removeDecorationsFromSet, removeMatchesFromSet } from './utils';
var handleDocChanged = function handleDocChanged(tr, pluginState) {
var _api$expand;
var isActive = pluginState.isActive,
findText = pluginState.findText;
if (!isActive || !findText) {
return pluginState;
}
if (!tr.steps.find(stepHasSlice)) {
return pluginState;
}
// Ignored via go/ees005
// eslint-disable-next-line prefer-const
var index = pluginState.index,
decorationSet = pluginState.decorationSet,
matches = pluginState.matches,
shouldMatchCase = pluginState.shouldMatchCase,
getIntl = pluginState.getIntl,
api = pluginState.api;
var newMatches = findMatches({
content: tr.doc,
searchText: findText,
shouldMatchCase: shouldMatchCase,
getIntl: getIntl,
api: api
});
decorationSet = decorationSet.map(tr.mapping, tr.doc);
var numDecorations = decorationSet.find().length;
var mappedMatches = matches.map(function (match) {
return {
start: tr.mapping.map(match.start),
end: tr.mapping.map(match.end),
canReplace: match.canReplace,
nodeType: match.nodeType
};
});
var matchesToAdd = [];
var matchesToDelete = [];
if (newMatches.length > 0 && numDecorations === 0) {
matchesToAdd = newMatches;
} else if (newMatches.length === 0 && numDecorations > 0) {
decorationSet = DecorationSet.empty;
} else if (newMatches.length > 0 || numDecorations > 0) {
// go through tr steps and find any new matches from user adding content or
// any dead matches from user deleting content
tr.steps.forEach(function (step) {
if (stepHasSlice(step)) {
// add all matches that are between the affected positions and don't already have
// corresponding decorations
matchesToAdd = [].concat(_toConsumableArray(matchesToAdd), _toConsumableArray(newMatches.filter(function (match) {
return isMatchAffectedByStep(match, step, tr) && !findDecorationFromMatch(decorationSet, match);
})));
// delete any matches that are missing from the newMatches array and have a
// corresponding decoration
matchesToDelete = [].concat(_toConsumableArray(matchesToDelete), _toConsumableArray(findUniqueItemsIn(mappedMatches.filter(function (match) {
return isMatchAffectedByStep(match, step, tr) && !!findDecorationFromMatch(decorationSet, match);
}), newMatches, function (firstMatch, secondMatch) {
return firstMatch.start === secondMatch.start && firstMatch.end === secondMatch.end;
})));
}
});
}
// update decorations if matches changed following document update
if (matchesToDelete.length > 0) {
var decorationsToDelete = matchesToDelete.reduce(function (decorations, match) {
return [].concat(_toConsumableArray(decorations), _toConsumableArray(decorationSet.find(match.start, match.end)));
}, []);
decorationSet = removeDecorationsFromSet(decorationSet, decorationsToDelete, tr.doc);
}
if (matchesToAdd.length > 0) {
decorationSet = decorationSet.add(tr.doc, createDecorations(tr.selection.from, matchesToAdd));
}
// update selected match if it has changed
var newIndex = index;
var selectedMatch = mappedMatches[index];
if (selectedMatch) {
newIndex = newMatches.findIndex(function (match) {
return match.start === selectedMatch.start;
});
}
if (newIndex === undefined || newIndex === -1) {
newIndex = expValEquals('platform_editor_find_and_replace_improvements', 'isEnabled', true) ? findClosestMatch(tr.selection.from, newMatches) : findSearchIndex(tr.selection.from, newMatches);
}
var newSelectedMatch = newMatches[newIndex];
decorationSet = removeMatchesFromSet(decorationSet, [selectedMatch, newSelectedMatch], tr.doc);
if (newSelectedMatch) {
decorationSet = decorationSet.add(tr.doc, createDecorations(0, [newSelectedMatch]));
}
var newSelection = getSelectionForMatch(tr.selection, tr.doc, newIndex, newMatches);
api === null || api === void 0 || (_api$expand = api.expand) === null || _api$expand === void 0 || _api$expand.commands.toggleExpandWithMatch(newSelection)({
tr: tr
});
return _objectSpread(_objectSpread({}, pluginState), {}, {
matches: newMatches,
index: newIndex,
decorationSet: decorationSet
});
};
var dest = pluginFactory(findReplacePluginKey, reducer(function () {
return initialState;
}), {
onDocChanged: handleDocChanged
});
export var createCommand = dest.createCommand;
export var getPluginState = dest.getPluginState;
export var createPluginState = dest.createPluginState;