@lexical/yjs 0.44.1-nightly.20260518.0 → 0.45.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/{LexicalYjs.dev.js → dist/LexicalYjs.dev.js} +1 -1
- package/{LexicalYjs.dev.mjs → dist/LexicalYjs.dev.mjs} +1 -1
- package/{RenderSnapshot.d.ts → dist/RenderSnapshot.d.ts} +0 -7
- package/dist/simpleDiffWithCursor.d.ts +12 -0
- package/package.json +31 -16
- package/src/Bindings.ts +135 -0
- package/src/CollabDecoratorNode.ts +112 -0
- package/src/CollabElementNode.ts +696 -0
- package/src/CollabLineBreakNode.ts +70 -0
- package/src/CollabTextNode.ts +179 -0
- package/src/CollabV2Mapping.ts +117 -0
- package/src/RenderSnapshot.ts +97 -0
- package/src/SyncCursors.ts +823 -0
- package/src/SyncEditorStates.ts +469 -0
- package/src/SyncV2.ts +871 -0
- package/src/Utils.ts +648 -0
- package/src/index.ts +151 -0
- package/src/simpleDiffWithCursor.ts +49 -0
- package/src/types.ts +27 -0
- /package/{Bindings.d.ts → dist/Bindings.d.ts} +0 -0
- /package/{CollabDecoratorNode.d.ts → dist/CollabDecoratorNode.d.ts} +0 -0
- /package/{CollabElementNode.d.ts → dist/CollabElementNode.d.ts} +0 -0
- /package/{CollabLineBreakNode.d.ts → dist/CollabLineBreakNode.d.ts} +0 -0
- /package/{CollabTextNode.d.ts → dist/CollabTextNode.d.ts} +0 -0
- /package/{CollabV2Mapping.d.ts → dist/CollabV2Mapping.d.ts} +0 -0
- /package/{LexicalYjs.js → dist/LexicalYjs.js} +0 -0
- /package/{LexicalYjs.js.flow → dist/LexicalYjs.js.flow} +0 -0
- /package/{LexicalYjs.mjs → dist/LexicalYjs.mjs} +0 -0
- /package/{LexicalYjs.node.mjs → dist/LexicalYjs.node.mjs} +0 -0
- /package/{LexicalYjs.prod.js → dist/LexicalYjs.prod.js} +0 -0
- /package/{LexicalYjs.prod.mjs → dist/LexicalYjs.prod.mjs} +0 -0
- /package/{SyncCursors.d.ts → dist/SyncCursors.d.ts} +0 -0
- /package/{SyncEditorStates.d.ts → dist/SyncEditorStates.d.ts} +0 -0
- /package/{SyncV2.d.ts → dist/SyncV2.d.ts} +0 -0
- /package/{Utils.d.ts → dist/Utils.d.ts} +0 -0
- /package/{index.d.ts → dist/index.d.ts} +0 -0
- /package/{types.d.ts → dist/types.d.ts} +0 -0
|
@@ -1837,7 +1837,7 @@ const renderSnapshot__EXPERIMENTAL = (binding, snapshot = yjs.snapshot(binding.d
|
|
|
1837
1837
|
}
|
|
1838
1838
|
doc.transact(transaction => {
|
|
1839
1839
|
// Before rendering, we are going to sanitize ops and split deleted ops
|
|
1840
|
-
// if they were deleted by
|
|
1840
|
+
// if they were deleted by separate users.
|
|
1841
1841
|
const pud = new yjs.PermanentUserData(doc);
|
|
1842
1842
|
if (pud) {
|
|
1843
1843
|
pud.dss.forEach(ds => {
|
|
@@ -1835,7 +1835,7 @@ const renderSnapshot__EXPERIMENTAL = (binding, snapshot$1 = snapshot(binding.doc
|
|
|
1835
1835
|
}
|
|
1836
1836
|
doc.transact(transaction => {
|
|
1837
1837
|
// Before rendering, we are going to sanitize ops and split deleted ops
|
|
1838
|
-
// if they were deleted by
|
|
1838
|
+
// if they were deleted by separate users.
|
|
1839
1839
|
const pud = new PermanentUserData(doc);
|
|
1840
1840
|
if (pud) {
|
|
1841
1841
|
pud.dss.forEach(ds => {
|
|
@@ -1,10 +1,3 @@
|
|
|
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
1
|
import { LexicalNode } from 'lexical';
|
|
9
2
|
import { ID, Snapshot } from 'yjs';
|
|
10
3
|
import { BindingV2 } from './Bindings';
|
|
@@ -0,0 +1,12 @@
|
|
|
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
|
+
export default function simpleDiffWithCursor(a: string, b: string, cursor: number): {
|
|
9
|
+
index: number;
|
|
10
|
+
insert: string;
|
|
11
|
+
remove: number;
|
|
12
|
+
};
|
package/package.json
CHANGED
|
@@ -11,12 +11,13 @@
|
|
|
11
11
|
"crdt"
|
|
12
12
|
],
|
|
13
13
|
"license": "MIT",
|
|
14
|
-
"version": "0.
|
|
15
|
-
"main": "LexicalYjs.js",
|
|
16
|
-
"types": "index.d.ts",
|
|
14
|
+
"version": "0.45.0",
|
|
15
|
+
"main": "./dist/LexicalYjs.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@lexical/
|
|
19
|
-
"lexical": "0.
|
|
18
|
+
"@lexical/internal": "0.45.0",
|
|
19
|
+
"@lexical/selection": "0.45.0",
|
|
20
|
+
"lexical": "0.45.0"
|
|
20
21
|
},
|
|
21
22
|
"devDependencies": {
|
|
22
23
|
"yjs": "^13.6.30"
|
|
@@ -29,23 +30,37 @@
|
|
|
29
30
|
"url": "git+https://github.com/facebook/lexical.git",
|
|
30
31
|
"directory": "packages/lexical-yjs"
|
|
31
32
|
},
|
|
32
|
-
"module": "LexicalYjs.mjs",
|
|
33
|
+
"module": "./dist/LexicalYjs.mjs",
|
|
33
34
|
"sideEffects": false,
|
|
34
35
|
"exports": {
|
|
35
36
|
".": {
|
|
37
|
+
"source": "./src/index.ts",
|
|
36
38
|
"import": {
|
|
37
|
-
"types": "./index.d.ts",
|
|
38
|
-
"development": "./LexicalYjs.dev.mjs",
|
|
39
|
-
"production": "./LexicalYjs.prod.mjs",
|
|
40
|
-
"node": "./LexicalYjs.node.mjs",
|
|
41
|
-
"default": "./LexicalYjs.mjs"
|
|
39
|
+
"types": "./dist/index.d.ts",
|
|
40
|
+
"development": "./dist/LexicalYjs.dev.mjs",
|
|
41
|
+
"production": "./dist/LexicalYjs.prod.mjs",
|
|
42
|
+
"node": "./dist/LexicalYjs.node.mjs",
|
|
43
|
+
"default": "./dist/LexicalYjs.mjs"
|
|
42
44
|
},
|
|
43
45
|
"require": {
|
|
44
|
-
"types": "./index.d.ts",
|
|
45
|
-
"development": "./LexicalYjs.dev.js",
|
|
46
|
-
"production": "./LexicalYjs.prod.js",
|
|
47
|
-
"default": "./LexicalYjs.js"
|
|
46
|
+
"types": "./dist/index.d.ts",
|
|
47
|
+
"development": "./dist/LexicalYjs.dev.js",
|
|
48
|
+
"production": "./dist/LexicalYjs.prod.js",
|
|
49
|
+
"default": "./dist/LexicalYjs.js"
|
|
48
50
|
}
|
|
49
51
|
}
|
|
50
|
-
}
|
|
52
|
+
},
|
|
53
|
+
"files": [
|
|
54
|
+
"dist",
|
|
55
|
+
"src",
|
|
56
|
+
"!src/__tests__",
|
|
57
|
+
"!src/__bench__",
|
|
58
|
+
"!src/__mocks__",
|
|
59
|
+
"!src/**/*.test.ts",
|
|
60
|
+
"!src/**/*.test.tsx",
|
|
61
|
+
"!src/**/*.bench.ts",
|
|
62
|
+
"!src/**/*.bench.tsx",
|
|
63
|
+
"README.md",
|
|
64
|
+
"LICENSE"
|
|
65
|
+
]
|
|
51
66
|
}
|
package/src/Bindings.ts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
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
|
+
|
|
9
|
+
import type {CollabDecoratorNode} from './CollabDecoratorNode';
|
|
10
|
+
import type {CollabElementNode} from './CollabElementNode';
|
|
11
|
+
import type {CollabLineBreakNode} from './CollabLineBreakNode';
|
|
12
|
+
import type {CollabTextNode} from './CollabTextNode';
|
|
13
|
+
import type {Cursor} from './SyncCursors';
|
|
14
|
+
import type {LexicalEditor, NodeKey} from 'lexical';
|
|
15
|
+
|
|
16
|
+
import invariant from '@lexical/internal/invariant';
|
|
17
|
+
import {Klass, LexicalNode} from 'lexical';
|
|
18
|
+
import {Doc, XmlElement, XmlText} from 'yjs';
|
|
19
|
+
|
|
20
|
+
import {Provider} from '.';
|
|
21
|
+
import {$createCollabElementNode} from './CollabElementNode';
|
|
22
|
+
import {CollabV2Mapping} from './CollabV2Mapping';
|
|
23
|
+
import {initializeNodeProperties} from './Utils';
|
|
24
|
+
|
|
25
|
+
export type ClientID = number;
|
|
26
|
+
export interface BaseBinding {
|
|
27
|
+
clientID: number;
|
|
28
|
+
cursors: Map<ClientID, Cursor>;
|
|
29
|
+
cursorsContainer: null | HTMLElement;
|
|
30
|
+
doc: Doc;
|
|
31
|
+
docMap: Map<string, Doc>;
|
|
32
|
+
editor: LexicalEditor;
|
|
33
|
+
id: string;
|
|
34
|
+
nodeProperties: Map<string, {[property: string]: unknown}>; // node type to property to default value
|
|
35
|
+
excludedProperties: ExcludedProperties;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface Binding extends BaseBinding {
|
|
39
|
+
collabNodeMap: Map<
|
|
40
|
+
NodeKey,
|
|
41
|
+
| CollabElementNode
|
|
42
|
+
| CollabTextNode
|
|
43
|
+
| CollabDecoratorNode
|
|
44
|
+
| CollabLineBreakNode
|
|
45
|
+
>;
|
|
46
|
+
root: CollabElementNode;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface BindingV2 extends BaseBinding {
|
|
50
|
+
mapping: CollabV2Mapping;
|
|
51
|
+
root: XmlElement;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export type AnyBinding = Binding | BindingV2;
|
|
55
|
+
|
|
56
|
+
export type ExcludedProperties = Map<Klass<LexicalNode>, Set<string>>;
|
|
57
|
+
|
|
58
|
+
function createBaseBinding(
|
|
59
|
+
editor: LexicalEditor,
|
|
60
|
+
id: string,
|
|
61
|
+
doc: Doc | null | undefined,
|
|
62
|
+
docMap: Map<string, Doc>,
|
|
63
|
+
excludedProperties?: ExcludedProperties,
|
|
64
|
+
): BaseBinding {
|
|
65
|
+
invariant(
|
|
66
|
+
doc !== undefined && doc !== null,
|
|
67
|
+
'createBinding: doc is null or undefined',
|
|
68
|
+
);
|
|
69
|
+
const binding = {
|
|
70
|
+
clientID: doc.clientID,
|
|
71
|
+
cursors: new Map(),
|
|
72
|
+
cursorsContainer: null,
|
|
73
|
+
doc,
|
|
74
|
+
docMap,
|
|
75
|
+
editor,
|
|
76
|
+
excludedProperties: excludedProperties || new Map(),
|
|
77
|
+
id,
|
|
78
|
+
nodeProperties: new Map(),
|
|
79
|
+
};
|
|
80
|
+
initializeNodeProperties(binding);
|
|
81
|
+
return binding;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function createBinding(
|
|
85
|
+
editor: LexicalEditor,
|
|
86
|
+
provider: Provider,
|
|
87
|
+
id: string,
|
|
88
|
+
doc: Doc | null | undefined,
|
|
89
|
+
docMap: Map<string, Doc>,
|
|
90
|
+
excludedProperties?: ExcludedProperties,
|
|
91
|
+
): Binding {
|
|
92
|
+
invariant(
|
|
93
|
+
doc !== undefined && doc !== null,
|
|
94
|
+
'createBinding: doc is null or undefined',
|
|
95
|
+
);
|
|
96
|
+
const rootXmlText = doc.get('root', XmlText) as XmlText;
|
|
97
|
+
const root: CollabElementNode = $createCollabElementNode(
|
|
98
|
+
rootXmlText,
|
|
99
|
+
null,
|
|
100
|
+
'root',
|
|
101
|
+
);
|
|
102
|
+
root._key = 'root';
|
|
103
|
+
return {
|
|
104
|
+
...createBaseBinding(editor, id, doc, docMap, excludedProperties),
|
|
105
|
+
collabNodeMap: new Map(),
|
|
106
|
+
root,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function createBindingV2__EXPERIMENTAL(
|
|
111
|
+
editor: LexicalEditor,
|
|
112
|
+
id: string,
|
|
113
|
+
doc: Doc | null | undefined,
|
|
114
|
+
docMap: Map<string, Doc>,
|
|
115
|
+
options: {excludedProperties?: ExcludedProperties; rootName?: string} = {},
|
|
116
|
+
): BindingV2 {
|
|
117
|
+
invariant(
|
|
118
|
+
doc !== undefined && doc !== null,
|
|
119
|
+
'createBinding: doc is null or undefined',
|
|
120
|
+
);
|
|
121
|
+
const {excludedProperties, rootName = 'root-v2'} = options;
|
|
122
|
+
return {
|
|
123
|
+
...createBaseBinding(editor, id, doc, docMap, excludedProperties),
|
|
124
|
+
mapping: new CollabV2Mapping(),
|
|
125
|
+
root: doc.get(rootName, XmlElement) as XmlElement,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function isBindingV1(binding: BaseBinding): binding is Binding {
|
|
130
|
+
return Object.prototype.hasOwnProperty.call(binding, 'collabNodeMap');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function isBindingV2(binding: BaseBinding): binding is BindingV2 {
|
|
134
|
+
return Object.prototype.hasOwnProperty.call(binding, 'mapping');
|
|
135
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
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
|
+
|
|
9
|
+
import type {Binding} from '.';
|
|
10
|
+
import type {CollabElementNode} from './CollabElementNode';
|
|
11
|
+
import type {DecoratorNode, NodeKey, NodeMap} from 'lexical';
|
|
12
|
+
import type {XmlElement} from 'yjs';
|
|
13
|
+
|
|
14
|
+
import invariant from '@lexical/internal/invariant';
|
|
15
|
+
import {$getNodeByKey, $isDecoratorNode} from 'lexical';
|
|
16
|
+
|
|
17
|
+
import {$syncPropertiesFromYjs, syncPropertiesFromLexical} from './Utils';
|
|
18
|
+
|
|
19
|
+
export class CollabDecoratorNode {
|
|
20
|
+
_xmlElem: XmlElement;
|
|
21
|
+
_key: NodeKey;
|
|
22
|
+
_parent: CollabElementNode;
|
|
23
|
+
_type: string;
|
|
24
|
+
|
|
25
|
+
constructor(xmlElem: XmlElement, parent: CollabElementNode, type: string) {
|
|
26
|
+
this._key = '';
|
|
27
|
+
this._xmlElem = xmlElem;
|
|
28
|
+
this._parent = parent;
|
|
29
|
+
this._type = type;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
getPrevNode(nodeMap: null | NodeMap): null | DecoratorNode<unknown> {
|
|
33
|
+
if (nodeMap === null) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const node = nodeMap.get(this._key);
|
|
38
|
+
return $isDecoratorNode(node) ? node : null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
getNode(): null | DecoratorNode<unknown> {
|
|
42
|
+
const node = $getNodeByKey(this._key);
|
|
43
|
+
return $isDecoratorNode(node) ? node : null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
getSharedType(): XmlElement {
|
|
47
|
+
return this._xmlElem;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
getType(): string {
|
|
51
|
+
return this._type;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
getKey(): NodeKey {
|
|
55
|
+
return this._key;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
getSize(): number {
|
|
59
|
+
return 1;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
getOffset(): number {
|
|
63
|
+
const collabElementNode = this._parent;
|
|
64
|
+
return collabElementNode.getChildOffset(this);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
syncPropertiesFromLexical(
|
|
68
|
+
binding: Binding,
|
|
69
|
+
nextLexicalNode: DecoratorNode<unknown>,
|
|
70
|
+
prevNodeMap: null | NodeMap,
|
|
71
|
+
): void {
|
|
72
|
+
const prevLexicalNode = this.getPrevNode(prevNodeMap);
|
|
73
|
+
const xmlElem = this._xmlElem;
|
|
74
|
+
|
|
75
|
+
syncPropertiesFromLexical(
|
|
76
|
+
binding,
|
|
77
|
+
xmlElem,
|
|
78
|
+
prevLexicalNode,
|
|
79
|
+
nextLexicalNode,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
syncPropertiesFromYjs(
|
|
84
|
+
binding: Binding,
|
|
85
|
+
keysChanged: null | Set<string>,
|
|
86
|
+
): void {
|
|
87
|
+
const lexicalNode = this.getNode();
|
|
88
|
+
invariant(
|
|
89
|
+
lexicalNode !== null,
|
|
90
|
+
'syncPropertiesFromYjs: could not find decorator node',
|
|
91
|
+
);
|
|
92
|
+
const xmlElem = this._xmlElem;
|
|
93
|
+
$syncPropertiesFromYjs(binding, xmlElem, lexicalNode, keysChanged);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
destroy(binding: Binding): void {
|
|
97
|
+
const collabNodeMap = binding.collabNodeMap;
|
|
98
|
+
if (collabNodeMap.get(this._key) === this) {
|
|
99
|
+
collabNodeMap.delete(this._key);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function $createCollabDecoratorNode(
|
|
105
|
+
xmlElem: XmlElement,
|
|
106
|
+
parent: CollabElementNode,
|
|
107
|
+
type: string,
|
|
108
|
+
): CollabDecoratorNode {
|
|
109
|
+
const collabNode = new CollabDecoratorNode(xmlElem, parent, type);
|
|
110
|
+
xmlElem._collabNode = collabNode;
|
|
111
|
+
return collabNode;
|
|
112
|
+
}
|