@remirror/extension-yjs 1.0.20 → 1.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import type { Doc } from 'yjs';
2
- import { AcceptUndefined, Dispose, EditorState, KeyBindingProps, NonChainableCommandFunction, OnSetOptionsProps, PlainExtension, ProsemirrorPlugin, Selection, Shape } from '@remirror/core';
2
+ import { AcceptUndefined, Dispose, EditorState, KeyBindingProps, NonChainableCommandFunction, OnSetOptionsProps, PlainExtension, ProsemirrorPlugin, Selection, Shape, Static } from '@remirror/core';
3
3
  export interface ColorDef {
4
4
  light: string;
5
5
  dark: string;
@@ -54,13 +54,14 @@ export interface YjsOptions<Provider extends YjsRealtimeProvider = YjsRealtimePr
54
54
  * @default `(state) => state.selection`
55
55
  */
56
56
  getSelection?: (state: EditorState) => Selection;
57
+ disableUndo?: Static<boolean>;
57
58
  /**
58
59
  * Names of nodes in the editor which should be protected.
59
60
  *
60
61
  * @default `new Set('paragraph')`
61
62
  */
62
- protectedNodes?: Set<string>;
63
- trackedOrigins?: any[];
63
+ protectedNodes?: Static<Set<string>>;
64
+ trackedOrigins?: Static<any[]>;
64
65
  }
65
66
  /**
66
67
  * The YJS extension is the recommended extension for creating a collaborative
@@ -73,6 +74,9 @@ export declare class YjsExtension extends PlainExtension<YjsOptions> {
73
74
  * The provider that is being used for the editor.
74
75
  */
75
76
  get provider(): YjsRealtimeProvider;
77
+ getBinding(): {
78
+ mapping: Map<any, any>;
79
+ } | undefined;
76
80
  onView(): Dispose | void;
77
81
  /**
78
82
  * Create the yjs plugins.
@@ -87,19 +91,17 @@ export declare class YjsExtension extends PlainExtension<YjsOptions> {
87
91
  */
88
92
  onDestroy(): void;
89
93
  /**
90
- * Undo within a collaborative editor.
91
- *
92
- * This should be used instead of the built in `undo` command.
94
+ * Undo that last Yjs transaction(s)
93
95
  *
94
96
  * This command does **not** support chaining.
97
+ * This command is a no-op and always returns `false` when the `disableUndo` option is set.
95
98
  */
96
99
  yUndo(): NonChainableCommandFunction;
97
100
  /**
98
- * Redo, within a collaborative editor.
99
- *
100
- * This should be used instead of the built in `redo` command.
101
+ * Redo the last transaction undone with a previous `yUndo` command.
101
102
  *
102
103
  * This command does **not** support chaining.
104
+ * This command is a no-op and always returns `false` when the `disableUndo` option is set.
103
105
  */
104
106
  yRedo(): NonChainableCommandFunction;
105
107
  /**
@@ -110,8 +112,6 @@ export declare class YjsExtension extends PlainExtension<YjsOptions> {
110
112
  * Handle the redo keybinding for the editor.
111
113
  */
112
114
  redoShortcut(props: KeyBindingProps): boolean;
113
- private absolutePositionToRelativePosition;
114
- private relativePositionToAbsolutePosition;
115
115
  }
116
116
  /**
117
117
  * The default destroy provider method.
@@ -3,6 +3,8 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var _applyDecoratedDescriptor = require('@babel/runtime/helpers/applyDecoratedDescriptor');
6
+ var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
7
+ var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
6
8
  var yProsemirror = require('y-prosemirror');
7
9
  var yjs = require('yjs');
8
10
  var core = require('@remirror/core');
@@ -10,6 +12,98 @@ var extensionAnnotation = require('@remirror/extension-annotation');
10
12
  var messages = require('@remirror/messages');
11
13
 
12
14
  var _dec, _dec2, _dec3, _dec4, _dec5, _class, _class2;
15
+
16
+ var _excluded = ["from", "to"],
17
+ _excluded2 = ["from", "to"];
18
+
19
+ class YjsAnnotationStore {
20
+ constructor(doc, pmName, mapName, getMapping) {
21
+ this.doc = doc;
22
+ this.getMapping = getMapping;
23
+ this.type = doc.getXmlFragment(pmName);
24
+ this.map = doc.getMap(mapName);
25
+ }
26
+
27
+ addAnnotation(_ref) {
28
+ var from = _ref.from,
29
+ to = _ref.to,
30
+ data = _objectWithoutProperties(_ref, _excluded);
31
+
32
+ // XXX: Why is this cast needed?
33
+ var storedData = _objectSpread(_objectSpread({}, data), {}, {
34
+ from: this.absolutePositionToRelativePosition(from),
35
+ to: this.absolutePositionToRelativePosition(to)
36
+ });
37
+
38
+ this.map.set(data.id, storedData);
39
+ }
40
+
41
+ updateAnnotation(id, updateData) {
42
+ var existing = this.map.get(id);
43
+
44
+ if (!existing) {
45
+ return;
46
+ }
47
+
48
+ this.map.set(id, _objectSpread(_objectSpread({}, updateData), {}, {
49
+ from: existing.from,
50
+ to: existing.to
51
+ }));
52
+ }
53
+
54
+ removeAnnotations(ids) {
55
+ yjs.transact(this.doc, () => {
56
+ ids.forEach(id => this.map.delete(id));
57
+ });
58
+ }
59
+
60
+ setAnnotations(annotations) {
61
+ yjs.transact(this.doc, () => {
62
+ this.map.clear();
63
+ annotations.forEach(annotation => this.addAnnotation(annotation));
64
+ });
65
+ }
66
+
67
+ formatAnnotations() {
68
+ var result = [];
69
+ this.map.forEach(_ref2 => {
70
+ var relFrom = _ref2.from,
71
+ relTo = _ref2.to,
72
+ data = _objectWithoutProperties(_ref2, _excluded2);
73
+
74
+ var from = this.relativePositionToAbsolutePosition(relFrom);
75
+ var to = this.relativePositionToAbsolutePosition(relTo);
76
+
77
+ if (!from || !to) {
78
+ return;
79
+ } // XXX: Why is this cast needed?
80
+
81
+
82
+ result.push(_objectSpread(_objectSpread({}, data), {}, {
83
+ from,
84
+ to
85
+ }));
86
+ });
87
+ return result;
88
+ }
89
+
90
+ absolutePositionToRelativePosition(pos) {
91
+ var mapping = this.getMapping();
92
+ return yProsemirror.absolutePositionToRelativePosition(pos, this.type, mapping);
93
+ }
94
+
95
+ relativePositionToAbsolutePosition(relPos) {
96
+ var mapping = this.getMapping();
97
+ return yProsemirror.relativePositionToAbsolutePosition(this.doc, this.type, relPos, mapping);
98
+ }
99
+
100
+ }
101
+ /**
102
+ * The YJS extension is the recommended extension for creating a collaborative
103
+ * editor.
104
+ */
105
+
106
+
13
107
  var YjsExtension = (_dec = core.extension({
14
108
  defaultOptions: {
15
109
  getProvider: () => {
@@ -23,29 +117,31 @@ var YjsExtension = (_dec = core.extension({
23
117
  cursorBuilder: yProsemirror.defaultCursorBuilder,
24
118
  cursorStateField: 'cursor',
25
119
  getSelection: state => state.selection,
120
+ disableUndo: false,
26
121
  protectedNodes: new Set('paragraph'),
27
122
  trackedOrigins: []
28
123
  },
124
+ staticKeys: ['disableUndo', 'protectedNodes', 'trackedOrigins'],
29
125
  defaultPriority: core.ExtensionPriority.High
30
126
  }), _dec2 = core.command({
31
127
  disableChaining: true,
32
- description: _ref => {
33
- var t = _ref.t;
128
+ description: _ref3 => {
129
+ var t = _ref3.t;
34
130
  return t(messages.ExtensionHistoryMessages.UNDO_DESCRIPTION);
35
131
  },
36
- label: _ref2 => {
37
- var t = _ref2.t;
132
+ label: _ref4 => {
133
+ var t = _ref4.t;
38
134
  return t(messages.ExtensionHistoryMessages.UNDO_LABEL);
39
135
  },
40
136
  icon: 'arrowGoBackFill'
41
137
  }), _dec3 = core.command({
42
138
  disableChaining: true,
43
- description: _ref3 => {
44
- var t = _ref3.t;
139
+ description: _ref5 => {
140
+ var t = _ref5.t;
45
141
  return t(messages.ExtensionHistoryMessages.REDO_DESCRIPTION);
46
142
  },
47
- label: _ref4 => {
48
- var t = _ref4.t;
143
+ label: _ref6 => {
144
+ var t = _ref6.t;
49
145
  return t(messages.ExtensionHistoryMessages.REDO_LABEL);
50
146
  },
51
147
  icon: 'arrowGoForwardFill'
@@ -70,12 +166,24 @@ var YjsExtension = (_dec = core.extension({
70
166
  return (_this$_provider = this._provider) !== null && _this$_provider !== void 0 ? _this$_provider : this._provider = getLazyValue(getProvider);
71
167
  }
72
168
 
169
+ getBinding() {
170
+ var state = this.store.getState();
171
+
172
+ var _ySyncPluginKey$getSt = yProsemirror.ySyncPluginKey.getState(state),
173
+ binding = _ySyncPluginKey$getSt.binding;
174
+
175
+ return binding;
176
+ }
177
+
73
178
  onView() {
74
179
  try {
180
+ var annotationStore = new YjsAnnotationStore(this.provider.doc, 'prosemirror', 'annotations', () => {
181
+ var _this$getBinding;
182
+
183
+ return (_this$getBinding = this.getBinding()) === null || _this$getBinding === void 0 ? void 0 : _this$getBinding.mapping;
184
+ });
75
185
  this.store.manager.getExtension(extensionAnnotation.AnnotationExtension).setOptions({
76
- getMap: () => this.provider.doc.getMap('annotations'),
77
- transformPosition: this.absolutePositionToRelativePosition.bind(this),
78
- transformPositionBeforeRender: this.relativePositionToAbsolutePosition.bind(this)
186
+ getStore: () => annotationStore
79
187
  });
80
188
 
81
189
  var handler = (_update, _origin, _doc, yjsTr) => {
@@ -107,21 +215,28 @@ var YjsExtension = (_dec = core.extension({
107
215
  cursorBuilder = _this$options.cursorBuilder,
108
216
  getSelection = _this$options.getSelection,
109
217
  cursorStateField = _this$options.cursorStateField,
218
+ disableUndo = _this$options.disableUndo,
110
219
  protectedNodes = _this$options.protectedNodes,
111
220
  trackedOrigins = _this$options.trackedOrigins;
112
221
  var yDoc = this.provider.doc;
113
222
  var type = yDoc.getXmlFragment('prosemirror');
114
- var undoManager = new yjs.UndoManager(type, {
115
- trackedOrigins: new Set([yProsemirror.ySyncPluginKey, ...trackedOrigins]),
116
- deleteFilter: item => yProsemirror.defaultDeleteFilter(item, protectedNodes)
117
- });
118
- return [yProsemirror.ySyncPlugin(type, syncPluginOptions), yProsemirror.yCursorPlugin(this.provider.awareness, {
223
+ var plugins = [yProsemirror.ySyncPlugin(type, syncPluginOptions), yProsemirror.yCursorPlugin(this.provider.awareness, {
119
224
  cursorBuilder,
120
225
  cursorStateField,
121
226
  getSelection
122
- }, cursorStateField), yProsemirror.yUndoPlugin({
123
- undoManager
124
- })];
227
+ }, cursorStateField)];
228
+
229
+ if (!disableUndo) {
230
+ var undoManager = new yjs.UndoManager(type, {
231
+ trackedOrigins: new Set([yProsemirror.ySyncPluginKey, ...trackedOrigins]),
232
+ deleteFilter: item => yProsemirror.defaultDeleteFilter(item, protectedNodes)
233
+ });
234
+ plugins.push(yProsemirror.yUndoPlugin({
235
+ undoManager
236
+ }));
237
+ }
238
+
239
+ return plugins;
125
240
  }
126
241
  /**
127
242
  * This managers the updates of the collaboration provider.
@@ -131,14 +246,7 @@ var YjsExtension = (_dec = core.extension({
131
246
  onSetOptions(props) {
132
247
  var changes = props.changes,
133
248
  pickChanged = props.pickChanged;
134
- var changedPluginOptions = pickChanged(['cursorBuilder', 'cursorStateField', 'getProvider', 'getSelection', 'syncPluginOptions', 'protectedNodes', 'trackedOrigins']);
135
-
136
- if (changes.protectedNodes.changed || changes.trackedOrigins.changed) {
137
- // Cannot change these, as we would need a new undo manager instance, and for that
138
- // we would need to unregister the previous instance from the document to avoid
139
- // memory leaks.
140
- throw new Error("Cannot change \"protectedNodes\" or \"trackedOrigins\" options");
141
- }
249
+ var changedPluginOptions = pickChanged(['cursorBuilder', 'cursorStateField', 'getProvider', 'getSelection', 'syncPluginOptions']);
142
250
 
143
251
  if (changes.getProvider.changed) {
144
252
  this._provider = undefined;
@@ -171,16 +279,19 @@ var YjsExtension = (_dec = core.extension({
171
279
  this._provider = undefined;
172
280
  }
173
281
  /**
174
- * Undo within a collaborative editor.
175
- *
176
- * This should be used instead of the built in `undo` command.
282
+ * Undo that last Yjs transaction(s)
177
283
  *
178
284
  * This command does **not** support chaining.
285
+ * This command is a no-op and always returns `false` when the `disableUndo` option is set.
179
286
  */
180
287
 
181
288
 
182
289
  yUndo() {
183
290
  return core.nonChainable(props => {
291
+ if (this.options.disableUndo) {
292
+ return false;
293
+ }
294
+
184
295
  var state = props.state,
185
296
  dispatch = props.dispatch;
186
297
  var undoManager = yProsemirror.yUndoPluginKey.getState(state).undoManager;
@@ -197,16 +308,19 @@ var YjsExtension = (_dec = core.extension({
197
308
  });
198
309
  }
199
310
  /**
200
- * Redo, within a collaborative editor.
201
- *
202
- * This should be used instead of the built in `redo` command.
311
+ * Redo the last transaction undone with a previous `yUndo` command.
203
312
  *
204
313
  * This command does **not** support chaining.
314
+ * This command is a no-op and always returns `false` when the `disableUndo` option is set.
205
315
  */
206
316
 
207
317
 
208
318
  yRedo() {
209
319
  return core.nonChainable(props => {
320
+ if (this.options.disableUndo) {
321
+ return false;
322
+ }
323
+
210
324
  var state = props.state,
211
325
  dispatch = props.dispatch;
212
326
  var undoManager = yProsemirror.yUndoPluginKey.getState(state).undoManager;
@@ -239,26 +353,6 @@ var YjsExtension = (_dec = core.extension({
239
353
  return this.yRedo()(props);
240
354
  }
241
355
 
242
- absolutePositionToRelativePosition(pos) {
243
- var state = this.store.getState();
244
-
245
- var _ySyncPluginKey$getSt = yProsemirror.ySyncPluginKey.getState(state),
246
- type = _ySyncPluginKey$getSt.type,
247
- binding = _ySyncPluginKey$getSt.binding;
248
-
249
- return yProsemirror.absolutePositionToRelativePosition(pos, type, binding.mapping);
250
- }
251
-
252
- relativePositionToAbsolutePosition(relPos) {
253
- var state = this.store.getState();
254
-
255
- var _ySyncPluginKey$getSt2 = yProsemirror.ySyncPluginKey.getState(state),
256
- type = _ySyncPluginKey$getSt2.type,
257
- binding = _ySyncPluginKey$getSt2.binding;
258
-
259
- return yProsemirror.relativePositionToAbsolutePosition(this.provider.doc, type, relPos, binding.mapping);
260
- }
261
-
262
356
  }, (_applyDecoratedDescriptor(_class2.prototype, "yUndo", [_dec2], Object.getOwnPropertyDescriptor(_class2.prototype, "yUndo"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "yRedo", [_dec3], Object.getOwnPropertyDescriptor(_class2.prototype, "yRedo"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "undoShortcut", [_dec4], Object.getOwnPropertyDescriptor(_class2.prototype, "undoShortcut"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "redoShortcut", [_dec5], Object.getOwnPropertyDescriptor(_class2.prototype, "redoShortcut"), _class2.prototype)), _class2)) || _class);
263
357
  /**
264
358
  * The default destroy provider method.
@@ -1,11 +1,105 @@
1
1
  import _applyDecoratedDescriptor from '@babel/runtime/helpers/esm/applyDecoratedDescriptor';
2
- import { defaultCursorBuilder, ySyncPluginKey, defaultDeleteFilter, ySyncPlugin, yCursorPlugin, yUndoPlugin, yUndoPluginKey, undo, redo, absolutePositionToRelativePosition, relativePositionToAbsolutePosition } from 'y-prosemirror';
3
- import { UndoManager } from 'yjs';
2
+ import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';
3
+ import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties';
4
+ import { defaultCursorBuilder, ySyncPluginKey, ySyncPlugin, yCursorPlugin, defaultDeleteFilter, yUndoPlugin, yUndoPluginKey, undo, redo, absolutePositionToRelativePosition, relativePositionToAbsolutePosition } from 'y-prosemirror';
5
+ import { UndoManager, transact } from 'yjs';
4
6
  import { extension, invariant, ErrorConstant, ExtensionPriority, command, keyBinding, NamedShortcut, PlainExtension, isFunction, isEmptyObject, nonChainable, convertCommand } from '@remirror/core';
5
7
  import { AnnotationExtension } from '@remirror/extension-annotation';
6
8
  import { ExtensionHistoryMessages } from '@remirror/messages';
7
9
 
8
10
  var _dec, _dec2, _dec3, _dec4, _dec5, _class, _class2;
11
+
12
+ var _excluded = ["from", "to"],
13
+ _excluded2 = ["from", "to"];
14
+
15
+ class YjsAnnotationStore {
16
+ constructor(doc, pmName, mapName, getMapping) {
17
+ this.doc = doc;
18
+ this.getMapping = getMapping;
19
+ this.type = doc.getXmlFragment(pmName);
20
+ this.map = doc.getMap(mapName);
21
+ }
22
+
23
+ addAnnotation(_ref) {
24
+ var from = _ref.from,
25
+ to = _ref.to,
26
+ data = _objectWithoutProperties(_ref, _excluded);
27
+
28
+ // XXX: Why is this cast needed?
29
+ var storedData = _objectSpread(_objectSpread({}, data), {}, {
30
+ from: this.absolutePositionToRelativePosition(from),
31
+ to: this.absolutePositionToRelativePosition(to)
32
+ });
33
+
34
+ this.map.set(data.id, storedData);
35
+ }
36
+
37
+ updateAnnotation(id, updateData) {
38
+ var existing = this.map.get(id);
39
+
40
+ if (!existing) {
41
+ return;
42
+ }
43
+
44
+ this.map.set(id, _objectSpread(_objectSpread({}, updateData), {}, {
45
+ from: existing.from,
46
+ to: existing.to
47
+ }));
48
+ }
49
+
50
+ removeAnnotations(ids) {
51
+ transact(this.doc, () => {
52
+ ids.forEach(id => this.map.delete(id));
53
+ });
54
+ }
55
+
56
+ setAnnotations(annotations) {
57
+ transact(this.doc, () => {
58
+ this.map.clear();
59
+ annotations.forEach(annotation => this.addAnnotation(annotation));
60
+ });
61
+ }
62
+
63
+ formatAnnotations() {
64
+ var result = [];
65
+ this.map.forEach(_ref2 => {
66
+ var relFrom = _ref2.from,
67
+ relTo = _ref2.to,
68
+ data = _objectWithoutProperties(_ref2, _excluded2);
69
+
70
+ var from = this.relativePositionToAbsolutePosition(relFrom);
71
+ var to = this.relativePositionToAbsolutePosition(relTo);
72
+
73
+ if (!from || !to) {
74
+ return;
75
+ } // XXX: Why is this cast needed?
76
+
77
+
78
+ result.push(_objectSpread(_objectSpread({}, data), {}, {
79
+ from,
80
+ to
81
+ }));
82
+ });
83
+ return result;
84
+ }
85
+
86
+ absolutePositionToRelativePosition(pos) {
87
+ var mapping = this.getMapping();
88
+ return absolutePositionToRelativePosition(pos, this.type, mapping);
89
+ }
90
+
91
+ relativePositionToAbsolutePosition(relPos) {
92
+ var mapping = this.getMapping();
93
+ return relativePositionToAbsolutePosition(this.doc, this.type, relPos, mapping);
94
+ }
95
+
96
+ }
97
+ /**
98
+ * The YJS extension is the recommended extension for creating a collaborative
99
+ * editor.
100
+ */
101
+
102
+
9
103
  var YjsExtension = (_dec = extension({
10
104
  defaultOptions: {
11
105
  getProvider: () => {
@@ -19,29 +113,31 @@ var YjsExtension = (_dec = extension({
19
113
  cursorBuilder: defaultCursorBuilder,
20
114
  cursorStateField: 'cursor',
21
115
  getSelection: state => state.selection,
116
+ disableUndo: false,
22
117
  protectedNodes: new Set('paragraph'),
23
118
  trackedOrigins: []
24
119
  },
120
+ staticKeys: ['disableUndo', 'protectedNodes', 'trackedOrigins'],
25
121
  defaultPriority: ExtensionPriority.High
26
122
  }), _dec2 = command({
27
123
  disableChaining: true,
28
- description: _ref => {
29
- var t = _ref.t;
124
+ description: _ref3 => {
125
+ var t = _ref3.t;
30
126
  return t(ExtensionHistoryMessages.UNDO_DESCRIPTION);
31
127
  },
32
- label: _ref2 => {
33
- var t = _ref2.t;
128
+ label: _ref4 => {
129
+ var t = _ref4.t;
34
130
  return t(ExtensionHistoryMessages.UNDO_LABEL);
35
131
  },
36
132
  icon: 'arrowGoBackFill'
37
133
  }), _dec3 = command({
38
134
  disableChaining: true,
39
- description: _ref3 => {
40
- var t = _ref3.t;
135
+ description: _ref5 => {
136
+ var t = _ref5.t;
41
137
  return t(ExtensionHistoryMessages.REDO_DESCRIPTION);
42
138
  },
43
- label: _ref4 => {
44
- var t = _ref4.t;
139
+ label: _ref6 => {
140
+ var t = _ref6.t;
45
141
  return t(ExtensionHistoryMessages.REDO_LABEL);
46
142
  },
47
143
  icon: 'arrowGoForwardFill'
@@ -66,12 +162,24 @@ var YjsExtension = (_dec = extension({
66
162
  return (_this$_provider = this._provider) !== null && _this$_provider !== void 0 ? _this$_provider : this._provider = getLazyValue(getProvider);
67
163
  }
68
164
 
165
+ getBinding() {
166
+ var state = this.store.getState();
167
+
168
+ var _ySyncPluginKey$getSt = ySyncPluginKey.getState(state),
169
+ binding = _ySyncPluginKey$getSt.binding;
170
+
171
+ return binding;
172
+ }
173
+
69
174
  onView() {
70
175
  try {
176
+ var annotationStore = new YjsAnnotationStore(this.provider.doc, 'prosemirror', 'annotations', () => {
177
+ var _this$getBinding;
178
+
179
+ return (_this$getBinding = this.getBinding()) === null || _this$getBinding === void 0 ? void 0 : _this$getBinding.mapping;
180
+ });
71
181
  this.store.manager.getExtension(AnnotationExtension).setOptions({
72
- getMap: () => this.provider.doc.getMap('annotations'),
73
- transformPosition: this.absolutePositionToRelativePosition.bind(this),
74
- transformPositionBeforeRender: this.relativePositionToAbsolutePosition.bind(this)
182
+ getStore: () => annotationStore
75
183
  });
76
184
 
77
185
  var handler = (_update, _origin, _doc, yjsTr) => {
@@ -103,21 +211,28 @@ var YjsExtension = (_dec = extension({
103
211
  cursorBuilder = _this$options.cursorBuilder,
104
212
  getSelection = _this$options.getSelection,
105
213
  cursorStateField = _this$options.cursorStateField,
214
+ disableUndo = _this$options.disableUndo,
106
215
  protectedNodes = _this$options.protectedNodes,
107
216
  trackedOrigins = _this$options.trackedOrigins;
108
217
  var yDoc = this.provider.doc;
109
218
  var type = yDoc.getXmlFragment('prosemirror');
110
- var undoManager = new UndoManager(type, {
111
- trackedOrigins: new Set([ySyncPluginKey, ...trackedOrigins]),
112
- deleteFilter: item => defaultDeleteFilter(item, protectedNodes)
113
- });
114
- return [ySyncPlugin(type, syncPluginOptions), yCursorPlugin(this.provider.awareness, {
219
+ var plugins = [ySyncPlugin(type, syncPluginOptions), yCursorPlugin(this.provider.awareness, {
115
220
  cursorBuilder,
116
221
  cursorStateField,
117
222
  getSelection
118
- }, cursorStateField), yUndoPlugin({
119
- undoManager
120
- })];
223
+ }, cursorStateField)];
224
+
225
+ if (!disableUndo) {
226
+ var undoManager = new UndoManager(type, {
227
+ trackedOrigins: new Set([ySyncPluginKey, ...trackedOrigins]),
228
+ deleteFilter: item => defaultDeleteFilter(item, protectedNodes)
229
+ });
230
+ plugins.push(yUndoPlugin({
231
+ undoManager
232
+ }));
233
+ }
234
+
235
+ return plugins;
121
236
  }
122
237
  /**
123
238
  * This managers the updates of the collaboration provider.
@@ -127,14 +242,7 @@ var YjsExtension = (_dec = extension({
127
242
  onSetOptions(props) {
128
243
  var changes = props.changes,
129
244
  pickChanged = props.pickChanged;
130
- var changedPluginOptions = pickChanged(['cursorBuilder', 'cursorStateField', 'getProvider', 'getSelection', 'syncPluginOptions', 'protectedNodes', 'trackedOrigins']);
131
-
132
- if (changes.protectedNodes.changed || changes.trackedOrigins.changed) {
133
- // Cannot change these, as we would need a new undo manager instance, and for that
134
- // we would need to unregister the previous instance from the document to avoid
135
- // memory leaks.
136
- throw new Error("Cannot change \"protectedNodes\" or \"trackedOrigins\" options");
137
- }
245
+ var changedPluginOptions = pickChanged(['cursorBuilder', 'cursorStateField', 'getProvider', 'getSelection', 'syncPluginOptions']);
138
246
 
139
247
  if (changes.getProvider.changed) {
140
248
  this._provider = undefined;
@@ -167,16 +275,19 @@ var YjsExtension = (_dec = extension({
167
275
  this._provider = undefined;
168
276
  }
169
277
  /**
170
- * Undo within a collaborative editor.
171
- *
172
- * This should be used instead of the built in `undo` command.
278
+ * Undo that last Yjs transaction(s)
173
279
  *
174
280
  * This command does **not** support chaining.
281
+ * This command is a no-op and always returns `false` when the `disableUndo` option is set.
175
282
  */
176
283
 
177
284
 
178
285
  yUndo() {
179
286
  return nonChainable(props => {
287
+ if (this.options.disableUndo) {
288
+ return false;
289
+ }
290
+
180
291
  var state = props.state,
181
292
  dispatch = props.dispatch;
182
293
  var undoManager = yUndoPluginKey.getState(state).undoManager;
@@ -193,16 +304,19 @@ var YjsExtension = (_dec = extension({
193
304
  });
194
305
  }
195
306
  /**
196
- * Redo, within a collaborative editor.
197
- *
198
- * This should be used instead of the built in `redo` command.
307
+ * Redo the last transaction undone with a previous `yUndo` command.
199
308
  *
200
309
  * This command does **not** support chaining.
310
+ * This command is a no-op and always returns `false` when the `disableUndo` option is set.
201
311
  */
202
312
 
203
313
 
204
314
  yRedo() {
205
315
  return nonChainable(props => {
316
+ if (this.options.disableUndo) {
317
+ return false;
318
+ }
319
+
206
320
  var state = props.state,
207
321
  dispatch = props.dispatch;
208
322
  var undoManager = yUndoPluginKey.getState(state).undoManager;
@@ -235,26 +349,6 @@ var YjsExtension = (_dec = extension({
235
349
  return this.yRedo()(props);
236
350
  }
237
351
 
238
- absolutePositionToRelativePosition(pos) {
239
- var state = this.store.getState();
240
-
241
- var _ySyncPluginKey$getSt = ySyncPluginKey.getState(state),
242
- type = _ySyncPluginKey$getSt.type,
243
- binding = _ySyncPluginKey$getSt.binding;
244
-
245
- return absolutePositionToRelativePosition(pos, type, binding.mapping);
246
- }
247
-
248
- relativePositionToAbsolutePosition(relPos) {
249
- var state = this.store.getState();
250
-
251
- var _ySyncPluginKey$getSt2 = ySyncPluginKey.getState(state),
252
- type = _ySyncPluginKey$getSt2.type,
253
- binding = _ySyncPluginKey$getSt2.binding;
254
-
255
- return relativePositionToAbsolutePosition(this.provider.doc, type, relPos, binding.mapping);
256
- }
257
-
258
352
  }, (_applyDecoratedDescriptor(_class2.prototype, "yUndo", [_dec2], Object.getOwnPropertyDescriptor(_class2.prototype, "yUndo"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "yRedo", [_dec3], Object.getOwnPropertyDescriptor(_class2.prototype, "yRedo"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "undoShortcut", [_dec4], Object.getOwnPropertyDescriptor(_class2.prototype, "undoShortcut"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "redoShortcut", [_dec5], Object.getOwnPropertyDescriptor(_class2.prototype, "redoShortcut"), _class2.prototype)), _class2)) || _class);
259
353
  /**
260
354
  * The default destroy provider method.