@textbus/collaborate 2.0.0-alpha.74 → 2.0.0-alpha.78

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import { Injectable } from '@tanbo/di'
2
- import { filter, microTask, Observable, Subject, Subscription } from '@tanbo/stream'
2
+ import { merge, microTask, Observable, Subject, Subscription } from '@tanbo/stream'
3
3
  import {
4
4
  RootComponentRef,
5
5
  Starter,
@@ -7,13 +7,21 @@ import {
7
7
  Registry,
8
8
  Selection,
9
9
  SelectionPaths,
10
- History, Renderer
10
+ History, Renderer, Slot, ComponentInstance, makeError, Slots, Formats
11
11
  } from '@textbus/core'
12
- import { Doc as YDoc, UndoManager } from 'yjs'
13
- import { LocalToRemote } from './collab/local-to-remote'
14
- import { RemoteToLocal } from './collab/remote-to-local'
12
+ import {
13
+ Doc as YDoc,
14
+ Map as YMap,
15
+ Text as YText,
16
+ Array as YArray,
17
+ UndoManager,
18
+ Transaction
19
+ } from 'yjs'
20
+
15
21
  import { CollaborateCursor, RemoteSelection } from './collab/_api'
16
22
 
23
+ const collaborateErrorFn = makeError('Collaborate')
24
+
17
25
  @Injectable()
18
26
  export class Collaborate implements History {
19
27
  onSelectionChange: Observable<SelectionPaths>
@@ -31,9 +39,6 @@ export class Collaborate implements History {
31
39
  return this.manager?.canRedo()
32
40
  }
33
41
 
34
- private localToRemote = new LocalToRemote()
35
- private remoteToLocal = new RemoteToLocal(this.yDoc, this.translator, this.selection, this.registry)
36
-
37
42
  private backEvent = new Subject<void>()
38
43
  private forwardEvent = new Subject<void>()
39
44
  private changeEvent = new Subject<void>()
@@ -42,7 +47,7 @@ export class Collaborate implements History {
42
47
  private manager!: UndoManager
43
48
 
44
49
  private subscriptions: Subscription[] = []
45
- private updateFromSelf = true
50
+ private updateFromRemote = false
46
51
 
47
52
  private selectionChangeEvent = new Subject<SelectionPaths>()
48
53
 
@@ -102,32 +107,316 @@ export class Collaborate implements History {
102
107
  this.manager = new UndoManager(root, {
103
108
  trackedOrigins: new Set<any>([this.yDoc])
104
109
  })
105
- root.observeDeep((events, transaction) => {
106
- if (transaction.origin === this.yDoc) {
107
- return
108
- }
109
- this.updateFromSelf = false
110
+ this.syncContent(root, rootComponent.slots.get(0)!)
110
111
 
111
- this.remoteToLocal.transform(events, rootComponent)
112
- this.renderer.render()
113
- this.selection.restore()
114
- this.updateFromSelf = true
115
- })
116
112
  this.subscriptions.push(
117
- this.rootComponentRef.component.changeMarker.onChange.pipe(
118
- filter(() => {
119
- return this.updateFromSelf
120
- }),
113
+ merge(
114
+ rootComponent.changeMarker.onForceChange,
115
+ rootComponent.changeMarker.onChange
116
+ ).pipe(
121
117
  microTask()
122
- ).subscribe((operations) => {
123
- this.yDoc.transact(() => {
124
- operations.forEach(operation => {
125
- this.localToRemote.transform(operation, root)
126
- })
127
- }, this.yDoc)
118
+ ).subscribe(() => {
128
119
  this.renderer.render()
129
120
  this.selection.restore()
130
121
  })
131
122
  )
132
123
  }
124
+
125
+ private syncContent(content: YText, slot: Slot) {
126
+ content.observe((ev, tr) => {
127
+ this.runRemoteUpdate(tr, () => {
128
+ slot.retain(0)
129
+ ev.delta.forEach(action => {
130
+ if (Reflect.has(action, 'retain')) {
131
+ if (action.attributes) {
132
+ slot.retain(action.retain!, Object.keys(action.attributes).map(key => {
133
+ return [this.registry.getFormatter(key)!, action.attributes![key]]
134
+ }))
135
+ }
136
+ slot.retain(action.retain!)
137
+ } else if (action.insert) {
138
+ const index = slot.index
139
+ let length = 1
140
+ if (typeof action.insert === 'string') {
141
+ length = action.insert.length
142
+ const attrs: Formats = action.attributes ? Object.keys(action.attributes).map(key => {
143
+ return [this.registry.getFormatter(key)!, action.attributes![key]]
144
+ }) : []
145
+ slot.insert(action.insert, attrs)
146
+ } else {
147
+ const sharedComponent = action.insert as YMap<any>
148
+ const component = this.createComponentBySharedComponent(sharedComponent)
149
+ this.syncSlots(sharedComponent.get('slots'), component.slots)
150
+ this.syncComponent(sharedComponent, component)
151
+ slot.insert(component)
152
+ }
153
+ if (this.selection.isSelected) {
154
+ if (slot === this.selection.startSlot && this.selection.startOffset! >= index) {
155
+ this.selection.setStart(slot, this.selection.startOffset! + length)
156
+ }
157
+ if (slot === this.selection.endSlot && this.selection.endOffset! >= index) {
158
+ this.selection.setEnd(slot, this.selection.endOffset! + length)
159
+ }
160
+ }
161
+ } else if (action.delete) {
162
+ const index = slot.index
163
+ slot.retain(slot.index)
164
+ slot.delete(action.delete)
165
+ if (this.selection.isSelected) {
166
+ if (slot === this.selection.startSlot && this.selection.startOffset! >= index) {
167
+ this.selection.setStart(slot, this.selection.startOffset! - action.delete)
168
+ }
169
+ if (slot === this.selection.endSlot && this.selection.endOffset! >= index) {
170
+ this.selection.setEnd(slot, this.selection.endOffset! - action.delete)
171
+ }
172
+ }
173
+ } else if (action.attributes) {
174
+ slot.updateState(draft => {
175
+ Object.assign(draft, action.attributes)
176
+ })
177
+ }
178
+ })
179
+ })
180
+ })
181
+
182
+ slot.onContentChange.subscribe(actions => {
183
+ this.runLocalUpdate(() => {
184
+ let offset = 0
185
+ let length = 0
186
+ for (const action of actions) {
187
+ if (action.type === 'retain') {
188
+ if (action.formats) {
189
+ content.format(offset, action.offset, action.formats)
190
+ } else {
191
+ offset = action.offset
192
+ }
193
+ } else if (action.type === 'insert') {
194
+ const delta = content.toDelta()
195
+ const isEmpty = delta.length === 1 && delta[0].insert === Slot.emptyPlaceholder
196
+ if (typeof action.content === 'string') {
197
+ length = action.content.length
198
+ content.insert(offset, action.content)
199
+ } else {
200
+ length = 1
201
+ const component = slot.getContentAtIndex(offset) as ComponentInstance
202
+ const sharedComponent = this.createSharedComponentByComponent(component)
203
+ content.insertEmbed(offset, sharedComponent)
204
+ }
205
+ if (action.formats) {
206
+ content.format(offset, length, action.formats)
207
+ }
208
+ if (isEmpty && offset === 0) {
209
+ content.delete(content.length - 1, 1)
210
+ }
211
+ offset += length
212
+ } else if (action.type === 'delete') {
213
+ const delta = content.toDelta()
214
+ content.delete(offset, action.count)
215
+ if (content.length === 0) {
216
+ content.insert(0, '\n', delta[0]?.attributes)
217
+ }
218
+ }
219
+ }
220
+ })
221
+ })
222
+ }
223
+
224
+ private syncSlot(remoteSlot: YMap<any>, slot: Slot) {
225
+ remoteSlot.observe((ev, tr) => {
226
+ this.runRemoteUpdate(tr, () => {
227
+ ev.keysChanged.forEach(key => {
228
+ if (key === 'state') {
229
+ const state = (ev.target as YMap<any>).get('state')
230
+ slot.updateState(draft => {
231
+ Object.assign(draft, state)
232
+ })
233
+ }
234
+ })
235
+ })
236
+ })
237
+
238
+ slot.onStateChange.subscribe(actions => {
239
+ this.runLocalUpdate(() => {
240
+ actions.forEach(action => {
241
+ remoteSlot.set('state', action.value)
242
+ })
243
+ })
244
+ })
245
+ }
246
+
247
+ private syncSlots(remoteSlots: YArray<any>, slots: Slots) {
248
+ remoteSlots.observe((ev, tr) => {
249
+ this.runRemoteUpdate(tr, () => {
250
+ ev.delta.forEach(action => {
251
+ if (Reflect.has(action, 'retain')) {
252
+ slots.retain(action.retain!)
253
+ } else if (action.insert) {
254
+ (action.insert as Array<YMap<any>>).forEach(item => {
255
+ const slot = this.createSlotBySharedSlot(item)
256
+ slots.insert(slot)
257
+ this.syncContent(item.get('content'), slot)
258
+ this.syncSlot(item, slot)
259
+ })
260
+ } else if (action.delete) {
261
+ slots.retain(slots.index)
262
+ slots.delete(action.delete)
263
+ }
264
+ })
265
+ })
266
+ })
267
+
268
+ slots.onChange.subscribe(operations => {
269
+ this.runLocalUpdate(() => {
270
+ const applyActions = operations.apply
271
+ let index: number
272
+ applyActions.forEach(action => {
273
+ if (action.type === 'retain') {
274
+ index = action.offset
275
+ } else if (action.type === 'insertSlot') {
276
+ const slot = slots.get(index)!
277
+ const sharedSlot = this.createSharedSlotBySlot(slot)
278
+ remoteSlots.insert(index, [sharedSlot])
279
+ index++
280
+ } else if (action.type === 'delete') {
281
+ remoteSlots.delete(index, action.count)
282
+ }
283
+ })
284
+ })
285
+ })
286
+ }
287
+
288
+ private syncComponent(remoteComponent: YMap<any>, component: ComponentInstance) {
289
+ remoteComponent.observe((ev, tr) => {
290
+ this.runRemoteUpdate(tr, () => {
291
+ ev.keysChanged.forEach(key => {
292
+ if (key === 'state') {
293
+ const state = (ev.target as YMap<any>).get('state')
294
+ component.updateState(draft => {
295
+ Object.assign(draft, state)
296
+ })
297
+ }
298
+ })
299
+ })
300
+ })
301
+
302
+ component.onStateChange.subscribe(newState => {
303
+ this.runLocalUpdate(() => {
304
+ remoteComponent.set('state', newState)
305
+ })
306
+ })
307
+ }
308
+
309
+ private runLocalUpdate(fn: () => void) {
310
+ if (this.updateFromRemote) {
311
+ return
312
+ }
313
+ fn()
314
+ }
315
+
316
+ private runRemoteUpdate(tr: Transaction, fn: () => void) {
317
+ if (!tr.origin) {
318
+ return
319
+ }
320
+ this.updateFromRemote = true
321
+ fn()
322
+ this.updateFromRemote = false
323
+ }
324
+
325
+ private createSharedComponentByComponent(component: ComponentInstance): YMap<any> {
326
+ const sharedComponent = new YMap()
327
+ sharedComponent.set('state', component.state)
328
+ sharedComponent.set('name', component.name)
329
+ const sharedSlots = new YArray()
330
+ sharedComponent.set('slots', sharedSlots)
331
+ component.slots.toArray().forEach(slot => {
332
+ const sharedSlot = this.createSharedSlotBySlot(slot)
333
+ sharedSlots.push([sharedSlot])
334
+ })
335
+ this.syncSlots(sharedSlots, component.slots)
336
+ this.syncComponent(sharedComponent, component)
337
+ return sharedComponent
338
+ }
339
+
340
+ private createSharedSlotBySlot(slot: Slot): YMap<any> {
341
+ const sharedSlot = new YMap()
342
+ sharedSlot.set('schema', slot.schema)
343
+ sharedSlot.set('state', slot.state)
344
+ const sharedContent = new YText()
345
+ sharedSlot.set('content', sharedContent)
346
+ let offset = 0
347
+ slot.toDelta().forEach(i => {
348
+ let formats: any = {}
349
+ if (i.formats) {
350
+ i.formats.forEach(item => {
351
+ formats[item[0].name] = item[1]
352
+ })
353
+ } else {
354
+ formats = null
355
+ }
356
+ if (typeof i.insert === 'string') {
357
+ sharedContent.insert(offset, i.insert, formats)
358
+ } else {
359
+ const sharedComponent = this.createSharedComponentByComponent(i.insert)
360
+ sharedContent.insertEmbed(offset, sharedComponent, formats)
361
+ }
362
+ offset += i.insert.length
363
+ })
364
+ this.syncContent(sharedContent, slot)
365
+ this.syncSlot(sharedSlot, slot)
366
+ return sharedSlot
367
+ }
368
+
369
+ private createComponentBySharedComponent(yMap: YMap<any>): ComponentInstance {
370
+ const sharedSlots = yMap.get('slots') as YArray<YMap<any>>
371
+ const slots: Slot[] = []
372
+ sharedSlots.forEach(sharedSlot => {
373
+ const slot = this.createSlotBySharedSlot(sharedSlot)
374
+ slots.push(slot)
375
+ })
376
+ const name = yMap.get('name')
377
+ const instance = this.translator.createComponentByData(name, {
378
+ state: yMap.get('state'),
379
+ slots
380
+ })
381
+ if (instance) {
382
+ instance.slots.toArray().forEach((slot, index) => {
383
+ const sharedSlot = sharedSlots.get(index)
384
+ this.syncSlot(sharedSlot, slot)
385
+ this.syncContent(sharedSlot.get('content'), slot)
386
+ })
387
+ return instance
388
+ }
389
+ throw collaborateErrorFn(`cannot find component factory \`${name}\`.`)
390
+ }
391
+
392
+ private createSlotBySharedSlot(sharedSlot: YMap<any>): Slot {
393
+ const content = sharedSlot.get('content') as YText
394
+ const delta = content.toDelta()
395
+
396
+ const slot = this.translator.createSlot({
397
+ schema: sharedSlot.get('schema'),
398
+ state: sharedSlot.get('state'),
399
+ formats: {},
400
+ content: []
401
+ })
402
+
403
+ for (const action of delta) {
404
+ if (action.insert) {
405
+ if (typeof action.insert === 'string') {
406
+ slot.insert(action.insert, action.attributes ? Object.keys(action.attributes).map(key => {
407
+ return [this.registry.getFormatter(key)!, action.attributes![key]]
408
+ }) : [])
409
+ } else {
410
+ const sharedComponent = action.insert as YMap<any>
411
+ const component = this.createComponentBySharedComponent(sharedComponent)
412
+ slot.insert(component)
413
+ this.syncSlots(sharedComponent.get('slots'), component.slots)
414
+ this.syncComponent(sharedComponent, component)
415
+ }
416
+ } else {
417
+ throw collaborateErrorFn('unexpected delta action.')
418
+ }
419
+ }
420
+ return slot
421
+ }
133
422
  }
@@ -1,11 +0,0 @@
1
- import { Operation } from '@textbus/core';
2
- import { Text as YText } from 'yjs';
3
- export declare class LocalToRemote {
4
- transform(operation: Operation, root: YText): void;
5
- private applyComponentOperationToSharedComponent;
6
- private applySlotOperationToSharedSlot;
7
- private mergeActionsToSharedSlot;
8
- private makeSharedSlotBySlotLiteral;
9
- private makeSharedComponentByComponentLiteral;
10
- private getSharedComponentByIndex;
11
- }
@@ -1,158 +0,0 @@
1
- import { makeError } from '@textbus/core';
2
- import { Array as YArray, Map as YMap, Text as YText } from 'yjs';
3
- const collaborateErrorFn = makeError('Collaborate');
4
- export class LocalToRemote {
5
- transform(operation, root) {
6
- const path = [...operation.path];
7
- path.shift();
8
- if (path.length) {
9
- const componentIndex = path.shift();
10
- const sharedComponent = this.getSharedComponentByIndex(root, componentIndex);
11
- if (sharedComponent) {
12
- this.applyComponentOperationToSharedComponent(path, operation.apply, sharedComponent);
13
- }
14
- return;
15
- }
16
- this.mergeActionsToSharedSlot(root, operation.apply);
17
- }
18
- applyComponentOperationToSharedComponent(path, actions, componentYMap) {
19
- const sharedSlots = componentYMap.get('slots');
20
- if (path.length) {
21
- const slotIndex = path.shift();
22
- const sharedSlot = sharedSlots.get(slotIndex);
23
- this.applySlotOperationToSharedSlot(path, actions, sharedSlot);
24
- return;
25
- }
26
- let index;
27
- actions.forEach(action => {
28
- switch (action.type) {
29
- case 'retain':
30
- index = action.offset;
31
- break;
32
- case 'insertSlot':
33
- sharedSlots.insert(index, [this.makeSharedSlotBySlotLiteral(action.slot)]);
34
- index++;
35
- break;
36
- case 'apply':
37
- componentYMap.set('state', action.value);
38
- break;
39
- case 'delete':
40
- sharedSlots.delete(index, action.count);
41
- break;
42
- }
43
- });
44
- }
45
- applySlotOperationToSharedSlot(path, actions, slotYMap) {
46
- if (path.length) {
47
- const componentIndex = path.shift();
48
- const sharedContent = slotYMap.get('content');
49
- const sharedComponent = this.getSharedComponentByIndex(sharedContent, componentIndex);
50
- this.applyComponentOperationToSharedComponent(path, actions, sharedComponent);
51
- return;
52
- }
53
- const content = slotYMap.get('content');
54
- this.mergeActionsToSharedSlot(content, actions, slotYMap);
55
- }
56
- mergeActionsToSharedSlot(content, actions, slotYMap) {
57
- let index;
58
- let length;
59
- actions.forEach(action => {
60
- var _a;
61
- if (action.type === 'retain') {
62
- if (action.formats) {
63
- content.format(index, action.offset, action.formats);
64
- }
65
- else {
66
- index = action.offset;
67
- }
68
- }
69
- else if (action.type === 'insert') {
70
- const delta = content.toDelta();
71
- const isEmpty = delta.length === 1 && delta[0].insert === '\n';
72
- if (typeof action.content === 'string') {
73
- length = action.content.length;
74
- content.insert(index, action.content);
75
- }
76
- else {
77
- length = 1;
78
- content.insertEmbed(index, this.makeSharedComponentByComponentLiteral(action.content));
79
- }
80
- if (action.formats) {
81
- content.format(index, length, action.formats);
82
- }
83
- if (isEmpty && index === 0) {
84
- content.delete(content.length - 1, 1);
85
- }
86
- index += length;
87
- }
88
- else if (action.type === 'delete') {
89
- const delta = content.toDelta();
90
- content.delete(index, action.count);
91
- if (content.length === 0) {
92
- content.insert(0, '\n', (_a = delta[0]) === null || _a === void 0 ? void 0 : _a.attributes);
93
- }
94
- }
95
- else if (action.type === 'apply') {
96
- slotYMap === null || slotYMap === void 0 ? void 0 : slotYMap.set('state', action.value);
97
- }
98
- });
99
- }
100
- makeSharedSlotBySlotLiteral(slotLiteral) {
101
- const content = new YText();
102
- let index = 0;
103
- slotLiteral.content.forEach(i => {
104
- let size;
105
- if (typeof i === 'string') {
106
- size = i.length;
107
- content.insert(index, i);
108
- }
109
- else {
110
- size = 1;
111
- content.insertEmbed(index, this.makeSharedComponentByComponentLiteral(i));
112
- }
113
- index += size;
114
- });
115
- const formats = slotLiteral.formats;
116
- Object.keys(formats).forEach(key => {
117
- const formatRanges = formats[key];
118
- formatRanges.forEach(formatRange => {
119
- content.format(formatRange.startIndex, formatRange.endIndex - formatRange.startIndex, {
120
- [key]: formatRange.value
121
- });
122
- });
123
- });
124
- const sharedSlot = new YMap();
125
- sharedSlot.set('content', content);
126
- sharedSlot.set('schema', slotLiteral.schema);
127
- sharedSlot.set('state', slotLiteral.state);
128
- return sharedSlot;
129
- }
130
- makeSharedComponentByComponentLiteral(componentLiteral) {
131
- const slots = new YArray();
132
- componentLiteral.slots.forEach(item => {
133
- slots.push([this.makeSharedSlotBySlotLiteral(item)]);
134
- });
135
- const sharedComponent = new YMap();
136
- sharedComponent.set('name', componentLiteral.name);
137
- sharedComponent.set('slots', slots);
138
- sharedComponent.set('state', componentLiteral.state);
139
- return sharedComponent;
140
- }
141
- getSharedComponentByIndex(host, index) {
142
- const delta = host.toDelta();
143
- let i = 0;
144
- for (const action of delta) {
145
- if (action.insert) {
146
- if (i === index) {
147
- return action.insert instanceof YMap ? action.insert : null;
148
- }
149
- i += action.insert instanceof YMap ? 1 : action.insert.length;
150
- }
151
- else {
152
- throw collaborateErrorFn('Unexpected delta action.');
153
- }
154
- }
155
- return null;
156
- }
157
- }
158
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9jYWwtdG8tcmVtb3RlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbGxhYi9sb2NhbC10by1yZW1vdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFvRCxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFDM0YsT0FBTyxFQUFFLEtBQUssSUFBSSxNQUFNLEVBQUUsR0FBRyxJQUFJLElBQUksRUFBRSxJQUFJLElBQUksS0FBSyxFQUFFLE1BQU0sS0FBSyxDQUFBO0FBRWpFLE1BQU0sa0JBQWtCLEdBQUcsU0FBUyxDQUFDLGFBQWEsQ0FBQyxDQUFBO0FBRW5ELE1BQU0sT0FBTyxhQUFhO0lBQ3hCLFNBQVMsQ0FBQyxTQUFvQixFQUFFLElBQVc7UUFDekMsTUFBTSxJQUFJLEdBQUcsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUNoQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUE7UUFDWixJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDZixNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsS0FBSyxFQUFHLENBQUE7WUFDcEMsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLHlCQUF5QixDQUFDLElBQUksRUFBRSxjQUFjLENBQUMsQ0FBQTtZQUM1RSxJQUFJLGVBQWUsRUFBRTtnQkFDbkIsSUFBSSxDQUFDLHdDQUF3QyxDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsS0FBSyxFQUFFLGVBQWUsQ0FBQyxDQUFBO2FBQ3RGO1lBQ0QsT0FBTTtTQUNQO1FBQ0QsSUFBSSxDQUFDLHdCQUF3QixDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUE7SUFDdEQsQ0FBQztJQUVPLHdDQUF3QyxDQUFDLElBQWMsRUFBRSxPQUFpQixFQUFFLGFBQXdCO1FBQzFHLE1BQU0sV0FBVyxHQUFHLGFBQWEsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFnQixDQUFBO1FBQzdELElBQUksSUFBSSxD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LENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFBO2lCQUM1RDtnQkFDRCxDQUFDLElBQUksTUFBTSxDQUFDLE1BQU0sWUFBWSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUE7YUFDOUQ7aUJBQU07Z0JBQ0wsTUFBTSxrQkFBa0IsQ0FBQywwQkFBMEIsQ0FBQyxDQUFBO2FBQ3JEO1NBQ0Y7UUFDRCxPQUFPLElBQUksQ0FBQTtJQUNiLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFjdGlvbiwgT3BlcmF0aW9uLCBTbG90TGl0ZXJhbCwgQ29tcG9uZW50TGl0ZXJhbCwgbWFrZUVycm9yIH0gZnJvbSAnQHRleHRidXMvY29yZSdcbmltcG9ydCB7IEFycmF5IGFzIFlBcnJheSwgTWFwIGFzIFlNYXAsIFRleHQgYXMgWVRleHQgfSBmcm9tICd5anMnXG5cbmNvbnN0IGNvbGxhYm9yYXRlRXJyb3JGbiA9IG1ha2VFcnJvcignQ29sbGFib3JhdGUnKVxuXG5leHBvcnQgY2xhc3MgTG9jYWxUb1JlbW90ZSB7XG4gIHRyYW5zZm9ybShvcGVyYXRpb246IE9wZXJhdGlvbiwgcm9vdDogWVRleHQpIHtcbiAgICBjb25zdCBwYXRoID0gWy4uLm9wZXJhdGlvbi5wYXRoXVxuICAgIHBhdGguc2hpZnQoKVxuICAgIGlmIChwYXRoLmxlbmd0aCkge1xuICAgICAgY29uc3QgY29tcG9uZW50SW5kZXggPSBwYXRoLnNoaWZ0KCkhXG4gICAgICBjb25zdCBzaGFyZWRDb21wb25lbnQgPSB0aGlzLmdldFNoYXJlZENvbXBvbmVudEJ5SW5kZXgocm9vdCwgY29tcG9uZW50SW5kZXgpXG4gICAgICBpZiAoc2hhcmVkQ29tcG9uZW50KSB7XG4gICAgICAgIHRoaXMuYXBwbHlDb21wb25lbnRPcGVyYXRpb25Ub1NoYXJlZENvbXBvbmVudChwYXRoLCBvcGVyYXRpb24uYXBwbHksIHNoYXJlZENvbXBvbmVudClcbiAgICAgIH1cbiAgICAgIHJldHVyblxuICAgIH1cbiAgICB0aGlzLm1lcmdlQWN0aW9uc1RvU2hhcmVkU2xvdChyb290LCBvcGVyYXRpb24uYXBwbHkpXG4gIH1cblxuICBwcml2YXRlIGFwcGx5Q29tcG9uZW50T3BlcmF0aW9uVG9TaGFyZWRDb21wb25lbnQocGF0aDogbnVtYmVyW10sIGFjdGlvbnM6IEFjdGlvbltdLCBjb21wb25lbnRZTWFwOiBZTWFwPGFueT4pIHtcbiAgICBjb25zdCBzaGFyZWRTbG90cyA9IGNvbXBvbmVudFlNYXAuZ2V0KCdzbG90cycpIGFzIFlBcnJheTxhbnk+XG4gICAgaWYgKHBhdGgubGVuZ3RoKSB7XG4gICAgICBjb25zdCBzbG90SW5kZXggPSBwYXRoLnNoaWZ0KCkhXG4gICAgICBjb25zdCBzaGFyZWRTbG90ID0gc2hhcmVkU2xvdHMuZ2V0KHNsb3RJbmRleClcbiAgICAgIHRoaXMuYXBwbHlTbG90T3BlcmF0aW9uVG9TaGFyZWRTbG90KHBhdGgsIGFjdGlvbnMsIHNoYXJlZFNsb3QpXG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgbGV0IGluZGV4OiBudW1iZXJcbiAgICBhY3Rpb25zLmZvckVhY2goYWN0aW9uID0+IHtcbiAgICAgIHN3aXRjaCAoYWN0aW9uLnR5cGUpIHtcbiAgICAgICAgY2FzZSAncmV0YWluJzpcbiAgICAgICAgICBpbmRleCA9IGFjdGlvbi5vZmZzZXRcbiAgICAgICAgICBicmVha1xuICAgICAgICBjYXNlICdpbnNlcnRTbG90JzpcbiAgICAgICAgICBzaGFyZWRTbG90cy5pbnNlcnQoaW5kZXgsIFt0aGlzLm1ha2VTaGFyZWRTbG90QnlTbG90TGl0ZXJhbChhY3Rpb24uc2xvdCldKVxuICAgICAgICAgIGluZGV4KytcbiAgICAgICAgICBicmVha1xuICAgICAgICBjYXNlICdhcHBseSc6XG4gICAgICAgICAgY29tcG9uZW50WU1hcC5zZXQoJ3N0YXRlJywgYWN0aW9uLnZhbHVlKVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGNhc2UgJ2RlbGV0ZSc6XG4gICAgICAgICAgc2hhcmVkU2xvdHMuZGVsZXRlKGluZGV4LCBhY3Rpb24uY291bnQpXG4gICAgICAgICAgYnJlYWtcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgcHJpdmF0ZSBhcHBseVNsb3RPcGVyYXRpb25Ub1NoYXJlZFNsb3QocGF0aDogbnVtYmVyW10sIGFjdGlvbnM6IEFjdGlvbltdLCBzbG90WU1hcDogWU1hcDxhbnk+KSB7XG4gICAgaWYgKHBhdGgubGVuZ3RoKSB7XG4gICAgICBjb25zdCBjb21wb25lbnRJbmRleCA9IHBhdGguc2hpZnQoKSFcbiAgICAgIGNvbnN0IHNoYXJlZENvbnRlbnQgPSBzbG90WU1hcC5nZXQoJ2NvbnRlbnQnKSBhcyBZVGV4dFxuICAgICAgY29uc3Qgc2hhcmVkQ29tcG9uZW50ID0gdGhpcy5nZXRTaGFyZWRDb21wb25lbnRCeUluZGV4KHNoYXJlZENvbnRlbnQsIGNvbXBvbmVudEluZGV4KSFcbiAgICAgIHRoaXMuYXBwbHlDb21wb25lbnRPcGVyYXRpb25Ub1NoYXJlZENvbXBvbmVudChwYXRoLCBhY3Rpb25zLCBzaGFyZWRDb21wb25lbnQpXG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgY29uc3QgY29udGVudCA9IHNsb3RZTWFwLmdldCgnY29udGVudCcpIGFzIFlUZXh0XG5cbiAgICB0aGlzLm1lcmdlQWN0aW9uc1RvU2hhcmVkU2xvdChjb250ZW50LCBhY3Rpb25zLCBzbG90WU1hcClcbiAgfVxuXG4gIHByaXZhdGUgbWVyZ2VBY3Rpb25zVG9TaGFyZWRTbG90KGNvbnRlbnQ6IFlUZXh0LCBhY3Rpb25zOiBBY3Rpb25bXSwgc2xvdFlNYXA/OiBZTWFwPGFueT4pIHtcbiAgICBsZXQgaW5kZXg6IG51bWJlclxuICAgIGxldCBsZW5ndGg6IG51bWJlclxuXG4gICAgYWN0aW9ucy5mb3JFYWNoKGFjdGlvbiA9PiB7XG4gICAgICBpZiAoYWN0aW9uLnR5cGUgPT09ICdyZXRhaW4nKSB7XG4gICAgICAgIGlmIChhY3Rpb24uZm9ybWF0cykge1xuICAgICAgICAgIGNvbnRlbnQuZm9ybWF0KGluZGV4LCBhY3Rpb24ub2Zmc2V0LCBhY3Rpb24uZm9ybWF0cylcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpbmRleCA9IGFjdGlvbi5vZmZzZXRcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChhY3Rpb24udHlwZSA9PT0gJ2luc2VydCcpIHtcbiAgICAgICAgY29uc3QgZGVsdGEgPSBjb250ZW50LnRvRGVsdGEoKVxuICAgICAgICBjb25zdCBpc0VtcHR5ID0gZGVsdGEubGVuZ3RoID09PSAxICYmIGRlbHRhWzBdLmluc2VydCA9PT0gJ1xcbidcblxuICAgICAgICBpZiAodHlwZW9mIGFjdGlvbi5jb250ZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIGxlbmd0aCA9IGFjdGlvbi5jb250ZW50Lmxlbmd0aFxuICAgICAgICAgIGNvbnRlbnQuaW5zZXJ0KGluZGV4LCBhY3Rpb24uY29udGVudClcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsZW5ndGggPSAxXG4gICAgICAgICAgY29udGVudC5pbnNlcnRFbWJlZChpbmRleCwgdGhpcy5tYWtlU2hhcmVkQ29tcG9uZW50QnlDb21wb25lbnRMaXRlcmFsKGFjdGlvbi5jb250ZW50KSlcbiAgICAgICAgfVxuICAgICAgICBpZiAoYWN0aW9uLmZvcm1hdHMpIHtcbiAgICAgICAgICBjb250ZW50LmZvcm1hdChpbmRleCwgbGVuZ3RoLCBhY3Rpb24uZm9ybWF0cylcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNFbXB0eSAmJiBpbmRleCA9PT0gMCkge1xuICAgICAgICAgIGNvbnRlbnQuZGVsZXRlKGNvbnRlbnQubGVuZ3RoIC0gMSwgMSlcbiAgICAgICAgfVxuICAgICAgICBpbmRleCArPSBsZW5ndGhcbiAgICAgIH0gZWxzZSBpZiAoYWN0aW9uLnR5cGUgPT09ICdkZWxldGUnKSB7XG4gICAgICAgIGNvbnN0IGRlbHRhID0gY29udGVudC50b0RlbHRhKClcbiAgICAgICAgY29udGVudC5kZWxldGUoaW5kZXgsIGFjdGlvbi5jb3VudClcbiAgICAgICAgaWYgKGNvbnRlbnQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgY29udGVudC5pbnNlcnQoMCwgJ1xcbicsIGRlbHRhWzBdPy5hdHRyaWJ1dGVzKVxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGFjdGlvbi50eXBlID09PSAnYXBwbHknKSB7XG4gICAgICAgIHNsb3RZTWFwPy5zZXQoJ3N0YXRlJywgYWN0aW9uLnZhbHVlKVxuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICBwcml2YXRlIG1ha2VTaGFyZWRTbG90QnlTbG90TGl0ZXJhbChzbG90TGl0ZXJhbDogU2xvdExpdGVyYWwpOiBZTWFwPGFueT4ge1xuICAgIGNvbnN0IGNvbnRlbnQgPSBuZXcgWVRleHQoKVxuICAgIGxldCBpbmRleCA9IDBcbiAgICBzbG90TGl0ZXJhbC5jb250ZW50LmZvckVhY2goaSA9PiB7XG4gICAgICBsZXQgc2l6ZTogbnVtYmVyXG4gICAgICBpZiAodHlwZW9mIGkgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHNpemUgPSBpLmxlbmd0aFxuICAgICAgICBjb250ZW50Lmluc2VydChpbmRleCwgaSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNpemUgPSAxXG4gICAgICAgIGNvbnRlbnQuaW5zZXJ0RW1iZWQoaW5kZXgsIHRoaXMubWFrZVNoYXJlZENvbXBvbmVudEJ5Q29tcG9uZW50TGl0ZXJhbChpKSlcbiAgICAgIH1cbiAgICAgIGluZGV4ICs9IHNpemVcbiAgICB9KVxuICAgIGNvbnN0IGZvcm1hdHMgPSBzbG90TGl0ZXJhbC5mb3JtYXRzXG4gICAgT2JqZWN0LmtleXMoZm9ybWF0cykuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgY29uc3QgZm9ybWF0UmFuZ2VzID0gZm9ybWF0c1trZXldXG4gICAgICBmb3JtYXRSYW5nZXMuZm9yRWFjaChmb3JtYXRSYW5nZSA9PiB7XG4gICAgICAgIGNvbnRlbnQuZm9ybWF0KGZvcm1hdFJhbmdlLnN0YXJ0SW5kZXgsIGZvcm1hdFJhbmdlLmVuZEluZGV4IC0gZm9ybWF0UmFuZ2Uuc3RhcnRJbmRleCwge1xuICAgICAgICAgIFtrZXldOiBmb3JtYXRSYW5nZS52YWx1ZVxuICAgICAgICB9KVxuICAgICAgfSlcbiAgICB9KVxuXG4gICAgY29uc3Qgc2hhcmVkU2xvdCA9IG5ldyBZTWFwKClcbiAgICBzaGFyZWRTbG90LnNldCgnY29udGVudCcsIGNvbnRlbnQpXG4gICAgc2hhcmVkU2xvdC5zZXQoJ3NjaGVtYScsIHNsb3RMaXRlcmFsLnNjaGVtYSlcbiAgICBzaGFyZWRTbG90LnNldCgnc3RhdGUnLCBzbG90TGl0ZXJhbC5zdGF0ZSlcbiAgICByZXR1cm4gc2hhcmVkU2xvdFxuICB9XG5cbiAgcHJpdmF0ZSBtYWtlU2hhcmVkQ29tcG9uZW50QnlDb21wb25lbnRMaXRlcmFsKGNvbXBvbmVudExpdGVyYWw6IENvbXBvbmVudExpdGVyYWwpOiBZTWFwPGFueT4ge1xuICAgIGNvbnN0IHNsb3RzID0gbmV3IFlBcnJheSgpXG4gICAgY29tcG9uZW50TGl0ZXJhbC5zbG90cy5mb3JFYWNoKGl0ZW0gPT4ge1xuICAgICAgc2xvdHMucHVzaChbdGhpcy5tYWtlU2hhcmVkU2xvdEJ5U2xvdExpdGVyYWwoaXRlbSldKVxuICAgIH0pXG4gICAgY29uc3Qgc2hhcmVkQ29tcG9uZW50ID0gbmV3IFlNYXAoKVxuICAgIHNoYXJlZENvbXBvbmVudC5zZXQoJ25hbWUnLCBjb21wb25lbnRMaXRlcmFsLm5hbWUpXG4gICAgc2hhcmVkQ29tcG9uZW50LnNldCgnc2xvdHMnLCBzbG90cylcbiAgICBzaGFyZWRDb21wb25lbnQuc2V0KCdzdGF0ZScsIGNvbXBvbmVudExpdGVyYWwuc3RhdGUpXG4gICAgcmV0dXJuIHNoYXJlZENvbXBvbmVudFxuICB9XG5cbiAgcHJpdmF0ZSBnZXRTaGFyZWRDb21wb25lbnRCeUluZGV4KGhvc3Q6IFlUZXh0LCBpbmRleDogbnVtYmVyKTogWU1hcDxhbnk+IHwgbnVsbCB7XG4gICAgY29uc3QgZGVsdGEgPSBob3N0LnRvRGVsdGEoKVxuICAgIGxldCBpID0gMFxuICAgIGZvciAoY29uc3QgYWN0aW9uIG9mIGRlbHRhKSB7XG4gICAgICBpZiAoYWN0aW9uLmluc2VydCkge1xuICAgICAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgICAgICByZXR1cm4gYWN0aW9uLmluc2VydCBpbnN0YW5jZW9mIFlNYXAgPyBhY3Rpb24uaW5zZXJ0IDogbnVsbFxuICAgICAgICB9XG4gICAgICAgIGkgKz0gYWN0aW9uLmluc2VydCBpbnN0YW5jZW9mIFlNYXAgPyAxIDogYWN0aW9uLmluc2VydC5sZW5ndGhcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IGNvbGxhYm9yYXRlRXJyb3JGbignVW5leHBlY3RlZCBkZWx0YSBhY3Rpb24uJylcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGxcbiAgfVxufVxuIl19
@@ -1,14 +0,0 @@
1
- import { Doc as YDoc, YEvent } from 'yjs';
2
- import { ComponentInstance, Registry, Selection, Translator } from '@textbus/core';
3
- export declare class RemoteToLocal {
4
- private yDoc;
5
- private translator;
6
- private selection;
7
- private registry;
8
- constructor(yDoc: YDoc, translator: Translator, selection: Selection, registry: Registry);
9
- transform(events: YEvent[], rootComponent: ComponentInstance): void;
10
- private applySharedComponentToComponent;
11
- private applySharedSlotToSlot;
12
- private createComponentBySharedComponent;
13
- private createSlotBySharedSlot;
14
- }