-
chris authoredfdd87283
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
trackedTransaction.js 4.31 KiB
import { TextSelection } from 'prosemirror-state';
import {
ReplaceStep,
ReplaceAroundStep,
AddMarkStep,
RemoveMarkStep,
Mapping,
} from 'prosemirror-transform';
import { DocumentHelpers } from 'wax-prosemirror-utilities';
import replaceStep from './helpers/replaceStep';
import replaceAroundStep from './helpers/replaceAroundStep';
import addMarkStep from './helpers/addMarkStep';
import removeMarkStep from './helpers/removeMarkStep';
const trackedTransaction = (tr, state, user, group = 'main') => {
// Don't track table operations
if (!tr.selectionSet) {
const $pos = state.selection.$anchor;
for (let { depth } = $pos; depth > 0; depth -= 1) {
const node = $pos.node(depth);
if (node.type.spec.tableRole === 'table') {
return tr;
}
}
}
// images
if (tr.meta.inputType === 'backwardsDelete' && !tr.steps.lenght) {
const $pos = state.selection.$anchor;
let node;
if ($pos.depth === 1) {
node = $pos.node($pos.depth);
if (
node.content.content[0] &&
node.content.content[0].type.name === 'image'
)
return tr;
}
}
if (
!tr.steps.length ||
(tr.meta &&
!Object.keys(tr.meta).every(meta =>
['inputType', 'uiEvent', 'paste'].includes(meta),
)) ||
['AcceptReject', 'Undo', 'Redo'].includes(tr.getMeta('inputType'))
) {
return tr;
}
// const group = tr.getMeta('outsideView') ? tr.getMeta('outsideView') : 'main';
const newTr = state.tr;
const map = new Mapping();
const date = Math.floor(Date.now() / 300000);
tr.steps.forEach(originalStep => {
const step = originalStep.map(map);
const { doc } = newTr;
if (!step) return;
switch (step.constructor) {
case ReplaceStep:
replaceStep(state, tr, step, newTr, map, doc, user, date, group);
break;
case ReplaceAroundStep:
replaceAroundStep(state, tr, step, newTr, map, doc, user, date, group);
break;
case AddMarkStep:
addMarkStep(state, tr, step, newTr, map, doc, user, date, group);
break;
case RemoveMarkStep:
removeMarkStep(state, tr, step, newTr, map, doc, user, date, group);
break;
default:
}
});
if (tr.getMeta('inputType')) newTr.setMeta(tr.getMeta('inputType'));
if (tr.getMeta('uiEvent')) newTr.setMeta(tr.getMeta('uiEvent'));
if (tr.selectionSet) {
const deletionMarkSchema = state.schema.marks.deletion;
const deletionMark = DocumentHelpers.findMark(
state,
deletionMarkSchema,
false,
);
if (
tr.selection instanceof TextSelection &&
(tr.selection.from < state.selection.from ||
tr.getMeta('inputType') === 'backwardsDelete')
) {
const caretPos = map.map(tr.selection.from, -1);
newTr.setSelection(new TextSelection(newTr.doc.resolve(caretPos)));
} else if (tr.selection.from > state.selection.from && deletionMark) {
const caretPos = map.map(deletionMark.to + 1, 1);
newTr.setSelection(new TextSelection(newTr.doc.resolve(caretPos)));
} else {
newTr.setSelection(tr.selection.map(newTr.doc, map));
}
} else if (
state.selection.from - tr.selection.from > 1 &&
tr.selection.$head.depth > 1
) {
const caretPos = map.map(tr.selection.from - 2, -1);
newTr.setSelection(new TextSelection(newTr.doc.resolve(caretPos)));
} else {
if (
state.selection.from === state.selection.to &&
tr.selection.$head.depth > 1 &&
state.selection.from - tr.selection.from === 1
) {
tr.steps.forEach(originalStep => {
const step = originalStep.map(map);
step.from += 1;
step.to += 1;
const { doc } = newTr;
replaceStep(state, tr, step, newTr, map, doc, user, date, group);
});
const caretPos = map.map(tr.selection.from - 1, -1);
newTr.setSelection(new TextSelection(newTr.doc.resolve(caretPos)));
} else if (state.selection.from === state.selection.to) {
const caretPos = map.map(tr.selection.from, -1);
newTr.setSelection(new TextSelection(newTr.doc.resolve(caretPos)));
}
const slice = map.slice(newTr.selection.from, newTr.selection.to);
map.appendMap(slice);
}
if (tr.storedMarksSet) newTr.setStoredMarks(tr.storedMarks);
if (tr.scrolledIntoView) newTr.scrollIntoView();
return newTr;
};
export default trackedTransaction;