@a3s-lab/office 0.48.1 → 0.50.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/COLLABORATION_ROADMAP.md +14 -6
- package/README.md +33 -0
- package/dist/{0~3320.js → 0~5600.js} +271 -13
- package/dist/0~controlled-editor-composition.js +167 -15
- package/dist/0~document-editor.js +354 -90
- package/dist/0~work-docx-export.js +143 -9
- package/dist/0~work-docx-import.js +5 -120
- package/dist/0~work-office-diagnostics.js +16 -5
- package/dist/4174.js +93 -8
- package/dist/internal/features/work/editors/controlled-editor-composition.d.ts +53 -7
- package/dist/internal/features/work/editors/use-document-pagination.d.ts +3 -1
- package/dist/internal/features/work/work-document-changes.d.ts +4 -2
- package/dist/internal/features/work/work-document-compare-identities.d.ts +28 -0
- package/dist/internal/features/work/work-document-compare-moves.d.ts +60 -0
- package/dist/internal/features/work/work-document-compare.d.ts +2 -13
- package/dist/internal/features/work/work-docx-change-import.d.ts +10 -1
- package/dist/internal/features/work/work-docx-move-revision-export.d.ts +35 -0
- package/dist/internal/features/work/work-types.d.ts +3 -1
- package/dist/office-kernel.wasm +0 -0
- package/dist/styles.css +9 -0
- package/docs/latest/en/browser-editor-architecture.md +21 -5
- package/package.json +11 -3
|
@@ -1,22 +1,114 @@
|
|
|
1
1
|
const COMPOSITION_SETTLE_RETRY_MS = 20;
|
|
2
2
|
const MAX_COMPOSITION_SETTLE_RETRIES = 4;
|
|
3
|
+
const COMPOSITION_SETTLE_QUIET_MS = 24;
|
|
4
|
+
const COMPOSITION_SETTLE_MAX_MS = 240;
|
|
5
|
+
function inputTypeOf(event) {
|
|
6
|
+
const inputType = event.inputType;
|
|
7
|
+
return 'string' == typeof inputType ? inputType : '';
|
|
8
|
+
}
|
|
9
|
+
function inputDataOf(event) {
|
|
10
|
+
const data = event.data;
|
|
11
|
+
return 'string' == typeof data ? data : null;
|
|
12
|
+
}
|
|
13
|
+
function isCommittedInput(event) {
|
|
14
|
+
return 'insertFromComposition' === inputTypeOf(event);
|
|
15
|
+
}
|
|
3
16
|
class ControlledEditorComposition {
|
|
4
17
|
active = false;
|
|
18
|
+
committedInputSeen = false;
|
|
19
|
+
committedText = null;
|
|
20
|
+
compositionData = null;
|
|
21
|
+
deadline = 0;
|
|
5
22
|
generation = 0;
|
|
23
|
+
awaitingCommittedTransaction = false;
|
|
24
|
+
range = null;
|
|
25
|
+
rangeFrozen = false;
|
|
6
26
|
settling = false;
|
|
27
|
+
settleAt = 0;
|
|
28
|
+
settleHandler = null;
|
|
29
|
+
settleEditor = null;
|
|
30
|
+
sessionId = 0;
|
|
7
31
|
timer = null;
|
|
8
|
-
start() {
|
|
32
|
+
start(editor) {
|
|
33
|
+
if (this.active) {
|
|
34
|
+
if (!this.range && editor && !editor.isDestroyed) this.range = this.selectionRange(editor);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
9
37
|
this.generation += 1;
|
|
10
38
|
this.cancelTimer();
|
|
11
39
|
this.active = true;
|
|
40
|
+
this.awaitingCommittedTransaction = false;
|
|
41
|
+
this.committedInputSeen = false;
|
|
42
|
+
this.committedText = null;
|
|
43
|
+
this.compositionData = null;
|
|
44
|
+
this.deadline = 0;
|
|
45
|
+
this.range = editor && !editor.isDestroyed ? this.selectionRange(editor) : null;
|
|
46
|
+
this.rangeFrozen = false;
|
|
12
47
|
this.settling = false;
|
|
48
|
+
this.settleAt = 0;
|
|
49
|
+
this.settleEditor = null;
|
|
50
|
+
this.settleHandler = null;
|
|
51
|
+
this.sessionId += 1;
|
|
13
52
|
}
|
|
14
|
-
|
|
53
|
+
recordTransaction(transaction) {
|
|
54
|
+
if (!this.active && !this.settling || !this.range || this.rangeFrozen || !transaction.docChanged) return;
|
|
55
|
+
const from = transaction.mapping.map(this.range.from, -1);
|
|
56
|
+
const to = transaction.mapping.map(this.range.to, 1);
|
|
57
|
+
this.range = {
|
|
58
|
+
from: Math.min(from, to),
|
|
59
|
+
to: Math.max(from, to)
|
|
60
|
+
};
|
|
61
|
+
if (this.settling && this.awaitingCommittedTransaction) {
|
|
62
|
+
this.awaitingCommittedTransaction = false;
|
|
63
|
+
this.rangeFrozen = true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
noteInput(event) {
|
|
67
|
+
const data = inputDataOf(event);
|
|
68
|
+
const committed = isCommittedInput(event);
|
|
69
|
+
if (this.active) {
|
|
70
|
+
if (committed && data) {
|
|
71
|
+
this.committedInputSeen = true;
|
|
72
|
+
this.committedText = data;
|
|
73
|
+
this.awaitingCommittedTransaction = true;
|
|
74
|
+
}
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (!this.settling) return;
|
|
78
|
+
const matchesCompositionData = Boolean(data && this.compositionData && data === this.compositionData);
|
|
79
|
+
if (!committed && !matchesCompositionData) {
|
|
80
|
+
if (data) {
|
|
81
|
+
this.awaitingCommittedTransaction = false;
|
|
82
|
+
this.rangeFrozen = true;
|
|
83
|
+
this.scheduleQuietSettlement();
|
|
84
|
+
}
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (data) this.committedText = data;
|
|
88
|
+
this.committedInputSeen = true;
|
|
89
|
+
this.awaitingCommittedTransaction = true;
|
|
90
|
+
this.scheduleQuietSettlement();
|
|
91
|
+
}
|
|
92
|
+
end(editor, dataOrHandler, maybeHandler) {
|
|
93
|
+
const legacySettlement = 'function' == typeof dataOrHandler;
|
|
94
|
+
const data = legacySettlement ? null : dataOrHandler;
|
|
95
|
+
const handler = 'function' == typeof dataOrHandler ? dataOrHandler : maybeHandler;
|
|
96
|
+
if (!handler || !this.active && !this.settling) return;
|
|
97
|
+
if ('string' == typeof data) {
|
|
98
|
+
this.compositionData = data;
|
|
99
|
+
if (data && !this.committedText) this.committedText = data;
|
|
100
|
+
if (data && this.currentRangeText(editor) === data) this.committedInputSeen = true;
|
|
101
|
+
}
|
|
15
102
|
const generation = ++this.generation;
|
|
16
103
|
this.cancelTimer();
|
|
17
104
|
this.active = false;
|
|
18
105
|
this.settling = true;
|
|
19
|
-
this.
|
|
106
|
+
this.deadline = Date.now() + COMPOSITION_SETTLE_MAX_MS;
|
|
107
|
+
this.settleEditor = editor;
|
|
108
|
+
this.settleHandler = handler;
|
|
109
|
+
this.settleAt = legacySettlement ? Date.now() : this.committedInputSeen ? Date.now() + COMPOSITION_SETTLE_QUIET_MS : this.deadline;
|
|
110
|
+
if (legacySettlement) this.deadline = Date.now() + COMPOSITION_SETTLE_RETRY_MS * MAX_COMPOSITION_SETTLE_RETRIES;
|
|
111
|
+
this.scheduleSettlement(generation);
|
|
20
112
|
}
|
|
21
113
|
isBlocking(editor) {
|
|
22
114
|
return this.active || this.settling || Boolean(editor && !editor.isDestroyed && editor.view.composing);
|
|
@@ -26,24 +118,84 @@ class ControlledEditorComposition {
|
|
|
26
118
|
this.cancelTimer();
|
|
27
119
|
this.active = false;
|
|
28
120
|
this.settling = false;
|
|
121
|
+
this.committedInputSeen = false;
|
|
122
|
+
this.committedText = null;
|
|
123
|
+
this.compositionData = null;
|
|
124
|
+
this.deadline = 0;
|
|
125
|
+
this.range = null;
|
|
126
|
+
this.rangeFrozen = false;
|
|
127
|
+
this.settleAt = 0;
|
|
128
|
+
this.settleEditor = null;
|
|
129
|
+
this.settleHandler = null;
|
|
130
|
+
}
|
|
131
|
+
selectionRange(editor) {
|
|
132
|
+
return {
|
|
133
|
+
from: editor.state.selection.from,
|
|
134
|
+
to: editor.state.selection.to
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
currentRangeText(editor) {
|
|
138
|
+
if (!this.range || editor.isDestroyed) return null;
|
|
139
|
+
const maximum = editor.state.doc.content.size;
|
|
140
|
+
if (this.range.from < 0 || this.range.to < this.range.from || this.range.to > maximum) return null;
|
|
141
|
+
return editor.state.doc.textBetween(this.range.from, this.range.to, '\n', '\n');
|
|
29
142
|
}
|
|
30
|
-
|
|
31
|
-
const
|
|
143
|
+
snapshot(editor) {
|
|
144
|
+
const maximum = editor.state.doc.content.size;
|
|
145
|
+
const from = this.range ? Math.max(0, Math.min(maximum, this.range.from)) : null;
|
|
146
|
+
const to = this.range ? Math.max(0, Math.min(maximum, this.range.to)) : null;
|
|
147
|
+
return {
|
|
148
|
+
id: this.sessionId,
|
|
149
|
+
range: null === from || null === to ? null : {
|
|
150
|
+
from: Math.min(from, to),
|
|
151
|
+
to: Math.max(from, to)
|
|
152
|
+
},
|
|
153
|
+
text: this.committedText
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
scheduleQuietSettlement() {
|
|
157
|
+
if (!this.settling) return;
|
|
158
|
+
this.settleAt = Math.min(this.deadline, Date.now() + COMPOSITION_SETTLE_QUIET_MS);
|
|
159
|
+
this.scheduleSettlement(this.generation);
|
|
160
|
+
}
|
|
161
|
+
scheduleSettlement(expectedGeneration) {
|
|
162
|
+
this.cancelTimer();
|
|
163
|
+
const wait = Math.max(0, this.settleAt - Date.now());
|
|
32
164
|
this.timer = setTimeout(()=>{
|
|
33
165
|
this.timer = null;
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
166
|
+
if (expectedGeneration !== this.generation || !this.settling) return;
|
|
167
|
+
const editor = this.settleEditor;
|
|
168
|
+
const handler = this.settleHandler;
|
|
169
|
+
if (!editor || !handler || editor.isDestroyed) return void this.clearSettlement();
|
|
39
170
|
if (editor.view.composing) {
|
|
40
|
-
if (
|
|
41
|
-
|
|
171
|
+
if (Date.now() < this.deadline) {
|
|
172
|
+
this.settleAt = Math.min(this.deadline, Date.now() + COMPOSITION_SETTLE_RETRY_MS);
|
|
173
|
+
this.scheduleSettlement(expectedGeneration);
|
|
174
|
+
} else this.clearSettlement();
|
|
42
175
|
return;
|
|
43
176
|
}
|
|
44
|
-
this.
|
|
45
|
-
|
|
46
|
-
|
|
177
|
+
if (Date.now() < this.settleAt) return void this.scheduleSettlement(expectedGeneration);
|
|
178
|
+
const snapshot = this.snapshot(editor);
|
|
179
|
+
try {
|
|
180
|
+
handler(editor, snapshot);
|
|
181
|
+
} finally{
|
|
182
|
+
this.clearSettlement();
|
|
183
|
+
}
|
|
184
|
+
}, wait);
|
|
185
|
+
}
|
|
186
|
+
clearSettlement() {
|
|
187
|
+
this.active = false;
|
|
188
|
+
this.awaitingCommittedTransaction = false;
|
|
189
|
+
this.settling = false;
|
|
190
|
+
this.committedInputSeen = false;
|
|
191
|
+
this.committedText = null;
|
|
192
|
+
this.compositionData = null;
|
|
193
|
+
this.deadline = 0;
|
|
194
|
+
this.range = null;
|
|
195
|
+
this.rangeFrozen = false;
|
|
196
|
+
this.settleAt = 0;
|
|
197
|
+
this.settleEditor = null;
|
|
198
|
+
this.settleHandler = null;
|
|
47
199
|
}
|
|
48
200
|
cancelTimer() {
|
|
49
201
|
if (null === this.timer) return;
|