@lexical/yjs 0.2.5 → 0.2.8
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/LexicalYjs.d.ts +277 -0
- package/LexicalYjs.dev.js +8 -87
- package/LexicalYjs.js.flow +364 -0
- package/LexicalYjs.prod.js +39 -41
- package/package.json +3 -3
package/LexicalYjs.d.ts
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
import type {
|
|
9
|
+
Doc,
|
|
10
|
+
RelativePosition,
|
|
11
|
+
UndoManager,
|
|
12
|
+
XmlElement,
|
|
13
|
+
XmlText,
|
|
14
|
+
Map as YMap,
|
|
15
|
+
} from 'yjs';
|
|
16
|
+
import type {
|
|
17
|
+
DecoratorNode,
|
|
18
|
+
EditorState,
|
|
19
|
+
ElementNode,
|
|
20
|
+
LexicalCommand,
|
|
21
|
+
LexicalEditor,
|
|
22
|
+
LineBreakNode,
|
|
23
|
+
NodeMap,
|
|
24
|
+
NodeKey,
|
|
25
|
+
TextNode,
|
|
26
|
+
IntentionallyMarkedAsDirtyElement,
|
|
27
|
+
} from 'lexical';
|
|
28
|
+
export type YjsEvent = Record<string, any>;
|
|
29
|
+
export type UserState = {
|
|
30
|
+
anchorPos: null | RelativePosition;
|
|
31
|
+
color: string;
|
|
32
|
+
focusing: boolean;
|
|
33
|
+
focusPos: null | RelativePosition;
|
|
34
|
+
name: string;
|
|
35
|
+
};
|
|
36
|
+
export type ProviderAwareness = {
|
|
37
|
+
getLocalState: () => UserState | null;
|
|
38
|
+
getStates: () => Map<number, UserState>;
|
|
39
|
+
off: (type: 'update', cb: () => void) => void;
|
|
40
|
+
on: (type: 'update', cb: () => void) => void;
|
|
41
|
+
setLocalState: (arg0: UserState) => void;
|
|
42
|
+
};
|
|
43
|
+
declare interface Provider {
|
|
44
|
+
awareness: ProviderAwareness;
|
|
45
|
+
connect(): void | Promise<void>;
|
|
46
|
+
disconnect(): void;
|
|
47
|
+
off(type: 'sync', cb: (isSynced: boolean) => void): void;
|
|
48
|
+
// $FlowFixMe: temp
|
|
49
|
+
off(type: 'update', cb: (arg0: any) => void): void;
|
|
50
|
+
off(type: 'status', cb: (arg0: {status: string}) => void): void;
|
|
51
|
+
off(type: 'reload', cb: (doc: Doc) => void): void;
|
|
52
|
+
on(type: 'sync', cb: (isSynced: boolean) => void): void;
|
|
53
|
+
on(type: 'status', cb: (arg0: {status: string}) => void): void;
|
|
54
|
+
// $FlowFixMe: temp
|
|
55
|
+
on(type: 'update', cb: (arg0: any) => void): void;
|
|
56
|
+
on(type: 'reload', cb: (doc: Doc) => void): void;
|
|
57
|
+
}
|
|
58
|
+
export type ClientID = number;
|
|
59
|
+
export type CursorSelection = {
|
|
60
|
+
anchor: {
|
|
61
|
+
key: NodeKey;
|
|
62
|
+
offset: number;
|
|
63
|
+
};
|
|
64
|
+
caret: HTMLElement;
|
|
65
|
+
color: string;
|
|
66
|
+
focus: {
|
|
67
|
+
key: NodeKey;
|
|
68
|
+
offset: number;
|
|
69
|
+
};
|
|
70
|
+
name: HTMLSpanElement;
|
|
71
|
+
selections: Array<HTMLElement>;
|
|
72
|
+
};
|
|
73
|
+
export type Cursor = {
|
|
74
|
+
color: string;
|
|
75
|
+
name: string;
|
|
76
|
+
selection: null | CursorSelection;
|
|
77
|
+
};
|
|
78
|
+
export type Binding = {
|
|
79
|
+
clientID: number;
|
|
80
|
+
collabNodeMap: Map<
|
|
81
|
+
NodeKey,
|
|
82
|
+
| CollabElementNode
|
|
83
|
+
| CollabTextNode
|
|
84
|
+
| CollabDecoratorNode
|
|
85
|
+
| CollabLineBreakNode
|
|
86
|
+
>;
|
|
87
|
+
cursors: Map<ClientID, Cursor>;
|
|
88
|
+
cursorsContainer: null | HTMLElement;
|
|
89
|
+
doc: Doc;
|
|
90
|
+
docMap: Map<string, Doc>;
|
|
91
|
+
editor: LexicalEditor;
|
|
92
|
+
id: string;
|
|
93
|
+
nodeProperties: Map<string, Array<string>>;
|
|
94
|
+
root: CollabElementNode;
|
|
95
|
+
};
|
|
96
|
+
export declare class CollabDecoratorNode {
|
|
97
|
+
_xmlElem: XmlElement;
|
|
98
|
+
_key: NodeKey;
|
|
99
|
+
_parent: CollabElementNode;
|
|
100
|
+
_type: string;
|
|
101
|
+
_unobservers: Set<() => void>;
|
|
102
|
+
constructor(xmlElem: XmlElement, parent: CollabElementNode, type: string);
|
|
103
|
+
getPrevNode(nodeMap: null | NodeMap): null | DecoratorNode<{}>;
|
|
104
|
+
getNode(): null | DecoratorNode<{}>;
|
|
105
|
+
getSharedType(): XmlElement;
|
|
106
|
+
getType(): string;
|
|
107
|
+
getKey(): NodeKey;
|
|
108
|
+
getSize(): number;
|
|
109
|
+
getOffset(): number;
|
|
110
|
+
syncPropertiesFromLexical(
|
|
111
|
+
binding: Binding,
|
|
112
|
+
nextLexicalNode: DecoratorNode<{}>,
|
|
113
|
+
prevNodeMap: null | NodeMap,
|
|
114
|
+
): void;
|
|
115
|
+
syncPropertiesFromYjs(
|
|
116
|
+
binding: Binding,
|
|
117
|
+
keysChanged: null | Set<string>,
|
|
118
|
+
): void;
|
|
119
|
+
destroy(binding: Binding): void;
|
|
120
|
+
}
|
|
121
|
+
export declare class CollabLineBreakNode {
|
|
122
|
+
_map: YMap<unknown>;
|
|
123
|
+
_key: NodeKey;
|
|
124
|
+
_parent: CollabElementNode;
|
|
125
|
+
_type: 'linebreak';
|
|
126
|
+
constructor(map: YMap<unknown>, parent: CollabElementNode);
|
|
127
|
+
getNode(): null | LineBreakNode;
|
|
128
|
+
getKey(): NodeKey;
|
|
129
|
+
getSharedType(): YMap<unknown>;
|
|
130
|
+
getType(): string;
|
|
131
|
+
getSize(): number;
|
|
132
|
+
getOffset(): number;
|
|
133
|
+
destroy(binding: Binding): void;
|
|
134
|
+
}
|
|
135
|
+
export declare class CollabTextNode {
|
|
136
|
+
_map: YMap<unknown>;
|
|
137
|
+
_key: NodeKey;
|
|
138
|
+
_parent: CollabElementNode;
|
|
139
|
+
_text: string;
|
|
140
|
+
_type: string;
|
|
141
|
+
_normalized: boolean;
|
|
142
|
+
constructor(
|
|
143
|
+
map: YMap<unknown>,
|
|
144
|
+
text: string,
|
|
145
|
+
parent: CollabElementNode,
|
|
146
|
+
type: string,
|
|
147
|
+
);
|
|
148
|
+
getPrevNode(nodeMap: null | NodeMap): null | TextNode;
|
|
149
|
+
getNode(): null | TextNode;
|
|
150
|
+
getSharedType(): YMap<unknown>;
|
|
151
|
+
getType(): string;
|
|
152
|
+
getKey(): NodeKey;
|
|
153
|
+
getSize(): number;
|
|
154
|
+
getOffset(): number;
|
|
155
|
+
spliceText(index: number, delCount: number, newText: string): void;
|
|
156
|
+
syncPropertiesAndTextFromLexical(
|
|
157
|
+
binding: Binding,
|
|
158
|
+
nextLexicalNode: TextNode,
|
|
159
|
+
prevNodeMap: null | NodeMap,
|
|
160
|
+
): void;
|
|
161
|
+
syncPropertiesAndTextFromYjs(
|
|
162
|
+
binding: Binding,
|
|
163
|
+
keysChanged: null | Set<string>,
|
|
164
|
+
): void;
|
|
165
|
+
destroy(binding: Binding): void;
|
|
166
|
+
}
|
|
167
|
+
export declare class CollabElementNode {
|
|
168
|
+
_key: NodeKey;
|
|
169
|
+
_children: Array<
|
|
170
|
+
| CollabElementNode
|
|
171
|
+
| CollabTextNode
|
|
172
|
+
| CollabDecoratorNode
|
|
173
|
+
| CollabLineBreakNode
|
|
174
|
+
>;
|
|
175
|
+
_xmlText: XmlText;
|
|
176
|
+
_type: string;
|
|
177
|
+
_parent: null | CollabElementNode;
|
|
178
|
+
constructor(xmlText: XmlText, parent: null | CollabElementNode, type: string);
|
|
179
|
+
getPrevNode(nodeMap: null | NodeMap): null | ElementNode;
|
|
180
|
+
getNode(): null | ElementNode;
|
|
181
|
+
getSharedType(): XmlText;
|
|
182
|
+
getType(): string;
|
|
183
|
+
getKey(): NodeKey;
|
|
184
|
+
isEmpty(): boolean;
|
|
185
|
+
getSize(): number;
|
|
186
|
+
getOffset(): number;
|
|
187
|
+
syncPropertiesFromYjs(
|
|
188
|
+
binding: Binding,
|
|
189
|
+
keysChanged: null | Set<string>,
|
|
190
|
+
): void;
|
|
191
|
+
applyChildrenYjsDelta(binding: Binding, deltas: Array<unknown>): void;
|
|
192
|
+
syncChildrenFromYjs(binding: Binding): void;
|
|
193
|
+
syncPropertiesFromLexical(
|
|
194
|
+
binding: Binding,
|
|
195
|
+
nextLexicalNode: ElementNode,
|
|
196
|
+
prevNodeMap: null | NodeMap,
|
|
197
|
+
): void;
|
|
198
|
+
_syncChildFromLexical(
|
|
199
|
+
binding: Binding,
|
|
200
|
+
index: number,
|
|
201
|
+
key: NodeKey,
|
|
202
|
+
prevNodeMap: null | NodeMap,
|
|
203
|
+
dirtyElements: null | Map<NodeKey, IntentionallyMarkedAsDirtyElement>,
|
|
204
|
+
dirtyLeaves: null | Set<NodeKey>,
|
|
205
|
+
): void;
|
|
206
|
+
syncChildrenFromLexical(
|
|
207
|
+
binding: Binding,
|
|
208
|
+
nextLexicalNode: ElementNode,
|
|
209
|
+
prevNodeMap: null | NodeMap,
|
|
210
|
+
dirtyElements: null | Map<NodeKey, IntentionallyMarkedAsDirtyElement>,
|
|
211
|
+
dirtyLeaves: null | Set<NodeKey>,
|
|
212
|
+
): void;
|
|
213
|
+
append(
|
|
214
|
+
collabNode:
|
|
215
|
+
| CollabElementNode
|
|
216
|
+
| CollabDecoratorNode
|
|
217
|
+
| CollabTextNode
|
|
218
|
+
| CollabLineBreakNode,
|
|
219
|
+
): void;
|
|
220
|
+
splice(
|
|
221
|
+
binding: Binding,
|
|
222
|
+
index: number,
|
|
223
|
+
delCount: number,
|
|
224
|
+
collabNode?:
|
|
225
|
+
| CollabElementNode
|
|
226
|
+
| CollabDecoratorNode
|
|
227
|
+
| CollabTextNode
|
|
228
|
+
| CollabLineBreakNode,
|
|
229
|
+
): void;
|
|
230
|
+
getChildOffset(
|
|
231
|
+
collabNode:
|
|
232
|
+
| CollabElementNode
|
|
233
|
+
| CollabTextNode
|
|
234
|
+
| CollabDecoratorNode
|
|
235
|
+
| CollabLineBreakNode,
|
|
236
|
+
): number;
|
|
237
|
+
destroy(binding: Binding): void;
|
|
238
|
+
}
|
|
239
|
+
export function createUndoManager(binding: Binding, root: XmlText): UndoManager;
|
|
240
|
+
export function initLocalState(
|
|
241
|
+
provider: Provider,
|
|
242
|
+
name: string,
|
|
243
|
+
color: string,
|
|
244
|
+
focusing: boolean,
|
|
245
|
+
): void;
|
|
246
|
+
export function setLocalStateFocus(
|
|
247
|
+
provider: Provider,
|
|
248
|
+
name: string,
|
|
249
|
+
color: string,
|
|
250
|
+
focusing: boolean,
|
|
251
|
+
): void;
|
|
252
|
+
export function createBinding(
|
|
253
|
+
editor: LexicalEditor,
|
|
254
|
+
provider: Provider,
|
|
255
|
+
id: string,
|
|
256
|
+
doc: Doc | null | undefined,
|
|
257
|
+
docMap: Map<string, Doc>,
|
|
258
|
+
): Binding;
|
|
259
|
+
export function syncCursorPositions(binding: Binding, provider: Provider): void;
|
|
260
|
+
export function syncLexicalUpdateToYjs(
|
|
261
|
+
binding: Binding,
|
|
262
|
+
provider: Provider,
|
|
263
|
+
prevEditorState: EditorState,
|
|
264
|
+
currEditorState: EditorState,
|
|
265
|
+
dirtyElements: Map<NodeKey, IntentionallyMarkedAsDirtyElement>,
|
|
266
|
+
dirtyLeaves: Set<NodeKey>,
|
|
267
|
+
normalizedNodes: Set<NodeKey>,
|
|
268
|
+
tags: Set<string>,
|
|
269
|
+
): void;
|
|
270
|
+
export function syncYjsChangesToLexical(
|
|
271
|
+
binding: Binding,
|
|
272
|
+
provider: Provider,
|
|
273
|
+
events: Array<YjsEvent>,
|
|
274
|
+
): void;
|
|
275
|
+
export declare var CONNECTED_COMMAND: LexicalCommand<boolean>;
|
|
276
|
+
export declare var TOGGLE_CONNECT_COMMAND: LexicalCommand<boolean>;
|
|
277
|
+
export type {Provider};
|
package/LexicalYjs.dev.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
var lexical = require('lexical');
|
|
10
10
|
var yjs = require('yjs');
|
|
11
|
+
var selection = require('@lexical/selection');
|
|
11
12
|
var offset = require('@lexical/offset');
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -1211,21 +1212,6 @@ function destroyCursor(binding, cursor) {
|
|
|
1211
1212
|
}
|
|
1212
1213
|
}
|
|
1213
1214
|
|
|
1214
|
-
function getDOMTextNode(element) {
|
|
1215
|
-
let node = element;
|
|
1216
|
-
|
|
1217
|
-
while (node != null) {
|
|
1218
|
-
if (node.nodeType === 3) {
|
|
1219
|
-
// $FlowFixMe: this is a Text
|
|
1220
|
-
return node;
|
|
1221
|
-
}
|
|
1222
|
-
|
|
1223
|
-
node = node.firstChild;
|
|
1224
|
-
}
|
|
1225
|
-
|
|
1226
|
-
return null;
|
|
1227
|
-
}
|
|
1228
|
-
|
|
1229
1215
|
function createCursorSelection(cursor, anchorKey, anchorOffset, focusKey, focusOffset) {
|
|
1230
1216
|
const color = cursor.color;
|
|
1231
1217
|
const caret = document.createElement('span');
|
|
@@ -1246,21 +1232,10 @@ function createCursorSelection(cursor, anchorKey, anchorOffset, focusKey, focusO
|
|
|
1246
1232
|
offset: focusOffset
|
|
1247
1233
|
},
|
|
1248
1234
|
name,
|
|
1249
|
-
range: document.createRange(),
|
|
1250
1235
|
selections: []
|
|
1251
1236
|
};
|
|
1252
1237
|
}
|
|
1253
1238
|
|
|
1254
|
-
function getDOMIndexWithinParent(node) {
|
|
1255
|
-
const parent = node.parentNode;
|
|
1256
|
-
|
|
1257
|
-
if (parent == null) {
|
|
1258
|
-
throw new Error('Should never happen');
|
|
1259
|
-
}
|
|
1260
|
-
|
|
1261
|
-
return [parent, Array.from(parent.childNodes).indexOf(node)];
|
|
1262
|
-
}
|
|
1263
|
-
|
|
1264
1239
|
function updateCursor(binding, cursor, nextSelection, nodeMap) {
|
|
1265
1240
|
const editor = binding.editor;
|
|
1266
1241
|
const rootElement = editor.getRootElement();
|
|
@@ -1284,7 +1259,6 @@ function updateCursor(binding, cursor, nextSelection, nodeMap) {
|
|
|
1284
1259
|
cursor.selection = nextSelection;
|
|
1285
1260
|
}
|
|
1286
1261
|
|
|
1287
|
-
const range = nextSelection.range;
|
|
1288
1262
|
const caret = nextSelection.caret;
|
|
1289
1263
|
const color = nextSelection.color;
|
|
1290
1264
|
const selections = nextSelection.selections;
|
|
@@ -1294,76 +1268,23 @@ function updateCursor(binding, cursor, nextSelection, nodeMap) {
|
|
|
1294
1268
|
const focusKey = focus.key;
|
|
1295
1269
|
const anchorNode = nodeMap.get(anchorKey);
|
|
1296
1270
|
const focusNode = nodeMap.get(focusKey);
|
|
1297
|
-
let anchorDOM = editor.getElementByKey(anchorKey);
|
|
1298
|
-
let focusDOM = editor.getElementByKey(focusKey);
|
|
1299
|
-
let anchorOffset = anchor.offset;
|
|
1300
|
-
let focusOffset = focus.offset;
|
|
1301
|
-
|
|
1302
|
-
if (lexical.$isTextNode(anchorNode)) {
|
|
1303
|
-
anchorDOM = getDOMTextNode(anchorDOM);
|
|
1304
|
-
}
|
|
1305
|
-
|
|
1306
|
-
if (lexical.$isTextNode(focusNode)) {
|
|
1307
|
-
focusDOM = getDOMTextNode(focusDOM);
|
|
1308
|
-
}
|
|
1309
1271
|
|
|
1310
|
-
if (anchorNode
|
|
1272
|
+
if (anchorNode == null || focusNode == null) {
|
|
1311
1273
|
return;
|
|
1312
1274
|
}
|
|
1313
1275
|
|
|
1314
|
-
|
|
1315
|
-
[anchorDOM, anchorOffset] = getDOMIndexWithinParent(anchorDOM);
|
|
1316
|
-
}
|
|
1317
|
-
|
|
1318
|
-
if (focusDOM.nodeName === 'BR') {
|
|
1319
|
-
[focusDOM, focusOffset] = getDOMIndexWithinParent(focusDOM);
|
|
1320
|
-
}
|
|
1321
|
-
|
|
1322
|
-
const firstChild = anchorDOM.firstChild;
|
|
1276
|
+
const range = selection.createDOMRange(editor, anchorNode, anchor.offset, focusNode, focus.offset);
|
|
1323
1277
|
|
|
1324
|
-
if (
|
|
1325
|
-
focusOffset = 1;
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
|
-
try {
|
|
1329
|
-
range.setStart(anchorDOM, anchorOffset);
|
|
1330
|
-
range.setEnd(focusDOM, focusOffset);
|
|
1331
|
-
} catch (e) {
|
|
1278
|
+
if (range === null) {
|
|
1332
1279
|
return;
|
|
1333
1280
|
}
|
|
1334
1281
|
|
|
1335
|
-
if (range.collapsed && (anchorOffset !== focusOffset || anchorKey !== focusKey)) {
|
|
1336
|
-
// Range is backwards, we need to reverse it
|
|
1337
|
-
range.setStart(focusDOM, focusOffset);
|
|
1338
|
-
range.setEnd(anchorDOM, anchorOffset);
|
|
1339
|
-
} // We need to
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
const rootRect = rootElement.getBoundingClientRect();
|
|
1343
|
-
const computedStyle = getComputedStyle(rootElement);
|
|
1344
|
-
const rootPadding = parseFloat(computedStyle.paddingLeft) + parseFloat(computedStyle.paddingRight);
|
|
1345
|
-
const selectionRects = Array.from(range.getClientRects());
|
|
1346
|
-
let selectionRectsLength = selectionRects.length;
|
|
1347
1282
|
const selectionsLength = selections.length;
|
|
1348
|
-
|
|
1283
|
+
const selectionRects = selection.createRectsFromDOMRange(editor, range);
|
|
1284
|
+
const selectionRectsLength = selectionRects.length;
|
|
1349
1285
|
|
|
1350
1286
|
for (let i = 0; i < selectionRectsLength; i++) {
|
|
1351
|
-
const selectionRect = selectionRects[i];
|
|
1352
|
-
// the same rect twice for some elements. A more sophisticated thing to do here is to
|
|
1353
|
-
// merge all the rects together into a set of rects that don't overlap, so we don't
|
|
1354
|
-
// generate backgrounds that are too dark.
|
|
1355
|
-
|
|
1356
|
-
const isDuplicateRect = prevRect && prevRect.top === selectionRect.top && prevRect.left === selectionRect.left && prevRect.width === selectionRect.width && prevRect.height === selectionRect.height; // Exclude selections that span the entire element
|
|
1357
|
-
|
|
1358
|
-
const selectionSpansElement = selectionRect.width + rootPadding === rootRect.width;
|
|
1359
|
-
|
|
1360
|
-
if (isDuplicateRect || selectionSpansElement) {
|
|
1361
|
-
selectionRects.splice(i--, 1);
|
|
1362
|
-
selectionRectsLength--;
|
|
1363
|
-
continue;
|
|
1364
|
-
}
|
|
1365
|
-
|
|
1366
|
-
prevRect = selectionRect;
|
|
1287
|
+
const selectionRect = selectionRects[i];
|
|
1367
1288
|
let selection = selections[i];
|
|
1368
1289
|
|
|
1369
1290
|
if (selection === undefined) {
|
|
@@ -1372,7 +1293,7 @@ function updateCursor(binding, cursor, nextSelection, nodeMap) {
|
|
|
1372
1293
|
cursorsContainer.appendChild(selection);
|
|
1373
1294
|
}
|
|
1374
1295
|
|
|
1375
|
-
const style = `position:absolute;top:${selectionRect.top}px;left:${selectionRect.left}px;height:${selectionRect.height}px;width:${selectionRect.width}px;background-color:rgba(${color}, 0.3);pointer-events:none;z-index:
|
|
1296
|
+
const style = `position:absolute;top:${selectionRect.top}px;left:${selectionRect.left}px;height:${selectionRect.height}px;width:${selectionRect.width}px;background-color:rgba(${color}, 0.3);pointer-events:none;z-index:5;`;
|
|
1376
1297
|
selection.style.cssText = style;
|
|
1377
1298
|
|
|
1378
1299
|
if (i === selectionRectsLength - 1) {
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @flow strict
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type {Doc, RelativePosition, UndoManager, XmlText} from 'yjs';
|
|
11
|
+
import type {
|
|
12
|
+
DecoratorNode,
|
|
13
|
+
EditorState,
|
|
14
|
+
ElementNode,
|
|
15
|
+
LexicalCommand,
|
|
16
|
+
LexicalEditor,
|
|
17
|
+
LineBreakNode,
|
|
18
|
+
NodeMap,
|
|
19
|
+
NodeKey,
|
|
20
|
+
TextNode,
|
|
21
|
+
IntentionallyMarkedAsDirtyElement,
|
|
22
|
+
} from 'lexical';
|
|
23
|
+
|
|
24
|
+
// $FlowFixMe: todo
|
|
25
|
+
export type YjsEvent = Object;
|
|
26
|
+
|
|
27
|
+
export type UserState = {
|
|
28
|
+
anchorPos: null | RelativePosition,
|
|
29
|
+
color: string,
|
|
30
|
+
focusing: boolean,
|
|
31
|
+
focusPos: null | RelativePosition,
|
|
32
|
+
name: string,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export type ProviderAwareness = {
|
|
36
|
+
getLocalState: () => UserState | null,
|
|
37
|
+
getStates: () => Map<number, UserState>,
|
|
38
|
+
off: (type: 'update', cb: () => void) => void,
|
|
39
|
+
on: (type: 'update', cb: () => void) => void,
|
|
40
|
+
setLocalState: (UserState) => void,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
declare interface Provider {
|
|
44
|
+
awareness: ProviderAwareness;
|
|
45
|
+
connect(): void | Promise<void>;
|
|
46
|
+
disconnect(): void;
|
|
47
|
+
off(type: 'sync', cb: (isSynced: boolean) => void): void;
|
|
48
|
+
// $FlowFixMe: temp
|
|
49
|
+
off(type: 'update', cb: (any) => void): void;
|
|
50
|
+
off(type: 'status', cb: ({status: string}) => void): void;
|
|
51
|
+
off(type: 'reload', cb: (doc: Doc) => void): void;
|
|
52
|
+
on(type: 'sync', cb: (isSynced: boolean) => void): void;
|
|
53
|
+
on(type: 'status', cb: ({status: string}) => void): void;
|
|
54
|
+
// $FlowFixMe: temp
|
|
55
|
+
on(type: 'update', cb: (any) => void): void;
|
|
56
|
+
on(type: 'reload', cb: (doc: Doc) => void): void;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export type ClientID = number;
|
|
60
|
+
// $FlowFixMe: work around for internal
|
|
61
|
+
export type XmlElement = Object;
|
|
62
|
+
// $FlowFixMe: work around for internal
|
|
63
|
+
export type YMap = Object;
|
|
64
|
+
// $FlowFixMe: work around for internal
|
|
65
|
+
export type TextOperation = Object;
|
|
66
|
+
|
|
67
|
+
export type CursorSelection = {
|
|
68
|
+
anchor: {
|
|
69
|
+
key: NodeKey,
|
|
70
|
+
offset: number,
|
|
71
|
+
},
|
|
72
|
+
caret: HTMLElement,
|
|
73
|
+
color: string,
|
|
74
|
+
focus: {
|
|
75
|
+
key: NodeKey,
|
|
76
|
+
offset: number,
|
|
77
|
+
},
|
|
78
|
+
name: HTMLSpanElement,
|
|
79
|
+
selections: Array<HTMLElement>,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export type Cursor = {
|
|
83
|
+
color: string,
|
|
84
|
+
name: string,
|
|
85
|
+
selection: null | CursorSelection,
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export type Binding = {
|
|
89
|
+
clientID: number,
|
|
90
|
+
collabNodeMap: Map<
|
|
91
|
+
NodeKey,
|
|
92
|
+
| CollabElementNode
|
|
93
|
+
| CollabTextNode
|
|
94
|
+
| CollabDecoratorNode
|
|
95
|
+
| CollabLineBreakNode,
|
|
96
|
+
>,
|
|
97
|
+
cursors: Map<ClientID, Cursor>,
|
|
98
|
+
cursorsContainer: null | HTMLElement,
|
|
99
|
+
doc: Doc,
|
|
100
|
+
docMap: Map<string, Doc>,
|
|
101
|
+
editor: LexicalEditor,
|
|
102
|
+
id: string,
|
|
103
|
+
nodeProperties: Map<string, Array<string>>,
|
|
104
|
+
root: CollabElementNode,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
declare export class CollabDecoratorNode {
|
|
108
|
+
_xmlElem: XmlElement;
|
|
109
|
+
_key: NodeKey;
|
|
110
|
+
_parent: CollabElementNode;
|
|
111
|
+
_type: string;
|
|
112
|
+
_unobservers: Set<() => void>;
|
|
113
|
+
|
|
114
|
+
constructor(
|
|
115
|
+
xmlElem: XmlElement,
|
|
116
|
+
parent: CollabElementNode,
|
|
117
|
+
type: string,
|
|
118
|
+
): void;
|
|
119
|
+
|
|
120
|
+
getPrevNode(nodeMap: null | NodeMap): null | DecoratorNode<{...}>;
|
|
121
|
+
|
|
122
|
+
getNode(): null | DecoratorNode<{...}>;
|
|
123
|
+
|
|
124
|
+
getSharedType(): XmlElement;
|
|
125
|
+
|
|
126
|
+
getType(): string;
|
|
127
|
+
|
|
128
|
+
getKey(): NodeKey;
|
|
129
|
+
|
|
130
|
+
getSize(): number;
|
|
131
|
+
|
|
132
|
+
getOffset(): number;
|
|
133
|
+
|
|
134
|
+
syncPropertiesFromLexical(
|
|
135
|
+
binding: Binding,
|
|
136
|
+
nextLexicalNode: DecoratorNode<{...}>,
|
|
137
|
+
prevNodeMap: null | NodeMap,
|
|
138
|
+
): void;
|
|
139
|
+
|
|
140
|
+
syncPropertiesFromYjs(
|
|
141
|
+
binding: Binding,
|
|
142
|
+
keysChanged: null | Set<string>,
|
|
143
|
+
): void;
|
|
144
|
+
|
|
145
|
+
destroy(binding: Binding): void;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
declare export class CollabLineBreakNode {
|
|
149
|
+
_map: YMap;
|
|
150
|
+
_key: NodeKey;
|
|
151
|
+
_parent: CollabElementNode;
|
|
152
|
+
_type: 'linebreak';
|
|
153
|
+
|
|
154
|
+
constructor(map: YMap, parent: CollabElementNode): void;
|
|
155
|
+
|
|
156
|
+
getNode(): null | LineBreakNode;
|
|
157
|
+
|
|
158
|
+
getKey(): NodeKey;
|
|
159
|
+
|
|
160
|
+
getSharedType(): YMap;
|
|
161
|
+
|
|
162
|
+
getType(): string;
|
|
163
|
+
|
|
164
|
+
getSize(): number;
|
|
165
|
+
|
|
166
|
+
getOffset(): number;
|
|
167
|
+
|
|
168
|
+
destroy(binding: Binding): void;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
declare export class CollabTextNode {
|
|
172
|
+
_map: YMap;
|
|
173
|
+
_key: NodeKey;
|
|
174
|
+
_parent: CollabElementNode;
|
|
175
|
+
_text: string;
|
|
176
|
+
_type: string;
|
|
177
|
+
_normalized: boolean;
|
|
178
|
+
|
|
179
|
+
constructor(
|
|
180
|
+
map: YMap,
|
|
181
|
+
text: string,
|
|
182
|
+
parent: CollabElementNode,
|
|
183
|
+
type: string,
|
|
184
|
+
): void;
|
|
185
|
+
|
|
186
|
+
getPrevNode(nodeMap: null | NodeMap): null | TextNode;
|
|
187
|
+
|
|
188
|
+
getNode(): null | TextNode;
|
|
189
|
+
|
|
190
|
+
getSharedType(): YMap;
|
|
191
|
+
|
|
192
|
+
getType(): string;
|
|
193
|
+
|
|
194
|
+
getKey(): NodeKey;
|
|
195
|
+
|
|
196
|
+
getSize(): number;
|
|
197
|
+
|
|
198
|
+
getOffset(): number;
|
|
199
|
+
|
|
200
|
+
spliceText(index: number, delCount: number, newText: string): void;
|
|
201
|
+
|
|
202
|
+
syncPropertiesAndTextFromLexical(
|
|
203
|
+
binding: Binding,
|
|
204
|
+
nextLexicalNode: TextNode,
|
|
205
|
+
prevNodeMap: null | NodeMap,
|
|
206
|
+
): void;
|
|
207
|
+
|
|
208
|
+
syncPropertiesAndTextFromYjs(
|
|
209
|
+
binding: Binding,
|
|
210
|
+
keysChanged: null | Set<string>,
|
|
211
|
+
): void;
|
|
212
|
+
|
|
213
|
+
destroy(binding: Binding): void;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
declare export class CollabElementNode {
|
|
217
|
+
_key: NodeKey;
|
|
218
|
+
_children: Array<
|
|
219
|
+
| CollabElementNode
|
|
220
|
+
| CollabTextNode
|
|
221
|
+
| CollabDecoratorNode
|
|
222
|
+
| CollabLineBreakNode,
|
|
223
|
+
>;
|
|
224
|
+
_xmlText: XmlText;
|
|
225
|
+
_type: string;
|
|
226
|
+
_parent: null | CollabElementNode;
|
|
227
|
+
|
|
228
|
+
constructor(
|
|
229
|
+
xmlText: XmlText,
|
|
230
|
+
parent: null | CollabElementNode,
|
|
231
|
+
type: string,
|
|
232
|
+
): void;
|
|
233
|
+
|
|
234
|
+
getPrevNode(nodeMap: null | NodeMap): null | ElementNode;
|
|
235
|
+
|
|
236
|
+
getNode(): null | ElementNode;
|
|
237
|
+
|
|
238
|
+
getSharedType(): XmlText;
|
|
239
|
+
|
|
240
|
+
getType(): string;
|
|
241
|
+
|
|
242
|
+
getKey(): NodeKey;
|
|
243
|
+
|
|
244
|
+
isEmpty(): boolean;
|
|
245
|
+
|
|
246
|
+
getSize(): number;
|
|
247
|
+
|
|
248
|
+
getOffset(): number;
|
|
249
|
+
|
|
250
|
+
syncPropertiesFromYjs(
|
|
251
|
+
binding: Binding,
|
|
252
|
+
keysChanged: null | Set<string>,
|
|
253
|
+
): void;
|
|
254
|
+
|
|
255
|
+
applyChildrenYjsDelta(binding: Binding, deltas: Array<TextOperation>): void;
|
|
256
|
+
|
|
257
|
+
syncChildrenFromYjs(binding: Binding): void;
|
|
258
|
+
|
|
259
|
+
syncPropertiesFromLexical(
|
|
260
|
+
binding: Binding,
|
|
261
|
+
nextLexicalNode: ElementNode,
|
|
262
|
+
prevNodeMap: null | NodeMap,
|
|
263
|
+
): void;
|
|
264
|
+
|
|
265
|
+
_syncChildFromLexical(
|
|
266
|
+
binding: Binding,
|
|
267
|
+
index: number,
|
|
268
|
+
key: NodeKey,
|
|
269
|
+
prevNodeMap: null | NodeMap,
|
|
270
|
+
dirtyElements: null | Map<NodeKey, IntentionallyMarkedAsDirtyElement>,
|
|
271
|
+
dirtyLeaves: null | Set<NodeKey>,
|
|
272
|
+
): void;
|
|
273
|
+
|
|
274
|
+
syncChildrenFromLexical(
|
|
275
|
+
binding: Binding,
|
|
276
|
+
nextLexicalNode: ElementNode,
|
|
277
|
+
prevNodeMap: null | NodeMap,
|
|
278
|
+
dirtyElements: null | Map<NodeKey, IntentionallyMarkedAsDirtyElement>,
|
|
279
|
+
dirtyLeaves: null | Set<NodeKey>,
|
|
280
|
+
): void;
|
|
281
|
+
|
|
282
|
+
append(
|
|
283
|
+
collabNode:
|
|
284
|
+
| CollabElementNode
|
|
285
|
+
| CollabDecoratorNode
|
|
286
|
+
| CollabTextNode
|
|
287
|
+
| CollabLineBreakNode,
|
|
288
|
+
): void;
|
|
289
|
+
|
|
290
|
+
splice(
|
|
291
|
+
binding: Binding,
|
|
292
|
+
index: number,
|
|
293
|
+
delCount: number,
|
|
294
|
+
collabNode?:
|
|
295
|
+
| CollabElementNode
|
|
296
|
+
| CollabDecoratorNode
|
|
297
|
+
| CollabTextNode
|
|
298
|
+
| CollabLineBreakNode,
|
|
299
|
+
): void;
|
|
300
|
+
|
|
301
|
+
getChildOffset(
|
|
302
|
+
collabNode:
|
|
303
|
+
| CollabElementNode
|
|
304
|
+
| CollabTextNode
|
|
305
|
+
| CollabDecoratorNode
|
|
306
|
+
| CollabLineBreakNode,
|
|
307
|
+
): number;
|
|
308
|
+
|
|
309
|
+
destroy(binding: Binding): void;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
declare export function createUndoManager(
|
|
313
|
+
binding: Binding,
|
|
314
|
+
root: XmlText,
|
|
315
|
+
): UndoManager;
|
|
316
|
+
|
|
317
|
+
declare export function initLocalState(
|
|
318
|
+
provider: Provider,
|
|
319
|
+
name: string,
|
|
320
|
+
color: string,
|
|
321
|
+
focusing: boolean,
|
|
322
|
+
): void;
|
|
323
|
+
|
|
324
|
+
declare export function setLocalStateFocus(
|
|
325
|
+
provider: Provider,
|
|
326
|
+
name: string,
|
|
327
|
+
color: string,
|
|
328
|
+
focusing: boolean,
|
|
329
|
+
): void;
|
|
330
|
+
|
|
331
|
+
declare export function createBinding(
|
|
332
|
+
editor: LexicalEditor,
|
|
333
|
+
provider: Provider,
|
|
334
|
+
id: string,
|
|
335
|
+
doc: ?Doc,
|
|
336
|
+
docMap: Map<string, Doc>,
|
|
337
|
+
): Binding;
|
|
338
|
+
|
|
339
|
+
declare export function syncCursorPositions(
|
|
340
|
+
binding: Binding,
|
|
341
|
+
provider: Provider,
|
|
342
|
+
): void;
|
|
343
|
+
|
|
344
|
+
declare export function syncLexicalUpdateToYjs(
|
|
345
|
+
binding: Binding,
|
|
346
|
+
provider: Provider,
|
|
347
|
+
prevEditorState: EditorState,
|
|
348
|
+
currEditorState: EditorState,
|
|
349
|
+
dirtyElements: Map<NodeKey, IntentionallyMarkedAsDirtyElement>,
|
|
350
|
+
dirtyLeaves: Set<NodeKey>,
|
|
351
|
+
normalizedNodes: Set<NodeKey>,
|
|
352
|
+
tags: Set<string>,
|
|
353
|
+
): void;
|
|
354
|
+
|
|
355
|
+
declare export function syncYjsChangesToLexical(
|
|
356
|
+
binding: Binding,
|
|
357
|
+
provider: Provider,
|
|
358
|
+
events: Array<YjsEvent>,
|
|
359
|
+
): void;
|
|
360
|
+
|
|
361
|
+
declare export var CONNECTED_COMMAND: LexicalCommand<boolean>;
|
|
362
|
+
declare export var TOGGLE_CONNECT_COMMAND: LexicalCommand<boolean>;
|
|
363
|
+
|
|
364
|
+
export type {Provider};
|
package/LexicalYjs.prod.js
CHANGED
|
@@ -4,46 +4,44 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
var q=require("lexical"),
|
|
7
|
+
var q=require("lexical"),v=require("yjs"),y=require("@lexical/selection"),A=require("@lexical/offset");class B{constructor(a,b){this._key="";this._map=a;this._parent=b;this._type="linebreak"}getNode(){const a=q.$getNodeByKey(this._key);return q.$isLineBreakNode(a)?a:null}getKey(){return this._key}getSharedType(){return this._map}getType(){return this._type}getSize(){return 1}getOffset(){return this._parent.getChildOffset(this)}destroy(a){a.collabNodeMap.delete(this._key)}}
|
|
8
|
+
function C(a,b){b=new B(a,b);return a._collabNode=b}
|
|
8
9
|
class D{constructor(a,b,c,d){this._key="";this._map=a;this._parent=c;this._text=b;this._type=d;this._normalized=!1}getPrevNode(a){if(null===a)return null;a=a.get(this._key);return q.$isTextNode(a)?a:null}getNode(){const a=q.$getNodeByKey(this._key);return q.$isTextNode(a)?a:null}getSharedType(){return this._map}getType(){return this._type}getKey(){return this._key}getSize(){return this._text.length+(this._normalized?0:1)}getOffset(){return this._parent.getChildOffset(this)}spliceText(a,b,c){const d=
|
|
9
|
-
this._parent._xmlText;a=this.getOffset()+1+a;0!==b&&d.delete(a,b);""!==c&&d.insert(a,c)}syncPropertiesAndTextFromLexical(a,b,c){var d=this.getPrevNode(c);c=b.__text;
|
|
10
|
-
e;a=c.slice(e,f-
|
|
11
|
-
function
|
|
12
|
-
function
|
|
10
|
+
this._parent._xmlText;a=this.getOffset()+1+a;0!==b&&d.delete(a,b);""!==c&&d.insert(a,c)}syncPropertiesAndTextFromLexical(a,b,c){var d=this.getPrevNode(c);c=b.__text;E(a,this._map,d,b);if(null!==d&&(a=d.__text,a!==c)){d=b.__key;b=a;var e=q.$getSelection();a=c.length;q.$isRangeSelection(e)&&e.isCollapsed()&&(e=e.anchor,e.key===d&&(a=e.offset));d=b.length;const f=c.length;let h=e=0;for(;e<d&&e<f&&b[e]===c[e]&&e<a;)e++;for(;h+e<d&&h+e<f&&b[d-h-1]===c[f-h-1];)h++;for(;h+e<d&&h+e<f&&b[e]===c[e];)e++;b=
|
|
11
|
+
e;a=c.slice(e,f-h);d=d-e-h;this.spliceText(b,d,a);this._text=c}}syncPropertiesAndTextFromYjs(a,b){const c=this.getNode();if(null===c)throw Error("Should never happen");F(a,this._map,c,b);a=this._text;c.__text!==a&&(c.getWritable().__text=a)}destroy(a){a.collabNodeMap.delete(this._key)}}function G(a,b,c,d){b=new D(a,b,c,d);return a._collabNode=b}const H=new Set(["__key","__children","__parent","__cachedText","__text"]);
|
|
12
|
+
function I(a){a=q.$getNodeByKey(a);if(null===a)throw Error("Should never happen");return a}
|
|
13
|
+
function J(a,b,c){const d=b.__type;if(q.$isElementNode(b)){var e=new v.XmlText;c=K(e,c,d);c.syncPropertiesFromLexical(a,b,null);c.syncChildrenFromLexical(a,b,null,null,null)}else if(q.$isTextNode(b))e=new v.Map,c=G(e,b.__text,c,d),c.syncPropertiesAndTextFromLexical(a,b,null);else if(q.$isLineBreakNode(b))a=new v.Map,a.set("__type","linebreak"),c=C(a,c);else if(q.$isDecoratorNode(b))e=new v.XmlElement,c=L(e,c,d),c.syncPropertiesFromLexical(a,b,null);else throw Error("Should never happen");c._key=b.__key;
|
|
13
14
|
return c}
|
|
14
|
-
function
|
|
15
|
-
f)}if(b instanceof
|
|
16
|
-
function
|
|
17
|
-
function
|
|
18
|
-
function
|
|
19
|
-
class
|
|
20
|
-
|
|
21
|
-
class
|
|
22
|
-
return a.getChildOffset(this)}syncPropertiesFromYjs(a,b){const c=this.getNode();if(null===c)throw this.getNode(),Error("Should never happen");
|
|
23
|
-
D){e=Math.min(f,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
this._xmlText,this.getPrevNode(c),b)}_syncChildFromLexical(a,b,c,d,e,f){b=this._children[b];c=
|
|
28
|
-
a.collabNodeMap;let l,t
|
|
29
|
-
this._xmlText;var c=this._children;c=c[c.length-1];c=void 0!==c?c.getOffset()+c.getSize():0;if(a instanceof
|
|
30
|
-
if(-1===
|
|
31
|
-
if(e===a)return b;b+=e.getSize()}return-1}destroy(a){const b=a.collabNodeMap,c=this._children;for(let d=0;d<c.length;d++)c[d].destroy(a);b.delete(this._key)}}function
|
|
32
|
-
function
|
|
33
|
-
function
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
n.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
function
|
|
43
|
-
|
|
44
|
-
exports.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
exports.syncYjsChangesToLexical=function(a,b,c){const d=a.editor,e=d._editorState;d.update(()=>{var f=d._pendingEditorState;for(var g=0;g<c.length;g++){var h=a,k=c[g],{target:m}=k;m=Q(h,m);if(m instanceof R&&k instanceof w.YTextEvent){const {keysChanged:l,childListChanged:t,delta:u}=k;0<l.size&&m.syncPropertiesFromYjs(h,l);t&&(m.applyChildrenYjsDelta(h,u),m.syncChildrenFromYjs(h))}else if(m instanceof D&&k instanceof w.YMapEvent)({keysChanged:k}=k),0<k.size&&m.syncPropertiesAndTextFromYjs(h,k);else if(m instanceof
|
|
48
|
-
U&&k instanceof w.YXmlEvent)({attributesChanged:k}=k),0<k.size&&m.syncPropertiesFromYjs(h,k);else throw Error("Should never happen");}g=q.$getSelection();if(q.$isRangeSelection(g))if(T(g)){h=e._selection;if(q.$isRangeSelection(h)){m=z.$createOffsetView(d,0,e);f=z.$createOffsetView(d,0,f);const [l,t]=m.getOffsetsFromSelection(h);f=f.createSelectionFromOffsets(l,t,m);null!==f?q.$setSelection(f):(da(a,b),T(g)&&(f=q.$getRoot(),0===f.getChildrenSize()&&f.append(q.$createParagraphNode()),q.$getRoot().selectEnd()))}ka(a,
|
|
49
|
-
b,h,q.$getSelection())}else da(a,b)},{onUpdate:()=>{ja(a,b)},skipTransforms:!0,tag:"collaboration"})};
|
|
15
|
+
function M(a,b,c){const d=b._collabNode;if(void 0===d){var e=a.editor._nodes;const f=b instanceof v.Map?b.get("__type"):b.getAttribute("__type");if(null==f)throw Error("Should never happen");if(void 0===e.get(f))throw Error("Should never happen");e=b.parent;a=void 0===c&&null!==e?M(a,e):c||null;if(!(a instanceof N))throw Error("Should never happen");if(b instanceof v.XmlText)return K(b,a,f);if(b instanceof v.Map){if(null===a)throw Error("Should never happen");return"linebreak"===f?C(b,a):G(b,"",a,
|
|
16
|
+
f)}if(b instanceof v.XmlElement)return L(b,a,f)}return d}function F(a,b,c,d){d=null===d?b instanceof v.Map?Array.from(b.keys()):Object.keys(b.getAttributes()):Array.from(d);let e;for(let h=0;h<d.length;h++){const g=d[h];if(H.has(g))continue;var f=c[g];let k=b instanceof v.Map?b.get(g):b.getAttribute(g);if(f!==k){if(k instanceof v.Doc){const m=a.docMap;f instanceof v.Doc&&m.delete(f.guid);f=q.createEditor();const l=k.guid;f._key=l;m.set(l,k);k=f}void 0===e&&(e=c.getWritable());e[g]=k}}}
|
|
17
|
+
function E(a,b,c,d){var e=d.__type,f=a.nodeProperties;let h=f.get(e);void 0===h&&(h=Object.keys(d).filter(k=>!H.has(k)),f.set(e,h));e=a.editor.constructor;for(f=0;f<h.length;f++){const k=h[f];var g=null===c?void 0:c[k];let m=d[k];if(g!==m){if(m instanceof e){const l=a.docMap;let r;g instanceof e&&(g=g._key,r=l.get(g),l.delete(g));g=r||new v.Doc;const t=g.guid;m._key=t;l.set(t,g);m=g;a.editor.update(()=>{d.markDirty()})}b instanceof v.Map?b.set(k,m):b.setAttribute(k,m)}}}
|
|
18
|
+
function O(a,b,c){let d=0,e=0;const f=a._children,h=f.length;for(;e<h;e++){a=f[e];const g=d,k=a.getSize();d+=k;if((c?d>=b:d>b)&&a instanceof D)return c=b-g-1,0>c&&(c=0),{length:d-b,node:a,nodeIndex:e,offset:c};if(d>b)return{length:0,node:a,nodeIndex:e,offset:g};if(e===h-1)return{length:0,node:null,nodeIndex:e+1,offset:g+1}}return{length:0,node:null,nodeIndex:0,offset:0}}
|
|
19
|
+
function P(a){const b=a.anchor;a=a.focus;let c=!1;try{const d=b.getNode(),e=a.getNode();if(!d.isAttached()||!e.isAttached()||q.$isTextNode(d)&&b.offset>d.getTextContentSize()||q.$isTextNode(e)&&a.offset>e.getTextContentSize())c=!0}catch(d){c=!0}return c}function ea(a,b){a.doc.transact(b,a)}
|
|
20
|
+
class Q{constructor(a,b,c){this._key="";this._xmlElem=a;this._parent=b;this._type=c;this._unobservers=new Set}getPrevNode(a){if(null===a)return null;a=a.get(this._key);return q.$isDecoratorNode(a)?a:null}getNode(){const a=q.$getNodeByKey(this._key);return q.$isDecoratorNode(a)?a:null}getSharedType(){return this._xmlElem}getType(){return this._type}getKey(){return this._key}getSize(){return 1}getOffset(){return this._parent.getChildOffset(this)}syncPropertiesFromLexical(a,b,c){c=this.getPrevNode(c);
|
|
21
|
+
E(a,this._xmlElem,c,b)}syncPropertiesFromYjs(a,b){const c=this.getNode();if(null===c)throw Error("Should never happen");F(a,this._xmlElem,c,b)}destroy(a){a.collabNodeMap.delete(this._key);this._unobservers.forEach(b=>b());this._unobservers.clear()}}function L(a,b,c){b=new Q(a,b,c);return a._collabNode=b}
|
|
22
|
+
class N{constructor(a,b,c){this._key="";this._children=[];this._xmlText=a;this._type=c;this._parent=b}getPrevNode(a){if(null===a)return null;a=a.get(this._key);return q.$isElementNode(a)?a:null}getNode(){const a=q.$getNodeByKey(this._key);return q.$isElementNode(a)?a:null}getSharedType(){return this._xmlText}getType(){return this._type}getKey(){return this._key}isEmpty(){return 0===this._children.length}getSize(){return 1}getOffset(){const a=this._parent;if(null===a)throw Error("Should never happen");
|
|
23
|
+
return a.getChildOffset(this)}syncPropertiesFromYjs(a,b){const c=this.getNode();if(null===c)throw this.getNode(),Error("Should never happen");F(a,this._xmlText,c,b)}applyChildrenYjsDelta(a,b){const c=this._children;let d=0;for(let m=0;m<b.length;m++){var e=b[m],f=e.insert,h=e.delete;if(null!=e.retain)d+=e.retain;else if("number"===typeof h)for(f=h;0<f;){const {node:l,nodeIndex:r,offset:t,length:n}=O(this,d,!1);if(l instanceof N||l instanceof B||l instanceof Q)c.splice(r,1),--f;else if(l instanceof
|
|
24
|
+
D){e=Math.min(f,n);h=0!==r?c[r-1]:null;var g=l.getSize();if(0===t&&1===e&&0<r&&h instanceof D&&n===g&&0===Array.from(l._map.keys()).length)h._text+=l._text,c.splice(r,1);else if(0===t&&e===g)c.splice(r,1);else{h=l._text;g=t;var k=e;h=h.slice(0,g)+""+h.slice(g+k);l._text=h}f-=e}else break}else if(null!=f)if("string"===typeof f){const {node:l,offset:r}=O(this,d,!0);l instanceof D?(e=l._text,h=r,g=f,e=e.slice(0,h)+g+e.slice(h+0),l._text=e):this._xmlText.delete(r,f.length);d+=f.length}else e=f,{nodeIndex:f}=
|
|
25
|
+
O(this,d,!1),e=M(a,e,this),c.splice(f,0,e),d+=1;else throw Error("Unexpected delta format");}}syncChildrenFromYjs(a){var b=this.getNode();if(null===b)throw this.getNode(),Error("Should never happen");var c=b.__key;const d=b.__children;var e=[];const f=d.length,h=this._children,g=h.length,k=a.collabNodeMap,m=new Set;let l,r;g!==f&&(r=R(b,r,e));let t=0;for(let z=0;z<g;z++){var n=d[t];const x=h[z];var p=x.getNode(),u=x._key;if(null!==p&&n===u){p=q.$isTextNode(p);m.add(n);if(p)if(x._key=n,x instanceof
|
|
26
|
+
N)p=x._xmlText,x.syncPropertiesFromYjs(a,null),x.applyChildrenYjsDelta(a,p.toDelta()),x.syncChildrenFromYjs(a);else if(x instanceof D)x.syncPropertiesAndTextFromYjs(a,null);else if(x instanceof Q)x.syncPropertiesFromYjs(a,null);else if(!(x instanceof B))throw Error("Should never happen");e[z]=n;t++}else{if(void 0===l)for(l=new Set,u=0;u<g;u++){var w=h[u]._key;""!==w&&l.add(w)}if(null===p||void 0===n||l.has(n)){r=R(b,r,e);n=a;p=x;u=c;w=p.getType();w=n.editor._nodes.get(w);if(void 0===w)throw Error("createLexicalNode failed");
|
|
27
|
+
w=new w.klass;w.__parent=u;p._key=w.__key;p instanceof N?(u=p._xmlText,p.syncPropertiesFromYjs(n,null),p.applyChildrenYjsDelta(n,u.toDelta()),p.syncChildrenFromYjs(n)):p instanceof D?p.syncPropertiesAndTextFromYjs(n,null):p instanceof Q&&p.syncPropertiesFromYjs(n,null);n.collabNodeMap.set(w.__key,p);n=w.__key;k.set(n,x);e[z]=n}else z--,t++}}for(b=0;b<f;b++)e=d[b],m.has(e)||(c=I(e).getWritable(),e=a.collabNodeMap.get(e),void 0!==e&&e.destroy(a),c.__parent=null)}syncPropertiesFromLexical(a,b,c){E(a,
|
|
28
|
+
this._xmlText,this.getPrevNode(c),b)}_syncChildFromLexical(a,b,c,d,e,f){b=this._children[b];c=I(c);b instanceof N&&q.$isElementNode(c)?(b.syncPropertiesFromLexical(a,c,d),b.syncChildrenFromLexical(a,c,d,e,f)):b instanceof D&&q.$isTextNode(c)?b.syncPropertiesAndTextFromLexical(a,c,d):b instanceof Q&&q.$isDecoratorNode(c)&&b.syncPropertiesFromLexical(a,c,d)}syncChildrenFromLexical(a,b,c,d,e){var f=this.getPrevNode(c);const h=null===f?[]:f.__children;f=b.__children;const g=h.length-1,k=f.length-1,m=
|
|
29
|
+
a.collabNodeMap;let l,r,t=0;for(b=0;t<=g&&b<=k;){var n=h[t];const u=f[b];if(n===u)this._syncChildFromLexical(a,b,u,c,d,e),t++,b++;else{void 0===l&&(l=new Set(h));void 0===r&&(r=new Set(f));var p=r.has(n);n=l.has(u);p?(p=I(u),p=J(a,p,this),m.set(u,p),n?(this.splice(a,b,1,p),t++):this.splice(a,b,0,p),b++):(this.splice(a,b,1),t++)}}c=t>g;d=b>k;if(c&&!d)for(;b<=k;++b)c=f[b],d=I(c),d=J(a,d,this),this.append(d),m.set(c,d);else if(d&&!c)for(f=this._children.length-1;f>=b;f--)this.splice(a,f,1)}append(a){const b=
|
|
30
|
+
this._xmlText;var c=this._children;c=c[c.length-1];c=void 0!==c?c.getOffset()+c.getSize():0;if(a instanceof N)b.insertEmbed(c,a._xmlText);else if(a instanceof D){const d=a._map;null===d.parent&&b.insertEmbed(c,d);b.insert(c+1,a._text)}else a instanceof B?b.insertEmbed(c,a._map):a instanceof Q&&b.insertEmbed(c,a._xmlElem);this._children.push(a)}splice(a,b,c,d){const e=this._children;var f=e[b];if(void 0===f)if(void 0!==d)this.append(d);else throw Error("Should never happen");else{var h=f.getOffset();
|
|
31
|
+
if(-1===h)throw Error("Should never happen");var g=this._xmlText;0!==c&&g.delete(h,f.getSize());d instanceof N?g.insertEmbed(h,d._xmlText):d instanceof D?(f=d._map,null===f.parent&&g.insertEmbed(h,f),g.insert(h+1,d._text)):d instanceof B?g.insertEmbed(h,d._map):d instanceof Q&&g.insertEmbed(h,d._xmlElem);if(0!==c)for(h=e.slice(b,b+c),g=0;g<h.length;g++)h[g].destroy(a);void 0!==d?e.splice(b,c,d):e.splice(b,c)}}getChildOffset(a){let b=0;const c=this._children;for(let d=0;d<c.length;d++){const e=c[d];
|
|
32
|
+
if(e===a)return b;b+=e.getSize()}return-1}destroy(a){const b=a.collabNodeMap,c=this._children;for(let d=0;d<c.length;d++)c[d].destroy(a);b.delete(this._key)}}function R(a,b,c){return void 0===b?(a=a.getWritable(),a.__children=c,a):b}function K(a,b,c){b=new N(a,b,c);return a._collabNode=b}
|
|
33
|
+
function S(a,b){b=b.collabNodeMap.get(a.key);if(void 0===b)return null;a=a.offset;let c=b.getSharedType();if(b instanceof D){c=b._parent._xmlText;b=b.getOffset();if(-1===b)return null;a=b+1+a}return v.createRelativePositionFromTypeIndex(c,a)}function T(a,b){if(null==a){if(null!=b)return!0}else if(null==b||!v.compareRelativePositions(a,b))return!0;return!1}function U(a,b){a=a.cursorsContainer;if(null!==a){b=b.selections;const c=b.length;for(let d=0;d<c;d++)a.removeChild(b[d])}}
|
|
34
|
+
function V(a,b){var c=b.awareness.getLocalState();if(null!==c&&(b=c.anchorPos,c=c.focusPos,null!==b&&null!==c&&(b=v.createAbsolutePositionFromRelativePosition(b,a.doc),a=v.createAbsolutePositionFromRelativePosition(c,a.doc),null!==b&&null!==a))){const [e,f]=W(b.type,b.index),[h,g]=W(a.type,a.index);if(null!==e&&null!==h){const k=e.getKey();a=h.getKey();b=q.$getSelection();if(q.$isRangeSelection(b)){var d=b.anchor;c=b.focus;if(d.key!==k||d.offset!==f)d=q.$getNodeByKey(k),b.anchor.set(k,f,q.$isElementNode(d)?
|
|
35
|
+
"element":"text");if(c.key!==a||c.offset!==g)c=q.$getNodeByKey(a),b.focus.set(a,g,q.$isElementNode(c)?"element":"text")}}}}function W(a,b){a=a._collabNode;if(void 0===a)return[null,0];if(a instanceof N){const {node:c,offset:d}=O(a,b,!0);return null===c?[a,0]:[c,d]}return[null,0]}
|
|
36
|
+
function X(a,b){var c=Array.from(b.awareness.getStates()),d=a.clientID;b=a.cursors;var e=a.editor._editorState._nodeMap;const f=new Set;for(var h=0;h<c.length;h++){const [z,x]=c[h];if(z!==d){f.add(z);const {anchorPos:Y,focusPos:Z,name:ha,color:ia,focusing:ja}=x;var g=null,k=b.get(z);void 0===k&&(k={color:ia,name:ha,selection:null},b.set(z,k));if(null!==Y&&null!==Z&&ja){var m=v.createAbsolutePositionFromRelativePosition(Y,a.doc),l=v.createAbsolutePositionFromRelativePosition(Z,a.doc);if(null!==m&&
|
|
37
|
+
null!==l){const [aa,ba]=W(m.type,m.index),[ca,da]=W(l.type,l.index);if(null!==aa&&null!==ca){l=aa.getKey();var r=ca.getKey();g=k.selection;if(null===g){m=k;g=l;l=ba;var t=da,n=m.color,p=document.createElement("span");p.style.cssText=`position:absolute;top:0;bottom:0;right:-1px;width:1px;background-color:rgb(${n});z-index:10;`;var u=document.createElement("span");u.textContent=m.name;u.style.cssText=`position:absolute;left:-2px;top:-16px;background-color:rgb(${n});color:#fff;line-height:12px;height:12px;font-size:12px;padding:2px;font-family:Arial;font-weight:bold;white-space:nowrap;`;
|
|
38
|
+
p.appendChild(u);g={anchor:{key:g,offset:l},caret:p,color:n,focus:{key:r,offset:t},name:u,selections:[]}}else m=g.anchor,t=g.focus,m.key=l,m.offset=ba,t.key=r,t.offset=da}}}m=a;l=k;n=g;t=e;r=m.editor;g=r.getRootElement();k=m.cursorsContainer;if(null!==k&&null!==g)if(g=l.selection,null===n)null!==g&&(l.selection=null,U(m,g));else{l.selection=n;g=n.caret;l=n.color;m=n.selections;p=n.anchor;n=n.focus;var w=n.key;u=t.get(p.key);t=t.get(w);if(null!=u&&null!=t&&(n=y.createDOMRange(r,u,p.offset,t,n.offset),
|
|
39
|
+
null!==n)){t=m.length;n=y.createRectsFromDOMRange(r,n);r=n.length;for(p=0;p<r;p++)u=n[p],w=m[p],void 0===w&&(w=document.createElement("span"),m[p]=w,k.appendChild(w)),w.style.cssText=`position:absolute;top:${u.top}px;left:${u.left}px;height:${u.height}px;width:${u.width}px;background-color:rgba(${l}, 0.3);pointer-events:none;z-index:5;`,p===r-1&&g.parentNode!==w&&w.appendChild(g);for(g=t-1;g>=r;g--)k.removeChild(m[g]),m.pop()}}}}c=Array.from(b.keys());for(d=0;d<c.length;d++)e=c[d],f.has(e)||(h=b.get(e),
|
|
40
|
+
void 0!==h&&(h=h.selection,null!==h&&U(a,h),b.delete(e)))}function fa(a,b,c,d){b=b.awareness;var e=b.getLocalState();if(null!==e){var {anchorPos:f,focusPos:h,name:g,color:k,focusing:m}=e,l=e=null;if(null!==d&&(null===f||d.is(c))||null!==c)q.$isRangeSelection(d)&&(e=S(d.anchor,a),l=S(d.focus,a)),(T(f,e)||T(h,l))&&b.setLocalState({anchorPos:e,color:k,focusPos:l,focusing:m,name:g})}}const ka=q.createCommand(),la=q.createCommand();exports.CONNECTED_COMMAND=ka;exports.TOGGLE_CONNECT_COMMAND=la;
|
|
41
|
+
exports.createBinding=function(a,b,c,d,e){if(void 0===d||null===d)throw Error("Should never happen");b=d.get("root",v.XmlText);b=K(b,null,"root");b._key="root";return{clientID:d.clientID,collabNodeMap:new Map,cursors:new Map,cursorsContainer:null,doc:d,docMap:e,editor:a,id:c,nodeProperties:new Map,root:b}};exports.createUndoManager=function(a,b){return new v.UndoManager(b,{trackedOrigins:new Set([a,null])})};
|
|
42
|
+
exports.initLocalState=function(a,b,c,d){a.awareness.setLocalState({anchorPos:null,color:c,focusPos:null,focusing:d,name:b})};exports.setLocalStateFocus=function(a,b,c,d){({awareness:a}=a);let e=a.getLocalState();null===e&&(e={anchorPos:null,color:c,focusPos:null,focusing:d,name:b});e.focusing=d;a.setLocalState(e)};exports.syncCursorPositions=X;
|
|
43
|
+
exports.syncLexicalUpdateToYjs=function(a,b,c,d,e,f,h,g){ea(a,()=>{d.read(()=>{if(g.has("collaboration")){if(0<h.size){var k=Array.from(h),m=a.collabNodeMap,l=[];for(let p=0;p<k.length;p++){var r=k[p],t=q.$getNodeByKey(r),n=m.get(r);if(n instanceof D)if(q.$isTextNode(t))l.push([n,t.__text]);else{t=n.getOffset();if(-1===t)continue;const u=n._parent;n._normalized=!0;u._xmlText.delete(t,1);m.delete(r);r=u._children;n=r.indexOf(n);r.splice(n,1)}}for(k=0;k<l.length;k++){const [p,u]=l[k];p._text=u}}}else e.has("root")&&
|
|
44
|
+
(l=c._nodeMap,k=q.$getRoot(),m=a.root,m.syncPropertiesFromLexical(a,k,l),m.syncChildrenFromLexical(a,k,l,e,f)),l=q.$getSelection(),fa(a,b,c._selection,l)})})};
|
|
45
|
+
exports.syncYjsChangesToLexical=function(a,b,c){const d=a.editor,e=d._editorState;d.update(()=>{var f=d._pendingEditorState;for(var h=0;h<c.length;h++){var g=a,k=c[h],{target:m}=k;m=M(g,m);if(m instanceof N&&k instanceof v.YTextEvent){const {keysChanged:l,childListChanged:r,delta:t}=k;0<l.size&&m.syncPropertiesFromYjs(g,l);r&&(m.applyChildrenYjsDelta(g,t),m.syncChildrenFromYjs(g))}else if(m instanceof D&&k instanceof v.YMapEvent)({keysChanged:k}=k),0<k.size&&m.syncPropertiesAndTextFromYjs(g,k);else if(m instanceof
|
|
46
|
+
Q&&k instanceof v.YXmlEvent)({attributesChanged:k}=k),0<k.size&&m.syncPropertiesFromYjs(g,k);else throw Error("Should never happen");}h=q.$getSelection();if(q.$isRangeSelection(h))if(P(h)){g=e._selection;if(q.$isRangeSelection(g)){m=A.$createOffsetView(d,0,e);f=A.$createOffsetView(d,0,f);const [l,r]=m.getOffsetsFromSelection(g);f=f.createSelectionFromOffsets(l,r,m);null!==f?q.$setSelection(f):(V(a,b),P(h)&&(f=q.$getRoot(),0===f.getChildrenSize()&&f.append(q.$createParagraphNode()),q.$getRoot().selectEnd()))}fa(a,
|
|
47
|
+
b,g,q.$getSelection())}else V(a,b)},{onUpdate:()=>{X(a,b)},skipTransforms:!0,tag:"collaboration"})};
|
package/package.json
CHANGED
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
"crdt"
|
|
12
12
|
],
|
|
13
13
|
"license": "MIT",
|
|
14
|
-
"version": "0.2.
|
|
14
|
+
"version": "0.2.8",
|
|
15
15
|
"main": "LexicalYjs.js",
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@lexical/offset": "0.2.
|
|
17
|
+
"@lexical/offset": "0.2.8"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
|
-
"lexical": "0.2.
|
|
20
|
+
"lexical": "0.2.8",
|
|
21
21
|
"yjs": ">=13.5.22"
|
|
22
22
|
},
|
|
23
23
|
"repository": {
|