@textbus/collaborate 2.0.0-alpha.36

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/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
+ }