@kerebron/extension-yjs 0.2.1 → 0.3.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/esm/editor/src/CoreEditor.d.ts +11 -5
- package/esm/editor/src/CoreEditor.d.ts.map +1 -1
- package/esm/editor/src/CoreEditor.js +62 -61
- package/esm/editor/src/DummyEditorView.d.ts +60 -0
- package/esm/editor/src/DummyEditorView.d.ts.map +1 -0
- package/esm/editor/src/DummyEditorView.js +277 -0
- package/esm/editor/src/Extension.d.ts +9 -9
- package/esm/editor/src/Extension.d.ts.map +1 -1
- package/esm/editor/src/Extension.js +2 -2
- package/esm/editor/src/ExtensionManager.d.ts +8 -7
- package/esm/editor/src/ExtensionManager.d.ts.map +1 -1
- package/esm/editor/src/ExtensionManager.js +58 -39
- package/esm/editor/src/Mark.d.ts +8 -6
- package/esm/editor/src/Mark.d.ts.map +1 -1
- package/esm/editor/src/Mark.js +8 -2
- package/esm/editor/src/Node.d.ts +14 -12
- package/esm/editor/src/Node.d.ts.map +1 -1
- package/esm/editor/src/Node.js +10 -4
- package/esm/editor/src/commands/CommandManager.d.ts +5 -9
- package/esm/editor/src/commands/CommandManager.d.ts.map +1 -1
- package/esm/editor/src/commands/CommandManager.js +7 -6
- package/esm/editor/src/commands/mod.d.ts +12 -6
- package/esm/editor/src/commands/mod.d.ts.map +1 -1
- package/esm/editor/src/commands/mod.js +0 -45
- package/esm/editor/src/mod.d.ts +1 -0
- package/esm/editor/src/mod.d.ts.map +1 -1
- package/esm/editor/src/mod.js +1 -0
- package/esm/editor/src/nodeToTreeString.d.ts.map +1 -1
- package/esm/editor/src/nodeToTreeString.js +23 -21
- package/esm/editor/src/plugins/input-rules/InputRulesPlugin.js +2 -2
- package/esm/editor/src/plugins/keymap/keymap.d.ts +11 -0
- package/esm/editor/src/plugins/keymap/keymap.d.ts.map +1 -0
- package/esm/editor/src/plugins/keymap/keymap.js +125 -0
- package/esm/editor/src/plugins/keymap/w3c-keyname.d.ts +4 -0
- package/esm/editor/src/plugins/keymap/w3c-keyname.d.ts.map +1 -0
- package/esm/editor/src/plugins/keymap/w3c-keyname.js +124 -0
- package/esm/editor/src/types.d.ts +10 -5
- package/esm/editor/src/types.d.ts.map +1 -1
- package/esm/editor/src/utilities/createNodeFromContent.d.ts +4 -3
- package/esm/editor/src/utilities/createNodeFromContent.d.ts.map +1 -1
- package/esm/editor/src/utilities/createNodeFromContent.js +4 -5
- package/esm/editor/src/utilities/getHtmlAttributes.d.ts +8 -3
- package/esm/editor/src/utilities/getHtmlAttributes.d.ts.map +1 -1
- package/esm/extension-yjs/src/ExtensionYjs.d.ts +5 -5
- package/esm/extension-yjs/src/ExtensionYjs.d.ts.map +1 -1
- package/esm/extension-yjs/src/ExtensionYjs.js +3 -2
- package/esm/extension-yjs/src/keys.d.ts +15 -0
- package/esm/extension-yjs/src/keys.d.ts.map +1 -0
- package/esm/extension-yjs/src/keys.js +13 -0
- package/esm/extension-yjs/src/lib.js +269 -0
- package/esm/extension-yjs/src/utils.d.ts +0 -3
- package/esm/extension-yjs/src/utils.d.ts.map +1 -1
- package/esm/extension-yjs/src/utils.js +0 -8
- package/esm/extension-yjs/src/yCursorPlugin.d.ts +3 -17
- package/esm/extension-yjs/src/yCursorPlugin.d.ts.map +1 -1
- package/esm/extension-yjs/src/yCursorPlugin.js +21 -13
- package/esm/extension-yjs/src/ySyncPlugin.d.ts +54 -91
- package/esm/extension-yjs/src/ySyncPlugin.d.ts.map +1 -1
- package/esm/extension-yjs/src/ySyncPlugin.js +99 -222
- package/esm/extension-yjs/src/yUndoPlugin.d.ts +21 -0
- package/esm/extension-yjs/src/yUndoPlugin.d.ts.map +1 -0
- package/esm/extension-yjs/src/yUndoPlugin.js +86 -0
- package/package.json +2 -4
- package/LICENSE +0 -23
- package/README.md +0 -57
- package/esm/package.json +0 -3
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import * as Y from 'yjs';
|
|
2
|
+
import { Fragment, Node } from 'prosemirror-model';
|
|
3
|
+
import * as error from 'lib0/error';
|
|
4
|
+
import * as map from 'lib0/map';
|
|
5
|
+
import * as eventloop from 'lib0/eventloop';
|
|
6
|
+
import { createEmptyMeta, createNodeFromYElement, updateYFragment, } from './ySyncPlugin.js';
|
|
7
|
+
import { ySyncPluginKey } from './keys.js';
|
|
8
|
+
/**
|
|
9
|
+
* Is null if no timeout is in progress.
|
|
10
|
+
* Is defined if a timeout is in progress.
|
|
11
|
+
* Maps from view
|
|
12
|
+
*/
|
|
13
|
+
let viewsToUpdate = null;
|
|
14
|
+
const updateMetas = () => {
|
|
15
|
+
const ups = viewsToUpdate;
|
|
16
|
+
viewsToUpdate = null;
|
|
17
|
+
ups.forEach((metas, view) => {
|
|
18
|
+
const tr = view.state.tr;
|
|
19
|
+
const syncState = ySyncPluginKey.getState(view.state);
|
|
20
|
+
if (syncState && syncState.binding && !syncState.binding.isDestroyed) {
|
|
21
|
+
metas.forEach((val, key) => {
|
|
22
|
+
tr.setMeta(key, val);
|
|
23
|
+
});
|
|
24
|
+
view.dispatch(tr);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
export const setMeta = (view, key, value) => {
|
|
29
|
+
if (!viewsToUpdate) {
|
|
30
|
+
viewsToUpdate = new Map();
|
|
31
|
+
eventloop.timeout(0, updateMetas);
|
|
32
|
+
}
|
|
33
|
+
map.setIfUndefined(viewsToUpdate, view, map.create).set(key, value);
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Transforms a Prosemirror based absolute position to a Yjs Cursor (relative position in the Yjs model).
|
|
37
|
+
*/
|
|
38
|
+
export const absolutePositionToRelativePosition = (pos, type, mapping) => {
|
|
39
|
+
if (pos === 0) {
|
|
40
|
+
// if the type is later populated, we want to retain the 0 position (hence assoc=-1)
|
|
41
|
+
return Y.createRelativePositionFromTypeIndex(type, 0, type.length === 0 ? -1 : 0);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* @type {any}
|
|
45
|
+
*/
|
|
46
|
+
let n = type._first === null
|
|
47
|
+
? null
|
|
48
|
+
: /** @type {Y.ContentType} */ (type._first.content).type;
|
|
49
|
+
while (n !== null && type !== n) {
|
|
50
|
+
if (n instanceof Y.XmlText) {
|
|
51
|
+
if (n._length >= pos) {
|
|
52
|
+
return Y.createRelativePositionFromTypeIndex(n, pos, type.length === 0 ? -1 : 0);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
pos -= n._length;
|
|
56
|
+
}
|
|
57
|
+
if (n._item !== null && n._item.next !== null) {
|
|
58
|
+
n = /** @type {Y.ContentType} */ (n._item.next.content).type;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
do {
|
|
62
|
+
n = n._item === null ? null : n._item.parent;
|
|
63
|
+
pos--;
|
|
64
|
+
} while (n !== type && n !== null && n._item !== null && n._item.next === null);
|
|
65
|
+
if (n !== null && n !== type) {
|
|
66
|
+
// @ts-gnore we know that n.next !== null because of above loop conditition
|
|
67
|
+
n = n._item === null
|
|
68
|
+
? null
|
|
69
|
+
: /** @type {Y.ContentType} */ ( /** @type Y.Item */(n._item.next)
|
|
70
|
+
.content).type;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
const pNodeSize =
|
|
76
|
+
/** @type {any} */ (mapping.get(n) || { nodeSize: 0 }).nodeSize;
|
|
77
|
+
if (n._first !== null && pos < pNodeSize) {
|
|
78
|
+
n = /** @type {Y.ContentType} */ (n._first.content).type;
|
|
79
|
+
pos--;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
if (pos === 1 && n._length === 0 && pNodeSize > 1) {
|
|
83
|
+
// edge case, should end in this paragraph
|
|
84
|
+
return new Y.RelativePosition(n._item === null ? null : n._item.id, n._item === null ? Y.findRootTypeKey(n) : null, null);
|
|
85
|
+
}
|
|
86
|
+
pos -= pNodeSize;
|
|
87
|
+
if (n._item !== null && n._item.next !== null) {
|
|
88
|
+
n = /** @type {Y.ContentType} */ (n._item.next.content).type;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
if (pos === 0) {
|
|
92
|
+
// set to end of n.parent
|
|
93
|
+
n = n._item === null ? n : n._item.parent;
|
|
94
|
+
return new Y.RelativePosition(n._item === null ? null : n._item.id, n._item === null ? Y.findRootTypeKey(n) : null, null);
|
|
95
|
+
}
|
|
96
|
+
do {
|
|
97
|
+
n = /** @type {Y.Item} */ (n._item).parent;
|
|
98
|
+
pos--;
|
|
99
|
+
} while (n !== type && /** @type {Y.Item} */ (n._item).next === null);
|
|
100
|
+
// if n is null at this point, we have an unexpected case
|
|
101
|
+
if (n !== type) {
|
|
102
|
+
// We know that n._item.next is defined because of above loop condition
|
|
103
|
+
n =
|
|
104
|
+
/** @type {Y.ContentType} */ ( /** @type {Y.Item} */( /** @type {Y.Item} */(n
|
|
105
|
+
._item).next).content).type;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (n === null) {
|
|
111
|
+
throw error.unexpectedCase();
|
|
112
|
+
}
|
|
113
|
+
if (pos === 0 && n.constructor !== Y.XmlText && n !== type) { // TODO: set to <= 0
|
|
114
|
+
return createRelativePosition(n._item.parent, n._item);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return Y.createRelativePositionFromTypeIndex(type, type._length, type.length === 0 ? -1 : 0);
|
|
118
|
+
};
|
|
119
|
+
const createRelativePosition = (type, item) => {
|
|
120
|
+
let typeid = null;
|
|
121
|
+
let tname = null;
|
|
122
|
+
if (type._item === null) {
|
|
123
|
+
tname = Y.findRootTypeKey(type);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
typeid = Y.createID(type._item.id.client, type._item.id.clock);
|
|
127
|
+
}
|
|
128
|
+
return new Y.RelativePosition(typeid, tname, item.id);
|
|
129
|
+
};
|
|
130
|
+
export const relativePositionToAbsolutePosition = (y, documentType, relPos, mapping) => {
|
|
131
|
+
const decodedPos = Y.createAbsolutePositionFromRelativePosition(relPos, y);
|
|
132
|
+
if (decodedPos === null ||
|
|
133
|
+
(decodedPos.type !== documentType &&
|
|
134
|
+
!Y.isParentOf(documentType, decodedPos.type._item))) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
let type = decodedPos.type;
|
|
138
|
+
let pos = 0;
|
|
139
|
+
if (type.constructor === Y.XmlText) {
|
|
140
|
+
pos = decodedPos.index;
|
|
141
|
+
}
|
|
142
|
+
else if (type._item === null || !type._item.deleted) {
|
|
143
|
+
let n = type._first;
|
|
144
|
+
let i = 0;
|
|
145
|
+
while (i < type._length && i < decodedPos.index && n !== null) {
|
|
146
|
+
if (!n.deleted) {
|
|
147
|
+
const t = n.content.type;
|
|
148
|
+
i++;
|
|
149
|
+
if (t instanceof Y.XmlText) {
|
|
150
|
+
pos += t._length;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
pos += /** @type {any} */ (mapping.get(t)).nodeSize;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
n = n.right;
|
|
157
|
+
}
|
|
158
|
+
pos += 1; // increase because we go out of n
|
|
159
|
+
}
|
|
160
|
+
while (type !== documentType && type._item !== null) {
|
|
161
|
+
// @ts-ignore
|
|
162
|
+
const parent = type._item.parent;
|
|
163
|
+
// @ts-ignore
|
|
164
|
+
if (parent._item === null || !parent._item.deleted) {
|
|
165
|
+
pos += 1; // the start tag
|
|
166
|
+
let n = /** @type {Y.AbstractType} */ (parent)._first;
|
|
167
|
+
// now iterate until we found type
|
|
168
|
+
while (n !== null) {
|
|
169
|
+
const contentType = /** @type {Y.ContentType} */ (n.content).type;
|
|
170
|
+
if (contentType === type) {
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
if (!n.deleted) {
|
|
174
|
+
if (contentType instanceof Y.XmlText) {
|
|
175
|
+
pos += contentType._length;
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
pos += /** @type {any} */ (mapping.get(contentType)).nodeSize;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
n = n.right;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
type = /** @type {Y.AbstractType} */ (parent);
|
|
185
|
+
}
|
|
186
|
+
return pos - 1; // we don't count the most outer tag, because it is a fragment
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* Utility function for converting an Y.Fragment to a ProseMirror fragment.
|
|
190
|
+
*/
|
|
191
|
+
export const yXmlFragmentToProseMirrorFragment = (yXmlFragment, schema) => {
|
|
192
|
+
const fragmentContent = yXmlFragment.toArray().map((t) => createNodeFromYElement(
|
|
193
|
+
/** @type {Y.XmlElement} */ (t), schema, createEmptyMeta())).filter((n) => n !== null);
|
|
194
|
+
return Fragment.fromArray(fragmentContent);
|
|
195
|
+
};
|
|
196
|
+
/**
|
|
197
|
+
* Utility function for converting an Y.Fragment to a ProseMirror node.
|
|
198
|
+
*/
|
|
199
|
+
export const yXmlFragmentToProseMirrorRootNode = (yXmlFragment, schema) => schema.topNodeType.create(null, yXmlFragmentToProseMirrorFragment(yXmlFragment, schema));
|
|
200
|
+
/**
|
|
201
|
+
* The initial ProseMirror content should be supplied by Yjs. This function transforms a Y.Fragment
|
|
202
|
+
* to a ProseMirror Doc node and creates a mapping that is used by the sync plugin.
|
|
203
|
+
*
|
|
204
|
+
* @todo deprecate mapping property
|
|
205
|
+
*/
|
|
206
|
+
export const initProseMirrorDoc = (yXmlFragment, schema) => {
|
|
207
|
+
const meta = createEmptyMeta();
|
|
208
|
+
const fragmentContent = yXmlFragment.toArray().map((t) => createNodeFromYElement(
|
|
209
|
+
/** @type {Y.XmlElement} */ (t), schema, meta)).filter((n) => n !== null);
|
|
210
|
+
const doc = schema.topNodeType.create(null, Fragment.fromArray(fragmentContent));
|
|
211
|
+
return { doc, meta, mapping: meta.mapping };
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
* Utility method to convert a Prosemirror Doc Node into a Y.Doc.
|
|
215
|
+
*
|
|
216
|
+
* This can be used when importing existing content to Y.Doc for the first time,
|
|
217
|
+
* note that this should not be used to rehydrate a Y.Doc from a database once
|
|
218
|
+
* collaboration has begun as all history will be lost
|
|
219
|
+
*/
|
|
220
|
+
export function prosemirrorToYDoc(doc, xmlFragment = 'prosemirror') {
|
|
221
|
+
const ydoc = new Y.Doc();
|
|
222
|
+
const type =
|
|
223
|
+
/** @type {Y.XmlFragment} */ (ydoc.get(xmlFragment, Y.XmlFragment));
|
|
224
|
+
if (!type.doc) {
|
|
225
|
+
return ydoc;
|
|
226
|
+
}
|
|
227
|
+
prosemirrorToYXmlFragment(doc, type);
|
|
228
|
+
return type.doc;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Utility method to update an empty Y.XmlFragment with content from a Prosemirror Doc Node.
|
|
232
|
+
*
|
|
233
|
+
* This can be used when importing existing content to Y.Doc for the first time,
|
|
234
|
+
* note that this should not be used to rehydrate a Y.Doc from a database once
|
|
235
|
+
* collaboration has begun as all history will be lost
|
|
236
|
+
*
|
|
237
|
+
* Note: The Y.XmlFragment does not need to be part of a Y.Doc document at the time that this
|
|
238
|
+
* method is called, but it must be added before any other operations are performed on it.
|
|
239
|
+
*/
|
|
240
|
+
export function prosemirrorToYXmlFragment(doc, xmlFragment) {
|
|
241
|
+
const type = xmlFragment || new Y.XmlFragment();
|
|
242
|
+
const ydoc = type.doc
|
|
243
|
+
? type.doc
|
|
244
|
+
: { transact: (transaction) => transaction(undefined) };
|
|
245
|
+
updateYFragment(ydoc, type, doc, { mapping: new Map(), isOMark: new Map() });
|
|
246
|
+
return type;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Utility method to convert Prosemirror compatible JSON into a Y.Doc.
|
|
250
|
+
*
|
|
251
|
+
* This can be used when importing existing content to Y.Doc for the first time,
|
|
252
|
+
* note that this should not be used to rehydrate a Y.Doc from a database once
|
|
253
|
+
* collaboration has begun as all history will be lost
|
|
254
|
+
*/
|
|
255
|
+
export function prosemirrorJSONToYDoc(schema, state, xmlFragment = 'prosemirror') {
|
|
256
|
+
const doc = Node.fromJSON(schema, state);
|
|
257
|
+
return prosemirrorToYDoc(doc, xmlFragment);
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Utility method to convert Prosemirror compatible JSON to a Y.XmlFragment
|
|
261
|
+
*
|
|
262
|
+
* This can be used when importing existing content to Y.Doc for the first time,
|
|
263
|
+
* note that this should not be used to rehydrate a Y.Doc from a database once
|
|
264
|
+
* collaboration has begun as all history will be lost
|
|
265
|
+
*/
|
|
266
|
+
export function prosemirrorJSONToYXmlFragment(schema, state, xmlFragment) {
|
|
267
|
+
const doc = Node.fromJSON(schema, state);
|
|
268
|
+
return prosemirrorToYXmlFragment(doc, xmlFragment);
|
|
269
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/extension-yjs/src/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/extension-yjs/src/utils.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,UAAU,GAAI,MAAM,GAAG,WAC0B,CAAC"}
|
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import * as sha256 from 'lib0/hash/sha256';
|
|
2
2
|
import * as buf from 'lib0/buffer';
|
|
3
|
-
/**
|
|
4
|
-
* Custom function to transform sha256 hash to N byte
|
|
5
|
-
*
|
|
6
|
-
* @param {Uint8Array} digest
|
|
7
|
-
*/
|
|
8
3
|
const _convolute = (digest) => {
|
|
9
4
|
const N = 6;
|
|
10
5
|
for (let i = N; i < digest.length; i++) {
|
|
@@ -12,7 +7,4 @@ const _convolute = (digest) => {
|
|
|
12
7
|
}
|
|
13
8
|
return digest.slice(0, N);
|
|
14
9
|
};
|
|
15
|
-
/**
|
|
16
|
-
* @param {any} json
|
|
17
|
-
*/
|
|
18
10
|
export const hashOfJSON = (json) => buf.toBase64(_convolute(sha256.digest(buf.encodeAny(json))));
|
|
@@ -1,32 +1,18 @@
|
|
|
1
1
|
import * as awarenessProtocol from 'y-protocols/awareness';
|
|
2
2
|
import { Plugin } from 'prosemirror-state';
|
|
3
|
-
import { DecorationAttrs } from 'prosemirror-view';
|
|
3
|
+
import { type DecorationAttrs } from 'prosemirror-view';
|
|
4
4
|
/**
|
|
5
5
|
* Default awareness state filter
|
|
6
|
-
*
|
|
7
|
-
* @param {number} currentClientId current client id
|
|
8
|
-
* @param {number} userClientId user client id
|
|
9
|
-
* @param {any} _user user data
|
|
10
|
-
* @return {boolean}
|
|
11
6
|
*/
|
|
12
7
|
export declare const defaultAwarenessStateFilter: (currentClientId: number, userClientId: number, _user: any) => boolean;
|
|
13
8
|
/**
|
|
14
9
|
* Default generator for a cursor element
|
|
15
|
-
*
|
|
16
|
-
* @param {any} user user data
|
|
17
|
-
* @return {HTMLElement}
|
|
18
10
|
*/
|
|
19
|
-
export declare const defaultCursorBuilder: (user: any) =>
|
|
11
|
+
export declare const defaultCursorBuilder: (user: any) => HTMLElement;
|
|
20
12
|
/**
|
|
21
13
|
* Default generator for the selection attributes
|
|
22
|
-
*
|
|
23
|
-
* @param {any} user user data
|
|
24
|
-
* @return {import('prosemirror-view').DecorationAttrs}
|
|
25
14
|
*/
|
|
26
|
-
export declare const defaultSelectionBuilder: (user: any) =>
|
|
27
|
-
style: string;
|
|
28
|
-
class: string;
|
|
29
|
-
};
|
|
15
|
+
export declare const defaultSelectionBuilder: (user: any) => DecorationAttrs;
|
|
30
16
|
export declare const createDecorations: (state: any, awareness: awarenessProtocol.Awareness, awarenessFilter: (arg0: number, arg1: number, arg2: any) => boolean, createCursor: (user: {
|
|
31
17
|
name: string;
|
|
32
18
|
color: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yCursorPlugin.d.ts","sourceRoot":"","sources":["../../../src/extension-yjs/src/yCursorPlugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,iBAAiB,MAAM,uBAAuB,CAAC;AAG3D,OAAO,EAAe,MAAM,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"yCursorPlugin.d.ts","sourceRoot":"","sources":["../../../src/extension-yjs/src/yCursorPlugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,iBAAiB,MAAM,uBAAuB,CAAC;AAG3D,OAAO,EAAe,MAAM,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAYxD;;GAEG;AACH,eAAO,MAAM,2BAA2B,GACtC,iBAAiB,MAAM,EACvB,cAAc,MAAM,EACpB,OAAO,GAAG,KACT,OAA2C,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAI,MAAM,GAAG,KAAG,WAahD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,MAAM,GAAG,KAAG,eAKnD,CAAC;AAIF,eAAO,MAAM,iBAAiB,GAC5B,OAAO,GAAG,EACV,WAAW,iBAAiB,CAAC,SAAS,EACtC,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,OAAO,EACnE,cAAc,CACZ,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EACrC,QAAQ,EAAE,MAAM,KACb,OAAO,EACZ,iBAAiB,CACf,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EACrC,QAAQ,EAAE,MAAM,KACb,eAAe,KACnB,GA6DF,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,WAAW,iBAAiB,CAAC,SAAS,EACtC,2EAKG;IACD,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC;IACpE,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,KAAK,WAAW,CAAC;IAC7D,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,KAAK,eAAe,CAAC;IACpE,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,GAAG,CAAC;CAC9B,EACN,mBAAkB,MAAiB,gBAsJpC,CAAC"}
|
|
@@ -1,23 +1,15 @@
|
|
|
1
1
|
import * as Y from 'yjs';
|
|
2
2
|
import { Decoration, DecorationSet } from 'prosemirror-view'; // eslint-disable-line
|
|
3
3
|
import { Plugin } from 'prosemirror-state'; // eslint-disable-line
|
|
4
|
-
import { absolutePositionToRelativePosition, relativePositionToAbsolutePosition, setMeta, } from '
|
|
5
|
-
import { yCursorPluginKey, ySyncPluginKey } from '
|
|
4
|
+
import { absolutePositionToRelativePosition, relativePositionToAbsolutePosition, setMeta, } from './lib.js';
|
|
5
|
+
import { yCursorPluginKey, ySyncPluginKey } from './keys.js';
|
|
6
6
|
import * as math from 'lib0/math';
|
|
7
7
|
/**
|
|
8
8
|
* Default awareness state filter
|
|
9
|
-
*
|
|
10
|
-
* @param {number} currentClientId current client id
|
|
11
|
-
* @param {number} userClientId user client id
|
|
12
|
-
* @param {any} _user user data
|
|
13
|
-
* @return {boolean}
|
|
14
9
|
*/
|
|
15
10
|
export const defaultAwarenessStateFilter = (currentClientId, userClientId, _user) => currentClientId !== userClientId;
|
|
16
11
|
/**
|
|
17
12
|
* Default generator for a cursor element
|
|
18
|
-
*
|
|
19
|
-
* @param {any} user user data
|
|
20
|
-
* @return {HTMLElement}
|
|
21
13
|
*/
|
|
22
14
|
export const defaultCursorBuilder = (user) => {
|
|
23
15
|
const cursor = document.createElement('span');
|
|
@@ -35,9 +27,6 @@ export const defaultCursorBuilder = (user) => {
|
|
|
35
27
|
};
|
|
36
28
|
/**
|
|
37
29
|
* Default generator for the selection attributes
|
|
38
|
-
*
|
|
39
|
-
* @param {any} user user data
|
|
40
|
-
* @return {import('prosemirror-view').DecorationAttrs}
|
|
41
30
|
*/
|
|
42
31
|
export const defaultSelectionBuilder = (user) => {
|
|
43
32
|
return {
|
|
@@ -165,5 +154,24 @@ export const yCursorPlugin = (awareness, { awarenessStateFilter = defaultAwarene
|
|
|
165
154
|
},
|
|
166
155
|
};
|
|
167
156
|
},
|
|
157
|
+
updateCursorInfo(state) {
|
|
158
|
+
const ystate = ySyncPluginKey.getState(state);
|
|
159
|
+
// @note We make implicit checks when checking for the cursor property
|
|
160
|
+
const current = awareness.getLocalState() || {};
|
|
161
|
+
const selection = getSelection(state);
|
|
162
|
+
const anchor = absolutePositionToRelativePosition(selection.anchor, ystate.type, ystate.binding.mapping);
|
|
163
|
+
const head = absolutePositionToRelativePosition(selection.head, ystate.type, ystate.binding.mapping);
|
|
164
|
+
if (current.cursor == null ||
|
|
165
|
+
!Y.compareRelativePositions(Y.createRelativePositionFromJSON(current.cursor.anchor), anchor) ||
|
|
166
|
+
!Y.compareRelativePositions(Y.createRelativePositionFromJSON(current.cursor.head), head)) {
|
|
167
|
+
awareness.setLocalStateField(cursorStateField, {
|
|
168
|
+
anchor,
|
|
169
|
+
head,
|
|
170
|
+
});
|
|
171
|
+
awareness.setLocalStateField('cm-cursor', null);
|
|
172
|
+
}
|
|
173
|
+
// delete cursor information if current cursor information is owned by this editor binding
|
|
174
|
+
// awareness.setLocalStateField(cursorStateField, null);
|
|
175
|
+
},
|
|
168
176
|
});
|
|
169
177
|
};
|
|
@@ -1,46 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
*
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
import * as Y from 'yjs';
|
|
2
|
+
import * as PModel from 'prosemirror-model';
|
|
3
|
+
import { Transaction } from 'prosemirror-state';
|
|
4
|
+
import { MarkType, Node, Schema } from 'prosemirror-model';
|
|
5
|
+
import { EditorState } from 'prosemirror-state';
|
|
6
|
+
interface BindingMetadata {
|
|
7
|
+
mapping: ProsemirrorMapping;
|
|
8
|
+
isOMark: Map<MarkType, boolean>;
|
|
9
|
+
}
|
|
10
|
+
export declare const createEmptyMeta: () => BindingMetadata;
|
|
11
|
+
export declare const isVisible: (item: Y.Item, snapshot: Y.Snapshot) => boolean;
|
|
12
|
+
type ProsemirrorMapping = Map<Y.AbstractType<any>, PModel.Node | Array<PModel.Node>>;
|
|
13
|
+
interface ColorDef {
|
|
14
|
+
light: string;
|
|
15
|
+
dark: string;
|
|
16
|
+
}
|
|
17
|
+
interface YSyncOpts {
|
|
18
|
+
colors?: Array<ColorDef>;
|
|
19
|
+
colorMapping?: Map<string, ColorDef>;
|
|
20
|
+
permanentUserData?: Y.PermanentUserData | null;
|
|
21
|
+
mapping?: ProsemirrorMapping;
|
|
22
|
+
onFirstRender?: Function;
|
|
23
|
+
}
|
|
22
24
|
/**
|
|
23
25
|
* This plugin listens to changes in prosemirror view and keeps yXmlState and view in sync.
|
|
24
26
|
*
|
|
25
27
|
* This plugin also keeps references to the type and the shared document so other plugins can access it.
|
|
26
|
-
* @param {Y.XmlFragment} yXmlFragment
|
|
27
|
-
* @param {YSyncOpts} opts
|
|
28
|
-
* @return {any} Returns a prosemirror plugin that binds to this type
|
|
29
28
|
*/
|
|
30
|
-
export declare const ySyncPlugin: (yXmlFragment:
|
|
31
|
-
|
|
32
|
-
light: string;
|
|
33
|
-
dark: string;
|
|
34
|
-
}[] | undefined;
|
|
35
|
-
colorMapping?: Map<any, any> | undefined;
|
|
36
|
-
permanentUserData?: null | undefined;
|
|
37
|
-
onFirstRender?: (() => void) | undefined;
|
|
38
|
-
}) => Plugin<any>;
|
|
39
|
-
/**
|
|
40
|
-
* @param {ProsemirrorBinding} pmbinding
|
|
41
|
-
* @param {import('prosemirror-state').EditorState} state
|
|
42
|
-
*/
|
|
43
|
-
export declare const getRelativeSelection: (pmbinding: any, state: any) => {
|
|
29
|
+
export declare const ySyncPlugin: (yXmlFragment: Y.XmlFragment, { colors, colorMapping, permanentUserData, onFirstRender, mapping, }?: YSyncOpts) => any;
|
|
30
|
+
export declare const getRelativeSelection: (pmbinding: ProsemirrorBinding, state: EditorState) => {
|
|
44
31
|
type: any;
|
|
45
32
|
anchor: any;
|
|
46
33
|
head: any;
|
|
@@ -51,70 +38,48 @@ export declare const getRelativeSelection: (pmbinding: any, state: any) => {
|
|
|
51
38
|
* @protected
|
|
52
39
|
*/
|
|
53
40
|
export declare class ProsemirrorBinding {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
41
|
+
doc: Y.Doc;
|
|
42
|
+
private type;
|
|
43
|
+
private mux;
|
|
44
|
+
private prosemirrorView;
|
|
45
|
+
private isOMark;
|
|
46
|
+
private _observeFunction;
|
|
47
|
+
private mapping;
|
|
48
|
+
private _beforeTransactionSelection;
|
|
49
|
+
private beforeAllTransactions;
|
|
50
|
+
private afterAllTransactions;
|
|
51
|
+
private _domSelectionInView;
|
|
52
|
+
get beforeTransactionSelection(): null;
|
|
53
|
+
set beforeTransactionSelection(value: null);
|
|
54
|
+
constructor(yXmlFragment: Y.XmlFragment, mapping?: ProsemirrorMapping);
|
|
59
55
|
/**
|
|
60
56
|
* Create a transaction for changing the prosemirror state.
|
|
61
57
|
*
|
|
62
58
|
* @returns
|
|
63
59
|
*/
|
|
64
|
-
get _tr():
|
|
65
|
-
_isLocalCursorInView():
|
|
60
|
+
get _tr(): Transaction;
|
|
61
|
+
_isLocalCursorInView(): false | null;
|
|
66
62
|
_isDomSelectionInView(): boolean;
|
|
67
|
-
|
|
68
|
-
* @param {Y.Snapshot} snapshot
|
|
69
|
-
* @param {Y.Snapshot} prevSnapshot
|
|
70
|
-
*/
|
|
71
|
-
renderSnapshot(snapshot: any, prevSnapshot: any): void;
|
|
63
|
+
renderSnapshot(snapshot: Y.Snapshot, prevSnapshot: Y.Snapshot): void;
|
|
72
64
|
unrenderSnapshot(): void;
|
|
73
65
|
_forceRerender(): void;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
* @param {Object} pluginState
|
|
78
|
-
*/
|
|
79
|
-
_renderSnapshot(snapshot: any, prevSnapshot: any, pluginState: any): void;
|
|
80
|
-
/**
|
|
81
|
-
* @param {Array<Y.YEvent<any>>} events
|
|
82
|
-
* @param {Y.Transaction} transaction
|
|
83
|
-
*/
|
|
84
|
-
_typeChanged(events: any, transaction: any): void;
|
|
85
|
-
/**
|
|
86
|
-
* @param {import('prosemirror-model').Node} doc
|
|
87
|
-
*/
|
|
88
|
-
_prosemirrorChanged(doc: any): void;
|
|
66
|
+
_renderSnapshot(snapshot: Y.Snapshot | Uint8Array, prevSnapshot: Y.Snapshot | Uint8Array, pluginState: Object): void;
|
|
67
|
+
_typeChanged(events: Array<Y.YEvent<any>>, transaction: Y.Transaction): void;
|
|
68
|
+
_prosemirrorChanged(doc: Node): void;
|
|
89
69
|
/**
|
|
90
70
|
* View is ready to listen to changes. Register observers.
|
|
91
|
-
* @param {any} prosemirrorView
|
|
92
71
|
*/
|
|
93
72
|
initView(prosemirrorView: any): void;
|
|
94
73
|
destroy(): void;
|
|
95
74
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
* @param {Y.XmlElement} el
|
|
99
|
-
* @param {any} schema
|
|
100
|
-
* @param {BindingMetadata} meta
|
|
101
|
-
* @param {Y.Snapshot} [snapshot]
|
|
102
|
-
* @param {Y.Snapshot} [prevSnapshot]
|
|
103
|
-
* @param {function('removed' | 'added', Y.ID):any} [computeYChange]
|
|
104
|
-
* @return {PModel.Node | null} Returns node if node could be created. Otherwise it deletes the yjs type and returns null
|
|
105
|
-
*/
|
|
106
|
-
export declare const createNodeFromYElement: (el: any, schema: any, meta: any, snapshot: any, prevSnapshot: any, computeYChange: any) => any;
|
|
107
|
-
/**
|
|
108
|
-
* @param {string} attrName
|
|
109
|
-
*/
|
|
110
|
-
export declare const yattr2markname: (attrName: any) => any;
|
|
75
|
+
export declare const createNodeFromYElement: (el: Y.XmlElement, schema: any, meta: BindingMetadata, snapshot: Y.Snapshot, prevSnapshot: Y.Snapshot, computeYChange: (arg0: "removed" | "added", arg1: Y.ID) => any) => PModel.Node | null;
|
|
76
|
+
export declare const yattr2markname: (attrName: string) => string;
|
|
111
77
|
/**
|
|
112
78
|
* @todo move this to markstoattributes
|
|
113
|
-
*
|
|
114
|
-
* @param {Object<string, any>} attrs
|
|
115
|
-
* @param {import('prosemirror-model').Schema} schema
|
|
116
79
|
*/
|
|
117
|
-
export declare const attributesToMarks: (attrs:
|
|
80
|
+
export declare const attributesToMarks: (attrs: {
|
|
81
|
+
[s: string]: any;
|
|
82
|
+
}, schema: Schema) => PModel.Mark[];
|
|
118
83
|
/**
|
|
119
84
|
* Update a yDom node by syncing the current content of the prosemirror node.
|
|
120
85
|
*
|
|
@@ -122,11 +87,9 @@ export declare const attributesToMarks: (attrs: any, schema: any) => any[];
|
|
|
122
87
|
*
|
|
123
88
|
* @private
|
|
124
89
|
* @unstable
|
|
125
|
-
*
|
|
126
|
-
* @param {{transact: Function}} y
|
|
127
|
-
* @param {Y.XmlFragment} yDomFragment
|
|
128
|
-
* @param {any} pNode
|
|
129
|
-
* @param {BindingMetadata} meta
|
|
130
90
|
*/
|
|
131
|
-
export declare const updateYFragment: (y:
|
|
91
|
+
export declare const updateYFragment: (y: {
|
|
92
|
+
transact: Function;
|
|
93
|
+
}, yDomFragment: Y.XmlFragment, pNode: any, meta: BindingMetadata) => void;
|
|
94
|
+
export {};
|
|
132
95
|
//# sourceMappingURL=ySyncPlugin.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ySyncPlugin.d.ts","sourceRoot":"","sources":["../../../src/extension-yjs/src/ySyncPlugin.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ySyncPlugin.d.ts","sourceRoot":"","sources":["../../../src/extension-yjs/src/ySyncPlugin.ts"],"names":[],"mappings":"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"}
|