@atlaskit/prosemirror-collab 0.1.0
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.
- package/CHANGELOG.md +80 -0
- package/LICENSE.md +19 -0
- package/README.md +30 -0
- package/dist/cjs/collab.js +215 -0
- package/dist/cjs/version.json +5 -0
- package/dist/es2019/collab.js +190 -0
- package/dist/es2019/version.json +5 -0
- package/dist/esm/collab.js +197 -0
- package/dist/esm/version.json +5 -0
- package/dist/types/collab.d.ts +25 -0
- package/package.json +51 -0
- package/report.api.md +85 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
## 1.3.0 (2022-05-30)
|
|
2
|
+
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`883590cbe7d`](https://bitbucket.org/atlassian/atlassian-frontend/commits/883590cbe7d) - [ESS-2914] Forked the prosemirror-collab library to create a version that filters out analytics steps
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
|
|
13
|
+
### New features
|
|
14
|
+
|
|
15
|
+
Include TypeScript type declarations.
|
|
16
|
+
|
|
17
|
+
## 1.2.2 (2019-11-20)
|
|
18
|
+
|
|
19
|
+
### Bug fixes
|
|
20
|
+
|
|
21
|
+
Rename ES module files to use a .js extension, since Webpack gets confused by .mjs
|
|
22
|
+
|
|
23
|
+
## 1.2.1 (2019-11-19)
|
|
24
|
+
|
|
25
|
+
### Bug fixes
|
|
26
|
+
|
|
27
|
+
The file referred to in the package's `module` field now is compiled down to ES5.
|
|
28
|
+
|
|
29
|
+
## 1.2.0 (2019-11-08)
|
|
30
|
+
|
|
31
|
+
### New features
|
|
32
|
+
|
|
33
|
+
Add a `module` field to package json file.
|
|
34
|
+
|
|
35
|
+
## 1.1.2 (2019-05-29)
|
|
36
|
+
|
|
37
|
+
### Bug fixes
|
|
38
|
+
|
|
39
|
+
Fix an issue where in `mapSelectionBackward` mode, the plugin flipped the head and anchor of the selection, leading to selection glitches during collaborative editing.
|
|
40
|
+
|
|
41
|
+
## 1.1.1 (2018-10-09)
|
|
42
|
+
|
|
43
|
+
### Bug fixes
|
|
44
|
+
|
|
45
|
+
Fix issue where `mapSelectionBackward` didn't work because of a typo.
|
|
46
|
+
|
|
47
|
+
## 1.1.0 (2018-08-21)
|
|
48
|
+
|
|
49
|
+
### New features
|
|
50
|
+
|
|
51
|
+
[`receiveTransaction`](https://prosemirror.net/docs/ref/#collab.receiveTransaction) now supports a `mapSelectionBackward` option that makes it so that text selections are mapped to stay in place when remote changes insert content at their position.
|
|
52
|
+
|
|
53
|
+
## 0.19.0 (2017-03-16)
|
|
54
|
+
|
|
55
|
+
### New features
|
|
56
|
+
|
|
57
|
+
You can now use strings (as well as numbers) as client IDs (this already worked, but now the documentation reflects this).
|
|
58
|
+
|
|
59
|
+
## 0.18.0 (2017-02-24)
|
|
60
|
+
|
|
61
|
+
### New features
|
|
62
|
+
|
|
63
|
+
[`sendableSteps`](https://prosemirror.net/docs/ref/version/0.18.0.html#collab.sendableSteps) now also returns information about the original transactions that produced the steps.
|
|
64
|
+
|
|
65
|
+
## 0.11.0 (2016-09-21)
|
|
66
|
+
|
|
67
|
+
### Breaking changes
|
|
68
|
+
|
|
69
|
+
Moved into a separate module.
|
|
70
|
+
|
|
71
|
+
Interface [adjusted](https://prosemirror.net/docs/ref/version/0.11.0.html#collab) to work with the new
|
|
72
|
+
[plugin](https://prosemirror.net/docs/ref/version/0.11.0.html#state.Plugin) system.
|
|
73
|
+
|
|
74
|
+
### New features
|
|
75
|
+
|
|
76
|
+
When receiving changes, the module now
|
|
77
|
+
[generates](https://prosemirror.net/docs/ref/version/0.11.0.html#collab.receiveAction) a regular
|
|
78
|
+
[transform action](https://prosemirror.net/docs/ref/version/0.11.0.html#state.TransformAction) instead of hard-setting
|
|
79
|
+
the editor's document. This solves problematic corner cases for code
|
|
80
|
+
keeping track of the document by listening to transform actions.
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (C) 2015-2017 by Marijn Haverbeke <marijnh@gmail.com> and others
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
|
11
|
+
all copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
+
THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# prosemirror-collab
|
|
2
|
+
|
|
3
|
+
This is a fork of the ProseMirror Collab module: [GitHub](https://github.com/prosemirror/prosemirror-collab) [NPM](https://www.npmjs.com/package/prosemirror-collab)
|
|
4
|
+
|
|
5
|
+
[ [**WEBSITE**](https://prosemirror.net) | [**ISSUES**](https://github.com/prosemirror/prosemirror/issues) | [**FORUM**](https://discuss.prosemirror.net) | [**CHANGELOG**](https://github.com/ProseMirror/prosemirror-collab/blob/master/CHANGELOG.md) ]
|
|
6
|
+
|
|
7
|
+
This is a [core module](https://prosemirror.net/docs/ref/#collab) of [ProseMirror](https://prosemirror.net).
|
|
8
|
+
ProseMirror is a well-behaved rich semantic content editor based on
|
|
9
|
+
contentEditable, with support for collaborative editing and custom
|
|
10
|
+
document schemas.
|
|
11
|
+
|
|
12
|
+
This [module](https://prosemirror.net/docs/ref/#collab) implements a
|
|
13
|
+
plugin that helps track and merge changes for
|
|
14
|
+
[collaborative editing](https://prosemirror.net/docs/guide/#collab).
|
|
15
|
+
|
|
16
|
+
The [project page](https://prosemirror.net) has more information, a
|
|
17
|
+
number of [examples](https://prosemirror.net/examples/) and the
|
|
18
|
+
[documentation](https://prosemirror.net/docs/).
|
|
19
|
+
|
|
20
|
+
This code is released under an
|
|
21
|
+
[MIT license](https://github.com/prosemirror/prosemirror/tree/master/LICENSE).
|
|
22
|
+
There's a [forum](http://discuss.prosemirror.net) for general
|
|
23
|
+
discussion and support requests, and the
|
|
24
|
+
[Github bug tracker](https://github.com/prosemirror/prosemirror/issues)
|
|
25
|
+
is the place to report issues.
|
|
26
|
+
|
|
27
|
+
We aim to be an inclusive, welcoming community. To make that explicit,
|
|
28
|
+
we have a [code of
|
|
29
|
+
conduct](http://contributor-covenant.org/version/1/1/0/) that applies
|
|
30
|
+
to communication around the project.
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.collab = collab;
|
|
9
|
+
exports.getVersion = getVersion;
|
|
10
|
+
exports.rebaseSteps = rebaseSteps;
|
|
11
|
+
exports.receiveTransaction = receiveTransaction;
|
|
12
|
+
exports.sendableSteps = sendableSteps;
|
|
13
|
+
|
|
14
|
+
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
15
|
+
|
|
16
|
+
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
17
|
+
|
|
18
|
+
var _prosemirrorState = require("prosemirror-state");
|
|
19
|
+
|
|
20
|
+
var _steps = require("@atlaskit/adf-schema/steps");
|
|
21
|
+
|
|
22
|
+
var Rebaseable = /*#__PURE__*/(0, _createClass2.default)(function Rebaseable(step, inverted, origin) {
|
|
23
|
+
(0, _classCallCheck2.default)(this, Rebaseable);
|
|
24
|
+
this.step = step;
|
|
25
|
+
this.inverted = inverted;
|
|
26
|
+
this.origin = origin;
|
|
27
|
+
}); /// Undo a given set of steps, apply a set of other steps, and then
|
|
28
|
+
/// redo them @internal
|
|
29
|
+
|
|
30
|
+
function rebaseSteps(steps, over, transform) {
|
|
31
|
+
for (var i = steps.length - 1; i >= 0; i--) {
|
|
32
|
+
transform.step(steps[i].inverted);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
for (var _i = 0; _i < over.length; _i++) {
|
|
36
|
+
transform.step(over[_i]);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
var result = [];
|
|
40
|
+
|
|
41
|
+
for (var _i2 = 0, mapFrom = steps.length; _i2 < steps.length; _i2++) {
|
|
42
|
+
var mapped = steps[_i2].step.map(transform.mapping.slice(mapFrom));
|
|
43
|
+
|
|
44
|
+
mapFrom--;
|
|
45
|
+
|
|
46
|
+
if (mapped && !transform.maybeStep(mapped).failed) {
|
|
47
|
+
// Open ticket for setMirror https://github.com/ProseMirror/prosemirror/issues/869
|
|
48
|
+
// @ts-expect-error
|
|
49
|
+
transform.mapping.setMirror(mapFrom, transform.steps.length - 1);
|
|
50
|
+
result.push(new Rebaseable(mapped, mapped.invert(transform.docs[transform.docs.length - 1]), steps[_i2].origin));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return result;
|
|
55
|
+
} // This state field accumulates changes that have to be sent to the
|
|
56
|
+
// central authority in the collaborating group and makes it possible
|
|
57
|
+
// to integrate changes made by peers into our local document. It is
|
|
58
|
+
// defined by the plugin, and will be available as the `collab` field
|
|
59
|
+
// in the resulting editor state.
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
var CollabState = /*#__PURE__*/(0, _createClass2.default)(function CollabState( // The version number of the last update received from the central
|
|
63
|
+
// authority. Starts at 0 or the value of the `version` property
|
|
64
|
+
// in the option object, for the editor's value when the option
|
|
65
|
+
// was enabled.
|
|
66
|
+
version, // The local steps that havent been successfully sent to the
|
|
67
|
+
// server yet.
|
|
68
|
+
unconfirmed) {
|
|
69
|
+
(0, _classCallCheck2.default)(this, CollabState);
|
|
70
|
+
this.version = version;
|
|
71
|
+
this.unconfirmed = unconfirmed;
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
function unconfirmedFrom(transform) {
|
|
75
|
+
var result = [];
|
|
76
|
+
|
|
77
|
+
for (var i = 0; i < transform.steps.length; i++) {
|
|
78
|
+
// Filter out the analytics steps, they don't need to be sent to the collab service
|
|
79
|
+
if (transform.steps[i] instanceof _steps.AnalyticsStep) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
result.push(new Rebaseable(transform.steps[i], transform.steps[i].invert(transform.docs[i]), transform));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
var collabKey = new _prosemirrorState.PluginKey('collab');
|
|
90
|
+
|
|
91
|
+
/// Creates a plugin that enables the collaborative editing framework
|
|
92
|
+
/// for the editor.
|
|
93
|
+
function collab() {
|
|
94
|
+
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
95
|
+
var conf = {
|
|
96
|
+
version: config.version || 0,
|
|
97
|
+
clientID: // eslint-disable-next-line eqeqeq
|
|
98
|
+
config.clientID == null ? Math.floor(Math.random() * 0xffffffff) : config.clientID
|
|
99
|
+
};
|
|
100
|
+
return new _prosemirrorState.Plugin({
|
|
101
|
+
key: collabKey,
|
|
102
|
+
state: {
|
|
103
|
+
init: function init() {
|
|
104
|
+
return new CollabState(conf.version, []);
|
|
105
|
+
},
|
|
106
|
+
apply: function apply(tr, collab) {
|
|
107
|
+
var newState = tr.getMeta(collabKey);
|
|
108
|
+
|
|
109
|
+
if (newState) {
|
|
110
|
+
return newState;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (tr.docChanged) {
|
|
114
|
+
return new CollabState(collab.version, // @ts-expect-error
|
|
115
|
+
collab.unconfirmed.concat(unconfirmedFrom(tr)));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return collab;
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
// @ts-expect-error
|
|
122
|
+
config: conf,
|
|
123
|
+
// This is used to notify the history plugin to not merge steps,
|
|
124
|
+
// so that the history can be rebased.
|
|
125
|
+
historyPreserveItems: true
|
|
126
|
+
});
|
|
127
|
+
} /// Create a transaction that represents a set of new steps received from
|
|
128
|
+
/// the authority. Applying this transaction moves the state forward to
|
|
129
|
+
/// adjust to the authority's view of the document.
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
function receiveTransaction(state, steps, clientIDs) {
|
|
133
|
+
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
|
|
134
|
+
// Pushes a set of steps (received from the central authority) into
|
|
135
|
+
// the editor state (which should have the collab plugin enabled).
|
|
136
|
+
// Will recognize its own changes, and confirm unconfirmed steps as
|
|
137
|
+
// appropriate. Remaining unconfirmed steps will be rebased over
|
|
138
|
+
// remote steps.
|
|
139
|
+
var collabState = collabKey.getState(state);
|
|
140
|
+
var version = collabState.version + steps.length;
|
|
141
|
+
var ourID = collabKey.get(state).spec.config.clientID; // Find out which prefix of the steps originated with us
|
|
142
|
+
|
|
143
|
+
var ours = 0; // eslint-disable-next-line eqeqeq
|
|
144
|
+
|
|
145
|
+
while (ours < clientIDs.length && clientIDs[ours] == ourID) {
|
|
146
|
+
++ours;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
var unconfirmed = collabState.unconfirmed.slice(ours);
|
|
150
|
+
steps = ours ? steps.slice(ours) : steps; // If all steps originated with us, we're done.
|
|
151
|
+
|
|
152
|
+
if (!steps.length) {
|
|
153
|
+
return state.tr.setMeta(collabKey, new CollabState(version, unconfirmed));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
var nUnconfirmed = unconfirmed.length;
|
|
157
|
+
var tr = state.tr;
|
|
158
|
+
|
|
159
|
+
if (nUnconfirmed) {
|
|
160
|
+
unconfirmed = rebaseSteps(unconfirmed, steps, tr);
|
|
161
|
+
} else {
|
|
162
|
+
for (var i = 0; i < steps.length; i++) {
|
|
163
|
+
tr.step(steps[i]);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
unconfirmed = [];
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
var newCollabState = new CollabState(version, unconfirmed);
|
|
170
|
+
|
|
171
|
+
if (options && options.mapSelectionBackward && state.selection instanceof _prosemirrorState.TextSelection) {
|
|
172
|
+
tr.setSelection(_prosemirrorState.TextSelection.between(tr.doc.resolve(tr.mapping.map(state.selection.anchor, -1)), tr.doc.resolve(tr.mapping.map(state.selection.head, -1)), -1));
|
|
173
|
+
tr.updated &= ~1;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return tr.setMeta('rebased', nUnconfirmed).setMeta('addToHistory', false).setMeta(collabKey, newCollabState);
|
|
177
|
+
} /// Provides data describing the editor's unconfirmed steps, which need
|
|
178
|
+
/// to be sent to the central authority. Returns null when there is
|
|
179
|
+
/// nothing to send.
|
|
180
|
+
///
|
|
181
|
+
/// `origins` holds the _original_ transactions that produced each
|
|
182
|
+
/// steps. This can be useful for looking up time stamps and other
|
|
183
|
+
/// metadata for the steps, but note that the steps may have been
|
|
184
|
+
/// rebased, whereas the origin transactions are still the old,
|
|
185
|
+
/// unchanged objects.
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
function sendableSteps(state) {
|
|
189
|
+
var collabState = collabKey.getState(state); // eslint-disable-next-line eqeqeq
|
|
190
|
+
|
|
191
|
+
if (collabState.unconfirmed.length == 0) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
version: collabState.version,
|
|
197
|
+
steps: collabState.unconfirmed.map(function (s) {
|
|
198
|
+
return s.step;
|
|
199
|
+
}),
|
|
200
|
+
clientID: collabKey.get(state).spec.config.clientID,
|
|
201
|
+
|
|
202
|
+
get origins() {
|
|
203
|
+
return this._origins || (this._origins = collabState.unconfirmed.map(function (s) {
|
|
204
|
+
return s.origin;
|
|
205
|
+
}));
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
};
|
|
209
|
+
} /// Get the version up to which the collab plugin has synced with the
|
|
210
|
+
/// central authority.
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
function getVersion(state) {
|
|
214
|
+
return collabKey.getState(state).version;
|
|
215
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { Plugin, PluginKey, TextSelection } from 'prosemirror-state';
|
|
2
|
+
import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
|
|
3
|
+
|
|
4
|
+
class Rebaseable {
|
|
5
|
+
constructor(step, inverted, origin) {
|
|
6
|
+
this.step = step;
|
|
7
|
+
this.inverted = inverted;
|
|
8
|
+
this.origin = origin;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
} /// Undo a given set of steps, apply a set of other steps, and then
|
|
12
|
+
/// redo them @internal
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
export function rebaseSteps(steps, over, transform) {
|
|
16
|
+
for (let i = steps.length - 1; i >= 0; i--) {
|
|
17
|
+
transform.step(steps[i].inverted);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
for (let i = 0; i < over.length; i++) {
|
|
21
|
+
transform.step(over[i]);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let result = [];
|
|
25
|
+
|
|
26
|
+
for (let i = 0, mapFrom = steps.length; i < steps.length; i++) {
|
|
27
|
+
let mapped = steps[i].step.map(transform.mapping.slice(mapFrom));
|
|
28
|
+
mapFrom--;
|
|
29
|
+
|
|
30
|
+
if (mapped && !transform.maybeStep(mapped).failed) {
|
|
31
|
+
// Open ticket for setMirror https://github.com/ProseMirror/prosemirror/issues/869
|
|
32
|
+
// @ts-expect-error
|
|
33
|
+
transform.mapping.setMirror(mapFrom, transform.steps.length - 1);
|
|
34
|
+
result.push(new Rebaseable(mapped, mapped.invert(transform.docs[transform.docs.length - 1]), steps[i].origin));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return result;
|
|
39
|
+
} // This state field accumulates changes that have to be sent to the
|
|
40
|
+
// central authority in the collaborating group and makes it possible
|
|
41
|
+
// to integrate changes made by peers into our local document. It is
|
|
42
|
+
// defined by the plugin, and will be available as the `collab` field
|
|
43
|
+
// in the resulting editor state.
|
|
44
|
+
|
|
45
|
+
class CollabState {
|
|
46
|
+
constructor( // The version number of the last update received from the central
|
|
47
|
+
// authority. Starts at 0 or the value of the `version` property
|
|
48
|
+
// in the option object, for the editor's value when the option
|
|
49
|
+
// was enabled.
|
|
50
|
+
version, // The local steps that havent been successfully sent to the
|
|
51
|
+
// server yet.
|
|
52
|
+
unconfirmed) {
|
|
53
|
+
this.version = version;
|
|
54
|
+
this.unconfirmed = unconfirmed;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function unconfirmedFrom(transform) {
|
|
60
|
+
let result = [];
|
|
61
|
+
|
|
62
|
+
for (let i = 0; i < transform.steps.length; i++) {
|
|
63
|
+
// Filter out the analytics steps, they don't need to be sent to the collab service
|
|
64
|
+
if (transform.steps[i] instanceof AnalyticsStep) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
result.push(new Rebaseable(transform.steps[i], transform.steps[i].invert(transform.docs[i]), transform));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const collabKey = new PluginKey('collab');
|
|
75
|
+
/// Creates a plugin that enables the collaborative editing framework
|
|
76
|
+
/// for the editor.
|
|
77
|
+
export function collab(config = {}) {
|
|
78
|
+
let conf = {
|
|
79
|
+
version: config.version || 0,
|
|
80
|
+
clientID: // eslint-disable-next-line eqeqeq
|
|
81
|
+
config.clientID == null ? Math.floor(Math.random() * 0xffffffff) : config.clientID
|
|
82
|
+
};
|
|
83
|
+
return new Plugin({
|
|
84
|
+
key: collabKey,
|
|
85
|
+
state: {
|
|
86
|
+
init: () => new CollabState(conf.version, []),
|
|
87
|
+
|
|
88
|
+
apply(tr, collab) {
|
|
89
|
+
let newState = tr.getMeta(collabKey);
|
|
90
|
+
|
|
91
|
+
if (newState) {
|
|
92
|
+
return newState;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (tr.docChanged) {
|
|
96
|
+
return new CollabState(collab.version, // @ts-expect-error
|
|
97
|
+
collab.unconfirmed.concat(unconfirmedFrom(tr)));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return collab;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
},
|
|
104
|
+
// @ts-expect-error
|
|
105
|
+
config: conf,
|
|
106
|
+
// This is used to notify the history plugin to not merge steps,
|
|
107
|
+
// so that the history can be rebased.
|
|
108
|
+
historyPreserveItems: true
|
|
109
|
+
});
|
|
110
|
+
} /// Create a transaction that represents a set of new steps received from
|
|
111
|
+
/// the authority. Applying this transaction moves the state forward to
|
|
112
|
+
/// adjust to the authority's view of the document.
|
|
113
|
+
|
|
114
|
+
export function receiveTransaction(state, steps, clientIDs, options = {}) {
|
|
115
|
+
// Pushes a set of steps (received from the central authority) into
|
|
116
|
+
// the editor state (which should have the collab plugin enabled).
|
|
117
|
+
// Will recognize its own changes, and confirm unconfirmed steps as
|
|
118
|
+
// appropriate. Remaining unconfirmed steps will be rebased over
|
|
119
|
+
// remote steps.
|
|
120
|
+
let collabState = collabKey.getState(state);
|
|
121
|
+
let version = collabState.version + steps.length;
|
|
122
|
+
let ourID = collabKey.get(state).spec.config.clientID; // Find out which prefix of the steps originated with us
|
|
123
|
+
|
|
124
|
+
let ours = 0; // eslint-disable-next-line eqeqeq
|
|
125
|
+
|
|
126
|
+
while (ours < clientIDs.length && clientIDs[ours] == ourID) {
|
|
127
|
+
++ours;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
let unconfirmed = collabState.unconfirmed.slice(ours);
|
|
131
|
+
steps = ours ? steps.slice(ours) : steps; // If all steps originated with us, we're done.
|
|
132
|
+
|
|
133
|
+
if (!steps.length) {
|
|
134
|
+
return state.tr.setMeta(collabKey, new CollabState(version, unconfirmed));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
let nUnconfirmed = unconfirmed.length;
|
|
138
|
+
let tr = state.tr;
|
|
139
|
+
|
|
140
|
+
if (nUnconfirmed) {
|
|
141
|
+
unconfirmed = rebaseSteps(unconfirmed, steps, tr);
|
|
142
|
+
} else {
|
|
143
|
+
for (let i = 0; i < steps.length; i++) {
|
|
144
|
+
tr.step(steps[i]);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
unconfirmed = [];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
let newCollabState = new CollabState(version, unconfirmed);
|
|
151
|
+
|
|
152
|
+
if (options && options.mapSelectionBackward && state.selection instanceof TextSelection) {
|
|
153
|
+
tr.setSelection(TextSelection.between(tr.doc.resolve(tr.mapping.map(state.selection.anchor, -1)), tr.doc.resolve(tr.mapping.map(state.selection.head, -1)), -1));
|
|
154
|
+
tr.updated &= ~1;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return tr.setMeta('rebased', nUnconfirmed).setMeta('addToHistory', false).setMeta(collabKey, newCollabState);
|
|
158
|
+
} /// Provides data describing the editor's unconfirmed steps, which need
|
|
159
|
+
/// to be sent to the central authority. Returns null when there is
|
|
160
|
+
/// nothing to send.
|
|
161
|
+
///
|
|
162
|
+
/// `origins` holds the _original_ transactions that produced each
|
|
163
|
+
/// steps. This can be useful for looking up time stamps and other
|
|
164
|
+
/// metadata for the steps, but note that the steps may have been
|
|
165
|
+
/// rebased, whereas the origin transactions are still the old,
|
|
166
|
+
/// unchanged objects.
|
|
167
|
+
|
|
168
|
+
export function sendableSteps(state) {
|
|
169
|
+
let collabState = collabKey.getState(state); // eslint-disable-next-line eqeqeq
|
|
170
|
+
|
|
171
|
+
if (collabState.unconfirmed.length == 0) {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return {
|
|
176
|
+
version: collabState.version,
|
|
177
|
+
steps: collabState.unconfirmed.map(s => s.step),
|
|
178
|
+
clientID: collabKey.get(state).spec.config.clientID,
|
|
179
|
+
|
|
180
|
+
get origins() {
|
|
181
|
+
return this._origins || (this._origins = collabState.unconfirmed.map(s => s.origin));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
};
|
|
185
|
+
} /// Get the version up to which the collab plugin has synced with the
|
|
186
|
+
/// central authority.
|
|
187
|
+
|
|
188
|
+
export function getVersion(state) {
|
|
189
|
+
return collabKey.getState(state).version;
|
|
190
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import _createClass from "@babel/runtime/helpers/createClass";
|
|
2
|
+
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
3
|
+
import { Plugin, PluginKey, TextSelection } from 'prosemirror-state';
|
|
4
|
+
import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
|
|
5
|
+
|
|
6
|
+
var Rebaseable = /*#__PURE__*/_createClass(function Rebaseable(step, inverted, origin) {
|
|
7
|
+
_classCallCheck(this, Rebaseable);
|
|
8
|
+
|
|
9
|
+
this.step = step;
|
|
10
|
+
this.inverted = inverted;
|
|
11
|
+
this.origin = origin;
|
|
12
|
+
}); /// Undo a given set of steps, apply a set of other steps, and then
|
|
13
|
+
/// redo them @internal
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
export function rebaseSteps(steps, over, transform) {
|
|
17
|
+
for (var i = steps.length - 1; i >= 0; i--) {
|
|
18
|
+
transform.step(steps[i].inverted);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
for (var _i = 0; _i < over.length; _i++) {
|
|
22
|
+
transform.step(over[_i]);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
var result = [];
|
|
26
|
+
|
|
27
|
+
for (var _i2 = 0, mapFrom = steps.length; _i2 < steps.length; _i2++) {
|
|
28
|
+
var mapped = steps[_i2].step.map(transform.mapping.slice(mapFrom));
|
|
29
|
+
|
|
30
|
+
mapFrom--;
|
|
31
|
+
|
|
32
|
+
if (mapped && !transform.maybeStep(mapped).failed) {
|
|
33
|
+
// Open ticket for setMirror https://github.com/ProseMirror/prosemirror/issues/869
|
|
34
|
+
// @ts-expect-error
|
|
35
|
+
transform.mapping.setMirror(mapFrom, transform.steps.length - 1);
|
|
36
|
+
result.push(new Rebaseable(mapped, mapped.invert(transform.docs[transform.docs.length - 1]), steps[_i2].origin));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return result;
|
|
41
|
+
} // This state field accumulates changes that have to be sent to the
|
|
42
|
+
// central authority in the collaborating group and makes it possible
|
|
43
|
+
// to integrate changes made by peers into our local document. It is
|
|
44
|
+
// defined by the plugin, and will be available as the `collab` field
|
|
45
|
+
// in the resulting editor state.
|
|
46
|
+
|
|
47
|
+
var CollabState = /*#__PURE__*/_createClass(function CollabState( // The version number of the last update received from the central
|
|
48
|
+
// authority. Starts at 0 or the value of the `version` property
|
|
49
|
+
// in the option object, for the editor's value when the option
|
|
50
|
+
// was enabled.
|
|
51
|
+
version, // The local steps that havent been successfully sent to the
|
|
52
|
+
// server yet.
|
|
53
|
+
unconfirmed) {
|
|
54
|
+
_classCallCheck(this, CollabState);
|
|
55
|
+
|
|
56
|
+
this.version = version;
|
|
57
|
+
this.unconfirmed = unconfirmed;
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
function unconfirmedFrom(transform) {
|
|
61
|
+
var result = [];
|
|
62
|
+
|
|
63
|
+
for (var i = 0; i < transform.steps.length; i++) {
|
|
64
|
+
// Filter out the analytics steps, they don't need to be sent to the collab service
|
|
65
|
+
if (transform.steps[i] instanceof AnalyticsStep) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
result.push(new Rebaseable(transform.steps[i], transform.steps[i].invert(transform.docs[i]), transform));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
var collabKey = new PluginKey('collab');
|
|
76
|
+
/// Creates a plugin that enables the collaborative editing framework
|
|
77
|
+
/// for the editor.
|
|
78
|
+
export function collab() {
|
|
79
|
+
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
80
|
+
var conf = {
|
|
81
|
+
version: config.version || 0,
|
|
82
|
+
clientID: // eslint-disable-next-line eqeqeq
|
|
83
|
+
config.clientID == null ? Math.floor(Math.random() * 0xffffffff) : config.clientID
|
|
84
|
+
};
|
|
85
|
+
return new Plugin({
|
|
86
|
+
key: collabKey,
|
|
87
|
+
state: {
|
|
88
|
+
init: function init() {
|
|
89
|
+
return new CollabState(conf.version, []);
|
|
90
|
+
},
|
|
91
|
+
apply: function apply(tr, collab) {
|
|
92
|
+
var newState = tr.getMeta(collabKey);
|
|
93
|
+
|
|
94
|
+
if (newState) {
|
|
95
|
+
return newState;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (tr.docChanged) {
|
|
99
|
+
return new CollabState(collab.version, // @ts-expect-error
|
|
100
|
+
collab.unconfirmed.concat(unconfirmedFrom(tr)));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return collab;
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
// @ts-expect-error
|
|
107
|
+
config: conf,
|
|
108
|
+
// This is used to notify the history plugin to not merge steps,
|
|
109
|
+
// so that the history can be rebased.
|
|
110
|
+
historyPreserveItems: true
|
|
111
|
+
});
|
|
112
|
+
} /// Create a transaction that represents a set of new steps received from
|
|
113
|
+
/// the authority. Applying this transaction moves the state forward to
|
|
114
|
+
/// adjust to the authority's view of the document.
|
|
115
|
+
|
|
116
|
+
export function receiveTransaction(state, steps, clientIDs) {
|
|
117
|
+
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
|
|
118
|
+
// Pushes a set of steps (received from the central authority) into
|
|
119
|
+
// the editor state (which should have the collab plugin enabled).
|
|
120
|
+
// Will recognize its own changes, and confirm unconfirmed steps as
|
|
121
|
+
// appropriate. Remaining unconfirmed steps will be rebased over
|
|
122
|
+
// remote steps.
|
|
123
|
+
var collabState = collabKey.getState(state);
|
|
124
|
+
var version = collabState.version + steps.length;
|
|
125
|
+
var ourID = collabKey.get(state).spec.config.clientID; // Find out which prefix of the steps originated with us
|
|
126
|
+
|
|
127
|
+
var ours = 0; // eslint-disable-next-line eqeqeq
|
|
128
|
+
|
|
129
|
+
while (ours < clientIDs.length && clientIDs[ours] == ourID) {
|
|
130
|
+
++ours;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
var unconfirmed = collabState.unconfirmed.slice(ours);
|
|
134
|
+
steps = ours ? steps.slice(ours) : steps; // If all steps originated with us, we're done.
|
|
135
|
+
|
|
136
|
+
if (!steps.length) {
|
|
137
|
+
return state.tr.setMeta(collabKey, new CollabState(version, unconfirmed));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
var nUnconfirmed = unconfirmed.length;
|
|
141
|
+
var tr = state.tr;
|
|
142
|
+
|
|
143
|
+
if (nUnconfirmed) {
|
|
144
|
+
unconfirmed = rebaseSteps(unconfirmed, steps, tr);
|
|
145
|
+
} else {
|
|
146
|
+
for (var i = 0; i < steps.length; i++) {
|
|
147
|
+
tr.step(steps[i]);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
unconfirmed = [];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
var newCollabState = new CollabState(version, unconfirmed);
|
|
154
|
+
|
|
155
|
+
if (options && options.mapSelectionBackward && state.selection instanceof TextSelection) {
|
|
156
|
+
tr.setSelection(TextSelection.between(tr.doc.resolve(tr.mapping.map(state.selection.anchor, -1)), tr.doc.resolve(tr.mapping.map(state.selection.head, -1)), -1));
|
|
157
|
+
tr.updated &= ~1;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return tr.setMeta('rebased', nUnconfirmed).setMeta('addToHistory', false).setMeta(collabKey, newCollabState);
|
|
161
|
+
} /// Provides data describing the editor's unconfirmed steps, which need
|
|
162
|
+
/// to be sent to the central authority. Returns null when there is
|
|
163
|
+
/// nothing to send.
|
|
164
|
+
///
|
|
165
|
+
/// `origins` holds the _original_ transactions that produced each
|
|
166
|
+
/// steps. This can be useful for looking up time stamps and other
|
|
167
|
+
/// metadata for the steps, but note that the steps may have been
|
|
168
|
+
/// rebased, whereas the origin transactions are still the old,
|
|
169
|
+
/// unchanged objects.
|
|
170
|
+
|
|
171
|
+
export function sendableSteps(state) {
|
|
172
|
+
var collabState = collabKey.getState(state); // eslint-disable-next-line eqeqeq
|
|
173
|
+
|
|
174
|
+
if (collabState.unconfirmed.length == 0) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
version: collabState.version,
|
|
180
|
+
steps: collabState.unconfirmed.map(function (s) {
|
|
181
|
+
return s.step;
|
|
182
|
+
}),
|
|
183
|
+
clientID: collabKey.get(state).spec.config.clientID,
|
|
184
|
+
|
|
185
|
+
get origins() {
|
|
186
|
+
return this._origins || (this._origins = collabState.unconfirmed.map(function (s) {
|
|
187
|
+
return s.origin;
|
|
188
|
+
}));
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
};
|
|
192
|
+
} /// Get the version up to which the collab plugin has synced with the
|
|
193
|
+
/// central authority.
|
|
194
|
+
|
|
195
|
+
export function getVersion(state) {
|
|
196
|
+
return collabKey.getState(state).version;
|
|
197
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type EditorState, Plugin, type Transaction } from 'prosemirror-state';
|
|
2
|
+
import type { Step as ProseMirrorStep, Transform as ProseMirrorTransform } from 'prosemirror-transform';
|
|
3
|
+
declare class Rebaseable {
|
|
4
|
+
readonly step: ProseMirrorStep;
|
|
5
|
+
readonly inverted: ProseMirrorStep;
|
|
6
|
+
readonly origin: ProseMirrorTransform;
|
|
7
|
+
constructor(step: ProseMirrorStep, inverted: ProseMirrorStep, origin: ProseMirrorTransform);
|
|
8
|
+
}
|
|
9
|
+
export declare function rebaseSteps(steps: readonly Rebaseable[], over: readonly ProseMirrorStep[], transform: ProseMirrorTransform): Rebaseable[];
|
|
10
|
+
declare type CollabConfig = {
|
|
11
|
+
version?: number;
|
|
12
|
+
clientID?: number | string | null;
|
|
13
|
+
};
|
|
14
|
+
export declare function collab(config?: CollabConfig): Plugin;
|
|
15
|
+
export declare function receiveTransaction(state: EditorState, steps: readonly ProseMirrorStep[], clientIDs: readonly (string | number)[], options?: {
|
|
16
|
+
mapSelectionBackward?: boolean;
|
|
17
|
+
}): Transaction<any>;
|
|
18
|
+
export declare function sendableSteps(state: EditorState): {
|
|
19
|
+
version: number;
|
|
20
|
+
steps: readonly ProseMirrorStep[];
|
|
21
|
+
clientID: number | string;
|
|
22
|
+
origins: readonly Transaction[];
|
|
23
|
+
} | null;
|
|
24
|
+
export declare function getVersion(state: EditorState): number;
|
|
25
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atlaskit/prosemirror-collab",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Collaborative editing for ProseMirror - Atlassian Fork",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"registry": "https://registry.npmjs.org/"
|
|
7
|
+
},
|
|
8
|
+
"repository": "https://bitbucket.org/atlassian/atlassian-frontend",
|
|
9
|
+
"author": "Atlassian Pty Ltd",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"main": "dist/cjs/collab.js",
|
|
12
|
+
"module": "dist/esm/collab.js",
|
|
13
|
+
"module:es2019": "dist/es2019/collab.js",
|
|
14
|
+
"types": "dist/types/collab.d.ts",
|
|
15
|
+
"sideEffects": false,
|
|
16
|
+
"atlaskit:src": "src/collab.ts",
|
|
17
|
+
"atlassian": {
|
|
18
|
+
"team": "Editor Services",
|
|
19
|
+
"inPublicMirror": true,
|
|
20
|
+
"releaseModel": "scheduled"
|
|
21
|
+
},
|
|
22
|
+
"af:exports": {
|
|
23
|
+
".": "./src/collab.ts"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@atlaskit/adf-schema": "^25.1.0",
|
|
27
|
+
"@babel/runtime": "^7.0.0",
|
|
28
|
+
"prosemirror-state": "1.3.4"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@atlaskit/editor-test-helpers": "^18.0.0",
|
|
32
|
+
"@atlassian/atlassian-frontend-prettier-config-1.0.0": "npm:@atlassian/atlassian-frontend-prettier-config@1.0.0",
|
|
33
|
+
"@types/prosemirror-history": "^1.0.1",
|
|
34
|
+
"@types/prosemirror-model": "^1.11.0",
|
|
35
|
+
"@types/prosemirror-transform": "^1.1.0",
|
|
36
|
+
"prosemirror-history": "^1.1.3",
|
|
37
|
+
"prosemirror-model": "1.14.3",
|
|
38
|
+
"prosemirror-transform": "1.3.2"
|
|
39
|
+
},
|
|
40
|
+
"techstack": {
|
|
41
|
+
"@atlassian/frontend": {
|
|
42
|
+
"import-structure": [
|
|
43
|
+
"atlassian-conventions"
|
|
44
|
+
],
|
|
45
|
+
"circular-dependencies": [
|
|
46
|
+
"file-and-folder-level"
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"prettier": "@atlassian/atlassian-frontend-prettier-config-1.0.0"
|
|
51
|
+
}
|
package/report.api.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<!-- API Report Version: 2.3 -->
|
|
2
|
+
|
|
3
|
+
## API Report File for "@atlaskit/prosemirror-collab"
|
|
4
|
+
|
|
5
|
+
> Do not edit this file. This report is auto-generated using [API Extractor](https://api-extractor.com/).
|
|
6
|
+
> [Learn more about API reports](https://hello.atlassian.net/wiki/spaces/UR/pages/1825484529/Package+API+Reports)
|
|
7
|
+
|
|
8
|
+
### Table of contents
|
|
9
|
+
|
|
10
|
+
- [Main Entry Types](#main-entry-types)
|
|
11
|
+
- [Peer Dependencies](#peer-dependencies)
|
|
12
|
+
|
|
13
|
+
### Main Entry Types
|
|
14
|
+
|
|
15
|
+
<!--SECTION START: Main Entry Types-->
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { EditorState } from 'prosemirror-state';
|
|
19
|
+
import { Plugin as Plugin_2 } from 'prosemirror-state';
|
|
20
|
+
import type { Step } from 'prosemirror-transform';
|
|
21
|
+
import { Transaction } from 'prosemirror-state';
|
|
22
|
+
import type { Transform } from 'prosemirror-transform';
|
|
23
|
+
|
|
24
|
+
// @public (undocumented)
|
|
25
|
+
export function collab(config?: CollabConfig): Plugin_2;
|
|
26
|
+
|
|
27
|
+
// @public (undocumented)
|
|
28
|
+
type CollabConfig = {
|
|
29
|
+
version?: number;
|
|
30
|
+
clientID?: null | number | string;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// @public (undocumented)
|
|
34
|
+
export function getVersion(state: EditorState): number;
|
|
35
|
+
|
|
36
|
+
// @public (undocumented)
|
|
37
|
+
class Rebaseable {
|
|
38
|
+
constructor(step: Step, inverted: Step, origin: Transform);
|
|
39
|
+
// (undocumented)
|
|
40
|
+
readonly inverted: Step;
|
|
41
|
+
// (undocumented)
|
|
42
|
+
readonly origin: Transform;
|
|
43
|
+
// (undocumented)
|
|
44
|
+
readonly step: Step;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// @public (undocumented)
|
|
48
|
+
export function rebaseSteps(
|
|
49
|
+
steps: readonly Rebaseable[],
|
|
50
|
+
over: readonly Step[],
|
|
51
|
+
transform: Transform,
|
|
52
|
+
): Rebaseable[];
|
|
53
|
+
|
|
54
|
+
// @public (undocumented)
|
|
55
|
+
export function receiveTransaction(
|
|
56
|
+
state: EditorState,
|
|
57
|
+
steps: readonly Step[],
|
|
58
|
+
clientIDs: readonly (number | string)[],
|
|
59
|
+
options?: {
|
|
60
|
+
mapSelectionBackward?: boolean;
|
|
61
|
+
},
|
|
62
|
+
): Transaction<any>;
|
|
63
|
+
|
|
64
|
+
// @public (undocumented)
|
|
65
|
+
export function sendableSteps(state: EditorState): null | {
|
|
66
|
+
version: number;
|
|
67
|
+
steps: readonly Step[];
|
|
68
|
+
clientID: number | string;
|
|
69
|
+
origins: readonly Transaction[];
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// (No @packageDocumentation comment for this package)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
<!--SECTION END: Main Entry Types-->
|
|
76
|
+
|
|
77
|
+
### Peer Dependencies
|
|
78
|
+
|
|
79
|
+
<!--SECTION START: Peer Dependencies-->
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
<!--SECTION END: Peer Dependencies-->
|