@web-ppt/collab 0.5.0-beta.2
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/CHANGELOG.md +291 -0
- package/LICENSE +21 -0
- package/README.md +61 -0
- package/dist/atomic-patches.d.ts +6 -0
- package/dist/binding.d.ts +3 -0
- package/dist/broadcast-channel.d.ts +23 -0
- package/dist/checkpoint.d.ts +7 -0
- package/dist/collab.js +897 -0
- package/dist/evaluate.d.ts +16 -0
- package/dist/hierarchy-conflict.d.ts +16 -0
- package/dist/index.d.ts +4 -0
- package/dist/message.d.ts +6 -0
- package/dist/seen.d.ts +15 -0
- package/dist/slide-conflict.d.ts +3 -0
- package/dist/slide-order.d.ts +5 -0
- package/dist/state.d.ts +57 -0
- package/dist/types.d.ts +83 -0
- package/package.json +36 -0
package/dist/collab.js
ADDED
|
@@ -0,0 +1,897 @@
|
|
|
1
|
+
import { MAX_COLLABORATION_VERSION as N, assertIdentityAllocation as we, configureCollaborationIdentity as Se, stageExternalPatches as J } from "@web-ppt/edit-core";
|
|
2
|
+
function D(t, e) {
|
|
3
|
+
return t.clock !== e.clock ? t.clock < e.clock ? -1 : 1 : t.replicaId === e.replicaId ? 0 : t.replicaId < e.replicaId ? -1 : 1;
|
|
4
|
+
}
|
|
5
|
+
const R = (t) => typeof t == "number" && Number.isSafeInteger(t) && t > 0, H = (t) => typeof t == "string" && t.length >= 1 && t.length <= 128 && !/[\0-\x1f\x7f]/.test(t);
|
|
6
|
+
function Ie(t) {
|
|
7
|
+
const e = t, r = (n, s = 1, c = Number.MAX_SAFE_INTEGER) => n === void 0 || R(n) && n >= s && n <= c;
|
|
8
|
+
if (!e || typeof e != "object" || typeof e.prefix != "string" || !e.prefix || !R(e.nextSlide) || !R(e.nextElement) || !e.nextSpid || typeof e.nextSpid != "object" || Array.isArray(e.nextSpid) || Object.entries(e.nextSpid).some(([n, s]) => !n || !R(s)) || !r(e.nextSlidePart) || !r(e.nextNotesPart) || !r(e.nextPresentationSlideId, 256, 2147483648) || !r(e.nextPresentationRelationship))
|
|
9
|
+
throw new Error("协同消息的身份水位无效");
|
|
10
|
+
const o = e.allocation;
|
|
11
|
+
if (o !== void 0) {
|
|
12
|
+
if (!H(o == null ? void 0 : o.replicaId)) throw new Error("协同消息的身份分配命名空间无效");
|
|
13
|
+
try {
|
|
14
|
+
we(o, "协同消息的身份分配命名空间", e.prefix);
|
|
15
|
+
} catch {
|
|
16
|
+
throw new Error("协同消息的身份分配命名空间无效");
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function he(t) {
|
|
21
|
+
const e = t, r = e == null ? void 0 : e.stamp;
|
|
22
|
+
if (!e || typeof e != "object" || e.version !== 1 || !H(e.documentId) || !H(e.replicaId) || !R(e.sequence) || e.sequence > N || !r || !R(r.clock) || r.clock > N || r.replicaId !== e.replicaId || !Array.isArray(e.patches) || !e.patches.length || e.patches.length > 1e4 || e.patches.some((n) => !n || typeof n != "object" || !Array.isArray(n.path) || !n.path.length || typeof n.op != "string" || typeof n.origin != "string") || typeof e.label != "string" || !Number.isFinite(e.time))
|
|
23
|
+
throw new Error("协同消息结构无效");
|
|
24
|
+
Ie(e.identity);
|
|
25
|
+
const o = e.identity.allocation;
|
|
26
|
+
if (!o || o.replicaId !== e.replicaId || o.clock !== r.clock || o.sequence !== e.sequence)
|
|
27
|
+
throw new Error("协同消息的身份版本与消息头不一致");
|
|
28
|
+
}
|
|
29
|
+
const W = (t) => JSON.stringify(t.path), Ee = (t) => `${t.replicaId}\0${t.sequence}`, me = 4096, ye = 1e4;
|
|
30
|
+
function be(t = []) {
|
|
31
|
+
return new Map(t.map((e) => [e.replicaId, {
|
|
32
|
+
contiguous: e.contiguous,
|
|
33
|
+
sparse: new Set(e.sparse)
|
|
34
|
+
}]));
|
|
35
|
+
}
|
|
36
|
+
function Oe(t) {
|
|
37
|
+
return new Map([...t].map(([e, r]) => [e, {
|
|
38
|
+
contiguous: r.contiguous,
|
|
39
|
+
sparse: new Set(r.sparse)
|
|
40
|
+
}]));
|
|
41
|
+
}
|
|
42
|
+
function Me(t) {
|
|
43
|
+
return [...t].map(([e, r]) => ({
|
|
44
|
+
replicaId: e,
|
|
45
|
+
contiguous: r.contiguous,
|
|
46
|
+
sparse: [...r.sparse].sort((o, n) => o - n)
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
function Ce(t, e) {
|
|
50
|
+
const r = t.get(e.replicaId);
|
|
51
|
+
return !!r && (e.sequence <= r.contiguous || r.sparse.has(e.sequence));
|
|
52
|
+
}
|
|
53
|
+
function re(t, e) {
|
|
54
|
+
var r;
|
|
55
|
+
return e.sequence > (((r = t.get(e.replicaId)) == null ? void 0 : r.contiguous) ?? 0) + 1;
|
|
56
|
+
}
|
|
57
|
+
function ne(t, e) {
|
|
58
|
+
let r = t.get(e.replicaId);
|
|
59
|
+
if (!r) {
|
|
60
|
+
if (t.size >= me) throw new Error("协同消息副本数超过安全上限");
|
|
61
|
+
r = { contiguous: 0, sparse: /* @__PURE__ */ new Set() }, t.set(e.replicaId, r);
|
|
62
|
+
}
|
|
63
|
+
if (e.sequence <= r.contiguous || r.sparse.has(e.sequence)) return;
|
|
64
|
+
if (e.sequence === r.contiguous + 1) {
|
|
65
|
+
for (r.contiguous++; r.sparse.delete(r.contiguous + 1); ) r.contiguous++;
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if ([...t.values()].reduce((n, s) => n + s.sparse.size, 0) >= ye) throw new Error("协同消息乱序缺口超过安全上限");
|
|
69
|
+
r.sparse.add(e.sequence);
|
|
70
|
+
}
|
|
71
|
+
const K = (t) => typeof t == "number" && Number.isSafeInteger(t) && t >= 0 && t <= N;
|
|
72
|
+
function Q(t, e) {
|
|
73
|
+
const r = t;
|
|
74
|
+
if (!r || typeof r != "object" || !Number.isSafeInteger(r.clock) || r.clock <= 0 || r.clock > N || typeof r.replicaId != "string" || !r.replicaId)
|
|
75
|
+
throw new Error(`${e} 的 LWW 时间戳无效`);
|
|
76
|
+
}
|
|
77
|
+
function _(t, e, r) {
|
|
78
|
+
if (!Array.isArray(t) || t.length > 1e5) throw new Error(`${e} 无效`);
|
|
79
|
+
const o = /* @__PURE__ */ new Set();
|
|
80
|
+
t.forEach((n, s) => {
|
|
81
|
+
if (!Array.isArray(n) || n.length !== 2 || typeof n[0] != "string" || !n[0] || o.has(n[0])) throw new Error(`${e} 的键无效`);
|
|
82
|
+
o.add(n[0]), r(n[1], `${e}[${s}]`);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
function ke(t, e) {
|
|
86
|
+
const r = t;
|
|
87
|
+
if (!r || typeof r != "object" || r.kind !== "field" && r.kind !== "hierarchy")
|
|
88
|
+
throw new Error(`${e} 的 register 无效`);
|
|
89
|
+
Q(r.stamp, e);
|
|
90
|
+
}
|
|
91
|
+
function se(t, e) {
|
|
92
|
+
const r = t;
|
|
93
|
+
if (!r || typeof r != "object" || r.state !== "present" && r.state !== "removed")
|
|
94
|
+
throw new Error(`${e} 的生命周期无效`);
|
|
95
|
+
Q(r.stamp, e);
|
|
96
|
+
}
|
|
97
|
+
function Le(t, e) {
|
|
98
|
+
const r = t;
|
|
99
|
+
if (!r || typeof r != "object" || r.after !== null && (typeof r.after != "string" || !r.after) || typeof r.ordinal != "number" || !Number.isSafeInteger(r.ordinal) || r.ordinal < 0)
|
|
100
|
+
throw new Error(`${e} 的页序意图无效`);
|
|
101
|
+
Q(r.stamp, e);
|
|
102
|
+
}
|
|
103
|
+
function je(t) {
|
|
104
|
+
if (!Array.isArray(t) || t.length > me)
|
|
105
|
+
throw new Error("协同 checkpoint seen 无效");
|
|
106
|
+
const e = /* @__PURE__ */ new Set();
|
|
107
|
+
let r = 0;
|
|
108
|
+
for (const o of t) {
|
|
109
|
+
const n = o;
|
|
110
|
+
if (!n || typeof n != "object" || typeof n.replicaId != "string" || !n.replicaId || n.replicaId.length > 128 || /[\0-\x1f\x7f]/.test(n.replicaId) || e.has(n.replicaId) || !K(n.contiguous) || !Array.isArray(n.sparse)) throw new Error("协同 checkpoint seen 无效");
|
|
111
|
+
e.add(n.replicaId);
|
|
112
|
+
let s = n.contiguous;
|
|
113
|
+
for (const c of n.sparse) {
|
|
114
|
+
if (!Number.isSafeInteger(c) || c <= s || c > N) throw new Error("协同 checkpoint seen 无效");
|
|
115
|
+
s = c, r++;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (r > ye) throw new Error("协同 checkpoint seen 无效");
|
|
119
|
+
}
|
|
120
|
+
function xe(t, e, r) {
|
|
121
|
+
const o = t;
|
|
122
|
+
if (!o || typeof o != "object" || o.version !== 1 || o.documentId !== e.documentId || o.replicaId !== e.replicaId || o.replicaSlot !== e.replicaSlot || !K(o.clock) || !K(o.sequence) || o.clock !== r.clock || o.sequence !== r.sequence || !Array.isArray(o.baseSlideOrder) || o.baseSlideOrder.some((n) => typeof n != "string" || !n) || new Set(o.baseSlideOrder).size !== o.baseSlideOrder.length || !Array.isArray(o.deferred) || o.deferred.length > 1e4)
|
|
123
|
+
throw new Error("协同 checkpoint 与恢复文档不匹配");
|
|
124
|
+
_(o.registers, "协同 checkpoint registers", ke), _(o.elementLifecycles, "协同 checkpoint elementLifecycles", se), _(o.slideLifecycles, "协同 checkpoint slideLifecycles", se), _(o.slideMoves, "协同 checkpoint slideMoves", Le), je(o.seen), o.deferred.forEach((n, s) => {
|
|
125
|
+
if (!n || typeof n != "object" || !Number.isSafeInteger(n.ordinal) || n.ordinal < 0) throw new Error(`协同 checkpoint deferred[${s}] 无效`);
|
|
126
|
+
if (he(n.message), n.message.documentId !== e.documentId || n.ordinal >= n.message.patches.length || JSON.stringify(n.patch) !== JSON.stringify(n.message.patches[n.ordinal]))
|
|
127
|
+
throw new Error(`协同 checkpoint deferred[${s}] 与消息不匹配`);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
const oe = (t) => t === "__proto__" || t === "prototype" || t === "constructor";
|
|
131
|
+
function Ae(t) {
|
|
132
|
+
const e = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), o = t.map((s) => structuredClone(s));
|
|
133
|
+
if (t.forEach((s, c) => {
|
|
134
|
+
let d = null;
|
|
135
|
+
(s.op === "insert" && s.path.length === 2 && s.path[0] === "elements" || s.op === "set" && s.path.length === 3 && s.path[0] === "elements" && s.path[2] === "hierarchy") && (d = o[c].value.records);
|
|
136
|
+
for (const [a, f] of Object.entries(d ?? {}))
|
|
137
|
+
f && e.set(a, { index: c, record: f });
|
|
138
|
+
if (s.op === "insert" && s.path.length === 2 && s.path[0] === "slides") {
|
|
139
|
+
const a = o[c];
|
|
140
|
+
r.set(a.path[1], { index: c, record: a.value.slide });
|
|
141
|
+
for (const [f, i] of Object.entries(a.value.records))
|
|
142
|
+
e.set(f, { index: c, record: i });
|
|
143
|
+
}
|
|
144
|
+
}), !e.size && !r.size) return [...t];
|
|
145
|
+
const n = /* @__PURE__ */ new Set();
|
|
146
|
+
for (let s = 0; s < t.length; s++) {
|
|
147
|
+
const c = t[s];
|
|
148
|
+
if (c.path.length >= 3 && c.path[0] === "slides" && (c.op === "set" || c.op === "del")) {
|
|
149
|
+
const f = r.get(c.path[1]);
|
|
150
|
+
if (!f || f.index >= s) continue;
|
|
151
|
+
const i = c.path.slice(2);
|
|
152
|
+
if (i.some((b) => typeof b != "string" || oe(b))) continue;
|
|
153
|
+
let h = f.record, m = !0;
|
|
154
|
+
for (const b of i.slice(0, -1)) {
|
|
155
|
+
const v = h[b];
|
|
156
|
+
if (!v || typeof v != "object" || Array.isArray(v)) {
|
|
157
|
+
m = !1;
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
h = v;
|
|
161
|
+
}
|
|
162
|
+
if (!m) continue;
|
|
163
|
+
const S = i[i.length - 1];
|
|
164
|
+
c.op === "set" ? h[S] = structuredClone(c.value) : delete h[S], n.add(s);
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (c.path.length !== 4 || c.path[0] !== "elements" || c.path[2] !== "ovr" || c.op !== "set" && c.op !== "del" || oe(c.path[3])) continue;
|
|
168
|
+
const d = e.get(c.path[1]);
|
|
169
|
+
if (!d || d.index >= s) continue;
|
|
170
|
+
const a = d.record.ovr;
|
|
171
|
+
c.op === "set" ? a[c.path[3]] = structuredClone(c.value) : delete a[c.path[3]], n.add(s);
|
|
172
|
+
}
|
|
173
|
+
return o.filter((s, c) => !n.has(c));
|
|
174
|
+
}
|
|
175
|
+
const qe = ["x", "y", "w", "h", "rot", "flipH", "flipV"], Pe = (t) => t.op === "set" && t.path.length === 3 && t.path[0] === "elements" && t.path[2] === "hierarchy" ? t.value.records : null;
|
|
176
|
+
function Re(t, e, r) {
|
|
177
|
+
const o = e.path[1];
|
|
178
|
+
if (r.has(e.value.parent) || r.has(o) && e.value.records[o] !== null) return null;
|
|
179
|
+
const n = Object.keys(e.value.records).filter((a) => a !== o && r.has(a) && e.value.records[a] !== null);
|
|
180
|
+
if (!n.length) return e;
|
|
181
|
+
const s = structuredClone(e), c = s.value, d = new Set(n);
|
|
182
|
+
for (const a of n) {
|
|
183
|
+
const f = c.records[a], i = t.removedElements[a];
|
|
184
|
+
c.removed[a] = i ? structuredClone(i) : {
|
|
185
|
+
id: a,
|
|
186
|
+
parent: f.parent,
|
|
187
|
+
meta: structuredClone(f.meta),
|
|
188
|
+
...f.meta.origin ? { sourceSpids: [f.meta.origin.spid] } : {}
|
|
189
|
+
}, delete c.records[a], delete c.children[a];
|
|
190
|
+
}
|
|
191
|
+
c.affected = c.affected.filter((a) => !d.has(a));
|
|
192
|
+
for (const [a, f] of Object.entries(c.children))
|
|
193
|
+
c.children[a] = f.filter((i) => !d.has(i));
|
|
194
|
+
for (const a of Object.values(c.records))
|
|
195
|
+
a != null && a.children && (a.children = a.children.filter((f) => !d.has(f)));
|
|
196
|
+
return s;
|
|
197
|
+
}
|
|
198
|
+
function Ne(t, e) {
|
|
199
|
+
if (!e.size) return t;
|
|
200
|
+
const r = t.path[1];
|
|
201
|
+
if (t.value.records[r] === null) return t;
|
|
202
|
+
if (e.has(r)) return null;
|
|
203
|
+
const n = structuredClone(t), s = n.value, c = (s.children[r] ?? []).filter((a) => !e.has(a));
|
|
204
|
+
if (!c.length) return null;
|
|
205
|
+
for (const a of e)
|
|
206
|
+
a !== r && (delete s.records[a], delete s.children[a]);
|
|
207
|
+
s.children[r] = c;
|
|
208
|
+
const d = /* @__PURE__ */ new Set([r, ...c]);
|
|
209
|
+
return s.affected = s.affected.filter((a) => d.has(a)), n;
|
|
210
|
+
}
|
|
211
|
+
function V(t, e) {
|
|
212
|
+
var r, o;
|
|
213
|
+
return ((r = t.slides[e]) == null ? void 0 : r.children) ?? ((o = t.elements[e]) == null ? void 0 : o.children) ?? [];
|
|
214
|
+
}
|
|
215
|
+
function ce(t) {
|
|
216
|
+
return t.order ?? t.z;
|
|
217
|
+
}
|
|
218
|
+
function ie(t, e, r) {
|
|
219
|
+
return [...new Set(t)].filter((o) => e[o] !== null && !!(e[o] ?? r.elements[o])).sort((o, n) => {
|
|
220
|
+
const s = e[o] ?? r.elements[o], c = e[n] ?? r.elements[n], d = ce(s), a = ce(c);
|
|
221
|
+
return (d < a ? -1 : d === a ? 0 : 1) || (o < n ? -1 : o === n ? 0 : 1);
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
function $e(t, e, r, o) {
|
|
225
|
+
const n = structuredClone(t);
|
|
226
|
+
if (n.parent = e.parent, n.z = e.z, r(e.id, "order") && (e.order === void 0 ? delete n.order : n.order = e.order), e.meta.sourceParent === void 0 ? delete n.meta.sourceParent : n.meta.sourceParent = e.meta.sourceParent, o) for (const s of qe)
|
|
227
|
+
r(e.id, s) && (Object.prototype.hasOwnProperty.call(e.ovr, s) ? n.ovr[s] = e.ovr[s] : delete n.ovr[s]);
|
|
228
|
+
return n;
|
|
229
|
+
}
|
|
230
|
+
function _e(t, e, r) {
|
|
231
|
+
const o = t.elements[e];
|
|
232
|
+
if (!o) throw new Error(`协同层级闭包找不到元素:${e}`);
|
|
233
|
+
const n = /* @__PURE__ */ Object.create(null), s = (c) => {
|
|
234
|
+
if (!r.has(c)) return;
|
|
235
|
+
const d = t.elements[c];
|
|
236
|
+
if (!d) throw new Error(`协同层级闭包找不到后代:${c}`);
|
|
237
|
+
n[c] = {
|
|
238
|
+
...structuredClone(d),
|
|
239
|
+
...d.children ? { children: d.children.filter((a) => r.has(a)) } : {}
|
|
240
|
+
};
|
|
241
|
+
for (const a of d.children ?? []) s(a);
|
|
242
|
+
};
|
|
243
|
+
return s(e), { root: e, parent: o.parent, records: n };
|
|
244
|
+
}
|
|
245
|
+
function le(t, e) {
|
|
246
|
+
const r = /* @__PURE__ */ new Set(), o = (n) => {
|
|
247
|
+
if (r.has(n)) return;
|
|
248
|
+
const s = t.elements[n];
|
|
249
|
+
if (!s) throw new Error(`协同层级闭包找不到元素:${n}`);
|
|
250
|
+
r.add(n);
|
|
251
|
+
for (const c of s.children ?? []) o(c);
|
|
252
|
+
};
|
|
253
|
+
return e.forEach(o), r;
|
|
254
|
+
}
|
|
255
|
+
function ze(t, e, r) {
|
|
256
|
+
var v, I;
|
|
257
|
+
const o = structuredClone(e);
|
|
258
|
+
if (!t.slides[e.value.parent] && !t.elements[e.value.parent]) return o;
|
|
259
|
+
const n = o.value, s = e.path[1], d = n.records[s] === null, a = Object.entries(n.records).flatMap(([p, y]) => p !== s && y !== null ? [p] : []), f = new Set(a), i = /* @__PURE__ */ new Set();
|
|
260
|
+
if (d) {
|
|
261
|
+
const p = le(t, a.filter((w) => !!t.elements[w]));
|
|
262
|
+
if (t.elements[s]) for (const w of le(t, [s]))
|
|
263
|
+
w !== s && !p.has(w) && i.add(w);
|
|
264
|
+
const E = [...i].filter((w) => {
|
|
265
|
+
var l;
|
|
266
|
+
return !i.has(((l = t.elements[w]) == null ? void 0 : l.parent) ?? "");
|
|
267
|
+
});
|
|
268
|
+
for (const w of i)
|
|
269
|
+
n.records[w] = null, n.affected.push(w), delete n.children[w];
|
|
270
|
+
for (const w of E) {
|
|
271
|
+
const l = _e(t, w, i), u = l.records[w];
|
|
272
|
+
if (u.meta.created) {
|
|
273
|
+
n.removed[w] = null;
|
|
274
|
+
for (const g of Object.values(l.records))
|
|
275
|
+
!g.meta.created && g.meta.sourceParent !== void 0 && (n.removed[g.id] = B(l, g));
|
|
276
|
+
} else n.removed[w] = B(l, u);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
for (const p of a) {
|
|
280
|
+
const y = t.elements[p], E = n.records[p];
|
|
281
|
+
y && E && (n.records[p] = $e(y, E, r, d));
|
|
282
|
+
}
|
|
283
|
+
const h = /* @__PURE__ */ new Set();
|
|
284
|
+
for (const p of a) {
|
|
285
|
+
const y = (v = t.elements[p]) == null ? void 0 : v.parent;
|
|
286
|
+
if (y && y !== n.parent && y !== s) {
|
|
287
|
+
const E = t.elements[y], w = d ? s : n.parent;
|
|
288
|
+
(E == null ? void 0 : E.src.kind) === "group" && E.meta.created && E.parent === w && h.add(y);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
const m = /* @__PURE__ */ new Set();
|
|
292
|
+
for (const p of h) {
|
|
293
|
+
const y = t.elements[p], E = (y.children ?? []).filter((w) => !f.has(w) && !i.has(w));
|
|
294
|
+
n.affected.push(p), E.length ? (n.records[p] = { ...structuredClone(y), children: E }, n.children[p] = E) : (n.records[p] = null, n.removed[p] = null, delete n.children[p], m.add(p));
|
|
295
|
+
}
|
|
296
|
+
if (d) {
|
|
297
|
+
const p = (I = t.elements[s]) == null ? void 0 : I.parent, y = p ? t.elements[p] : void 0;
|
|
298
|
+
if ((y == null ? void 0 : y.src.kind) === "group" && p !== n.parent) {
|
|
299
|
+
const E = (y.children ?? []).filter((w) => w !== s);
|
|
300
|
+
n.affected.push(y.id), E.length || !y.meta.created ? (n.records[y.id] = { ...structuredClone(y), children: E }, n.children[y.id] = E) : (n.records[y.id] = null, n.removed[y.id] = null, delete n.children[y.id], m.add(y.id), y.parent !== n.parent && (n.children[y.parent] = V(t, y.parent).filter((w) => w !== y.id)));
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
const b = V(t, n.parent).filter((p) => !f.has(p) && p !== s && !m.has(p));
|
|
304
|
+
return d ? b.push(...a) : b.push(s), n.children[n.parent] = ie(b, n.records, t), d || (n.children[s] = ie(a, n.records, t)), n.affected = [...new Set(n.affected)], o;
|
|
305
|
+
}
|
|
306
|
+
function Be(t, e) {
|
|
307
|
+
var s;
|
|
308
|
+
const r = (s = e.meta.origin) == null ? void 0 : s.part, o = [], n = (c) => {
|
|
309
|
+
const d = t.records[c];
|
|
310
|
+
if (!d) return;
|
|
311
|
+
const a = d.meta.origin;
|
|
312
|
+
a && a.part === r && o.push(a.spid);
|
|
313
|
+
for (const f of d.children ?? []) n(f);
|
|
314
|
+
};
|
|
315
|
+
return n(e.id), [...new Set(o)].sort((c, d) => c - d);
|
|
316
|
+
}
|
|
317
|
+
function B(t, e) {
|
|
318
|
+
const r = Be(t, e);
|
|
319
|
+
return {
|
|
320
|
+
id: e.id,
|
|
321
|
+
parent: e.parent,
|
|
322
|
+
meta: structuredClone(e.meta),
|
|
323
|
+
...r.length ? { sourceSpids: r } : {}
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
function De(t, e) {
|
|
327
|
+
let r = e;
|
|
328
|
+
const o = /* @__PURE__ */ new Set();
|
|
329
|
+
for (; !t.slides[r]; ) {
|
|
330
|
+
if (o.has(r)) throw new Error(`协同删除父链成环:${e}`);
|
|
331
|
+
o.add(r);
|
|
332
|
+
const n = t.elements[r];
|
|
333
|
+
if (!n) throw new Error(`协同删除找不到所属页:${e}`);
|
|
334
|
+
r = n.parent;
|
|
335
|
+
}
|
|
336
|
+
return r;
|
|
337
|
+
}
|
|
338
|
+
function Te(t, e) {
|
|
339
|
+
if (e.op !== "remove") return e;
|
|
340
|
+
const r = t.elements[e.path[1]];
|
|
341
|
+
if (!!r && r.parent === e.value.parent && Object.entries(e.value.records).every(([m, S]) => {
|
|
342
|
+
var b;
|
|
343
|
+
return ((b = t.elements[m]) == null ? void 0 : b.parent) === S.parent;
|
|
344
|
+
})) return e;
|
|
345
|
+
const n = new Set(Object.keys(e.value.records).filter((m) => !!t.elements[m]));
|
|
346
|
+
if (r) {
|
|
347
|
+
const m = (S) => {
|
|
348
|
+
var v;
|
|
349
|
+
if (n.has(S)) {
|
|
350
|
+
for (const I of ((v = t.elements[S]) == null ? void 0 : v.children) ?? []) m(I);
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
const b = t.elements[S];
|
|
354
|
+
if (b) {
|
|
355
|
+
n.add(S);
|
|
356
|
+
for (const I of b.children ?? []) m(I);
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
m(r.id);
|
|
360
|
+
}
|
|
361
|
+
const s = [...n];
|
|
362
|
+
if (!s.length) return null;
|
|
363
|
+
const c = Object.fromEntries(s.map((m) => [m, null])), d = /* @__PURE__ */ Object.create(null), a = e.value.records[e.value.root];
|
|
364
|
+
if (a.meta.created) {
|
|
365
|
+
d[a.id] = null;
|
|
366
|
+
for (const m of Object.values(e.value.records))
|
|
367
|
+
!m.meta.created && m.meta.sourceParent !== void 0 && (d[m.id] = B(e.value, m));
|
|
368
|
+
} else d[a.id] = B(e.value, a);
|
|
369
|
+
for (const m of s)
|
|
370
|
+
Object.prototype.hasOwnProperty.call(e.value.records, m) || (d[m] = null);
|
|
371
|
+
const f = new Set(s), i = /* @__PURE__ */ Object.create(null);
|
|
372
|
+
for (const m of s) {
|
|
373
|
+
const S = t.elements[m].parent;
|
|
374
|
+
!f.has(S) && i[S] === void 0 && (i[S] = V(t, S).filter((b) => !f.has(b)));
|
|
375
|
+
}
|
|
376
|
+
const h = De(t, s[0]);
|
|
377
|
+
return {
|
|
378
|
+
op: "set",
|
|
379
|
+
path: ["elements", e.path[1], "hierarchy"],
|
|
380
|
+
origin: e.origin,
|
|
381
|
+
value: { parent: h, affected: s, records: c, children: i, removed: d }
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
function Fe(t, e) {
|
|
385
|
+
if (e.op !== "remove") return e;
|
|
386
|
+
const r = t.slides[e.path[1]];
|
|
387
|
+
if (!r) return null;
|
|
388
|
+
const o = /* @__PURE__ */ Object.create(null), n = (c) => {
|
|
389
|
+
const d = t.elements[c];
|
|
390
|
+
if (!d) throw new Error(`协同删页找不到当前元素:${c}`);
|
|
391
|
+
o[c] = structuredClone(d);
|
|
392
|
+
for (const a of d.children ?? []) n(a);
|
|
393
|
+
};
|
|
394
|
+
for (const c of r.children) n(c);
|
|
395
|
+
const s = t.slideOrder.indexOf(r.id);
|
|
396
|
+
if (s < 0) throw new Error(`协同删页找不到当前页序:${r.id}`);
|
|
397
|
+
return {
|
|
398
|
+
...e,
|
|
399
|
+
value: {
|
|
400
|
+
slide: structuredClone(r),
|
|
401
|
+
after: t.slideOrder[s - 1] ?? null,
|
|
402
|
+
before: t.slideOrder[s + 1] ?? null,
|
|
403
|
+
records: o
|
|
404
|
+
}
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
const Je = ["x", "y", "w", "h", "rot", "flipH", "flipV"], z = (t) => `hierarchy:${JSON.stringify(t)}`, Y = (t) => t.path.length === 2 && t.path[0] === "elements" && (t.op === "insert" || t.op === "remove") ? { id: t.path[1], state: t.op === "insert" ? "present" : "removed" } : null, T = (t) => t.path.length === 2 && t.path[0] === "slides" && (t.op === "insert" || t.op === "remove") ? { id: t.path[1], state: t.op === "insert" ? "present" : "removed" } : null, Z = (t) => {
|
|
408
|
+
var r;
|
|
409
|
+
if (t.op !== "move" || t.path.length !== 2 || t.path[0] !== "slideOrder") return null;
|
|
410
|
+
const e = (r = t.value) == null ? void 0 : r.after;
|
|
411
|
+
return e === null || typeof e == "string" && e ? { id: t.path[1], after: e } : null;
|
|
412
|
+
}, ee = (t) => Pe(t), j = (t, e) => !e || D(t, e.stamp) > 0;
|
|
413
|
+
function X(t, e, r) {
|
|
414
|
+
var d, a;
|
|
415
|
+
const o = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Map();
|
|
416
|
+
for (let f = 0; f < e.length; f++) {
|
|
417
|
+
const i = e[f], h = ee(i);
|
|
418
|
+
if (h) {
|
|
419
|
+
const v = i.path[1], I = i.value;
|
|
420
|
+
for (const p of I.affected) o.set(z(p), "hierarchy");
|
|
421
|
+
for (const [p, y] of Object.entries(h))
|
|
422
|
+
n.set(p, y === null ? "removed" : "present"), y !== null && o.set(JSON.stringify(["elements", p, "order"]), "hierarchy");
|
|
423
|
+
if (h[v] === null) {
|
|
424
|
+
for (const [p, y] of Object.entries(I.records))
|
|
425
|
+
if (y !== null)
|
|
426
|
+
for (const E of Je)
|
|
427
|
+
o.set(JSON.stringify(["elements", p, "ovr", E]), "hierarchy");
|
|
428
|
+
}
|
|
429
|
+
o.set(W(i), "hierarchy");
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
const m = Y(i);
|
|
433
|
+
if (m) {
|
|
434
|
+
const v = (d = i.value) == null ? void 0 : d.records;
|
|
435
|
+
for (const I of Object.keys(v ?? { [m.id]: !0 }))
|
|
436
|
+
n.set(I, m.state), o.set(z(I), "hierarchy");
|
|
437
|
+
}
|
|
438
|
+
const S = T(i);
|
|
439
|
+
if (S) {
|
|
440
|
+
s.set(S.id, S.state);
|
|
441
|
+
const v = (a = i.value) == null ? void 0 : a.records;
|
|
442
|
+
for (const I of Object.keys(v ?? {}))
|
|
443
|
+
n.set(I, S.state), o.set(z(I), "hierarchy");
|
|
444
|
+
S.state === "present" && c.set(S.id, {
|
|
445
|
+
after: i.op === "insert" ? i.value.after : null,
|
|
446
|
+
ordinal: f
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
const b = Z(i);
|
|
450
|
+
b && c.set(b.id, { after: b.after, ordinal: f }), !m && !S && !b && o.set(W(i), "field");
|
|
451
|
+
}
|
|
452
|
+
for (const [f, i] of o) {
|
|
453
|
+
const h = t.registers.get(f);
|
|
454
|
+
(!h || D(r, h.stamp) >= 0) && t.registers.set(f, { stamp: r, kind: i });
|
|
455
|
+
}
|
|
456
|
+
for (const [f, i] of n) {
|
|
457
|
+
const h = t.elementLifecycles.get(f);
|
|
458
|
+
(i === "removed" && (h == null ? void 0 : h.stamp.replicaId) !== r.replicaId || j(r, h)) && t.elementLifecycles.set(f, { stamp: r, state: i });
|
|
459
|
+
}
|
|
460
|
+
for (const [f, i] of s)
|
|
461
|
+
j(r, t.slideLifecycles.get(f)) && t.slideLifecycles.set(f, { stamp: r, state: i });
|
|
462
|
+
for (const [f, i] of c)
|
|
463
|
+
j(r, t.slideMoves.get(f)) && t.slideMoves.set(f, { stamp: r, ...i });
|
|
464
|
+
}
|
|
465
|
+
function Xe(t, e) {
|
|
466
|
+
const [r, o] = e.path;
|
|
467
|
+
return r === "elements" && typeof o == "string" ? !!t.elements[o] : (r === "slides" || r === "slideOrder") && typeof o == "string" ? !!t.slides[o] : !0;
|
|
468
|
+
}
|
|
469
|
+
function U(t, e) {
|
|
470
|
+
const r = {
|
|
471
|
+
elements: new Set(e == null ? void 0 : e.elements),
|
|
472
|
+
slides: new Set(e == null ? void 0 : e.slides)
|
|
473
|
+
};
|
|
474
|
+
for (const o of t) {
|
|
475
|
+
const n = Y(o);
|
|
476
|
+
(n == null ? void 0 : n.state) === "present" && Object.keys(o.value.records).forEach((c) => r.elements.add(c));
|
|
477
|
+
const s = T(o);
|
|
478
|
+
if ((s == null ? void 0 : s.state) === "present" && (r.slides.add(s.id), Object.keys(o.value.records).forEach((c) => r.elements.add(c))), ee(o))
|
|
479
|
+
for (const [c, d] of Object.entries(
|
|
480
|
+
o.value.records
|
|
481
|
+
)) d && r.elements.add(c);
|
|
482
|
+
}
|
|
483
|
+
return r;
|
|
484
|
+
}
|
|
485
|
+
function ae(t, e, r) {
|
|
486
|
+
var s, c;
|
|
487
|
+
const [o, n] = t.path;
|
|
488
|
+
return o === "elements" && typeof n == "string" ? ((s = e.get(n)) == null ? void 0 : s.state) === "removed" : (o === "slides" || o === "slideOrder") && typeof n == "string" ? ((c = r.get(n)) == null ? void 0 : c.state) === "removed" : !1;
|
|
489
|
+
}
|
|
490
|
+
function de(t, e, r) {
|
|
491
|
+
const [o, n] = e.path;
|
|
492
|
+
return o === "elements" && r.elements.has(n) || (o === "slides" || o === "slideOrder") && r.slides.has(n) ? !0 : Xe(t, e);
|
|
493
|
+
}
|
|
494
|
+
function fe(t, e, r) {
|
|
495
|
+
return !!t.elements[e] || !!t.slides[e] || r.elements.has(e) || r.slides.has(e);
|
|
496
|
+
}
|
|
497
|
+
function ue(t, e, r, o) {
|
|
498
|
+
var a, f;
|
|
499
|
+
const n = [], s = [], c = U([], o);
|
|
500
|
+
let d = !1;
|
|
501
|
+
for (const i of r.patches) {
|
|
502
|
+
const h = Y(i), m = T(i), S = Z(i), b = ee(i);
|
|
503
|
+
if (h) {
|
|
504
|
+
if (h.state === "removed") {
|
|
505
|
+
const I = e.elementLifecycles.get(h.id);
|
|
506
|
+
if ((I == null ? void 0 : I.stamp.replicaId) === r.replicaId && !j(r.stamp, I)) continue;
|
|
507
|
+
const p = Te(t, i);
|
|
508
|
+
p && n.push(p), s.push(i), p && p !== i && s.push(p);
|
|
509
|
+
continue;
|
|
510
|
+
}
|
|
511
|
+
if (!j(r.stamp, e.elementLifecycles.get(h.id))) continue;
|
|
512
|
+
const v = i.value.parent;
|
|
513
|
+
if (((a = e.slideLifecycles.get(v)) == null ? void 0 : a.state) === "removed" || ((f = e.elementLifecycles.get(v)) == null ? void 0 : f.state) === "removed") {
|
|
514
|
+
s.push({ ...i, op: "remove" });
|
|
515
|
+
continue;
|
|
516
|
+
}
|
|
517
|
+
fe(t, v, c) || (d = !0), t.elements[h.id] || (n.push(i), Object.keys(i.value.records).forEach((I) => c.elements.add(I))), s.push(i);
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
520
|
+
if (m) {
|
|
521
|
+
if (!j(r.stamp, e.slideLifecycles.get(m.id))) continue;
|
|
522
|
+
if (m.state === "removed") {
|
|
523
|
+
const v = Fe(t, i);
|
|
524
|
+
v && n.push(v), s.push(v ?? i);
|
|
525
|
+
continue;
|
|
526
|
+
}
|
|
527
|
+
t.slides[m.id] || (n.push(i), c.slides.add(m.id), Object.keys(i.value.records).forEach((v) => c.elements.add(v))), s.push(i);
|
|
528
|
+
continue;
|
|
529
|
+
}
|
|
530
|
+
if (b) {
|
|
531
|
+
const v = i;
|
|
532
|
+
fe(t, v.value.parent, c) || (d = !0);
|
|
533
|
+
const I = new Set([...e.elementLifecycles].flatMap(([w, l]) => l.state === "removed" ? [w] : [])), p = new Set(v.value.affected.filter((w) => !j(r.stamp, e.registers.get(z(w))))), y = Ne(v, p), E = y && Re(
|
|
534
|
+
t,
|
|
535
|
+
y,
|
|
536
|
+
I
|
|
537
|
+
);
|
|
538
|
+
if (E) {
|
|
539
|
+
const w = E.value.records[E.path[1]] === null, l = ze(t, E, (u, g) => {
|
|
540
|
+
const M = g === "order" ? ["elements", u, "order"] : ["elements", u, "ovr", g], O = e.registers.get(JSON.stringify(M));
|
|
541
|
+
return w && (O == null ? void 0 : O.kind) === "hierarchy" || j(r.stamp, O);
|
|
542
|
+
});
|
|
543
|
+
n.push(l), s.push(l), Object.entries(l.value.records).forEach(([u, g]) => {
|
|
544
|
+
g && c.elements.add(u);
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
continue;
|
|
548
|
+
}
|
|
549
|
+
if (S) {
|
|
550
|
+
if (!j(r.stamp, e.slideMoves.get(S.id))) continue;
|
|
551
|
+
ae(i, e.elementLifecycles, e.slideLifecycles) ? s.push(i) : de(t, i, c) ? (n.push(i), s.push(i)) : d = !0;
|
|
552
|
+
continue;
|
|
553
|
+
}
|
|
554
|
+
j(r.stamp, e.registers.get(W(i))) && (ae(i, e.elementLifecycles, e.slideLifecycles) ? s.push(i) : de(t, i, c) ? (n.push(i), s.push(i)) : d = !0);
|
|
555
|
+
}
|
|
556
|
+
return { accepted: n, recorded: s, missingDependency: d, availability: c };
|
|
557
|
+
}
|
|
558
|
+
function Ge(t, e, r) {
|
|
559
|
+
const o = t.filter((s) => e.has(s));
|
|
560
|
+
o.push(...[...e].filter((s) => !o.includes(s)).sort());
|
|
561
|
+
const n = [...r.entries()].sort((s, c) => D(s[1].stamp, c[1].stamp) || s[1].ordinal - c[1].ordinal || (s[0] < c[0] ? -1 : s[0] === c[0] ? 0 : 1));
|
|
562
|
+
for (const [s, c] of n) {
|
|
563
|
+
const d = o.indexOf(s);
|
|
564
|
+
if (d < 0) continue;
|
|
565
|
+
o.splice(d, 1);
|
|
566
|
+
const a = c.after === null ? -1 : o.indexOf(c.after);
|
|
567
|
+
o.splice(a < 0 && c.after !== null ? o.length : a + 1, 0, s);
|
|
568
|
+
}
|
|
569
|
+
return o;
|
|
570
|
+
}
|
|
571
|
+
function He(t, e) {
|
|
572
|
+
const r = [...t], o = [];
|
|
573
|
+
for (let n = 0; n < e.length; n++) {
|
|
574
|
+
const s = e[n], c = e[n - 1] ?? null, d = r.indexOf(s);
|
|
575
|
+
if ((d > 0 ? r[d - 1] : null) === c) continue;
|
|
576
|
+
r.splice(d, 1);
|
|
577
|
+
const f = c === null ? -1 : r.indexOf(c);
|
|
578
|
+
r.splice(f + 1, 0, s), o.push({ op: "move", path: ["slideOrder", s], value: { after: c }, origin: "collab-order" });
|
|
579
|
+
}
|
|
580
|
+
return o;
|
|
581
|
+
}
|
|
582
|
+
function We(t, e, r) {
|
|
583
|
+
const o = /* @__PURE__ */ new Map(), n = [], s = [];
|
|
584
|
+
for (const h of r)
|
|
585
|
+
if (!Z(h))
|
|
586
|
+
if (h.path.length === 2 && h.path[0] === "slides" && (h.op === "insert" || h.op === "remove")) {
|
|
587
|
+
const m = structuredClone(h);
|
|
588
|
+
m.op === "insert" ? o.set(m.path[1], m) : n.push(m);
|
|
589
|
+
} else s.push(h);
|
|
590
|
+
const c = new Set(n.map((h) => h.path[1])), d = t.filter((h) => !c.has(h)), a = e.filter((h) => !o.has(h)), f = He(d, a), i = [];
|
|
591
|
+
for (let h = 0; h < e.length; h++) {
|
|
592
|
+
const m = e[h], S = o.get(m);
|
|
593
|
+
S && i.push({
|
|
594
|
+
...S,
|
|
595
|
+
value: { ...S.value, after: e[h - 1] ?? null }
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
return [...n, ...f, ...i, ...s];
|
|
599
|
+
}
|
|
600
|
+
const G = /* @__PURE__ */ new WeakMap(), Ke = 1e4;
|
|
601
|
+
function pe(t, e) {
|
|
602
|
+
if (!t || t.length > 128 || /[\0-\x1f\x7f]/.test(t))
|
|
603
|
+
throw new Error(`${e} 必须是 1–128 个不含控制字符的字符`);
|
|
604
|
+
}
|
|
605
|
+
function Ve(t, e, r) {
|
|
606
|
+
const o = t.doc.identity.allocation;
|
|
607
|
+
return {
|
|
608
|
+
documentId: e.documentId,
|
|
609
|
+
replicaId: e.replicaId,
|
|
610
|
+
replicaSlot: e.replicaSlot,
|
|
611
|
+
registers: new Map(r == null ? void 0 : r.registers.map(([n, s]) => [n, structuredClone(s)])),
|
|
612
|
+
elementLifecycles: new Map(structuredClone((r == null ? void 0 : r.elementLifecycles) ?? [])),
|
|
613
|
+
slideLifecycles: new Map(structuredClone((r == null ? void 0 : r.slideLifecycles) ?? [])),
|
|
614
|
+
slideMoves: new Map(structuredClone((r == null ? void 0 : r.slideMoves) ?? [])),
|
|
615
|
+
seen: be(r == null ? void 0 : r.seen),
|
|
616
|
+
baseSlideOrder: r ? [...r.baseSlideOrder] : [...t.doc.slideOrder],
|
|
617
|
+
deferred: (r == null ? void 0 : r.deferred.map((n) => structuredClone(n))) ?? [],
|
|
618
|
+
clock: o.clock,
|
|
619
|
+
sequence: o.sequence,
|
|
620
|
+
active: !1
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
function Ue(t) {
|
|
624
|
+
return structuredClone({
|
|
625
|
+
version: 1,
|
|
626
|
+
documentId: t.documentId,
|
|
627
|
+
replicaId: t.replicaId,
|
|
628
|
+
replicaSlot: t.replicaSlot,
|
|
629
|
+
clock: t.clock,
|
|
630
|
+
sequence: t.sequence,
|
|
631
|
+
baseSlideOrder: t.baseSlideOrder,
|
|
632
|
+
registers: [...t.registers].map(([e, r]) => [e, r]),
|
|
633
|
+
elementLifecycles: [...t.elementLifecycles],
|
|
634
|
+
slideLifecycles: [...t.slideLifecycles],
|
|
635
|
+
slideMoves: [...t.slideMoves],
|
|
636
|
+
seen: Me(t.seen),
|
|
637
|
+
deferred: t.deferred
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
function Qe(t, e) {
|
|
641
|
+
if (t.active) throw new Error("同一个 Editor 已经绑定协同 provider");
|
|
642
|
+
if (t.documentId !== e.documentId || t.replicaId !== e.replicaId || t.replicaSlot !== e.replicaSlot)
|
|
643
|
+
throw new Error("同一个 Editor 不能切换协同文档或副本身份");
|
|
644
|
+
}
|
|
645
|
+
function Ze(t, e) {
|
|
646
|
+
if (!t || typeof t.subscribePatches != "function" || typeof t.applyExternalPatches != "function")
|
|
647
|
+
throw new Error("协同绑定需要支持外部补丁 seam 的 Editor");
|
|
648
|
+
if (pe(e.documentId, "documentId"), pe(e.replicaId, "replicaId"), !e.provider || typeof e.provider.send != "function" || typeof e.provider.subscribe != "function") throw new Error("provider 接口无效");
|
|
649
|
+
if (!Number.isSafeInteger(e.replicaSlot) || e.replicaSlot < 0 || e.replicaSlot >= 4096)
|
|
650
|
+
throw new Error("replicaSlot 必须是 0–4095 的整数");
|
|
651
|
+
let r = G.get(t);
|
|
652
|
+
const o = !r;
|
|
653
|
+
let n = null;
|
|
654
|
+
if (r) Qe(r, e);
|
|
655
|
+
else {
|
|
656
|
+
const l = t.doc.identity.allocation, u = (l == null ? void 0 : l.replicaId) === e.replicaId && l.slot === e.replicaSlot && l.count === 4096;
|
|
657
|
+
if (t.history.undoCount || t.history.redoCount || t.isDirty() && !u)
|
|
658
|
+
throw new Error("协同绑定必须在本地编辑开始前建立");
|
|
659
|
+
n = structuredClone(t.doc.identity);
|
|
660
|
+
try {
|
|
661
|
+
Se(t.doc, e.replicaId, e.replicaSlot);
|
|
662
|
+
const g = t.doc.identity.allocation;
|
|
663
|
+
if ((g.clock > 0 || g.sequence > 0) && !e.checkpoint)
|
|
664
|
+
throw new Error("恢复协同文档必须同时提供 CollaborationCheckpoint");
|
|
665
|
+
e.checkpoint && xe(e.checkpoint, e, g), r = Ve(t, e, e.checkpoint), G.set(t, r);
|
|
666
|
+
} catch (g) {
|
|
667
|
+
throw t.doc.identity = n, g;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
const s = r, c = (l) => {
|
|
671
|
+
var u;
|
|
672
|
+
try {
|
|
673
|
+
(u = e.onError) == null || u.call(e, l);
|
|
674
|
+
} catch {
|
|
675
|
+
}
|
|
676
|
+
}, d = () => ({
|
|
677
|
+
registers: new Map(s.registers),
|
|
678
|
+
elementLifecycles: new Map(s.elementLifecycles),
|
|
679
|
+
slideLifecycles: new Map(s.slideLifecycles),
|
|
680
|
+
slideMoves: new Map(s.slideMoves),
|
|
681
|
+
seen: Oe(s.seen),
|
|
682
|
+
deferred: [...s.deferred],
|
|
683
|
+
clock: s.clock
|
|
684
|
+
}), a = (l) => {
|
|
685
|
+
s.registers.clear(), l.registers.forEach((u, g) => s.registers.set(g, u)), s.elementLifecycles.clear(), l.elementLifecycles.forEach((u, g) => s.elementLifecycles.set(g, u)), s.slideLifecycles.clear(), l.slideLifecycles.forEach((u, g) => s.slideLifecycles.set(g, u)), s.slideMoves.clear(), l.slideMoves.forEach((u, g) => s.slideMoves.set(g, u)), s.seen.clear(), l.seen.forEach((u, g) => s.seen.set(g, u)), s.deferred = [...l.deferred], s.clock = l.clock;
|
|
686
|
+
}, f = (l) => {
|
|
687
|
+
const u = Ae(l), g = new Set(t.doc.slideOrder);
|
|
688
|
+
for (const O of u) {
|
|
689
|
+
const x = T(O);
|
|
690
|
+
x && (x.state === "present" ? g.add(x.id) : g.delete(x.id));
|
|
691
|
+
}
|
|
692
|
+
const M = Ge(
|
|
693
|
+
s.baseSlideOrder,
|
|
694
|
+
g,
|
|
695
|
+
s.slideMoves
|
|
696
|
+
);
|
|
697
|
+
return We(t.doc.slideOrder, M, u);
|
|
698
|
+
}, i = (l, u) => {
|
|
699
|
+
const g = [], M = [];
|
|
700
|
+
let O = l, x = J(
|
|
701
|
+
t.doc,
|
|
702
|
+
f(u)
|
|
703
|
+
), P = !0;
|
|
704
|
+
for (; P; ) {
|
|
705
|
+
P = !1;
|
|
706
|
+
const $ = [...s.deferred].sort((L, C) => D(L.message.stamp, C.message.stamp) || L.ordinal - C.ordinal), k = /* @__PURE__ */ new Map();
|
|
707
|
+
for (const L of $) {
|
|
708
|
+
const C = Ee(L.message), q = k.get(C) ?? [];
|
|
709
|
+
q.push(L), k.set(C, q);
|
|
710
|
+
}
|
|
711
|
+
const A = /* @__PURE__ */ new Set();
|
|
712
|
+
for (const L of k.values()) {
|
|
713
|
+
const C = L[0].message;
|
|
714
|
+
if (A.has(C.replicaId)) continue;
|
|
715
|
+
if (re(s.seen, C)) {
|
|
716
|
+
A.add(C.replicaId);
|
|
717
|
+
continue;
|
|
718
|
+
}
|
|
719
|
+
const q = ue(x, s, C, O);
|
|
720
|
+
if (q.missingDependency) {
|
|
721
|
+
A.add(C.replicaId);
|
|
722
|
+
continue;
|
|
723
|
+
}
|
|
724
|
+
const ge = d(), te = new Set(L);
|
|
725
|
+
X(s, q.recorded, C.stamp);
|
|
726
|
+
try {
|
|
727
|
+
x = J(t.doc, f([
|
|
728
|
+
...u,
|
|
729
|
+
...g,
|
|
730
|
+
...q.accepted
|
|
731
|
+
]));
|
|
732
|
+
} catch (F) {
|
|
733
|
+
a(ge), s.deferred = s.deferred.filter((ve) => !te.has(ve)), M.push(F), P = !0;
|
|
734
|
+
continue;
|
|
735
|
+
}
|
|
736
|
+
s.deferred = s.deferred.filter((F) => !te.has(F)), g.push(...q.accepted), O = U(q.accepted, O), P = !0;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
return { patches: g, errors: M };
|
|
740
|
+
}, h = (l) => {
|
|
741
|
+
try {
|
|
742
|
+
if (he(l), l.documentId !== e.documentId || l.replicaId === e.replicaId) return;
|
|
743
|
+
if (l.identity.prefix !== t.doc.identity.prefix)
|
|
744
|
+
throw new Error("协同消息的文档身份前缀与本地基线不一致");
|
|
745
|
+
if (Ce(s.seen, l)) return;
|
|
746
|
+
const u = ue(t.doc, s, l), M = re(s.seen, l) || s.deferred.some((k) => k.message.replicaId === l.replicaId && k.message.sequence < l.sequence) || u.missingDependency ? l.patches.map((k, A) => ({ message: l, patch: k, ordinal: A })) : [];
|
|
747
|
+
if (s.deferred.length + M.length > Ke)
|
|
748
|
+
throw new Error("协同延迟补丁超过安全上限");
|
|
749
|
+
const O = t.doc.identity.allocation, x = d(), P = O.clock;
|
|
750
|
+
let $ = [];
|
|
751
|
+
try {
|
|
752
|
+
const k = Math.max(s.clock, l.stamp.clock);
|
|
753
|
+
s.clock = k, O.clock = k, ne(s.seen, l), M.length ? s.deferred.push(...M) : X(s, u.recorded, l.stamp), M.length || J(
|
|
754
|
+
t.doc,
|
|
755
|
+
f(u.accepted)
|
|
756
|
+
);
|
|
757
|
+
const A = M.length ? { patches: [], errors: [] } : i(U(u.accepted), u.accepted);
|
|
758
|
+
$ = A.errors;
|
|
759
|
+
const L = M.length ? [] : [...u.accepted, ...A.patches], C = f(L);
|
|
760
|
+
C.length ? t.applyExternalPatches(C, {
|
|
761
|
+
identity: l.identity,
|
|
762
|
+
origin: `collab:${l.replicaId}`,
|
|
763
|
+
label: l.label,
|
|
764
|
+
time: l.time
|
|
765
|
+
}) : t.applyExternalPatches([], {
|
|
766
|
+
identity: l.identity,
|
|
767
|
+
origin: `collab:${l.replicaId}`
|
|
768
|
+
});
|
|
769
|
+
} catch (k) {
|
|
770
|
+
throw a(x), O.clock = P, k;
|
|
771
|
+
}
|
|
772
|
+
$.forEach(c);
|
|
773
|
+
} catch (u) {
|
|
774
|
+
c(u);
|
|
775
|
+
}
|
|
776
|
+
}, m = /* @__PURE__ */ new Map(), S = (l) => {
|
|
777
|
+
if (!s.active || l.source === "external" || !l.patches.length) return;
|
|
778
|
+
const u = l.identity.allocation;
|
|
779
|
+
if (!u || u.replicaId !== e.replicaId || u.slot !== e.replicaSlot) {
|
|
780
|
+
c(new Error("本地补丁缺少匹配的协同身份版本"));
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
if (u.clock <= s.clock || u.sequence <= s.sequence) {
|
|
784
|
+
c(new Error("协同逻辑时钟或消息序号已耗尽"));
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
s.clock = u.clock, s.sequence = u.sequence;
|
|
788
|
+
const g = { clock: u.clock, replicaId: e.replicaId }, M = u.sequence;
|
|
789
|
+
X(s, l.patches, g);
|
|
790
|
+
const O = {
|
|
791
|
+
version: 1,
|
|
792
|
+
documentId: e.documentId,
|
|
793
|
+
replicaId: e.replicaId,
|
|
794
|
+
sequence: M,
|
|
795
|
+
stamp: g,
|
|
796
|
+
patches: l.patches,
|
|
797
|
+
identity: l.identity,
|
|
798
|
+
label: l.label,
|
|
799
|
+
time: l.time
|
|
800
|
+
};
|
|
801
|
+
ne(s.seen, O), m.set(M, O);
|
|
802
|
+
}, b = (l) => {
|
|
803
|
+
var M;
|
|
804
|
+
if (!s.active || l.source === "external" || !l.patches.length) return;
|
|
805
|
+
const u = (M = l.identity.allocation) == null ? void 0 : M.sequence, g = u === void 0 ? void 0 : m.get(u);
|
|
806
|
+
if (!g) {
|
|
807
|
+
c(new Error("本地补丁缺少 recovery 前协同 checkpoint"));
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
m.delete(g.sequence);
|
|
811
|
+
try {
|
|
812
|
+
const O = e.provider.send(structuredClone(g));
|
|
813
|
+
O && typeof O.then == "function" && O.catch(c);
|
|
814
|
+
} catch (O) {
|
|
815
|
+
c(O);
|
|
816
|
+
}
|
|
817
|
+
};
|
|
818
|
+
let v = null, I = null, p = null;
|
|
819
|
+
const y = [];
|
|
820
|
+
let E = !1, w = !1;
|
|
821
|
+
try {
|
|
822
|
+
v = t.subscribePatches(S, { phase: "before-recovery" }), I = t.subscribePatches(b);
|
|
823
|
+
const l = e.provider.subscribe((u) => {
|
|
824
|
+
w || (E ? h(u) : y.push(structuredClone(u)));
|
|
825
|
+
});
|
|
826
|
+
if (typeof l != "function") throw new Error("provider.subscribe 必须返回取消订阅函数");
|
|
827
|
+
p = l, s.active = !0, E = !0;
|
|
828
|
+
for (const u of y) h(u);
|
|
829
|
+
} catch (l) {
|
|
830
|
+
try {
|
|
831
|
+
v == null || v();
|
|
832
|
+
} catch {
|
|
833
|
+
}
|
|
834
|
+
try {
|
|
835
|
+
I == null || I();
|
|
836
|
+
} catch {
|
|
837
|
+
}
|
|
838
|
+
try {
|
|
839
|
+
p == null || p();
|
|
840
|
+
} catch {
|
|
841
|
+
}
|
|
842
|
+
throw o && n && (t.doc.identity = n, G.delete(t)), l;
|
|
843
|
+
}
|
|
844
|
+
return {
|
|
845
|
+
documentId: e.documentId,
|
|
846
|
+
replicaId: e.replicaId,
|
|
847
|
+
editor: t,
|
|
848
|
+
checkpoint: () => Ue(s),
|
|
849
|
+
dispose() {
|
|
850
|
+
if (!w) {
|
|
851
|
+
w = !0, s.active = !1, E = !1, y.length = 0, m.clear();
|
|
852
|
+
try {
|
|
853
|
+
v == null || v();
|
|
854
|
+
} catch (l) {
|
|
855
|
+
c(l);
|
|
856
|
+
}
|
|
857
|
+
try {
|
|
858
|
+
I == null || I();
|
|
859
|
+
} catch (l) {
|
|
860
|
+
c(l);
|
|
861
|
+
}
|
|
862
|
+
try {
|
|
863
|
+
p == null || p();
|
|
864
|
+
} catch (l) {
|
|
865
|
+
c(l);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
};
|
|
870
|
+
}
|
|
871
|
+
class et {
|
|
872
|
+
constructor(e, r = globalThis.BroadcastChannel) {
|
|
873
|
+
if (this.listeners = /* @__PURE__ */ new Set(), this.disposed = !1, this.receive = (o) => {
|
|
874
|
+
for (const n of [...this.listeners]) n(o.data);
|
|
875
|
+
}, typeof e != "string" || !e) throw new Error("BroadcastChannel 名称不能为空");
|
|
876
|
+
if (typeof r != "function") throw new Error("当前环境不支持 BroadcastChannel");
|
|
877
|
+
this.channel = new r(e), this.channel.addEventListener("message", this.receive);
|
|
878
|
+
}
|
|
879
|
+
send(e) {
|
|
880
|
+
if (this.disposed) throw new Error("BroadcastChannel provider 已释放");
|
|
881
|
+
this.channel.postMessage(e);
|
|
882
|
+
}
|
|
883
|
+
subscribe(e) {
|
|
884
|
+
if (this.disposed) throw new Error("BroadcastChannel provider 已释放");
|
|
885
|
+
if (typeof e != "function") throw new Error("协同消息订阅者必须是函数");
|
|
886
|
+
return this.listeners.add(e), () => {
|
|
887
|
+
this.listeners.delete(e);
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
dispose() {
|
|
891
|
+
this.disposed || (this.disposed = !0, this.channel.removeEventListener("message", this.receive), this.listeners.clear(), this.channel.close());
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
export {
|
|
895
|
+
et as BroadcastChannelCollabProvider,
|
|
896
|
+
Ze as bindCollaboration
|
|
897
|
+
};
|