@textbus/collaborate 2.0.0-alpha.36

Sign up to get free protection for your applications and to get access to all the features.
package/README.md ADDED
@@ -0,0 +1,10 @@
1
+ Textbus
2
+ =====================
3
+
4
+ Textbus 是一套用于构建富交互的富文本编辑框架。和大多数富文本编辑器不同的是,Textbus 以组件为核心,格式为辅助,并大幅简化了富文本编辑器开发中常见 API,且提供了更高的抽象层,使 Textbus 不仅易于上手,同时还能驱动复杂的富文本应用。
5
+
6
+ 本项目为 Textbus 协作编辑实现,提供了多人在线协作编辑能力的支持。
7
+
8
+ ### 文档
9
+
10
+ 更多文档请参考:[中文文档](https://textbus.io)
@@ -0,0 +1,15 @@
1
+ import { RootComponentRef, Starter, Translator, FormatterList } from '@textbus/core';
2
+ import { Doc as YDoc } from 'yjs';
3
+ export declare class Collaborate {
4
+ private rootComponentRef;
5
+ private translator;
6
+ private formatterList;
7
+ private starter;
8
+ yDoc: YDoc;
9
+ private subscriptions;
10
+ private updateFromSelf;
11
+ constructor(rootComponentRef: RootComponentRef, translator: Translator, formatterList: FormatterList, starter: Starter);
12
+ setup(): void;
13
+ destroy(): void;
14
+ private listen;
15
+ }
@@ -0,0 +1,69 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Injectable } from '@tanbo/di';
11
+ import { debounceTime, filter, tap } from '@tanbo/stream';
12
+ import { RootComponentRef, Starter, Translator, FormatterList } from '@textbus/core';
13
+ import { Doc as YDoc } from 'yjs';
14
+ import { localToRemote } from './local-to-remote';
15
+ import { remoteToLocal } from './remote-to-local';
16
+ // const collaborateErrorFn = makeError('Collaborate')
17
+ let Collaborate = class Collaborate {
18
+ constructor(rootComponentRef, translator, formatterList, starter) {
19
+ this.rootComponentRef = rootComponentRef;
20
+ this.translator = translator;
21
+ this.formatterList = formatterList;
22
+ this.starter = starter;
23
+ this.yDoc = new YDoc();
24
+ this.subscriptions = [];
25
+ this.updateFromSelf = true;
26
+ }
27
+ setup() {
28
+ this.subscriptions.push(this.starter.onReady.subscribe(() => {
29
+ this.listen();
30
+ }));
31
+ }
32
+ destroy() {
33
+ this.subscriptions.forEach(i => i.unsubscribe());
34
+ }
35
+ listen() {
36
+ const root = this.yDoc.getArray('content');
37
+ const slot = this.rootComponentRef.component.slots.get(0);
38
+ root.observeDeep((events, transaction) => {
39
+ if (transaction.origin === this.yDoc) {
40
+ return;
41
+ }
42
+ this.updateFromSelf = false;
43
+ remoteToLocal(events, slot, this.translator, this.formatterList);
44
+ this.updateFromSelf = true;
45
+ });
46
+ const operations = [];
47
+ this.subscriptions.push(this.rootComponentRef.component.changeMarker.onChange.pipe(filter(() => {
48
+ return this.updateFromSelf;
49
+ }), tap(op => {
50
+ operations.push(op);
51
+ }), debounceTime(1)).subscribe(() => {
52
+ this.yDoc.transact(() => {
53
+ operations.forEach(operation => {
54
+ localToRemote(operation, root);
55
+ });
56
+ operations.length = 0;
57
+ }, this.yDoc);
58
+ }));
59
+ }
60
+ };
61
+ Collaborate = __decorate([
62
+ Injectable(),
63
+ __metadata("design:paramtypes", [RootComponentRef,
64
+ Translator,
65
+ FormatterList,
66
+ Starter])
67
+ ], Collaborate);
68
+ export { Collaborate };
69
+ //# sourceMappingURL=collaborate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collaborate.js","sourceRoot":"","sources":["../src/collaborate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Operation } from '@textbus/core';
2
+ import { Array as YArray } from 'yjs';
3
+ export declare function localToRemote(operation: Operation, root: YArray<any>): void;
@@ -0,0 +1,173 @@
1
+ import { Format } from '@textbus/core';
2
+ import { Array as YArray, Map as YMap } from 'yjs';
3
+ export function localToRemote(operation, root) {
4
+ const path = [...operation.path];
5
+ path.shift();
6
+ if (path.length) {
7
+ const componentIndex = path.shift();
8
+ applyComponentOperationToSharedComponent(path, operation.apply, root.get(componentIndex));
9
+ return;
10
+ }
11
+ insertContent(root, operation.apply);
12
+ }
13
+ function applyComponentOperationToSharedComponent(path, actions, componentYMap) {
14
+ const sharedSlots = componentYMap.get('slots');
15
+ if (path.length) {
16
+ const slotIndex = path.shift();
17
+ const sharedSlot = sharedSlots.get(slotIndex);
18
+ applySlotOperationToSharedSlot(path, actions, sharedSlot);
19
+ return;
20
+ }
21
+ let index;
22
+ actions.forEach(action => {
23
+ switch (action.type) {
24
+ case 'retain':
25
+ index = action.index;
26
+ break;
27
+ case 'insertSlot':
28
+ sharedSlots.insert(index, [makeSharedSlotBySlotLiteral(action.slot)]);
29
+ break;
30
+ case 'apply':
31
+ componentYMap.set('state', action.value);
32
+ break;
33
+ case 'delete':
34
+ sharedSlots.delete(index, action.count);
35
+ break;
36
+ }
37
+ });
38
+ }
39
+ function applySlotOperationToSharedSlot(path, actions, slotYMap) {
40
+ if (path.length) {
41
+ const componentIndex = path.shift();
42
+ const sharedContent = slotYMap.get('content');
43
+ const sharedComponent = sharedContent.get(componentIndex);
44
+ applyComponentOperationToSharedComponent(path, actions, sharedComponent);
45
+ return;
46
+ }
47
+ const content = slotYMap.get('content');
48
+ let index;
49
+ let len;
50
+ actions.forEach(action => {
51
+ switch (action.type) {
52
+ case 'retain':
53
+ if (action.formats) {
54
+ mergeSharedFormats(index, action.index, action.formats, slotYMap);
55
+ }
56
+ index = action.index;
57
+ break;
58
+ case 'insert':
59
+ if (typeof action.content === 'string') {
60
+ len = action.content.length;
61
+ content.insert(index, action.content.split(''));
62
+ }
63
+ else {
64
+ len = 1;
65
+ content.insert(index, [makeSharedComponentByComponentLiteral(action.content)]);
66
+ }
67
+ if (action.formats) {
68
+ insertSharedFormats(index, len, action.formats, slotYMap);
69
+ }
70
+ break;
71
+ case 'delete':
72
+ if (content.length === 0) {
73
+ // 当内容为空时,slot 实例内容为 ['\n'],触发删除会导致长度溢出
74
+ return;
75
+ }
76
+ content.delete(index, action.count);
77
+ break;
78
+ case 'apply':
79
+ slotYMap.set('state', action.value);
80
+ break;
81
+ }
82
+ });
83
+ }
84
+ function insertSharedFormats(index, distance, formats, sharedSlots) {
85
+ const sharedFormats = sharedSlots.get('formats');
86
+ const keys = Array.from(sharedFormats.keys());
87
+ const expandedValues = Array.from({ length: distance });
88
+ keys.forEach(key => {
89
+ const formatRanges = sharedFormats.get(key);
90
+ const values = Format.tileRanges(formatRanges);
91
+ values.splice(index, 0, ...expandedValues);
92
+ const newRanges = Format.toRanges(values);
93
+ sharedFormats.set(key, newRanges);
94
+ });
95
+ mergeSharedFormats(index, index + distance, formats, sharedSlots);
96
+ }
97
+ function mergeSharedFormats(startIndex, endIndex, formats, sharedSlots) {
98
+ const sharedFormats = sharedSlots.get('formats');
99
+ Object.keys(formats).forEach(key => {
100
+ if (!sharedFormats.has(key)) {
101
+ sharedFormats.set(key, [{
102
+ startIndex,
103
+ endIndex,
104
+ value: formats[key]
105
+ }]);
106
+ }
107
+ const oldFormatRanges = sharedFormats.get(key);
108
+ const formatRanges = Format.normalizeFormatRange(oldFormatRanges, {
109
+ startIndex,
110
+ endIndex,
111
+ value: formats[key]
112
+ });
113
+ sharedFormats.set(key, formatRanges);
114
+ });
115
+ }
116
+ function insertContent(content, actions) {
117
+ let index;
118
+ actions.forEach(action => {
119
+ switch (action.type) {
120
+ case 'retain':
121
+ index = action.index;
122
+ break;
123
+ case 'insert':
124
+ content.insert(index, [
125
+ typeof action.content === 'string' ?
126
+ action.content :
127
+ makeSharedComponentByComponentLiteral(action.content)
128
+ ]);
129
+ if (action.formats) {
130
+ // TODO 根节点样式
131
+ }
132
+ break;
133
+ case 'delete':
134
+ content.delete(index, action.count);
135
+ break;
136
+ }
137
+ });
138
+ }
139
+ function makeSharedSlotBySlotLiteral(slotLiteral) {
140
+ const content = new YArray();
141
+ let index = 0;
142
+ slotLiteral.content.forEach(i => {
143
+ let size;
144
+ if (typeof i === 'string') {
145
+ size = i.length;
146
+ content.insert(index, [i]);
147
+ }
148
+ else {
149
+ size = 1;
150
+ content.insert(index, [makeSharedComponentByComponentLiteral(i)]);
151
+ }
152
+ index += size;
153
+ });
154
+ const formats = new YMap();
155
+ const sharedSlot = new YMap();
156
+ sharedSlot.set('state', slotLiteral.state);
157
+ sharedSlot.set('content', content);
158
+ sharedSlot.set('schema', slotLiteral.schema);
159
+ sharedSlot.set('formats', formats);
160
+ return sharedSlot;
161
+ }
162
+ function makeSharedComponentByComponentLiteral(componentLiteral) {
163
+ const slots = new YArray();
164
+ componentLiteral.slots.forEach(item => {
165
+ slots.push([makeSharedSlotBySlotLiteral(item)]);
166
+ });
167
+ const sharedComponent = new YMap();
168
+ sharedComponent.set('name', componentLiteral.name);
169
+ sharedComponent.set('slots', slots);
170
+ sharedComponent.set('state', componentLiteral.state);
171
+ return sharedComponent;
172
+ }
173
+ //# sourceMappingURL=local-to-remote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-to-remote.js","sourceRoot":"","sources":["../src/local-to-remote.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export * from './collaborate';
@@ -0,0 +1,2 @@
1
+ export * from './collaborate';
2
+ //# sourceMappingURL=public-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAA"}
@@ -0,0 +1,3 @@
1
+ import { YEvent } from 'yjs';
2
+ import { FormatterList, Slot, Translator } from '@textbus/core';
3
+ export declare function remoteToLocal(events: YEvent[], slot: Slot, translator: Translator, formatterList: FormatterList): void;
@@ -0,0 +1,143 @@
1
+ import { YArrayEvent, YMapEvent } from 'yjs';
2
+ import { FormatType } from '@textbus/core';
3
+ export function remoteToLocal(events, slot, translator, formatterList) {
4
+ events.forEach(ev => {
5
+ const path = [];
6
+ for (let i = 0; i < ev.path.length; i += 2) {
7
+ path.push(ev.path.slice(i, i + 2));
8
+ }
9
+ if (path.length) {
10
+ const componentIndex = path.shift()[0];
11
+ const component = slot.getContentAtIndex(componentIndex);
12
+ applySharedComponentToComponent(ev, path, component, translator, formatterList);
13
+ return;
14
+ }
15
+ apply(ev, slot, translator);
16
+ });
17
+ }
18
+ function applySharedComponentToComponent(ev, path, component, translator, formatterList) {
19
+ if (path.length) {
20
+ const childPath = path.shift();
21
+ const slot = component.slots.get(childPath[0]);
22
+ applySharedSlotToSlot(ev, path, slot, translator, formatterList, childPath[1] === 'formats');
23
+ return;
24
+ }
25
+ if (ev instanceof YMapEvent) {
26
+ ev.keysChanged.forEach(key => {
27
+ if (key === 'state') {
28
+ const state = ev.target.get('state');
29
+ component.updateState(draft => {
30
+ Object.assign(draft, state);
31
+ });
32
+ }
33
+ });
34
+ }
35
+ else if (ev instanceof YArrayEvent) {
36
+ const slots = component.slots;
37
+ ev.delta.forEach(action => {
38
+ if (Reflect.has(action, 'retain')) {
39
+ slots.retain(action.retain);
40
+ }
41
+ else if (action.insert) {
42
+ action.insert.forEach(item => {
43
+ slots.insert(translator.createSlot(item.toJSON()));
44
+ });
45
+ }
46
+ else if (action.delete) {
47
+ slots.retain(slots.index);
48
+ slots.delete(action.delete);
49
+ }
50
+ });
51
+ }
52
+ }
53
+ function applySharedSlotToSlot(ev, path, slot, translator, formatterList, isUpdateFormats) {
54
+ if (path.length) {
55
+ const componentIndex = path.shift()[0];
56
+ const component = slot.getContentAtIndex(componentIndex);
57
+ applySharedComponentToComponent(ev, path, component, translator, formatterList);
58
+ return;
59
+ }
60
+ if (ev instanceof YArrayEvent) {
61
+ ev.delta.forEach(action => {
62
+ if (Reflect.has(action, 'retain')) {
63
+ slot.retain(action.retain);
64
+ }
65
+ else if (action.insert) {
66
+ action.insert.forEach(item => {
67
+ if (typeof item === 'string') {
68
+ slot.insert(item);
69
+ }
70
+ else {
71
+ slot.insert(translator.createComponent(item.toJSON()));
72
+ }
73
+ });
74
+ }
75
+ else if (action.delete) {
76
+ slot.retain(slot.index);
77
+ slot.delete(action.delete);
78
+ }
79
+ });
80
+ }
81
+ else if (ev instanceof YMapEvent) {
82
+ if (isUpdateFormats) {
83
+ const json = ev.target.toJSON();
84
+ ev.keysChanged.forEach(key => {
85
+ const formats = json[key];
86
+ const formatter = formatterList.get(key);
87
+ if (formatter.type !== FormatType.Block) {
88
+ slot.applyFormat(formatter, {
89
+ startIndex: 0,
90
+ endIndex: slot.length,
91
+ value: null
92
+ });
93
+ }
94
+ formats.forEach(item => {
95
+ if (formatter.type === FormatType.Block) {
96
+ slot.applyFormat(formatter, item.value);
97
+ }
98
+ else {
99
+ slot.applyFormat(formatter, item);
100
+ }
101
+ });
102
+ });
103
+ }
104
+ else {
105
+ ev.keysChanged.forEach(key => {
106
+ if (key === 'state') {
107
+ const state = ev.target.get('state');
108
+ slot.updateState(draft => {
109
+ Object.assign(draft, state);
110
+ });
111
+ }
112
+ });
113
+ }
114
+ }
115
+ }
116
+ function apply(ev, slot, translator) {
117
+ if (ev instanceof YArrayEvent) {
118
+ slot.retain(0);
119
+ const delta = ev.delta;
120
+ delta.forEach(action => {
121
+ if (action.insert) {
122
+ action.insert.forEach(item => {
123
+ if (typeof item === 'string') {
124
+ slot.insert(item);
125
+ }
126
+ else {
127
+ const json = item.toJSON();
128
+ const component = translator.createComponent(json);
129
+ slot.insert(component);
130
+ }
131
+ });
132
+ }
133
+ else if (action.retain) {
134
+ slot.retain(action.retain);
135
+ }
136
+ else if (action.delete) {
137
+ slot.retain(slot.index);
138
+ slot.delete(action.delete);
139
+ }
140
+ });
141
+ }
142
+ }
143
+ //# sourceMappingURL=remote-to-local.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-to-local.js","sourceRoot":"","sources":["../src/remote-to-local.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@textbus/collaborate",
3
+ "version": "2.0.0-alpha.36",
4
+ "description": "TextBus is a rich text editor and framework that is highly customizable and extensible to achieve rich wysiwyg effects.",
5
+ "main": "./bundles/public-api.js",
6
+ "module": "./bundles/public-api.js",
7
+ "typings": "./bundles/public-api.d.ts",
8
+ "scripts": {
9
+ "start": "webpack-dev-server",
10
+ "test": "cross-env env=test jest",
11
+ "test-c": "cross-env env=test jest --coverage",
12
+ "build:lib": "rimraf bundles && tsc -p tsconfig-build.json",
13
+ "publish:lib": "npm run build:lib && npm publish --access=public"
14
+ },
15
+ "license": "GPL-3.0-only",
16
+ "keywords": [
17
+ "textbus",
18
+ "富文本编辑器",
19
+ "wysiwyg",
20
+ "wysiwyg editor",
21
+ "rich text editor",
22
+ "editor",
23
+ "html editor",
24
+ "web editor",
25
+ "typescript editor"
26
+ ],
27
+ "dependencies": {
28
+ "@tanbo/di": "^1.0.5",
29
+ "@tanbo/stream": "^0.0.11",
30
+ "@textbus/core": "^2.0.0-alpha.36",
31
+ "reflect-metadata": "^0.1.13",
32
+ "yjs": "^13.5.27",
33
+ "y-protocols": "^1.0.5"
34
+ },
35
+ "author": {
36
+ "name": "Tanbo",
37
+ "email": "tanbohb@qq.com"
38
+ },
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "git+https://github.com/textbus/textbus.git"
42
+ },
43
+ "bugs": {
44
+ "url": "https://github.com/textbus/textbus.git/issues"
45
+ },
46
+ "gitHead": "536327fc2609d3f2bbf3b0720738d3ed918d612c"
47
+ }
@@ -0,0 +1,74 @@
1
+ import { Injectable } from '@tanbo/di'
2
+ import { debounceTime, filter, Subscription, tap } from '@tanbo/stream'
3
+ import {
4
+ RootComponentRef,
5
+ Starter,
6
+ Operation,
7
+ Translator,
8
+ FormatterList
9
+ } from '@textbus/core'
10
+ import { Doc as YDoc } from 'yjs'
11
+ import { localToRemote } from './local-to-remote'
12
+ import { remoteToLocal } from './remote-to-local'
13
+
14
+ // const collaborateErrorFn = makeError('Collaborate')
15
+
16
+ @Injectable()
17
+ export class Collaborate {
18
+ yDoc = new YDoc()
19
+
20
+ private subscriptions: Subscription[] = []
21
+ private updateFromSelf = true
22
+
23
+ constructor(private rootComponentRef: RootComponentRef,
24
+ private translator: Translator,
25
+ private formatterList: FormatterList,
26
+ private starter: Starter) {
27
+ }
28
+
29
+ setup() {
30
+ this.subscriptions.push(
31
+ this.starter.onReady.subscribe(() => {
32
+ this.listen()
33
+ })
34
+ )
35
+ }
36
+
37
+ destroy() {
38
+ this.subscriptions.forEach(i => i.unsubscribe())
39
+ }
40
+
41
+ private listen() {
42
+ const root = this.yDoc.getArray('content')
43
+ const slot = this.rootComponentRef.component.slots.get(0)!
44
+ root.observeDeep((events, transaction) => {
45
+ if (transaction.origin === this.yDoc) {
46
+ return
47
+ }
48
+ this.updateFromSelf = false
49
+
50
+ remoteToLocal(events, slot, this.translator, this.formatterList)
51
+
52
+ this.updateFromSelf = true
53
+ })
54
+ const operations: Operation[] = []
55
+ this.subscriptions.push(
56
+ this.rootComponentRef.component.changeMarker.onChange.pipe(
57
+ filter(() => {
58
+ return this.updateFromSelf
59
+ }),
60
+ tap(op => {
61
+ operations.push(op)
62
+ }),
63
+ debounceTime(1)
64
+ ).subscribe(() => {
65
+ this.yDoc.transact(() => {
66
+ operations.forEach(operation => {
67
+ localToRemote(operation, root)
68
+ })
69
+ operations.length = 0
70
+ }, this.yDoc)
71
+ })
72
+ )
73
+ }
74
+ }