@ai-matrx/office 0.8.29 → 0.8.30
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 +11 -1
- package/dist/docs.cjs +123 -116
- package/dist/docs.cjs.map +1 -1
- package/dist/docs.d.cts +5 -0
- package/dist/docs.d.ts +5 -0
- package/dist/docs.js +104 -97
- package/dist/docs.js.map +1 -1
- package/dist/sheets-comment-anchors.cjs +13 -4
- package/dist/sheets-comment-anchors.cjs.map +1 -1
- package/dist/sheets-comment-anchors.js +13 -4
- package/dist/sheets-comment-anchors.js.map +1 -1
- package/dist/univer-collab.cjs +22 -6
- package/dist/univer-collab.cjs.map +1 -1
- package/dist/univer-collab.js +22 -6
- package/dist/univer-collab.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.8.
|
|
3
|
+
## 0.8.30
|
|
4
4
|
|
|
5
5
|
UNVERIFIED: this release has no Unreleased entry and the source comparison could not be made (the caller supplied no source comparison). Whether source changed is unknown; consumer action is unknown.
|
|
6
6
|
Check the package's gitHead on npm against this version's gitHead: `git diff <previous gitHead> <this gitHead> -- apps/shared/office/src`.
|
|
7
7
|
|
|
8
|
+
## 0.8.29
|
|
9
|
+
|
|
10
|
+
SOURCE CHANGED WITH NO RELEASE NOTE. This release shipped source changes that nobody described in an Unreleased entry,
|
|
11
|
+
so they may include breaking API changes. Consumer action is UNKNOWN: read the diff before upgrading.
|
|
12
|
+
Diff: `git diff 01daf620b4 acce3dd470 -- apps/shared/office/src`
|
|
13
|
+
|
|
14
|
+
Changed shipped source files (2):
|
|
15
|
+
- `apps/shared/office/src/collab/sheets/transform/fuzz/seats.ts`
|
|
16
|
+
- `apps/shared/office/src/univer/collab/sheets-ot/univer-port.ts`
|
|
17
|
+
|
|
8
18
|
## 0.8.28
|
|
9
19
|
|
|
10
20
|
Automatic changed-only republish (docs/metadata drift since the last published version; verified: `git diff 0c69bc7f5b 01daf620b4 -- apps/shared/office/src`
|
package/dist/docs.cjs
CHANGED
|
@@ -50,11 +50,111 @@ function takeCovered(snapshot) {
|
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
// src/docs/comment-anchors.ts
|
|
54
|
+
|
|
55
|
+
var COMMENT_ANCHOR_RANGE_TYPE = _core.CustomRangeType.COMMENT;
|
|
56
|
+
var COMMENT_ANCHOR_PART_PREFIX = "anchor:";
|
|
57
|
+
var COMMENT_ANCHOR_LABEL_MAX = 200;
|
|
58
|
+
var ID_ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
59
|
+
function newCommentAnchorId() {
|
|
60
|
+
const bytes = new Uint8Array(16);
|
|
61
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
62
|
+
let out = "c";
|
|
63
|
+
for (const b of bytes) out += ID_ALPHABET[b % ID_ALPHABET.length];
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
function commentAnchorPartKey(anchorId) {
|
|
67
|
+
return `${COMMENT_ANCHOR_PART_PREFIX}${anchorId}`;
|
|
68
|
+
}
|
|
69
|
+
function anchorIdOfPartAnchor(anchor) {
|
|
70
|
+
if (!anchor || typeof anchor !== "object") return null;
|
|
71
|
+
const a = anchor;
|
|
72
|
+
if ((a.__kind === "part_anchor" || a.__kind === "text_anchor") && typeof a.anchor_id === "string" && a.anchor_id.length > 0) return a.anchor_id;
|
|
73
|
+
if (a.__kind !== "part_anchor" || typeof a.part_key !== "string") return null;
|
|
74
|
+
if (!a.part_key.startsWith(COMMENT_ANCHOR_PART_PREFIX)) return null;
|
|
75
|
+
const id = a.part_key.slice(COMMENT_ANCHOR_PART_PREFIX.length);
|
|
76
|
+
return id.length > 0 ? id : null;
|
|
77
|
+
}
|
|
78
|
+
function quoteOfCommentAnchor(anchor) {
|
|
79
|
+
if (!anchor || typeof anchor !== "object") return "";
|
|
80
|
+
const a = anchor;
|
|
81
|
+
return typeof a.label === "string" ? a.label : typeof a.exact === "string" ? a.exact : "";
|
|
82
|
+
}
|
|
83
|
+
function commentPartAnchor(anchorId, quote) {
|
|
84
|
+
const label = quote.replace(/\s+/g, " ").trim().slice(0, COMMENT_ANCHOR_LABEL_MAX);
|
|
85
|
+
return { __kind: "part_anchor", part_key: commentAnchorPartKey(anchorId), ...label ? { label } : {} };
|
|
86
|
+
}
|
|
87
|
+
var CONTROL = /[\u0000-\u001f\u007f]/g;
|
|
88
|
+
function commentAnchorsOf(body) {
|
|
89
|
+
const out = /* @__PURE__ */ new Map();
|
|
90
|
+
const b = _nullishCoalesce(body, () => ( {}));
|
|
91
|
+
const stream = typeof b.dataStream === "string" ? b.dataStream : "";
|
|
92
|
+
for (const r of _nullishCoalesce(b.customRanges, () => ( []))) {
|
|
93
|
+
if (!r || r.rangeType !== COMMENT_ANCHOR_RANGE_TYPE || typeof r.rangeId !== "string") continue;
|
|
94
|
+
const start = r.startIndex;
|
|
95
|
+
const end = r.endIndex + 1;
|
|
96
|
+
if (!(end > start)) continue;
|
|
97
|
+
const had = out.get(r.rangeId);
|
|
98
|
+
const s2 = had ? Math.min(had.start, start) : start;
|
|
99
|
+
const e2 = had ? Math.max(had.end, end) : end;
|
|
100
|
+
out.set(r.rangeId, { id: r.rangeId, start: s2, end: e2, text: "" });
|
|
101
|
+
}
|
|
102
|
+
for (const span of out.values()) span.text = stream.slice(span.start, span.end).replace(CONTROL, " ");
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
function addCommentAnchorActions(body, start, end, anchorId) {
|
|
106
|
+
if (!(end > start) || start < 0) return null;
|
|
107
|
+
const textX = _core.BuildTextUtils.customRange.add({
|
|
108
|
+
body,
|
|
109
|
+
ranges: [{ startOffset: start, endOffset: end, collapsed: false }],
|
|
110
|
+
rangeId: anchorId,
|
|
111
|
+
rangeType: COMMENT_ANCHOR_RANGE_TYPE
|
|
112
|
+
});
|
|
113
|
+
if (!textX) return null;
|
|
114
|
+
return _core.JSONX.getInstance().editOp(textX.serialize(), ["body"]);
|
|
115
|
+
}
|
|
116
|
+
function removeCommentAnchorActions(documentDataModel, anchorId) {
|
|
117
|
+
const textX = _core.BuildTextUtils.customRange.delete({ documentDataModel, rangeId: anchorId });
|
|
118
|
+
if (!textX) return null;
|
|
119
|
+
return _core.JSONX.getInstance().editOp(textX.serialize(), ["body"]);
|
|
120
|
+
}
|
|
121
|
+
var RETAIN_KEYS = /* @__PURE__ */ new Set(["t", "len", "body", "coverType"]);
|
|
122
|
+
var RANGE_KEYS = /* @__PURE__ */ new Set(["rangeId", "rangeType", "startIndex", "endIndex", "properties"]);
|
|
123
|
+
var isObj = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
124
|
+
var keysOf = (o) => Object.keys(o).filter((k) => o[k] !== void 0);
|
|
125
|
+
function isDocsAnchorOnlyOp(op) {
|
|
126
|
+
if (!Array.isArray(op) || op.length !== 2 || op[0] !== "body") return false;
|
|
127
|
+
const x = op[1];
|
|
128
|
+
if (!isObj(x) || x.et !== "text-x" || !Array.isArray(x.e) || x.e.length === 0) return false;
|
|
129
|
+
if (keysOf(x).some((k) => k !== "et" && k !== "e")) return false;
|
|
130
|
+
for (const c of x.e) {
|
|
131
|
+
if (!isObj(c) || c.t !== "r" || typeof c.len !== "number") return false;
|
|
132
|
+
if (keysOf(c).some((k) => !RETAIN_KEYS.has(k))) return false;
|
|
133
|
+
if ("coverType" in c && typeof c.coverType !== "number") return false;
|
|
134
|
+
if ("body" in c) {
|
|
135
|
+
const b = c.body;
|
|
136
|
+
if (!isObj(b) || keysOf(b).some((k) => k !== "dataStream" && k !== "customRanges")) return false;
|
|
137
|
+
if (b.dataStream !== void 0 && b.dataStream !== "") return false;
|
|
138
|
+
if (!Array.isArray(b.customRanges) || b.customRanges.length === 0) return false;
|
|
139
|
+
for (const r of b.customRanges) {
|
|
140
|
+
if (!isObj(r) || r.rangeType !== COMMENT_ANCHOR_RANGE_TYPE) return false;
|
|
141
|
+
if (keysOf(r).some((k) => !RANGE_KEYS.has(k))) return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
|
|
53
148
|
// src/docs/document-model.ts
|
|
54
149
|
var RICH_TEXT_EDITING_ID = "doc.mutation.rich-text-editing";
|
|
55
150
|
var COMMAND_TYPE = 0;
|
|
56
151
|
var DEPTH_GUARDED = /* @__PURE__ */ Symbol.for("ai-matrx.office.docs.command-depth-guard");
|
|
57
152
|
var DOCUMENT_SAVE_DELAY_MS = 2500;
|
|
153
|
+
function isCommentAnchorMutation(info) {
|
|
154
|
+
if (info.id !== RICH_TEXT_EDITING_ID) return false;
|
|
155
|
+
const params = info.params;
|
|
156
|
+
return !!params && !params.segmentId && isDocsAnchorOnlyOp(params.actions);
|
|
157
|
+
}
|
|
58
158
|
var viewIds = 0;
|
|
59
159
|
var DocumentModel = (_class = class {
|
|
60
160
|
|
|
@@ -193,11 +293,13 @@ var DocumentModel = (_class = class {
|
|
|
193
293
|
onViewMutation(viewId, info, options) {
|
|
194
294
|
if (this.relaying || _optionalChain([options, 'optionalAccess', _19 => _19.fromCollab]) || _optionalChain([options, 'optionalAccess', _20 => _20.fromChangeset])) return;
|
|
195
295
|
const view = this.views.get(viewId);
|
|
196
|
-
if (!view
|
|
296
|
+
if (!view) return;
|
|
297
|
+
const editable = view.port.editable();
|
|
298
|
+
if (!editable && !(_optionalChain([view, 'access', _21 => _21.port, 'access', _22 => _22.commentOnly, 'optionalCall', _23 => _23()]) === true && isCommentAnchorMutation(info))) return;
|
|
197
299
|
this.lastEditedView = viewId;
|
|
198
300
|
this.relay(info, viewId);
|
|
199
301
|
for (const listener of this.collabListeners) listener(info, options);
|
|
200
|
-
if (this.otListeners.size && !_optionalChain([options, 'optionalAccess',
|
|
302
|
+
if (this.otListeners.size && !_optionalChain([options, 'optionalAccess', _24 => _24.onlyLocal])) {
|
|
201
303
|
const m = {
|
|
202
304
|
id: info.id,
|
|
203
305
|
params: info.params,
|
|
@@ -208,7 +310,7 @@ var DocumentModel = (_class = class {
|
|
|
208
310
|
view.pre = null;
|
|
209
311
|
for (const listener of Array.from(this.otListeners)) listener(m);
|
|
210
312
|
}
|
|
211
|
-
if (isContentMutation(info)) this.markDirty();
|
|
313
|
+
if (editable && isContentMutation(info)) this.markDirty();
|
|
212
314
|
}
|
|
213
315
|
/**
|
|
214
316
|
* Per view: the outermost command running (a mutation's group label) and, while a room listens, the document
|
|
@@ -257,7 +359,7 @@ var DocumentModel = (_class = class {
|
|
|
257
359
|
/** The unit id a view's document has (what a replayed mutation must be addressed to). */
|
|
258
360
|
unitIdOf(view) {
|
|
259
361
|
try {
|
|
260
|
-
return _nullishCoalesce(_nullishCoalesce(_optionalChain([view, 'access',
|
|
362
|
+
return _nullishCoalesce(_nullishCoalesce(_optionalChain([view, 'access', _25 => _25.port, 'access', _26 => _26.unitId, 'optionalCall', _27 => _27()]), () => ( _optionalChain([view, 'access', _28 => _28.port, 'access', _29 => _29.snapshot, 'call', _30 => _30(), 'optionalAccess', _31 => _31.id]))), () => ( null));
|
|
261
363
|
} catch (e6) {
|
|
262
364
|
return null;
|
|
263
365
|
}
|
|
@@ -291,7 +393,7 @@ var DocumentModel = (_class = class {
|
|
|
291
393
|
/** A view could not follow an edit: say so, then show the saved version (unless this tab has unsaved edits of its own). */
|
|
292
394
|
applyFailed(mutationId, error) {
|
|
293
395
|
try {
|
|
294
|
-
_optionalChain([this, 'access',
|
|
396
|
+
_optionalChain([this, 'access', _32 => _32.deps, 'access', _33 => _33.onApplyFailed, 'optionalCall', _34 => _34(this.documentId, mutationId, error)]);
|
|
295
397
|
} catch (notifyError) {
|
|
296
398
|
console.warn(`[document-model] the notice for ${this.documentId}'s failed apply also failed`, notifyError);
|
|
297
399
|
}
|
|
@@ -319,7 +421,7 @@ var DocumentModel = (_class = class {
|
|
|
319
421
|
async write(reason) {
|
|
320
422
|
if (this.ot) {
|
|
321
423
|
const wrote = await this.ot.write(reason);
|
|
322
|
-
if (wrote) _optionalChain([this, 'access',
|
|
424
|
+
if (wrote) _optionalChain([this, 'access', _35 => _35.deps, 'access', _36 => _36.onSaved, 'optionalCall', _37 => _37(this.documentId, reason === "manual" ? "manual" : "autosave")]);
|
|
323
425
|
return wrote;
|
|
324
426
|
}
|
|
325
427
|
const snapshot = this.latest();
|
|
@@ -344,7 +446,7 @@ var DocumentModel = (_class = class {
|
|
|
344
446
|
this.saving = false;
|
|
345
447
|
}
|
|
346
448
|
if (this.views.size === 0) this.stored = snapshot;
|
|
347
|
-
_optionalChain([this, 'access',
|
|
449
|
+
_optionalChain([this, 'access', _38 => _38.deps, 'access', _39 => _39.onSaved, 'optionalCall', _40 => _40(this.documentId, origin)]);
|
|
348
450
|
return true;
|
|
349
451
|
}
|
|
350
452
|
hasUnsaved() {
|
|
@@ -387,7 +489,7 @@ var DocumentModel = (_class = class {
|
|
|
387
489
|
replaceContent(row) {
|
|
388
490
|
if (this.ot) return this.ot.replace(row.snapshot);
|
|
389
491
|
this.show(row);
|
|
390
|
-
_optionalChain([this, 'access',
|
|
492
|
+
_optionalChain([this, 'access', _41 => _41.collab, 'optionalAccess', _42 => _42.announceReplaced, 'call', _43 => _43(row.id)]);
|
|
391
493
|
}
|
|
392
494
|
/** A peer replaced the document: show the newest save (once). */
|
|
393
495
|
async onPeerReplaced() {
|
|
@@ -410,7 +512,7 @@ var DocumentModel = (_class = class {
|
|
|
410
512
|
this.relaying = true;
|
|
411
513
|
try {
|
|
412
514
|
for (const view of this.views.values()) view.port.remount(snapshot);
|
|
413
|
-
_optionalChain([this, 'access',
|
|
515
|
+
_optionalChain([this, 'access', _44 => _44.parked, 'optionalAccess', _45 => _45.remount, 'call', _46 => _46(snapshot)]);
|
|
414
516
|
} finally {
|
|
415
517
|
this.relaying = false;
|
|
416
518
|
}
|
|
@@ -484,7 +586,7 @@ var DocumentModel = (_class = class {
|
|
|
484
586
|
const input = Array.isArray(params.actions) ? params.actions.length : 0;
|
|
485
587
|
let sel = null;
|
|
486
588
|
try {
|
|
487
|
-
sel = _nullishCoalesce(_optionalChain([view, 'access',
|
|
589
|
+
sel = _nullishCoalesce(_optionalChain([view, 'access', _47 => _47.port, 'access', _48 => _48.selection, 'optionalAccess', _49 => _49.get, 'call', _50 => _50()]), () => ( null));
|
|
488
590
|
} catch (e7) {
|
|
489
591
|
sel = null;
|
|
490
592
|
}
|
|
@@ -495,7 +597,7 @@ var DocumentModel = (_class = class {
|
|
|
495
597
|
const moved = sel && sel.length && sel.every((r) => !r.segmentId) ? moveRangesThroughBodyEdit(sel, params.actions) : null;
|
|
496
598
|
if (moved) {
|
|
497
599
|
try {
|
|
498
|
-
_optionalChain([view, 'access',
|
|
600
|
+
_optionalChain([view, 'access', _51 => _51.port, 'access', _52 => _52.selection, 'optionalAccess', _53 => _53.set, 'call', _54 => _54(moved)]);
|
|
499
601
|
} catch (error) {
|
|
500
602
|
console.warn(`[document-model] could not move this view's caret past a collaborator's edit`, error);
|
|
501
603
|
}
|
|
@@ -514,7 +616,7 @@ var DocumentModel = (_class = class {
|
|
|
514
616
|
this.relaying = true;
|
|
515
617
|
try {
|
|
516
618
|
for (const view of this.views.values()) view.port.remount(s2);
|
|
517
|
-
_optionalChain([this, 'access',
|
|
619
|
+
_optionalChain([this, 'access', _55 => _55.parked, 'optionalAccess', _56 => _56.remount, 'call', _57 => _57(s2)]);
|
|
518
620
|
} finally {
|
|
519
621
|
this.relaying = false;
|
|
520
622
|
}
|
|
@@ -523,7 +625,7 @@ var DocumentModel = (_class = class {
|
|
|
523
625
|
const out = [];
|
|
524
626
|
for (const view of this.views.values()) {
|
|
525
627
|
const unitId = this.unitIdOf(view);
|
|
526
|
-
const service = _optionalChain([view, 'access',
|
|
628
|
+
const service = _optionalChain([view, 'access', _58 => _58.port, 'access', _59 => _59.undoRedo, 'optionalCall', _60 => _60()]);
|
|
527
629
|
if (unitId && service) out.push({ service, unitId });
|
|
528
630
|
}
|
|
529
631
|
return out;
|
|
@@ -532,7 +634,7 @@ var DocumentModel = (_class = class {
|
|
|
532
634
|
selection: () => {
|
|
533
635
|
for (const view of this.views.values()) {
|
|
534
636
|
try {
|
|
535
|
-
const sel = _optionalChain([view, 'access',
|
|
637
|
+
const sel = _optionalChain([view, 'access', _61 => _61.port, 'access', _62 => _62.selection, 'optionalAccess', _63 => _63.get, 'call', _64 => _64()]);
|
|
536
638
|
if (sel) return sel;
|
|
537
639
|
} catch (e8) {
|
|
538
640
|
}
|
|
@@ -591,9 +693,9 @@ var DocumentModel = (_class = class {
|
|
|
591
693
|
* so a collaborator's save still reaches the body a returning view boots from.
|
|
592
694
|
*/
|
|
593
695
|
rest() {
|
|
594
|
-
_optionalChain([this, 'access',
|
|
696
|
+
_optionalChain([this, 'access', _65 => _65.collab, 'optionalAccess', _66 => _66.stop, 'call', _67 => _67()]);
|
|
595
697
|
this.collab = null;
|
|
596
|
-
_optionalChain([this, 'access',
|
|
698
|
+
_optionalChain([this, 'access', _68 => _68.ot, 'optionalAccess', _69 => _69.stop, 'call', _70 => _70()]);
|
|
597
699
|
this.ot = null;
|
|
598
700
|
this.awareness = null;
|
|
599
701
|
}
|
|
@@ -609,9 +711,9 @@ var DocumentModel = (_class = class {
|
|
|
609
711
|
console.warn(`[document-model] could not dispose ${this.documentId}'s kept editor`, error);
|
|
610
712
|
}
|
|
611
713
|
}
|
|
612
|
-
_optionalChain([this, 'access',
|
|
714
|
+
_optionalChain([this, 'access', _71 => _71.realtimeClose, 'optionalCall', _72 => _72()]);
|
|
613
715
|
this.realtimeClose = null;
|
|
614
|
-
_optionalChain([this, 'access',
|
|
716
|
+
_optionalChain([this, 'access', _73 => _73.pageClose, 'optionalCall', _74 => _74()]);
|
|
615
717
|
this.pageClose = null;
|
|
616
718
|
}
|
|
617
719
|
}, _class);
|
|
@@ -889,12 +991,12 @@ function movePeerRangesThroughBodyEdit(ranges, actions) {
|
|
|
889
991
|
}
|
|
890
992
|
var sameRanges = (a, b) => a.length === b.length && a.every((r, i) => r.start === b[i].start && r.end === b[i].end);
|
|
891
993
|
function readCaret(raw) {
|
|
892
|
-
const c = _optionalChain([raw, 'optionalAccess',
|
|
994
|
+
const c = _optionalChain([raw, 'optionalAccess', _75 => _75.caret]);
|
|
893
995
|
if (!c || !Array.isArray(c.ranges) || typeof c.at !== "number") return null;
|
|
894
996
|
const ranges = [];
|
|
895
997
|
for (const r of c.ranges.slice(0, CARET_MAX_RANGES)) {
|
|
896
|
-
const s2 = _optionalChain([r, 'optionalAccess',
|
|
897
|
-
const e2 = _optionalChain([r, 'optionalAccess',
|
|
998
|
+
const s2 = _optionalChain([r, 'optionalAccess', _76 => _76.start]);
|
|
999
|
+
const e2 = _optionalChain([r, 'optionalAccess', _77 => _77.end]);
|
|
898
1000
|
if (typeof s2 !== "number" || typeof e2 !== "number" || !Number.isFinite(s2) || !Number.isFinite(e2) || s2 < 0 || e2 < 0) return null;
|
|
899
1001
|
ranges.push({ start: s2, end: e2 });
|
|
900
1002
|
}
|
|
@@ -960,101 +1062,6 @@ var RemoteCaretBook = (_class2 = class {
|
|
|
960
1062
|
}
|
|
961
1063
|
}, _class2);
|
|
962
1064
|
|
|
963
|
-
// src/docs/comment-anchors.ts
|
|
964
|
-
|
|
965
|
-
var COMMENT_ANCHOR_RANGE_TYPE = _core.CustomRangeType.COMMENT;
|
|
966
|
-
var COMMENT_ANCHOR_PART_PREFIX = "anchor:";
|
|
967
|
-
var COMMENT_ANCHOR_LABEL_MAX = 200;
|
|
968
|
-
var ID_ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
969
|
-
function newCommentAnchorId() {
|
|
970
|
-
const bytes = new Uint8Array(16);
|
|
971
|
-
globalThis.crypto.getRandomValues(bytes);
|
|
972
|
-
let out = "c";
|
|
973
|
-
for (const b of bytes) out += ID_ALPHABET[b % ID_ALPHABET.length];
|
|
974
|
-
return out;
|
|
975
|
-
}
|
|
976
|
-
function commentAnchorPartKey(anchorId) {
|
|
977
|
-
return `${COMMENT_ANCHOR_PART_PREFIX}${anchorId}`;
|
|
978
|
-
}
|
|
979
|
-
function anchorIdOfPartAnchor(anchor) {
|
|
980
|
-
if (!anchor || typeof anchor !== "object") return null;
|
|
981
|
-
const a = anchor;
|
|
982
|
-
if ((a.__kind === "part_anchor" || a.__kind === "text_anchor") && typeof a.anchor_id === "string" && a.anchor_id.length > 0) return a.anchor_id;
|
|
983
|
-
if (a.__kind !== "part_anchor" || typeof a.part_key !== "string") return null;
|
|
984
|
-
if (!a.part_key.startsWith(COMMENT_ANCHOR_PART_PREFIX)) return null;
|
|
985
|
-
const id = a.part_key.slice(COMMENT_ANCHOR_PART_PREFIX.length);
|
|
986
|
-
return id.length > 0 ? id : null;
|
|
987
|
-
}
|
|
988
|
-
function quoteOfCommentAnchor(anchor) {
|
|
989
|
-
if (!anchor || typeof anchor !== "object") return "";
|
|
990
|
-
const a = anchor;
|
|
991
|
-
return typeof a.label === "string" ? a.label : typeof a.exact === "string" ? a.exact : "";
|
|
992
|
-
}
|
|
993
|
-
function commentPartAnchor(anchorId, quote) {
|
|
994
|
-
const label = quote.replace(/\s+/g, " ").trim().slice(0, COMMENT_ANCHOR_LABEL_MAX);
|
|
995
|
-
return { __kind: "part_anchor", part_key: commentAnchorPartKey(anchorId), ...label ? { label } : {} };
|
|
996
|
-
}
|
|
997
|
-
var CONTROL = /[\u0000-\u001f\u007f]/g;
|
|
998
|
-
function commentAnchorsOf(body) {
|
|
999
|
-
const out = /* @__PURE__ */ new Map();
|
|
1000
|
-
const b = _nullishCoalesce(body, () => ( {}));
|
|
1001
|
-
const stream = typeof b.dataStream === "string" ? b.dataStream : "";
|
|
1002
|
-
for (const r of _nullishCoalesce(b.customRanges, () => ( []))) {
|
|
1003
|
-
if (!r || r.rangeType !== COMMENT_ANCHOR_RANGE_TYPE || typeof r.rangeId !== "string") continue;
|
|
1004
|
-
const start = r.startIndex;
|
|
1005
|
-
const end = r.endIndex + 1;
|
|
1006
|
-
if (!(end > start)) continue;
|
|
1007
|
-
const had = out.get(r.rangeId);
|
|
1008
|
-
const s2 = had ? Math.min(had.start, start) : start;
|
|
1009
|
-
const e2 = had ? Math.max(had.end, end) : end;
|
|
1010
|
-
out.set(r.rangeId, { id: r.rangeId, start: s2, end: e2, text: "" });
|
|
1011
|
-
}
|
|
1012
|
-
for (const span of out.values()) span.text = stream.slice(span.start, span.end).replace(CONTROL, " ");
|
|
1013
|
-
return out;
|
|
1014
|
-
}
|
|
1015
|
-
function addCommentAnchorActions(body, start, end, anchorId) {
|
|
1016
|
-
if (!(end > start) || start < 0) return null;
|
|
1017
|
-
const textX = _core.BuildTextUtils.customRange.add({
|
|
1018
|
-
body,
|
|
1019
|
-
ranges: [{ startOffset: start, endOffset: end, collapsed: false }],
|
|
1020
|
-
rangeId: anchorId,
|
|
1021
|
-
rangeType: COMMENT_ANCHOR_RANGE_TYPE
|
|
1022
|
-
});
|
|
1023
|
-
if (!textX) return null;
|
|
1024
|
-
return _core.JSONX.getInstance().editOp(textX.serialize(), ["body"]);
|
|
1025
|
-
}
|
|
1026
|
-
function removeCommentAnchorActions(documentDataModel, anchorId) {
|
|
1027
|
-
const textX = _core.BuildTextUtils.customRange.delete({ documentDataModel, rangeId: anchorId });
|
|
1028
|
-
if (!textX) return null;
|
|
1029
|
-
return _core.JSONX.getInstance().editOp(textX.serialize(), ["body"]);
|
|
1030
|
-
}
|
|
1031
|
-
var RETAIN_KEYS = /* @__PURE__ */ new Set(["t", "len", "body", "coverType"]);
|
|
1032
|
-
var RANGE_KEYS = /* @__PURE__ */ new Set(["rangeId", "rangeType", "startIndex", "endIndex", "properties"]);
|
|
1033
|
-
var isObj = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
1034
|
-
var keysOf = (o) => Object.keys(o).filter((k) => o[k] !== void 0);
|
|
1035
|
-
function isDocsAnchorOnlyOp(op) {
|
|
1036
|
-
if (!Array.isArray(op) || op.length !== 2 || op[0] !== "body") return false;
|
|
1037
|
-
const x = op[1];
|
|
1038
|
-
if (!isObj(x) || x.et !== "text-x" || !Array.isArray(x.e) || x.e.length === 0) return false;
|
|
1039
|
-
if (keysOf(x).some((k) => k !== "et" && k !== "e")) return false;
|
|
1040
|
-
for (const c of x.e) {
|
|
1041
|
-
if (!isObj(c) || c.t !== "r" || typeof c.len !== "number") return false;
|
|
1042
|
-
if (keysOf(c).some((k) => !RETAIN_KEYS.has(k))) return false;
|
|
1043
|
-
if ("coverType" in c && typeof c.coverType !== "number") return false;
|
|
1044
|
-
if ("body" in c) {
|
|
1045
|
-
const b = c.body;
|
|
1046
|
-
if (!isObj(b) || keysOf(b).some((k) => k !== "dataStream" && k !== "customRanges")) return false;
|
|
1047
|
-
if (b.dataStream !== void 0 && b.dataStream !== "") return false;
|
|
1048
|
-
if (!Array.isArray(b.customRanges) || b.customRanges.length === 0) return false;
|
|
1049
|
-
for (const r of b.customRanges) {
|
|
1050
|
-
if (!isObj(r) || r.rangeType !== COMMENT_ANCHOR_RANGE_TYPE) return false;
|
|
1051
|
-
if (keysOf(r).some((k) => !RANGE_KEYS.has(k))) return false;
|
|
1052
|
-
}
|
|
1053
|
-
}
|
|
1054
|
-
}
|
|
1055
|
-
return true;
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
1065
|
|
|
1059
1066
|
|
|
1060
1067
|
|