UNPKG

@atlaskit/editor-plugin-editor-viewmode-effects

Version:

Editor-Viewmode effects plugin for @atlaskit/editor-core

126 lines (125 loc) 5.67 kB
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin'; import { TextSelection } from '@atlaskit/editor-prosemirror/state'; import { AddMarkStep, AddNodeMarkStep, ReplaceAroundStep, ReplaceStep, RemoveMarkStep, RemoveNodeMarkStep } from '@atlaskit/editor-prosemirror/transform'; import { fg } from '@atlaskit/platform-feature-flags'; import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals'; import { ViewModeNodeStep, ViewModeStep } from './pm-plugins/viewModeStep'; const createFilterStepsPlugin = api => () => new SafePlugin({ filterTransaction: tr => { var _api$editorViewMode, _api$editorViewMode$s; const mode = api === null || api === void 0 ? void 0 : (_api$editorViewMode = api.editorViewMode) === null || _api$editorViewMode === void 0 ? void 0 : (_api$editorViewMode$s = _api$editorViewMode.sharedState.currentState()) === null || _api$editorViewMode$s === void 0 ? void 0 : _api$editorViewMode$s.mode; if (mode !== 'view') { return true; } if (expValEquals('platform_editor_are_nodes_equal_ignore_mark_order', 'isEnabled', true)) { if (tr.getMeta('isRemote') || tr.getMeta('replaceDocument') || tr.getMeta('allowViewModeTransaction') && fg('platform_editor_allow_viewmode_transaction')) { return true; } } else { if (tr.getMeta('isRemote') || tr.getMeta('allowViewModeTransaction') && fg('platform_editor_allow_viewmode_transaction')) { return true; } } const viewModeSteps = tr.steps.reduce((acc, s) => { if (s instanceof ViewModeNodeStep || s instanceof ViewModeStep) { acc.push(s); } return acc; }, []); if (viewModeSteps.length === 0 || !api) { if (tr.docChanged && // Check if the transaction contains any steps that modify the document (view mode steps do not) tr.steps.filter(s => s instanceof ReplaceAroundStep || s instanceof ReplaceStep || s instanceof AddMarkStep || s instanceof AddNodeMarkStep || s instanceof RemoveMarkStep || s instanceof RemoveNodeMarkStep).length) { return false; } return true; return true; } viewModeSteps.forEach(step => { if (step.inverted || !step.mark) { return; } if (step.mark.type.name === 'annotation') { if (step instanceof ViewModeNodeStep) { var _api$collabEdit; (_api$collabEdit = api.collabEdit) === null || _api$collabEdit === void 0 ? void 0 : _api$collabEdit.actions.addInlineCommentNodeMark({ mark: step.mark, pos: step.pos }); } else if (step instanceof ViewModeStep) { var _api$collabEdit2; (_api$collabEdit2 = api.collabEdit) === null || _api$collabEdit2 === void 0 ? void 0 : _api$collabEdit2.actions.addInlineCommentMark({ mark: step.mark, from: step.from, to: step.to }); } } }); // Ignored via go/ees007 // eslint-disable-next-line @atlaskit/editor/enforce-todo-comment-format // TODO: Follow-up and improve annotation logic so we can filter out transactions here return true; } }); const createReplaceDocumentTransactionPlugin = api => () => new SafePlugin({ // Shouldn't need explicit types but sometimes TS can't infer them so 🤷 appendTransaction: (transactions, _oldState, newState) => { var _api$editorViewMode2, _api$editorViewMode2$; if (!api) { return; } const isViewMode = (api === null || api === void 0 ? void 0 : (_api$editorViewMode2 = api.editorViewMode) === null || _api$editorViewMode2 === void 0 ? void 0 : (_api$editorViewMode2$ = _api$editorViewMode2.sharedState.currentState()) === null || _api$editorViewMode2$ === void 0 ? void 0 : _api$editorViewMode2$.mode) === 'view'; if (!isViewMode) { return; } const remoteReplaceDocumentTransaction = transactions.find(tr => { var _api$collabEdit3, _api$collabEdit3$acti; return (_api$collabEdit3 = api.collabEdit) === null || _api$collabEdit3 === void 0 ? void 0 : (_api$collabEdit3$acti = _api$collabEdit3.actions) === null || _api$collabEdit3$acti === void 0 ? void 0 : _api$collabEdit3$acti.isRemoteReplaceDocumentTransaction(tr); }); if (!remoteReplaceDocumentTransaction || !remoteReplaceDocumentTransaction.selectionSet) { return; } const doc = newState.doc; const nextTr = newState.tr; const emptySelection = new TextSelection(doc.resolve(0)); nextTr.setSelection(emptySelection); return nextTr; } }); export const editorViewModeEffectsPlugin = ({ api }) => ({ name: 'editorViewModeEffects', actions: { allowViewModeTransaction: tr => { tr.setMeta('allowViewModeTransaction', true); return tr; }, applyViewModeStepAt: tr => { const marksSteps = tr.steps.reduce((acc, s) => { // Ignored via go/ees007 // eslint-disable-next-line @atlaskit/editor/enforce-todo-comment-format // TODO: We probably want to check the RemoveMarkStep flow too. if (s instanceof AddMarkStep || s instanceof AddNodeMarkStep) { acc.push(s); } return acc; }, []); if (marksSteps.length === 0) { return false; } marksSteps.reverse().map(s => s instanceof AddNodeMarkStep ? tr.step(ViewModeNodeStep.from(s)) : tr.step(ViewModeStep.from(s))); return true; } }, pmPlugins() { return [{ name: 'editorViewModeEffectsFilterSteps', plugin: createFilterStepsPlugin(api) }, { name: 'editorViewModeEffectsReplaceDocumentTransaction', plugin: createReplaceDocumentTransactionPlugin(api) }]; } });