@univerjs/docs 1.0.0-insiders.20260813-7c9aa50 → 1.0.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.
Files changed (55) hide show
  1. package/LICENSE +176 -0
  2. package/README.md +0 -1
  3. package/lib/cjs/facade.js +395 -78
  4. package/lib/cjs/index.js +2734 -100
  5. package/lib/es/facade.js +390 -80
  6. package/lib/es/index.js +2703 -105
  7. package/lib/facade.js +390 -80
  8. package/lib/index.js +2703 -105
  9. package/lib/types/commands/commands/core-editing.command.d.ts +5 -1
  10. package/lib/types/commands/commands/set-document-permission.command.d.ts +27 -0
  11. package/lib/types/commands/commands/set-document-permissions.command.d.ts +17 -0
  12. package/lib/types/commands/mutations/core-editing.mutation-id.d.ts +16 -0
  13. package/lib/types/commands/mutations/core-editing.mutation.d.ts +22 -1
  14. package/lib/types/commands/mutations/doc-structure-mutation-validation.d.ts +18 -0
  15. package/lib/types/commands/mutations/set-document-permission-rule.mutation.d.ts +17 -0
  16. package/lib/types/commands/mutations/set-document-permission-rules.mutation.d.ts +17 -0
  17. package/lib/types/controllers/doc-permission.controller.d.ts +26 -0
  18. package/lib/types/facade/f-document-paragraph.d.ts +15 -2
  19. package/lib/types/facade/f-document-permission.d.ts +177 -0
  20. package/lib/types/facade/f-document-section.d.ts +43 -2
  21. package/lib/types/facade/f-document-text-range.d.ts +7 -1
  22. package/lib/types/facade/f-document.d.ts +63 -15
  23. package/lib/types/facade/f-univer.d.ts +5 -4
  24. package/lib/types/facade/index.d.ts +1 -0
  25. package/lib/types/facade/utils.d.ts +2 -1
  26. package/lib/types/index.d.ts +13 -1
  27. package/lib/types/layout-worker/config/config.d.ts +32 -0
  28. package/lib/types/layout-worker/document-font-metrics.d.ts +18 -0
  29. package/lib/types/layout-worker/font-loader.d.ts +26 -0
  30. package/lib/types/layout-worker/index.d.ts +73 -0
  31. package/lib/types/layout-worker/performance-tracker.d.ts +27 -0
  32. package/lib/types/layout-worker/protocol.d.ts +37 -0
  33. package/lib/types/layout-worker/worker.d.ts +51 -0
  34. package/lib/types/plugin.d.ts +1 -0
  35. package/lib/types/services/doc-interceptor/interceptor-const.d.ts +2 -1
  36. package/lib/types/services/doc-layout-executor.service.d.ts +224 -0
  37. package/lib/types/services/doc-selection-manager.service.d.ts +7 -1
  38. package/lib/types/services/doc-skeleton-manager.service.d.ts +6 -1
  39. package/lib/types/services/doc-state-change-manager.service.d.ts +3 -0
  40. package/lib/types/services/doc-state-emit.service.d.ts +1 -0
  41. package/lib/types/services/document-layout-snapshot.d.ts +22 -0
  42. package/lib/types/services/permission/document-permission-resolver.d.ts +27 -0
  43. package/lib/types/services/permission/document-permission-rule.model.d.ts +19 -0
  44. package/lib/types/services/permission/document-permission.d.ts +35 -0
  45. package/lib/types/services/permission/permission-point/document/comment.d.ts +27 -0
  46. package/lib/types/services/permission/permission-point/document/copy.d.ts +27 -0
  47. package/lib/types/services/permission/permission-point/document/editable.d.ts +27 -0
  48. package/lib/types/services/permission/permission-point/document/export.d.ts +27 -0
  49. package/lib/types/services/permission/permission-point/document/print.d.ts +27 -0
  50. package/lib/types/services/permission/permission-point/entity/edit.d.ts +28 -0
  51. package/lib/types/services/permission/permission-point/paragraph/edit.d.ts +28 -0
  52. package/lib/types/services/permission/permission-point/section/edit.d.ts +28 -0
  53. package/lib/umd/facade.js +3 -3
  54. package/lib/umd/index.js +2 -2
  55. package/package.json +7 -5
package/lib/cjs/index.js CHANGED
@@ -2,6 +2,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  let _univerjs_core = require("@univerjs/core");
3
3
  let _univerjs_engine_render = require("@univerjs/engine-render");
4
4
  let rxjs = require("rxjs");
5
+ let _univerjs_protocol = require("@univerjs/protocol");
6
+ let _univerjs_rpc = require("@univerjs/rpc");
5
7
 
6
8
  //#region src/commands/operations/text-selection.operation.ts
7
9
  const SetTextSelectionsOperation = {
@@ -13,7 +15,7 @@ const SetTextSelectionsOperation = {
13
15
  };
14
16
 
15
17
  //#endregion
16
- //#region \0@oxc-project+runtime@0.140.0/helpers/esm/typeof.js
18
+ //#region \0@oxc-project+runtime@0.149.0/helpers/esm/typeof.js
17
19
  function _typeof(o) {
18
20
  "@babel/helpers - typeof";
19
21
  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
@@ -24,7 +26,7 @@ function _typeof(o) {
24
26
  }
25
27
 
26
28
  //#endregion
27
- //#region \0@oxc-project+runtime@0.140.0/helpers/esm/toPrimitive.js
29
+ //#region \0@oxc-project+runtime@0.149.0/helpers/esm/toPrimitive.js
28
30
  function toPrimitive(t, r) {
29
31
  if ("object" != _typeof(t) || !t) return t;
30
32
  var e = t[Symbol.toPrimitive];
@@ -37,14 +39,14 @@ function toPrimitive(t, r) {
37
39
  }
38
40
 
39
41
  //#endregion
40
- //#region \0@oxc-project+runtime@0.140.0/helpers/esm/toPropertyKey.js
42
+ //#region \0@oxc-project+runtime@0.149.0/helpers/esm/toPropertyKey.js
41
43
  function toPropertyKey(t) {
42
44
  var i = toPrimitive(t, "string");
43
45
  return "symbol" == _typeof(i) ? i : i + "";
44
46
  }
45
47
 
46
48
  //#endregion
47
- //#region \0@oxc-project+runtime@0.140.0/helpers/esm/defineProperty.js
49
+ //#region \0@oxc-project+runtime@0.149.0/helpers/esm/defineProperty.js
48
50
  function _defineProperty(e, r, t) {
49
51
  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
50
52
  value: t,
@@ -55,7 +57,7 @@ function _defineProperty(e, r, t) {
55
57
  }
56
58
 
57
59
  //#endregion
58
- //#region \0@oxc-project+runtime@0.140.0/helpers/esm/decorateParam.js
60
+ //#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorateParam.js
59
61
  function __decorateParam(paramIndex, decorator) {
60
62
  return function(target, key) {
61
63
  decorator(target, key, paramIndex);
@@ -63,7 +65,7 @@ function __decorateParam(paramIndex, decorator) {
63
65
  }
64
66
 
65
67
  //#endregion
66
- //#region \0@oxc-project+runtime@0.140.0/helpers/esm/decorate.js
68
+ //#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorate.js
67
69
  function __decorate(decorators, target, key, desc) {
68
70
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
69
71
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -107,9 +109,9 @@ let DocSelectionManagerService = class DocSelectionManagerService extends _unive
107
109
  getSelectionInfo(params = this._currentSelection) {
108
110
  return this._getTextRanges(params);
109
111
  }
110
- refreshSelection(params = this._currentSelection) {
112
+ refreshSelection(params = this._currentSelection, isEditing = false) {
111
113
  if (params == null) return;
112
- this._refresh(params);
114
+ this._refresh(params, isEditing);
113
115
  }
114
116
  __TEST_ONLY_setCurrentSelection(param) {
115
117
  this._currentSelection = param;
@@ -161,8 +163,19 @@ let DocSelectionManagerService = class DocSelectionManagerService extends _unive
161
163
  options
162
164
  });
163
165
  }
166
+ /**
167
+ * Replaces logical selection state without rebuilding render ranges. Atomic
168
+ * external mutations use this before applying document actions so layout can
169
+ * follow transformed offsets, then refresh after new geometry is available.
170
+ */
171
+ replaceSelectionInfoWithoutRefresh(selectionInfo, params = this._currentSelection) {
172
+ if (params == null) return;
173
+ this._replaceByParam({
174
+ ...selectionInfo,
175
+ ...params
176
+ });
177
+ }
164
178
  __replaceTextRangesWithNoRefresh(textSelectionInfo, search) {
165
- if (this._currentSelection == null) return;
166
179
  const params = {
167
180
  ...textSelectionInfo,
168
181
  ...search
@@ -197,7 +210,7 @@ let DocSelectionManagerService = class DocSelectionManagerService extends _unive
197
210
  const { unitId, subUnitId = "" } = param;
198
211
  return (_this$_textSelectionI = this._textSelectionInfo.get(unitId)) === null || _this$_textSelectionI === void 0 ? void 0 : _this$_textSelectionI.get(subUnitId);
199
212
  }
200
- _refresh(param) {
213
+ _refresh(param, isEditing = false) {
201
214
  const allTextSelectionInfo = this._getTextRanges(param);
202
215
  if (allTextSelectionInfo == null) return;
203
216
  const { textRanges, rectRanges, options } = allTextSelectionInfo;
@@ -207,8 +220,11 @@ let DocSelectionManagerService = class DocSelectionManagerService extends _unive
207
220
  unitId,
208
221
  subUnitId,
209
222
  docRanges,
210
- isEditing: false,
211
- options
223
+ isEditing,
224
+ options: (options === null || options === void 0 ? void 0 : options.forceFocus) ? {
225
+ ...options,
226
+ forceFocus: false
227
+ } : options
212
228
  });
213
229
  }
214
230
  _replaceByParam(insertParam) {
@@ -226,14 +242,664 @@ let DocSelectionManagerService = class DocSelectionManagerService extends _unive
226
242
  };
227
243
  DocSelectionManagerService = __decorate([__decorateParam(0, _univerjs_core.ICommandService), __decorateParam(1, _univerjs_core.IUniverInstanceService)], DocSelectionManagerService);
228
244
 
245
+ //#endregion
246
+ //#region src/commands/mutations/core-editing.mutation-id.ts
247
+ /**
248
+ * Copyright 2023-present DreamNum Co., Ltd.
249
+ *
250
+ * Licensed under the Apache License, Version 2.0 (the "License");
251
+ * you may not use this file except in compliance with the License.
252
+ * You may obtain a copy of the License at
253
+ *
254
+ * http://www.apache.org/licenses/LICENSE-2.0
255
+ *
256
+ * Unless required by applicable law or agreed to in writing, software
257
+ * distributed under the License is distributed on an "AS IS" BASIS,
258
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
259
+ * See the License for the specific language governing permissions and
260
+ * limitations under the License.
261
+ */
262
+ const RICH_TEXT_EDITING_MUTATION_ID = "doc.mutation.rich-text-editing";
263
+
264
+ //#endregion
265
+ //#region src/services/document-layout-snapshot.ts
266
+ function projectCustomBlock(block) {
267
+ const { docxRawXml: _docxRawXml, docxExportTs: _docxExportTs, ...layoutBlock } = block;
268
+ return layoutBlock;
269
+ }
270
+ function projectDocumentBody(body) {
271
+ const { docxRawCustomBlocks: _docxRawCustomBlocks, docxRawBlocks: _docxRawBlocks, docxExportExcludedRanges: _docxExportExcludedRanges, payloads: _payloads, customBlocks, ...layoutBody } = body;
272
+ return {
273
+ ...layoutBody,
274
+ ...customBlocks == null ? {} : { customBlocks: customBlocks.map(projectCustomBlock) }
275
+ };
276
+ }
277
+ function projectHeader(header) {
278
+ return {
279
+ ...header,
280
+ body: projectDocumentBody(header.body)
281
+ };
282
+ }
283
+ function projectFooter(footer) {
284
+ return {
285
+ ...footer,
286
+ body: projectDocumentBody(footer.body)
287
+ };
288
+ }
289
+ /**
290
+ * Builds the model snapshot owned by the layout Worker. Exchange-only payloads
291
+ * remain in the authoritative Main model and are deliberately excluded from
292
+ * the structured-clone boundary because they do not affect document geometry.
293
+ */
294
+ function createDocumentLayoutSnapshot(snapshot) {
295
+ const { resources: _resources, body, headers, footers, footnotes, endnotes, ...layoutSnapshot } = snapshot;
296
+ return {
297
+ ...layoutSnapshot,
298
+ ...footnotes == null ? {} : { footnotes: Object.fromEntries(Object.entries(footnotes).map(([id, note]) => [id, {
299
+ ...note,
300
+ body: projectDocumentBody(note.body)
301
+ }])) },
302
+ ...endnotes == null ? {} : { endnotes: Object.fromEntries(Object.entries(endnotes).map(([id, note]) => [id, {
303
+ ...note,
304
+ body: projectDocumentBody(note.body)
305
+ }])) },
306
+ ...body == null ? {} : { body: projectDocumentBody(body) },
307
+ ...headers == null ? {} : { headers: Object.fromEntries(Object.entries(headers).map(([headerId, header]) => [headerId, projectHeader(header)])) },
308
+ ...footers == null ? {} : { footers: Object.fromEntries(Object.entries(footers).map(([footerId, footer]) => [footerId, projectFooter(footer)])) }
309
+ };
310
+ }
311
+
312
+ //#endregion
313
+ //#region src/services/doc-layout-executor.service.ts
314
+ var _DocLayoutExecutorService;
315
+ let DocLayoutExecutorType = /* @__PURE__ */ function(DocLayoutExecutorType) {
316
+ DocLayoutExecutorType["MAIN_THREAD"] = "main-thread";
317
+ DocLayoutExecutorType["WORKER"] = "worker";
318
+ return DocLayoutExecutorType;
319
+ }({});
320
+ let DocLayoutSessionStatus = /* @__PURE__ */ function(DocLayoutSessionStatus) {
321
+ DocLayoutSessionStatus["ACCEPTED"] = "accepted";
322
+ DocLayoutSessionStatus["NOT_FOUND"] = "not-found";
323
+ DocLayoutSessionStatus["RESNAPSHOT_REQUIRED"] = "resnapshot-required";
324
+ DocLayoutSessionStatus["SUPERSEDED"] = "superseded";
325
+ return DocLayoutSessionStatus;
326
+ }({});
327
+ let DocLayoutExecutorState = /* @__PURE__ */ function(DocLayoutExecutorState) {
328
+ DocLayoutExecutorState["UNREGISTERED"] = "unregistered";
329
+ DocLayoutExecutorState["INITIALIZING"] = "initializing";
330
+ DocLayoutExecutorState["ACTIVE"] = "active";
331
+ DocLayoutExecutorState["RECOVERING"] = "recovering";
332
+ DocLayoutExecutorState["FAILED"] = "failed";
333
+ return DocLayoutExecutorState;
334
+ }({});
335
+ function areShallowRecordsEqual(left, right) {
336
+ const leftRecord = left;
337
+ const rightRecord = right;
338
+ const leftKeys = Object.keys(leftRecord);
339
+ const rightKeys = Object.keys(rightRecord);
340
+ return leftKeys.length === rightKeys.length && leftKeys.every((key) => leftRecord[key] === rightRecord[key]);
341
+ }
342
+ function createRecordPatch(previous, current) {
343
+ const upserts = {};
344
+ const removals = [];
345
+ for (const [key, value] of Object.entries(current)) if (previous[key] == null || !areShallowRecordsEqual(previous[key], value)) upserts[key] = value;
346
+ for (const key of Object.keys(previous)) if (current[key] == null) removals.push(key);
347
+ return {
348
+ removals,
349
+ upserts
350
+ };
351
+ }
352
+ function getCustomRangePresentationKey$1(entry) {
353
+ return JSON.stringify([entry.segmentId, entry.rangeId]);
354
+ }
355
+ function toCustomRangePresentationMap(entries) {
356
+ return new Map(entries.map((entry) => [getCustomRangePresentationKey$1(entry), entry]));
357
+ }
358
+ function createCustomRangePresentationPatch(previous, current) {
359
+ const upserts = [];
360
+ const removals = [];
361
+ for (const [key, entry] of current) {
362
+ const previousEntry = previous.get(key);
363
+ if (previousEntry == null || !areShallowRecordsEqual(previousEntry.presentation, entry.presentation)) upserts.push(entry);
364
+ }
365
+ for (const [key, entry] of previous) if (!current.has(key)) removals.push({
366
+ segmentId: entry.segmentId,
367
+ rangeId: entry.rangeId
368
+ });
369
+ return {
370
+ removals,
371
+ upserts
372
+ };
373
+ }
374
+ function isRichTextEditingMutationParams(value) {
375
+ return typeof value === "object" && value != null && "unitId" in value && typeof value.unitId === "string" && "actions" in value;
376
+ }
377
+ function collectCustomBlockViewports(dataModel) {
378
+ const snapshot = dataModel.getSnapshot();
379
+ const documentStyle = snapshot.documentStyle;
380
+ const viewports = {};
381
+ const bodies = [
382
+ snapshot.body,
383
+ ...Object.values(snapshot.headers ?? {}).map((header) => header.body),
384
+ ...Object.values(snapshot.footers ?? {}).map((footer) => footer.body)
385
+ ];
386
+ for (const customBlock of bodies.flatMap((body) => (body === null || body === void 0 ? void 0 : body.customBlocks) ?? [])) {
387
+ var _snapshot$drawings, _documentStyle$pageSi;
388
+ const drawing = (_snapshot$drawings = snapshot.drawings) === null || _snapshot$drawings === void 0 ? void 0 : _snapshot$drawings[customBlock.blockId];
389
+ if (drawing == null) continue;
390
+ const viewport = (0, _univerjs_engine_render.getDocsCustomBlockRenderViewport)(dataModel.getUnitId(), customBlock.blockId, {
391
+ fallbackHeight: drawing.docTransform.size.height ?? 0,
392
+ fallbackWidth: drawing.docTransform.size.width ?? 0,
393
+ pageMarginLeft: documentStyle.marginLeft,
394
+ pageMarginRight: documentStyle.marginRight,
395
+ pageWidth: (_documentStyle$pageSi = documentStyle.pageSize) === null || _documentStyle$pageSi === void 0 ? void 0 : _documentStyle$pageSi.width
396
+ });
397
+ if (viewport != null) viewports[customBlock.blockId] = { ...viewport };
398
+ }
399
+ return viewports;
400
+ }
401
+ let DocLayoutExecutorService = _DocLayoutExecutorService = class DocLayoutExecutorService extends _univerjs_core.Disposable {
402
+ constructor(_univerInstanceService, _commandService, _localeService, _logService) {
403
+ super();
404
+ this._univerInstanceService = _univerInstanceService;
405
+ this._commandService = _commandService;
406
+ this._localeService = _localeService;
407
+ this._logService = _logService;
408
+ _defineProperty(this, "_executor", null);
409
+ _defineProperty(this, "_executorReady", null);
410
+ _defineProperty(this, "_recoveryFailure", null);
411
+ _defineProperty(this, "_sessionEpoch", 0);
412
+ _defineProperty(this, "_sessions", /* @__PURE__ */ new Map());
413
+ _defineProperty(this, "_hydrationSamples", /* @__PURE__ */ new Map());
414
+ _defineProperty(this, "_customRangePresentationProviders", /* @__PURE__ */ new Set());
415
+ _defineProperty(this, "_executorStatus$", new rxjs.BehaviorSubject({
416
+ state: "unregistered",
417
+ executor: null,
418
+ diagnostic: null,
419
+ recoveryUnitId: null
420
+ }));
421
+ _defineProperty(this, "executorStatus$", this._executorStatus$.asObservable());
422
+ this.disposeWithMe(this._univerInstanceService.getTypeOfUnitAdded$(_univerjs_core.UniverInstanceType.UNIVER_DOC).subscribe(({ unit }) => this._createSessionIfEligible(unit)));
423
+ this.disposeWithMe(this._univerInstanceService.getTypeOfUnitDisposed$(_univerjs_core.UniverInstanceType.UNIVER_DOC).subscribe((unit) => this._disposeSession(unit.getUnitId())));
424
+ this.disposeWithMe(this._commandService.onCommandExecuted((command) => {
425
+ if (command.id !== "doc.mutation.rich-text-editing") return;
426
+ const params = command.params;
427
+ if (!isRichTextEditingMutationParams(params)) {
428
+ this._logService.warn("[DocLayoutExecutorService]: ignored malformed document mutation parameters.");
429
+ return;
430
+ }
431
+ this._enqueueCommittedMutation(params);
432
+ }));
433
+ this.disposeWithMe(this._localeService.localeChanged$.subscribe(() => {
434
+ for (const unitId of this._sessions.keys()) {
435
+ const dataModel = this._getEligibleModel(unitId);
436
+ if (dataModel != null) this._replaceSession(dataModel).catch((error) => {
437
+ this._logService.error("[DocLayoutExecutorService]: failed to refresh Worker locale.", error);
438
+ });
439
+ }
440
+ }));
441
+ }
442
+ register(executor) {
443
+ if (this._executor != null) throw new Error("A document layout executor is already registered.");
444
+ this._executor = executor;
445
+ this._recoveryFailure = null;
446
+ this._executorStatus$.next({
447
+ state: "initializing",
448
+ executor: executor.type,
449
+ diagnostic: null,
450
+ recoveryUnitId: null
451
+ });
452
+ const executorReady = executor.initialize();
453
+ this._executorReady = executorReady;
454
+ executorReady.then(() => {
455
+ if (this._executor === executor) this._executorStatus$.next({
456
+ state: "active",
457
+ executor: executor.type,
458
+ diagnostic: null,
459
+ recoveryUnitId: null
460
+ });
461
+ }).catch((error) => {
462
+ if (this._executor !== executor) return;
463
+ this._executor = null;
464
+ this._executorReady = null;
465
+ this._disposeManagedSessions();
466
+ this._sessions.clear();
467
+ const diagnostic = error instanceof Error ? error.message : String(error);
468
+ this._executorStatus$.next({
469
+ state: "failed",
470
+ executor: executor.type,
471
+ diagnostic,
472
+ recoveryUnitId: null
473
+ });
474
+ this._logService.error("[DocLayoutExecutorService]: document layout executor initialization failed.", error);
475
+ });
476
+ for (const unit of this._univerInstanceService.getAllUnitsForType(_univerjs_core.UniverInstanceType.UNIVER_DOC)) this._createSessionIfEligible(unit);
477
+ return (0, _univerjs_core.toDisposable)(() => {
478
+ if (this._executor === executor) {
479
+ this._executor = null;
480
+ this._executorReady = null;
481
+ this._disposeManagedSessions();
482
+ this._sessions.clear();
483
+ this._executorStatus$.next({
484
+ state: "unregistered",
485
+ executor: null,
486
+ diagnostic: null,
487
+ recoveryUnitId: null
488
+ });
489
+ }
490
+ });
491
+ }
492
+ getExecutor() {
493
+ return this._executor;
494
+ }
495
+ getExecutorStatus() {
496
+ return this._executorStatus$.value;
497
+ }
498
+ registerCustomRangePresentationProvider(provider) {
499
+ this._customRangePresentationProviders.add(provider);
500
+ return (0, _univerjs_core.toDisposable)(() => this._customRangePresentationProviders.delete(provider));
501
+ }
502
+ async getPerformanceMetrics(unitId) {
503
+ var _this$_executor;
504
+ const executorMetrics = await ((_this$_executor = this._executor) === null || _this$_executor === void 0 ? void 0 : _this$_executor.getPerformanceMetrics(unitId));
505
+ return {
506
+ hydrationMs: [...this._hydrationSamples.get(unitId) ?? []],
507
+ mutationTransferMs: [...(executorMetrics === null || executorMetrics === void 0 ? void 0 : executorMetrics.mutationTransferMs) ?? []],
508
+ patchTransferMs: [...(executorMetrics === null || executorMetrics === void 0 ? void 0 : executorMetrics.patchTransferMs) ?? []],
509
+ snapshotTransferMs: [...(executorMetrics === null || executorMetrics === void 0 ? void 0 : executorMetrics.snapshotTransferMs) ?? []]
510
+ };
511
+ }
512
+ async resetPerformanceMetrics(unitId) {
513
+ var _this$_executor2;
514
+ this._hydrationSamples.delete(unitId);
515
+ await ((_this$_executor2 = this._executor) === null || _this$_executor2 === void 0 ? void 0 : _this$_executor2.resetPerformanceMetrics(unitId));
516
+ }
517
+ recordHydrationDuration(unitId, durationMs) {
518
+ this._appendPerformanceSample(this._hydrationSamples, unitId, durationMs);
519
+ }
520
+ async recoverExecutor(unitId, diagnostic) {
521
+ const executor = this._requireExecutor();
522
+ this._executorStatus$.next({
523
+ state: "recovering",
524
+ executor: executor.type,
525
+ diagnostic,
526
+ recoveryUnitId: unitId
527
+ });
528
+ for (const session of this._sessions.values()) this._markSessionDisposed(session);
529
+ this._sessions.clear();
530
+ this._hydrationSamples.clear();
531
+ try {
532
+ const executorReady = executor.recover();
533
+ this._executorReady = executorReady;
534
+ await executorReady;
535
+ } catch (error) {
536
+ if (this._executor === executor) {
537
+ const recoveryDiagnostic = error instanceof Error ? error.message : String(error);
538
+ this._executor = null;
539
+ this._executorReady = null;
540
+ this._recoveryFailure = {
541
+ diagnostic: recoveryDiagnostic,
542
+ unitId
543
+ };
544
+ this._executorStatus$.next({
545
+ state: "recovering",
546
+ executor: executor.type,
547
+ diagnostic: recoveryDiagnostic,
548
+ recoveryUnitId: unitId
549
+ });
550
+ }
551
+ throw error;
552
+ }
553
+ }
554
+ completeRecovery(unitId) {
555
+ var _this$_recoveryFailur;
556
+ const status = this._executorStatus$.value;
557
+ if (status.state !== "recovering" || status.recoveryUnitId !== unitId) return;
558
+ const recoveryFailure = ((_this$_recoveryFailur = this._recoveryFailure) === null || _this$_recoveryFailur === void 0 ? void 0 : _this$_recoveryFailur.unitId) === unitId ? this._recoveryFailure : null;
559
+ this._recoveryFailure = null;
560
+ this._executorStatus$.next({
561
+ state: recoveryFailure == null ? "active" : "failed",
562
+ executor: status.executor,
563
+ diagnostic: (recoveryFailure === null || recoveryFailure === void 0 ? void 0 : recoveryFailure.diagnostic) ?? null,
564
+ recoveryUnitId: null
565
+ });
566
+ }
567
+ async startLayout(identity, options, budgetMs) {
568
+ const { unitId } = identity;
569
+ const executor = this._executor;
570
+ const dataModel = this._getEligibleModel(unitId);
571
+ if (executor == null || dataModel == null) return null;
572
+ let session = this._sessions.get(unitId);
573
+ if (session != null && session.sourceMutationRevision !== dataModel.getMutationRevision()) session.needsResnapshot = true;
574
+ if (session == null || session.needsResnapshot) session = await this._replaceSession(dataModel);
575
+ if (session.disposed || this._executor !== executor || this._getEligibleModel(unitId) !== dataModel) return null;
576
+ let result = await this._startSynchronizedLayout(executor, session, identity, options, budgetMs);
577
+ if (session.disposed || this._executor !== executor || this._getEligibleModel(unitId) !== dataModel) return null;
578
+ if (result.status === "not-found" || result.status === "resnapshot-required") {
579
+ session = await this._replaceSession(dataModel);
580
+ result = await this._startSynchronizedLayout(executor, session, identity, options, budgetMs);
581
+ }
582
+ return result;
583
+ }
584
+ stepLayout(request) {
585
+ return this._requireExecutor().stepLayout(request);
586
+ }
587
+ publishBacklog(request) {
588
+ return this._requireExecutor().publishBacklog(request);
589
+ }
590
+ getLayoutPage(request) {
591
+ return this._requireExecutor().getLayoutPage(request);
592
+ }
593
+ cancelLayout(request) {
594
+ const executor = this._executor;
595
+ return executor == null ? Promise.resolve() : executor.cancelLayout(request);
596
+ }
597
+ disposeLayoutMount(request) {
598
+ const executor = this._executor;
599
+ const session = this._sessions.get(request.unitId);
600
+ const latestStart = session === null || session === void 0 ? void 0 : session.latestStarts.get(request.mountId);
601
+ if ((latestStart === null || latestStart === void 0 ? void 0 : latestStart.mountEpoch) === request.mountEpoch && latestStart.viewportEpoch === request.viewportEpoch) {
602
+ session === null || session === void 0 || session.latestStarts.delete(request.mountId);
603
+ session === null || session === void 0 || session.customBlockViewportsByMount.delete(request.mountId);
604
+ }
605
+ return executor == null ? Promise.resolve() : executor.disposeLayoutMount(request);
606
+ }
607
+ dispose() {
608
+ const executor = this._executor;
609
+ if (executor != null) for (const [unitId, session] of this._sessions) {
610
+ this._markSessionDisposed(session);
611
+ executor.disposeSession({
612
+ unitId,
613
+ sessionEpoch: session.sessionEpoch
614
+ }).catch((error) => {
615
+ if (this._executor === executor) this._logService.error("[DocLayoutExecutorService]: failed to dispose a Worker session.", error);
616
+ });
617
+ }
618
+ this._sessions.clear();
619
+ this._executor = null;
620
+ this._executorReady = null;
621
+ this._recoveryFailure = null;
622
+ this._executorStatus$.complete();
623
+ this._customRangePresentationProviders.clear();
624
+ super.dispose();
625
+ }
626
+ _createSessionIfEligible(dataModel) {
627
+ if (this._executor == null || !this._isEligible(dataModel) || this._sessions.has(dataModel.getUnitId())) return;
628
+ this._replaceSession(dataModel).catch((error) => {
629
+ this._logService.error("[DocLayoutExecutorService]: failed to create a Worker session.", error);
630
+ });
631
+ }
632
+ _enqueueCommittedMutation(params) {
633
+ const executor = this._executor;
634
+ const dataModel = this._getEligibleModel(params.unitId);
635
+ if (executor == null || dataModel == null) return;
636
+ const session = this._sessions.get(params.unitId);
637
+ if (session == null) {
638
+ this._replaceSession(dataModel).catch((error) => {
639
+ this._logService.error("[DocLayoutExecutorService]: failed to snapshot a document mutation.", error);
640
+ });
641
+ return;
642
+ }
643
+ if (_univerjs_core.JSONX.isNoop(params.actions)) return;
644
+ const sourceMutationRevision = dataModel.getMutationRevision();
645
+ if (sourceMutationRevision !== session.sourceMutationRevision + 1) {
646
+ session.needsResnapshot = true;
647
+ return;
648
+ }
649
+ const baseRevision = session.modelRevision;
650
+ const modelRevision = baseRevision + 1;
651
+ session.modelRevision = modelRevision;
652
+ session.sourceMutationRevision = sourceMutationRevision;
653
+ session.pendingMutations.push({
654
+ baseRevision,
655
+ modelRevision,
656
+ actions: params.actions
657
+ });
658
+ }
659
+ async _startSynchronizedLayout(executor, session, identity, options, budgetMs) {
660
+ var _session$latestStarts;
661
+ const { unitId, mountId } = identity;
662
+ const startId = (((_session$latestStarts = session.latestStarts.get(mountId)) === null || _session$latestStarts === void 0 ? void 0 : _session$latestStarts.startId) ?? 0) + 1;
663
+ const startIdentity = {
664
+ startId,
665
+ mountEpoch: identity.mountEpoch,
666
+ viewportEpoch: identity.viewportEpoch
667
+ };
668
+ session.latestStarts.set(mountId, startIdentity);
669
+ const startTask = session.queue.then(async () => {
670
+ if (session.disposed || this._executor !== executor) return { status: "not-found" };
671
+ const currentModel = this._getEligibleModel(unitId);
672
+ if (currentModel == null || currentModel.getMutationRevision() !== session.sourceMutationRevision) {
673
+ session.needsResnapshot = true;
674
+ return {
675
+ status: "resnapshot-required",
676
+ modelRevision: session.workerRevision
677
+ };
678
+ }
679
+ if (session.latestStarts.get(mountId) !== startIdentity) return { status: "superseded" };
680
+ const mutations = session.pendingMutations.slice();
681
+ const projections = this._createLayoutProjectionPayload(session, identity, this._getRequiredModel(unitId));
682
+ const request = {
683
+ ...identity,
684
+ metricsRevision: startId,
685
+ baseRevision: session.workerRevision,
686
+ modelRevision: session.modelRevision,
687
+ mutations,
688
+ ...projections.request,
689
+ budgetMs,
690
+ ...options
691
+ };
692
+ const result = await executor.startLayout(request);
693
+ if (result.status === "accepted") {
694
+ session.workerRevision = request.modelRevision;
695
+ session.pendingMutations.splice(0, mutations.length);
696
+ session.customBlockViewportsByMount.set(mountId, {
697
+ mountEpoch: identity.mountEpoch,
698
+ value: projections.customBlockViewports
699
+ });
700
+ session.customRangePresentations = projections.customRangePresentations;
701
+ } else session.needsResnapshot = true;
702
+ return result;
703
+ });
704
+ session.queue = startTask.then(() => void 0, (error) => {
705
+ if (session.disposed || this._executor !== executor) return;
706
+ session.needsResnapshot = true;
707
+ this._logService.error("[DocLayoutExecutorService]: synchronized layout start failed.", error);
708
+ });
709
+ return startTask;
710
+ }
711
+ _createLayoutProjectionPayload(session, identity, dataModel) {
712
+ const customBlockViewports = collectCustomBlockViewports(dataModel);
713
+ const previousCustomBlockViewports = session.customBlockViewportsByMount.get(identity.mountId);
714
+ const customRangePresentations = this._collectCustomRangePresentations(dataModel);
715
+ const customRangePresentationMap = toCustomRangePresentationMap(customRangePresentations);
716
+ const request = {};
717
+ if (previousCustomBlockViewports == null || previousCustomBlockViewports.mountEpoch !== identity.mountEpoch) request.customBlockViewports = customBlockViewports;
718
+ else {
719
+ const patch = createRecordPatch(previousCustomBlockViewports.value, customBlockViewports);
720
+ if (patch.removals.length > 0 || Object.keys(patch.upserts).length > 0) request.customBlockViewportPatch = patch;
721
+ }
722
+ if (session.customRangePresentations == null) request.customRangePresentations = customRangePresentations;
723
+ else {
724
+ const patch = createCustomRangePresentationPatch(session.customRangePresentations, customRangePresentationMap);
725
+ if (patch.removals.length > 0 || patch.upserts.length > 0) request.customRangePresentationPatch = patch;
726
+ }
727
+ return {
728
+ request,
729
+ customBlockViewports,
730
+ customRangePresentations: customRangePresentationMap
731
+ };
732
+ }
733
+ async _replaceSession(dataModel) {
734
+ const executor = this._requireExecutor();
735
+ const unitId = dataModel.getUnitId();
736
+ const previous = this._sessions.get(unitId);
737
+ if (previous != null) this._markSessionDisposed(previous);
738
+ const modelRevision = (previous === null || previous === void 0 ? void 0 : previous.modelRevision) ?? 0;
739
+ const session = {
740
+ sessionEpoch: ++this._sessionEpoch,
741
+ modelRevision,
742
+ sourceMutationRevision: dataModel.getMutationRevision(),
743
+ workerRevision: modelRevision,
744
+ pendingMutations: [],
745
+ latestStarts: /* @__PURE__ */ new Map(),
746
+ customBlockViewportsByMount: /* @__PURE__ */ new Map(),
747
+ customRangePresentations: null,
748
+ queue: Promise.resolve(),
749
+ needsResnapshot: false,
750
+ disposed: false,
751
+ cancelPendingCreateTask: null
752
+ };
753
+ const createTask = this._createSessionOnNextMacroTask(executor, session, dataModel);
754
+ session.queue = createTask;
755
+ this._sessions.set(unitId, session);
756
+ try {
757
+ await createTask;
758
+ } catch (error) {
759
+ if (!session.disposed && this._executor === executor) {
760
+ session.needsResnapshot = true;
761
+ throw error;
762
+ }
763
+ }
764
+ return session;
765
+ }
766
+ _disposeSession(unitId) {
767
+ const session = this._sessions.get(unitId);
768
+ if (session == null) return;
769
+ this._markSessionDisposed(session);
770
+ this._sessions.delete(unitId);
771
+ this._hydrationSamples.delete(unitId);
772
+ const executor = this._executor;
773
+ executor === null || executor === void 0 || executor.disposeSession({
774
+ unitId,
775
+ sessionEpoch: session.sessionEpoch
776
+ }).catch((error) => {
777
+ if (this._executor === executor) this._logService.error("[DocLayoutExecutorService]: failed to dispose a Worker session.", error);
778
+ });
779
+ }
780
+ _getEligibleModel(unitId) {
781
+ const dataModel = this._univerInstanceService.getUnit(unitId, _univerjs_core.UniverInstanceType.UNIVER_DOC);
782
+ return dataModel != null && this._isEligible(dataModel) ? dataModel : null;
783
+ }
784
+ _getRequiredModel(unitId) {
785
+ const dataModel = this._getEligibleModel(unitId);
786
+ if (dataModel == null) throw new Error(`Eligible document model not found for Worker layout: "${unitId}".`);
787
+ return dataModel;
788
+ }
789
+ _collectCustomRangePresentations(dataModel) {
790
+ const presentations = [];
791
+ const providers = Array.from(this._customRangePresentationProviders).reverse();
792
+ if (providers.length === 0) return presentations;
793
+ const collectSegment = (segmentId, body) => {
794
+ if (body == null) return;
795
+ const seenRangeIds = /* @__PURE__ */ new Set();
796
+ for (const range of body.customRanges ?? []) {
797
+ if (seenRangeIds.has(range.rangeId)) continue;
798
+ seenRangeIds.add(range.rangeId);
799
+ for (const provider of providers) {
800
+ const presentation = provider(dataModel.getUnitId(), range, {
801
+ segmentId,
802
+ body
803
+ });
804
+ if (presentation != null) {
805
+ presentations.push({
806
+ segmentId,
807
+ rangeId: range.rangeId,
808
+ presentation: { ...presentation }
809
+ });
810
+ break;
811
+ }
812
+ }
813
+ }
814
+ };
815
+ collectSegment("", dataModel.getBody());
816
+ for (const [segmentId, headerModel] of dataModel.headerModelMap) collectSegment(segmentId, headerModel.getBody());
817
+ for (const [segmentId, footerModel] of dataModel.footerModelMap) collectSegment(segmentId, footerModel.getBody());
818
+ return presentations;
819
+ }
820
+ _isEligible(dataModel) {
821
+ if ((0, _univerjs_core.isInternalEditorID)(dataModel.getUnitId())) return false;
822
+ const flavor = dataModel.getSnapshot().documentStyle.documentFlavor;
823
+ return flavor === _univerjs_core.DocumentFlavor.TRADITIONAL || flavor === _univerjs_core.DocumentFlavor.MODERN;
824
+ }
825
+ _requireExecutor() {
826
+ if (this._executor == null) throw new Error("No document layout executor is registered.");
827
+ return this._executor;
828
+ }
829
+ _appendPerformanceSample(target, unitId, durationMs) {
830
+ const samples = target.get(unitId) ?? [];
831
+ samples.push(durationMs);
832
+ if (samples.length > _DocLayoutExecutorService._performanceSampleLimit) samples.splice(0, samples.length - _DocLayoutExecutorService._performanceSampleLimit);
833
+ target.set(unitId, samples);
834
+ }
835
+ _createSessionOnNextMacroTask(executor, session, dataModel) {
836
+ return new Promise((resolve, reject) => {
837
+ const cancelTask = (0, _univerjs_core.requestImmediateMacroTask)(() => {
838
+ session.cancelPendingCreateTask = null;
839
+ const unitId = dataModel.getUnitId();
840
+ if (session.disposed || this._executor !== executor || this._sessions.get(unitId) !== session) {
841
+ resolve();
842
+ return;
843
+ }
844
+ const executorReady = this._executorReady;
845
+ if (executorReady == null) {
846
+ resolve();
847
+ return;
848
+ }
849
+ executorReady.then(() => {
850
+ if (session.disposed || this._executor !== executor || this._sessions.get(unitId) !== session || this._getEligibleModel(unitId) !== dataModel) {
851
+ resolve();
852
+ return;
853
+ }
854
+ session.sourceMutationRevision = dataModel.getMutationRevision();
855
+ session.workerRevision = session.modelRevision;
856
+ session.pendingMutations.length = 0;
857
+ const request = {
858
+ unitId,
859
+ sessionEpoch: session.sessionEpoch,
860
+ snapshot: createDocumentLayoutSnapshot(dataModel.getSnapshot()),
861
+ modelRevision: session.modelRevision,
862
+ locale: this._localeService.getCurrentLocale(),
863
+ localeData: this._localeService.getLocales(),
864
+ direction: this._localeService.getDirection()
865
+ };
866
+ executor.createSession(request).then(resolve, reject);
867
+ }, reject);
868
+ });
869
+ session.cancelPendingCreateTask = () => {
870
+ cancelTask();
871
+ session.cancelPendingCreateTask = null;
872
+ resolve();
873
+ };
874
+ });
875
+ }
876
+ _markSessionDisposed(session) {
877
+ var _session$cancelPendin;
878
+ session.disposed = true;
879
+ (_session$cancelPendin = session.cancelPendingCreateTask) === null || _session$cancelPendin === void 0 || _session$cancelPendin.call(session);
880
+ session.cancelPendingCreateTask = null;
881
+ }
882
+ _disposeManagedSessions() {
883
+ for (const session of this._sessions.values()) this._markSessionDisposed(session);
884
+ }
885
+ };
886
+ _defineProperty(DocLayoutExecutorService, "_performanceSampleLimit", 2048);
887
+ DocLayoutExecutorService = _DocLayoutExecutorService = __decorate([
888
+ __decorateParam(0, _univerjs_core.IUniverInstanceService),
889
+ __decorateParam(1, _univerjs_core.ICommandService),
890
+ __decorateParam(2, (0, _univerjs_core.Inject)(_univerjs_core.LocaleService)),
891
+ __decorateParam(3, _univerjs_core.ILogService)
892
+ ], DocLayoutExecutorService);
893
+
229
894
  //#endregion
230
895
  //#region src/services/doc-skeleton-manager.service.ts
231
896
  let DocSkeletonManagerService = class DocSkeletonManagerService extends _univerjs_core.RxDisposable {
232
- constructor(_context, _localeService, _univerInstanceService) {
897
+ constructor(_context, _localeService, _univerInstanceService, _docLayoutExecutorService) {
233
898
  super();
234
899
  this._context = _context;
235
900
  this._localeService = _localeService;
236
901
  this._univerInstanceService = _univerInstanceService;
902
+ this._docLayoutExecutorService = _docLayoutExecutorService;
237
903
  _defineProperty(this, "_skeleton", void 0);
238
904
  _defineProperty(this, "_docViewModel", void 0);
239
905
  _defineProperty(this, "_currentSkeleton$", new rxjs.BehaviorSubject(null));
@@ -258,12 +924,23 @@ let DocSkeletonManagerService = class DocSkeletonManagerService extends _univerj
258
924
  getViewModel() {
259
925
  return this._docViewModel;
260
926
  }
927
+ getLayoutPerformanceMetrics() {
928
+ return this._docLayoutExecutorService.getPerformanceMetrics(this._context.unitId);
929
+ }
930
+ supportsIncrementalLayout() {
931
+ var _this$_context$unit$g;
932
+ const documentFlavor = (_this$_context$unit$g = this._context.unit.getSnapshot().documentStyle) === null || _this$_context$unit$g === void 0 ? void 0 : _this$_context$unit$g.documentFlavor;
933
+ return this._docLayoutExecutorService.getExecutor() != null && !(0, _univerjs_core.isInternalEditorID)(this._context.unitId) && !(0, _univerjs_engine_render.getDocumentLayoutPresentation)(this._context.unit) && (documentFlavor === _univerjs_core.DocumentFlavor.TRADITIONAL || documentFlavor === _univerjs_core.DocumentFlavor.MODERN);
934
+ }
261
935
  recalculate() {
262
936
  const skeleton = this._skeleton;
263
937
  skeleton.calculate();
938
+ this._publishSkeleton(skeleton);
939
+ return skeleton;
940
+ }
941
+ _publishSkeleton(skeleton) {
264
942
  this._currentSkeletonBefore$.next(skeleton);
265
943
  this._currentSkeleton$.next(skeleton);
266
- return skeleton;
267
944
  }
268
945
  _init() {
269
946
  const documentDataModel = this._context.unit;
@@ -277,7 +954,8 @@ let DocSkeletonManagerService = class DocSkeletonManagerService extends _univerj
277
954
  this._context.unit = documentDataModel;
278
955
  } else if (!this._docViewModel) this._docViewModel = this._buildDocViewModel(documentDataModel);
279
956
  if (!this._skeleton) this._skeleton = this._buildSkeleton(this._docViewModel);
280
- this.recalculate();
957
+ if (this.supportsIncrementalLayout()) this._publishSkeleton(this._skeleton);
958
+ else this.recalculate();
281
959
  this._currentViewModel$.next(this._docViewModel);
282
960
  }
283
961
  _buildSkeleton(documentViewModel) {
@@ -287,7 +965,11 @@ let DocSkeletonManagerService = class DocSkeletonManagerService extends _univerj
287
965
  return new _univerjs_engine_render.DocumentViewModel(documentDataModel);
288
966
  }
289
967
  };
290
- DocSkeletonManagerService = __decorate([__decorateParam(1, (0, _univerjs_core.Inject)(_univerjs_core.LocaleService)), __decorateParam(2, _univerjs_core.IUniverInstanceService)], DocSkeletonManagerService);
968
+ DocSkeletonManagerService = __decorate([
969
+ __decorateParam(1, (0, _univerjs_core.Inject)(_univerjs_core.LocaleService)),
970
+ __decorateParam(2, _univerjs_core.IUniverInstanceService),
971
+ __decorateParam(3, (0, _univerjs_core.Inject)(DocLayoutExecutorService))
972
+ ], DocSkeletonManagerService);
291
973
 
292
974
  //#endregion
293
975
  //#region src/services/doc-state-emit.service.ts
@@ -307,40 +989,404 @@ var DocStateEmitService = class extends _univerjs_core.RxDisposable {
307
989
  };
308
990
 
309
991
  //#endregion
310
- //#region src/commands/mutations/core-editing.mutation.ts
311
- const RichTextEditingMutationId = "doc.mutation.rich-text-editing";
992
+ //#region src/commands/mutations/doc-structure-mutation-validation.ts
993
+ const STRUCTURAL_BODY_FIELDS = [
994
+ "paragraphs",
995
+ "sectionBreaks",
996
+ "customBlocks",
997
+ "docxRawCustomBlocks",
998
+ "docxRawBlocks",
999
+ "docxExportExcludedRanges",
1000
+ "tables",
1001
+ "columnGroups",
1002
+ "blockRanges"
1003
+ ];
1004
+ const STRUCTURAL_DATA_STREAM_TOKENS = /* @__PURE__ */ new Set([
1005
+ _univerjs_core.DataStreamTreeTokenType.PARAGRAPH,
1006
+ _univerjs_core.DataStreamTreeTokenType.SECTION_BREAK,
1007
+ _univerjs_core.DataStreamTreeTokenType.TABLE_START,
1008
+ _univerjs_core.DataStreamTreeTokenType.TABLE_ROW_START,
1009
+ _univerjs_core.DataStreamTreeTokenType.TABLE_CELL_START,
1010
+ _univerjs_core.DataStreamTreeTokenType.TABLE_CELL_END,
1011
+ _univerjs_core.DataStreamTreeTokenType.TABLE_ROW_END,
1012
+ _univerjs_core.DataStreamTreeTokenType.TABLE_END,
1013
+ _univerjs_core.DataStreamTreeTokenType.COLUMN_GROUP_START,
1014
+ _univerjs_core.DataStreamTreeTokenType.COLUMN_START,
1015
+ _univerjs_core.DataStreamTreeTokenType.COLUMN_END,
1016
+ _univerjs_core.DataStreamTreeTokenType.COLUMN_GROUP_END,
1017
+ _univerjs_core.DataStreamTreeTokenType.BLOCK_START,
1018
+ _univerjs_core.DataStreamTreeTokenType.BLOCK_END,
1019
+ _univerjs_core.DataStreamTreeTokenType.CUSTOM_BLOCK
1020
+ ]);
1021
+ const NON_STRUCTURAL_ROOT_FIELDS = /* @__PURE__ */ new Set([
1022
+ "disabled",
1023
+ "documentStyle",
1024
+ "drawings",
1025
+ "drawingsOrder",
1026
+ "lists",
1027
+ "locale",
1028
+ "resources",
1029
+ "rev",
1030
+ "settings",
1031
+ "styles",
1032
+ "tableSource",
1033
+ "title"
1034
+ ]);
1035
+ function isRecord$3(value) {
1036
+ return typeof value === "object" && value != null && !Array.isArray(value);
1037
+ }
1038
+ function containsStructuralToken(dataStream) {
1039
+ for (let index = 0; index < dataStream.length; index++) if (STRUCTURAL_DATA_STREAM_TOKENS.has(dataStream[index])) return true;
1040
+ return false;
1041
+ }
1042
+ function isStructurePreservingBody(value) {
1043
+ if (!isRecord$3(value)) return false;
1044
+ const dataStream = value.dataStream;
1045
+ if (dataStream != null && (typeof dataStream !== "string" || containsStructuralToken(dataStream))) return false;
1046
+ return STRUCTURAL_BODY_FIELDS.every((field) => {
1047
+ const metadata = value[field];
1048
+ return metadata == null || Array.isArray(metadata) && metadata.length === 0;
1049
+ });
1050
+ }
1051
+ function isStructurePreservingTextXEdit(value) {
1052
+ if (!Array.isArray(value)) return false;
1053
+ return value.every((action) => {
1054
+ if (!isRecord$3(action) || typeof action.len !== "number" || !Number.isFinite(action.len)) return false;
1055
+ if (action.t === _univerjs_core.TextXActionType.DELETE) return true;
1056
+ if (action.t === _univerjs_core.TextXActionType.INSERT) return isStructurePreservingBody(action.body);
1057
+ return action.t === _univerjs_core.TextXActionType.RETAIN && (action.body == null || isStructurePreservingBody(action.body));
1058
+ });
1059
+ }
1060
+ function pathsEqual(left, right) {
1061
+ return left.length === right.length && left.every((item, index) => item === right[index]);
1062
+ }
1063
+ function isStructurePreservingJSONXEdit(actions, expectedPath) {
1064
+ const cursor = _univerjs_core.JSON1.type.readCursor(actions);
1065
+ let hasComponent = false;
1066
+ let isStructurePreserving = true;
1067
+ cursor.traverse(null, (component) => {
1068
+ if (!isStructurePreserving) return;
1069
+ const path = cursor.getPath();
1070
+ hasComponent = true;
1071
+ if (NON_STRUCTURAL_ROOT_FIELDS.has(String(path[0]))) return;
1072
+ const componentKeys = Object.keys(component);
1073
+ if (component.et !== _univerjs_core.TextX.id || componentKeys.some((key) => key !== "et" && key !== "e") || !pathsEqual(path, expectedPath)) {
1074
+ isStructurePreserving = false;
1075
+ return;
1076
+ }
1077
+ const edit = component.e;
1078
+ isStructurePreserving = isStructurePreservingTextXEdit(edit);
1079
+ });
1080
+ return hasComponent && isStructurePreserving;
1081
+ }
312
1082
  function getSegmentType(documentDataModel, segmentId) {
1083
+ var _documentDataModel$ge;
313
1084
  if (!segmentId) return "body";
314
1085
  const { headers, footers } = documentDataModel.getSnapshot();
315
1086
  if (headers === null || headers === void 0 ? void 0 : headers[segmentId]) return "header";
316
1087
  if (footers === null || footers === void 0 ? void 0 : footers[segmentId]) return "footer";
1088
+ if ((_documentDataModel$ge = documentDataModel.getSnapshot().notes) === null || _documentDataModel$ge === void 0 ? void 0 : _documentDataModel$ge[segmentId]) return "note";
317
1089
  return "body";
318
1090
  }
319
- function assertValidDocBodyStructure(documentDataModel, segmentId) {
1091
+ function getSnapshotBody(snapshot, segmentId) {
1092
+ var _snapshot$headers, _snapshot$footers, _snapshot$notes;
1093
+ if (!segmentId) return snapshot.body;
1094
+ return ((_snapshot$headers = snapshot.headers) === null || _snapshot$headers === void 0 || (_snapshot$headers = _snapshot$headers[segmentId]) === null || _snapshot$headers === void 0 ? void 0 : _snapshot$headers.body) ?? ((_snapshot$footers = snapshot.footers) === null || _snapshot$footers === void 0 || (_snapshot$footers = _snapshot$footers[segmentId]) === null || _snapshot$footers === void 0 ? void 0 : _snapshot$footers.body) ?? ((_snapshot$notes = snapshot.notes) === null || _snapshot$notes === void 0 || (_snapshot$notes = _snapshot$notes[segmentId]) === null || _snapshot$notes === void 0 ? void 0 : _snapshot$notes.body);
1095
+ }
1096
+ function containsTextXEdit(actions) {
1097
+ const cursor = _univerjs_core.JSON1.type.readCursor(actions);
1098
+ let found = false;
1099
+ cursor.traverse(null, (component) => {
1100
+ if (component.et === _univerjs_core.TextX.id) found = true;
1101
+ });
1102
+ return found;
1103
+ }
1104
+ function subtractBaselineIssues(issues, baseline) {
1105
+ const counts = /* @__PURE__ */ new Map();
1106
+ baseline.forEach((issue) => counts.set(issue.code, (counts.get(issue.code) ?? 0) + 1));
1107
+ return issues.filter((issue) => {
1108
+ const count = counts.get(issue.code) ?? 0;
1109
+ if (count === 0) return true;
1110
+ counts.set(issue.code, count - 1);
1111
+ return false;
1112
+ });
1113
+ }
1114
+ function assertValidDocBodyStructure(documentDataModel, segmentId, undoActions) {
1115
+ var _documentDataModel$ge2;
320
1116
  const segmentModel = documentDataModel.getSelfOrHeaderFooterModel(segmentId);
321
1117
  const body = segmentModel === null || segmentModel === void 0 ? void 0 : segmentModel.getBody();
322
1118
  if (!body) return;
323
1119
  const segmentType = getSegmentType(documentDataModel, segmentId);
324
- const issues = (0, _univerjs_core.validateDocBodyStructure)(body, {
1120
+ const context = {
1121
+ segmentType,
1122
+ segmentId: segmentId || void 0
1123
+ };
1124
+ const note = (_documentDataModel$ge2 = documentDataModel.getSnapshot().notes) === null || _documentDataModel$ge2 === void 0 ? void 0 : _documentDataModel$ge2[segmentId];
1125
+ const issues = note ? (0, _univerjs_core.validateDocumentStructure)({ notes: { [segmentId]: note } }) : (0, _univerjs_core.validateDocBodyStructure)(body, {
325
1126
  segmentType,
326
1127
  segmentId: segmentId || void 0
327
1128
  });
328
1129
  if (!issues.length) return;
329
- const detail = issues.map((issue) => `${issue.code}${issue.index == null ? "" : `@${issue.index}`}`).join(", ");
1130
+ const snapshot = _univerjs_core.Tools.deepClone(documentDataModel.getSnapshot());
1131
+ const baselineBody = getSnapshotBody(_univerjs_core.JSONX.apply(snapshot, undoActions), segmentId);
1132
+ const newIssues = baselineBody ? subtractBaselineIssues(issues, (0, _univerjs_core.validateDocBodyStructure)(baselineBody, context)) : issues;
1133
+ if (!newIssues.length) return;
1134
+ const detail = newIssues.map((issue) => `${issue.code}${issue.index == null ? "" : `@${issue.index}`}`).join(", ");
330
1135
  const segmentLabel = segmentId ? `${segmentType} ${segmentId}` : segmentType;
331
1136
  throw new Error(`[DocStructure] ${segmentLabel}: ${detail}`);
332
1137
  }
1138
+ function getLockedSdtContent(body, range) {
1139
+ var _range$properties;
1140
+ if (((_range$properties = range.properties) === null || _range$properties === void 0 ? void 0 : _range$properties.kind) !== "group") return body.dataStream.slice(range.startIndex, range.endIndex + 1);
1141
+ const children = (body.customRanges ?? []).filter((child) => child.rangeType === _univerjs_core.CustomRangeType.SDT && child.rangeId !== range.rangeId && child.startIndex >= range.startIndex && child.endIndex <= range.endIndex).sort((left, right) => {
1142
+ const position = left.startIndex - right.startIndex || right.endIndex - left.endIndex;
1143
+ if (position || left.rangeId === right.rangeId) return position;
1144
+ return left.rangeId < right.rangeId ? -1 : 1;
1145
+ });
1146
+ const protectedContent = [];
1147
+ let offset = range.startIndex;
1148
+ for (const child of children) {
1149
+ if (child.startIndex < offset) continue;
1150
+ protectedContent.push(body.dataStream.slice(offset, child.startIndex), child.rangeId);
1151
+ offset = child.endIndex + 1;
1152
+ }
1153
+ protectedContent.push(body.dataStream.slice(offset, range.endIndex + 1));
1154
+ return JSON.stringify(protectedContent);
1155
+ }
1156
+ function getRepeatingItemIds(body, section) {
1157
+ const ranges = body.customRanges ?? [];
1158
+ const sectionIndex = ranges.indexOf(section);
1159
+ const nestedSections = ranges.filter((range, index) => {
1160
+ var _range$properties2;
1161
+ return range.rangeType === _univerjs_core.CustomRangeType.SDT && ((_range$properties2 = range.properties) === null || _range$properties2 === void 0 ? void 0 : _range$properties2.kind) === "repeatingSection" && range.rangeId !== section.rangeId && range.startIndex >= section.startIndex && range.endIndex <= section.endIndex && (range.startIndex > section.startIndex || range.endIndex < section.endIndex || index < sectionIndex);
1162
+ });
1163
+ return ranges.filter((range, index) => {
1164
+ var _range$properties3;
1165
+ return range.rangeType === _univerjs_core.CustomRangeType.SDT && ((_range$properties3 = range.properties) === null || _range$properties3 === void 0 ? void 0 : _range$properties3.kind) === "repeatingSectionItem" && range.startIndex >= section.startIndex && range.endIndex <= section.endIndex && !nestedSections.some((nested) => nested.startIndex <= range.startIndex && range.endIndex <= nested.endIndex && (nested.startIndex < range.startIndex || range.endIndex < nested.endIndex || index < ranges.indexOf(nested)));
1166
+ }).map((range) => range.rangeId).sort();
1167
+ }
1168
+ function isDocSdtMutationAllowed(documentDataModel, segmentId, actions) {
1169
+ var _previousBody$customR;
1170
+ if (!containsTextXEdit(actions) && isStructurePreservingJSONXEdit(actions, (0, _univerjs_core.getRichTextEditPath)(documentDataModel, segmentId))) return true;
1171
+ const snapshot = documentDataModel.getSnapshot();
1172
+ const previousBody = getSnapshotBody(snapshot, segmentId);
1173
+ const lockedRanges = previousBody === null || previousBody === void 0 || (_previousBody$customR = previousBody.customRanges) === null || _previousBody$customR === void 0 ? void 0 : _previousBody$customR.filter((range) => {
1174
+ var _range$properties4, _range$properties5, _range$properties$rep;
1175
+ return range.rangeType === _univerjs_core.CustomRangeType.SDT && (((_range$properties4 = range.properties) === null || _range$properties4 === void 0 ? void 0 : _range$properties4.lock) && range.properties.lock !== "unlocked" || ((_range$properties5 = range.properties) === null || _range$properties5 === void 0 ? void 0 : _range$properties5.kind) === "repeatingSection" && ((_range$properties$rep = range.properties.repeatingSection) === null || _range$properties$rep === void 0 ? void 0 : _range$properties$rep.doNotAllowInsertDelete));
1176
+ });
1177
+ if (!previousBody || !(lockedRanges === null || lockedRanges === void 0 ? void 0 : lockedRanges.length)) return true;
1178
+ const candidate = _univerjs_core.JSONX.apply(_univerjs_core.Tools.deepClone(snapshot), actions);
1179
+ const currentBody = getSnapshotBody(candidate, segmentId);
1180
+ for (const previous of lockedRanges) {
1181
+ var _previous$properties, _currentBody$customRa, _previous$properties2, _previous$properties$;
1182
+ const lock = (_previous$properties = previous.properties) === null || _previous$properties === void 0 ? void 0 : _previous$properties.lock;
1183
+ const current = currentBody === null || currentBody === void 0 || (_currentBody$customRa = currentBody.customRanges) === null || _currentBody$customRa === void 0 ? void 0 : _currentBody$customRa.find((range) => range.rangeId === previous.rangeId && range.rangeType === _univerjs_core.CustomRangeType.SDT);
1184
+ const wrapperLocked = lock === "sdtLocked" || lock === "sdtContentLocked";
1185
+ const contentLocked = lock === "contentLocked" || lock === "sdtContentLocked";
1186
+ if (wrapperLocked && !current) return false;
1187
+ if (((_previous$properties2 = previous.properties) === null || _previous$properties2 === void 0 ? void 0 : _previous$properties2.kind) === "repeatingSection" && ((_previous$properties$ = previous.properties.repeatingSection) === null || _previous$properties$ === void 0 ? void 0 : _previous$properties$.doNotAllowInsertDelete) && current && currentBody) {
1188
+ const before = getRepeatingItemIds(previousBody, previous);
1189
+ const after = getRepeatingItemIds(currentBody, current);
1190
+ if (before.length !== after.length || before.some((id, index) => id !== after[index])) return false;
1191
+ }
1192
+ if (contentLocked && current && currentBody) {
1193
+ if (getLockedSdtContent(previousBody, previous) !== getLockedSdtContent(currentBody, current) && !isBoundSdtValueUpdate(snapshot, candidate, previous, current, currentBody)) return false;
1194
+ }
1195
+ }
1196
+ return true;
1197
+ }
1198
+ function isBoundSdtValueUpdate(before, after, previous, current, currentBody) {
1199
+ const key = (0, _univerjs_core.getSdtBindingKey)(previous);
1200
+ const value = (0, _univerjs_core.getSdtBindingValue)(currentBody, current);
1201
+ if (!key || key !== (0, _univerjs_core.getSdtBindingKey)(current) || value === void 0) return false;
1202
+ return [
1203
+ "",
1204
+ ...Object.keys(before.headers ?? {}),
1205
+ ...Object.keys(before.footers ?? {}),
1206
+ ...Object.keys(before.notes ?? {})
1207
+ ].some((segmentId) => {
1208
+ var _previousBody$customR2;
1209
+ const previousBody = getSnapshotBody(before, segmentId);
1210
+ const nextBody = getSnapshotBody(after, segmentId);
1211
+ if (!previousBody || !nextBody) return false;
1212
+ return ((_previousBody$customR2 = previousBody.customRanges) === null || _previousBody$customR2 === void 0 ? void 0 : _previousBody$customR2.some((range) => {
1213
+ var _range$properties6, _range$properties7, _nextBody$customRange;
1214
+ if (range.rangeType !== _univerjs_core.CustomRangeType.SDT || ((_range$properties6 = range.properties) === null || _range$properties6 === void 0 ? void 0 : _range$properties6.lock) === "contentLocked" || ((_range$properties7 = range.properties) === null || _range$properties7 === void 0 ? void 0 : _range$properties7.lock) === "sdtContentLocked" || (0, _univerjs_core.getSdtBindingKey)(range) !== key) return false;
1215
+ const next = (_nextBody$customRange = nextBody.customRanges) === null || _nextBody$customRange === void 0 ? void 0 : _nextBody$customRange.find((item) => item.rangeType === _univerjs_core.CustomRangeType.SDT && item.rangeId === range.rangeId);
1216
+ return next != null && (0, _univerjs_core.getSdtBindingKey)(next) === key && (0, _univerjs_core.getSdtBindingValue)(previousBody, range) !== value && (0, _univerjs_core.getSdtBindingValue)(nextBody, next) === value;
1217
+ })) ?? false;
1218
+ });
1219
+ }
1220
+ function validateDocStructureMutation(documentDataModel, segmentId, actions, undoActions, isHistoryReplay = false) {
1221
+ const editPath = (0, _univerjs_core.getRichTextEditPath)(documentDataModel, segmentId);
1222
+ const preservesStructure = isStructurePreservingJSONXEdit(actions, editPath) && isStructurePreservingJSONXEdit(undoActions, editPath);
1223
+ let changesFootnoteStructure = false;
1224
+ const cursor = _univerjs_core.JSON1.type.readCursor(actions);
1225
+ cursor.traverse(null, (component) => {
1226
+ const path = cursor.getPath();
1227
+ if (path[0] === "notes" && (path.length <= 2 || path[2] !== "body") || path.includes("customRanges")) changesFootnoteStructure = true;
1228
+ if (component.et === _univerjs_core.TextX.id && Array.isArray(component.e)) for (const action of component.e) {
1229
+ if (isRecord$3(action) && Array.isArray(action.rangeUpdates) && action.rangeUpdates.some((update) => isRecord$3(update) && isRecord$3(update.range) && (update.range.rangeType === _univerjs_core.CustomRangeType.FOOTNOTE || update.range.rangeType === _univerjs_core.CustomRangeType.ENDNOTE))) changesFootnoteStructure = true;
1230
+ const ranges = isRecord$3(action) && isRecord$3(action.body) ? action.body.customRanges : void 0;
1231
+ if (Array.isArray(ranges) && ranges.some((range) => isRecord$3(range) && (range.rangeType === _univerjs_core.CustomRangeType.FOOTNOTE || range.rangeType === _univerjs_core.CustomRangeType.ENDNOTE))) changesFootnoteStructure = true;
1232
+ }
1233
+ });
1234
+ if (changesFootnoteStructure) {
1235
+ const issues = (0, _univerjs_core.validateDocumentStructure)(documentDataModel.getSnapshot());
1236
+ if (issues.length > 0) throw new Error(`[DocStructure] ${issues.map((issue) => `${issue.code}@${issue.index ?? issue.segmentId ?? ""}`).join(", ")}`);
1237
+ } else if (!preservesStructure && !isHistoryReplay) assertValidDocBodyStructure(documentDataModel, segmentId, undoActions);
1238
+ return preservesStructure && !changesFootnoteStructure;
1239
+ }
1240
+
1241
+ //#endregion
1242
+ //#region src/commands/mutations/core-editing.mutation.ts
1243
+ let DocHistoryAction = /* @__PURE__ */ function(DocHistoryAction) {
1244
+ DocHistoryAction["DeleteChart"] = "delete-chart";
1245
+ DocHistoryAction["DeleteDivider"] = "delete-divider";
1246
+ DocHistoryAction["DeleteImage"] = "delete-image";
1247
+ DocHistoryAction["DeleteShape"] = "delete-shape";
1248
+ DocHistoryAction["EditTableCell"] = "edit-table-cell";
1249
+ DocHistoryAction["FormatParagraph"] = "format-paragraph";
1250
+ DocHistoryAction["InsertCustomRange"] = "insert-custom-range";
1251
+ DocHistoryAction["UpdateImage"] = "update-image";
1252
+ DocHistoryAction["UpdatePageLayout"] = "update-page-layout";
1253
+ return DocHistoryAction;
1254
+ }({});
1255
+ function extractDocumentBodyActions(actions, segmentId) {
1256
+ if (!Array.isArray(actions)) return;
1257
+ const bodyActions = actions.indexOf("body") > -1 ? actions : actions.find((action) => Array.isArray(action) && action.indexOf("body") > -1);
1258
+ if (!Array.isArray(bodyActions)) return;
1259
+ const bodyIndex = bodyActions.indexOf("body");
1260
+ if (bodyIndex === -1) return;
1261
+ return (bodyIndex === 0 ? "" : bodyActions[bodyIndex - 1]) === segmentId ? bodyActions.slice(bodyIndex) : void 0;
1262
+ }
1263
+ /**
1264
+ * Transforms document selections through the same JSONX actions applied by a rich-text mutation.
1265
+ * Collaboration and rendering use this shared offset rule so the Main interaction window follows
1266
+ * the transformed local caret before an authoritative background layout is published.
1267
+ */
1268
+ function transformDocumentTextRanges(actions, textRanges, priority = "right") {
1269
+ if (textRanges.length === 0) return [];
1270
+ const bodyActions = extractDocumentBodyActions(actions, textRanges[0].segmentId ?? "");
1271
+ if (bodyActions == null) return textRanges;
1272
+ return textRanges.map((textRange) => {
1273
+ const startOffset = _univerjs_core.JSONX.transformPosition(bodyActions, textRange.startOffset, priority);
1274
+ const endOffset = _univerjs_core.JSONX.transformPosition(bodyActions, textRange.endOffset, priority);
1275
+ return {
1276
+ ...textRange,
1277
+ startOffset,
1278
+ endOffset,
1279
+ collapsed: startOffset === endOffset
1280
+ };
1281
+ });
1282
+ }
1283
+ function canRemoveFootnoteReference(actions, references) {
1284
+ let canRemove = false;
1285
+ const cursor = _univerjs_core.JSON1.type.readCursor(actions);
1286
+ cursor.traverse(null, (component) => {
1287
+ const path = cursor.getPath();
1288
+ if (path.length === 0) canRemove = true;
1289
+ if (canRemove || path[0] !== "body") return;
1290
+ if (path.length === 1 && component.et === _univerjs_core.TextX.id && Array.isArray(component.e)) {
1291
+ let offset = 0;
1292
+ for (const action of component.e) {
1293
+ var _action$body, _action$rangeUpdates;
1294
+ if (action.t === _univerjs_core.TextXActionType.DELETE && references.some((reference) => offset <= reference.endIndex && offset + action.len > reference.startIndex)) {
1295
+ canRemove = true;
1296
+ return;
1297
+ }
1298
+ if (action.t === _univerjs_core.TextXActionType.RETAIN && (((_action$body = action.body) === null || _action$body === void 0 ? void 0 : _action$body.customRanges) != null || ((_action$rangeUpdates = action.rangeUpdates) === null || _action$rangeUpdates === void 0 ? void 0 : _action$rangeUpdates.some((update) => references.some((reference) => reference.rangeId === update.rangeId))))) {
1299
+ canRemove = true;
1300
+ return;
1301
+ }
1302
+ if (action.t !== _univerjs_core.TextXActionType.INSERT) offset += action.len;
1303
+ }
1304
+ } else if (path.length === 1 || path[1] === "customRanges" || path[1] === "dataStream") canRemove = true;
1305
+ });
1306
+ return canRemove;
1307
+ }
1308
+ function includeFootnoteCleanup(before, actions) {
1309
+ var _before$body, _after$body;
1310
+ if (!before.notes) return actions;
1311
+ const references = ((_before$body = before.body) === null || _before$body === void 0 || (_before$body = _before$body.customRanges) === null || _before$body === void 0 ? void 0 : _before$body.filter((range) => range.rangeType === _univerjs_core.CustomRangeType.FOOTNOTE || range.rangeType === _univerjs_core.CustomRangeType.ENDNOTE)) ?? [];
1312
+ if (references.length === 0 || !canRemoveFootnoteReference(actions, references)) return actions;
1313
+ const after = _univerjs_core.JSONX.apply(_univerjs_core.Tools.deepClone(before), actions);
1314
+ const remaining = new Set((_after$body = after.body) === null || _after$body === void 0 || (_after$body = _after$body.customRanges) === null || _after$body === void 0 ? void 0 : _after$body.filter((range) => range.rangeType === _univerjs_core.CustomRangeType.FOOTNOTE || range.rangeType === _univerjs_core.CustomRangeType.ENDNOTE).map((range) => {
1315
+ var _range$properties;
1316
+ return (_range$properties = range.properties) === null || _range$properties === void 0 ? void 0 : _range$properties.noteId;
1317
+ }));
1318
+ let cleanup = null;
1319
+ const previousIds = new Set(references.map((reference) => {
1320
+ var _reference$properties;
1321
+ return (_reference$properties = reference.properties) === null || _reference$properties === void 0 ? void 0 : _reference$properties.noteId;
1322
+ }));
1323
+ for (const id of previousIds) {
1324
+ var _after$notes;
1325
+ if (typeof id === "string" && !remaining.has(id) && ((_after$notes = after.notes) === null || _after$notes === void 0 ? void 0 : _after$notes[id])) cleanup = _univerjs_core.JSONX.compose(cleanup, _univerjs_core.JSONX.getInstance().removeOp(["notes", id], after.notes[id]));
1326
+ }
1327
+ return _univerjs_core.JSONX.isNoop(cleanup) ? actions : _univerjs_core.JSONX.compose(actions, cleanup);
1328
+ }
1329
+ function applyValidatedDocumentActions(documentDataModel, segmentId, actions, isHistoryReplay = false) {
1330
+ const before = documentDataModel.getSnapshot();
1331
+ const appliedActions = includeFootnoteCleanup(before, actions);
1332
+ const undoActions = _univerjs_core.JSONX.invertWithDoc(appliedActions, before);
1333
+ documentDataModel.apply(appliedActions);
1334
+ try {
1335
+ return {
1336
+ actions: appliedActions,
1337
+ undoActions,
1338
+ preservesStructure: validateDocStructureMutation(documentDataModel, segmentId, appliedActions, undoActions, isHistoryReplay)
1339
+ };
1340
+ } catch (error) {
1341
+ documentDataModel.apply(undoActions);
1342
+ throw error;
1343
+ }
1344
+ }
1345
+ function resetDocumentViewModel(documentViewModel, documentDataModel, segmentId, actions, preservesStructure) {
1346
+ var _documentViewModel$re, _documentViewModel$re2;
1347
+ if (documentViewModel == null) return;
1348
+ if (!(segmentId === "" && preservesStructure && (((_documentViewModel$re = documentViewModel.resetByValidatedTextMutation) === null || _documentViewModel$re === void 0 ? void 0 : _documentViewModel$re.call(documentViewModel, documentDataModel, actions)) || ((_documentViewModel$re2 = documentViewModel.resetByValidatedMetadataMutation) === null || _documentViewModel$re2 === void 0 ? void 0 : _documentViewModel$re2.call(documentViewModel, documentDataModel, actions))))) documentViewModel.reset(documentDataModel);
1349
+ }
1350
+ function scheduleDocumentSelectionUpdate(selectionManager, params, isSync) {
1351
+ const { unitId, textRanges, trigger, noNeedSetTextRange, isEditing = true } = params;
1352
+ if (noNeedSetTextRange || textRanges == null || textRanges.length === 0 || trigger == null || isSync) return;
1353
+ const selectionTarget = {
1354
+ unitId,
1355
+ subUnitId: unitId
1356
+ };
1357
+ const currentSelection = selectionManager.getSelectionInfo(selectionTarget);
1358
+ const logicalTextRanges = textRanges.map((textRange, index) => ({
1359
+ ...textRange,
1360
+ segmentId: textRange.segmentId ?? params.segmentId ?? "",
1361
+ collapsed: textRange.startOffset === textRange.endOffset,
1362
+ isActive: index === textRanges.length - 1
1363
+ }));
1364
+ if (currentSelection != null) selectionManager.replaceSelectionInfoWithoutRefresh({
1365
+ ...currentSelection,
1366
+ segmentId: logicalTextRanges[logicalTextRanges.length - 1].segmentId,
1367
+ textRanges: logicalTextRanges,
1368
+ rectRanges: [],
1369
+ isEditing,
1370
+ options: params.options
1371
+ }, selectionTarget);
1372
+ const updatedSelection = selectionManager.getSelectionInfo(selectionTarget);
1373
+ queueMicrotask(() => {
1374
+ if (selectionManager.getSelectionInfo(selectionTarget) !== updatedSelection) return;
1375
+ if (updatedSelection == null) selectionManager.replaceDocRanges(logicalTextRanges, selectionTarget, isEditing, params.options);
1376
+ else selectionManager.refreshSelection(selectionTarget, isEditing);
1377
+ });
1378
+ }
333
1379
  /**
334
1380
  * The core mutator to change rich text actions. The execution result would be undo mutation params. Could be directly
335
1381
  * send to undo redo service (will be used by the triggering command).
336
1382
  */
337
1383
  const RichTextEditingMutation = {
338
- id: RichTextEditingMutationId,
1384
+ id: RICH_TEXT_EDITING_MUTATION_ID,
339
1385
  type: _univerjs_core.CommandType.MUTATION,
340
1386
  handler: (accessor, params, options) => {
341
1387
  var _renderManagerService;
342
- const { unitId, segmentId = "", actions, textRanges, prevTextRanges, trigger, noHistory, isCompositionEnd, noNeedSetTextRange, debounce, isEditing = true, isSync: paramsIsSync, syncer } = params;
343
- const isSync = paramsIsSync || (options === null || options === void 0 ? void 0 : options.fromCollab) || (options === null || options === void 0 ? void 0 : options.fromChangeset);
1388
+ const { unitId, segmentId = "", actions, textRanges, prevTextRanges, trigger, noHistory, isCompositionEnd, debounce, isEditing = true, isSync: paramsIsSync, syncer } = params;
1389
+ const isSync = Boolean(paramsIsSync || (options === null || options === void 0 ? void 0 : options.fromCollab) || (options === null || options === void 0 ? void 0 : options.fromChangeset));
344
1390
  const univerInstanceService = accessor.get(_univerjs_core.IUniverInstanceService);
345
1391
  const renderManagerService = accessor.get(_univerjs_engine_render.IRenderManagerService);
346
1392
  const docStateEmitService = accessor.get(DocStateEmitService);
@@ -356,35 +1402,46 @@ const RichTextEditingMutation = {
356
1402
  actions: [],
357
1403
  textRanges: docRanges
358
1404
  };
359
- const undoActions = _univerjs_core.JSONX.invertWithDoc(actions, documentDataModel.getSnapshot());
360
- documentDataModel.apply(actions);
361
- try {
362
- assertValidDocBodyStructure(documentDataModel, segmentId);
1405
+ const isHistoryReplay = trigger === _univerjs_core.UndoCommandId || trigger === _univerjs_core.RedoCommandId;
1406
+ if (!isHistoryReplay && !isDocSdtMutationAllowed(documentDataModel, segmentId, actions)) {
1407
+ params.actions = [];
1408
+ return {
1409
+ unitId,
1410
+ actions: [],
1411
+ textRanges: docRanges
1412
+ };
1413
+ }
1414
+ const presentation = (0, _univerjs_engine_render.getDocumentLayoutPresentation)(documentDataModel);
1415
+ const previousLayoutState = presentation === null || presentation === void 0 ? void 0 : presentation.captureState();
1416
+ const { actions: appliedActions, undoActions, preservesStructure } = applyValidatedDocumentActions(documentDataModel, segmentId, actions, isHistoryReplay);
1417
+ if (presentation) try {
1418
+ if (params.layoutState !== void 0) presentation.restoreState(params.layoutState);
1419
+ else presentation.applyActions(appliedActions, documentDataModel.getSnapshot());
1420
+ params.layoutState = presentation.captureState();
363
1421
  } catch (error) {
364
1422
  documentDataModel.apply(undoActions);
1423
+ presentation.restoreState(previousLayoutState);
365
1424
  throw error;
366
1425
  }
367
- documentViewModel === null || documentViewModel === void 0 || documentViewModel.reset(documentDataModel);
368
- if (!noNeedSetTextRange && textRanges && trigger != null && !isSync) queueMicrotask(() => {
369
- docSelectionManagerService.replaceDocRanges(textRanges, {
370
- unitId,
371
- subUnitId: unitId
372
- }, isEditing, params.options);
373
- });
1426
+ params.actions = appliedActions;
1427
+ resetDocumentViewModel(documentViewModel, documentDataModel, segmentId, appliedActions, preservesStructure);
1428
+ scheduleDocumentSelectionUpdate(docSelectionManagerService, params, isSync);
374
1429
  const changeState = {
375
- commandId: RichTextEditingMutationId,
1430
+ commandId: RICH_TEXT_EDITING_MUTATION_ID,
376
1431
  unitId,
377
1432
  segmentId,
378
1433
  trigger,
379
1434
  noHistory,
380
1435
  debounce,
381
1436
  redoState: {
382
- actions,
1437
+ ...presentation ? { layoutState: params.layoutState } : {},
1438
+ actions: appliedActions,
383
1439
  textRanges,
384
1440
  options: params.options,
385
1441
  isEditing
386
1442
  },
387
1443
  undoState: {
1444
+ ...presentation ? { layoutState: previousLayoutState } : {},
388
1445
  actions: undoActions,
389
1446
  textRanges: prevTextRanges ?? docRanges,
390
1447
  options: selectionInfo === null || selectionInfo === void 0 ? void 0 : selectionInfo.options,
@@ -398,6 +1455,7 @@ const RichTextEditingMutation = {
398
1455
  return {
399
1456
  unitId,
400
1457
  actions: undoActions,
1458
+ ...presentation ? { layoutState: previousLayoutState } : {},
401
1459
  textRanges: docRanges
402
1460
  };
403
1461
  }
@@ -414,59 +1472,63 @@ const InsertTextCommand = {
414
1472
  handler: (accessor, params) => {
415
1473
  var _docDataModel$getSelf;
416
1474
  const commandService = accessor.get(_univerjs_core.ICommandService);
417
- const { range, segmentId, body, unitId, cursorOffset } = params;
1475
+ const { range, segmentId, body, unitId, cursorOffset, debounce = true, textRanges, noNeedSetTextRange, isEditing } = params;
418
1476
  const docSelectionManagerService = accessor.get(DocSelectionManagerService);
419
1477
  const docDataModel = accessor.get(_univerjs_core.IUniverInstanceService).getUnit(unitId, _univerjs_core.UniverInstanceType.UNIVER_DOC);
420
1478
  if (docDataModel == null) return false;
421
1479
  const activeRange = docSelectionManagerService.getActiveTextRange();
422
- const rangeSegmentId = "segmentId" in range ? range.segmentId : void 0;
1480
+ const rangeSegmentId = "segmentId" in range && typeof range.segmentId === "string" ? range.segmentId : void 0;
423
1481
  const targetSegmentId = segmentId ?? rangeSegmentId ?? (activeRange === null || activeRange === void 0 ? void 0 : activeRange.segmentId) ?? "";
424
1482
  const originBody = (_docDataModel$getSelf = docDataModel.getSelfOrHeaderFooterModel(targetSegmentId)) === null || _docDataModel$getSelf === void 0 ? void 0 : _docDataModel$getSelf.getBody();
425
1483
  if (originBody == null) return false;
426
1484
  const { startOffset, collapsed } = range;
427
1485
  const cursorMove = cursorOffset ?? body.dataStream.length;
428
- const textRanges = [{
1486
+ const mutationTextRanges = textRanges ?? [{
429
1487
  startOffset: startOffset + cursorMove,
430
1488
  endOffset: startOffset + cursorMove,
431
- style: activeRange === null || activeRange === void 0 ? void 0 : activeRange.style,
432
1489
  collapsed
433
1490
  }];
434
1491
  const doMutation = {
435
1492
  id: RichTextEditingMutation.id,
436
1493
  params: {
437
1494
  unitId,
1495
+ segmentId: targetSegmentId,
438
1496
  actions: [],
439
- textRanges,
440
- debounce: true
1497
+ textRanges: mutationTextRanges,
1498
+ debounce,
1499
+ noNeedSetTextRange,
1500
+ isEditing
441
1501
  }
442
1502
  };
443
- const textX = new _univerjs_core.TextX();
444
- const jsonX = _univerjs_core.JSONX.getInstance();
445
- if (collapsed) {
446
- if (startOffset > 0) textX.push({
447
- t: _univerjs_core.TextXActionType.RETAIN,
448
- len: startOffset
449
- });
450
- textX.push({
451
- t: _univerjs_core.TextXActionType.INSERT,
452
- body,
453
- len: body.dataStream.length
454
- });
455
- } else {
456
- const dos = _univerjs_core.BuildTextUtils.selection.delete([range], originBody, 0, body);
457
- textX.push(...dos);
458
- }
459
- doMutation.params.textRanges = [{
460
- startOffset: startOffset + cursorMove,
461
- endOffset: startOffset + cursorMove,
462
- collapsed
463
- }];
464
- const path = (0, _univerjs_core.getRichTextEditPath)(docDataModel, segmentId);
465
- doMutation.params.actions = jsonX.editOp(textX.serialize(), path);
1503
+ doMutation.params.actions = buildInsertTextActions(docDataModel, originBody, range, body, targetSegmentId);
466
1504
  const result = commandService.syncExecuteCommand(doMutation.id, doMutation.params);
467
1505
  return Boolean(result);
468
1506
  }
469
1507
  };
1508
+ function buildInsertTextActions(documentDataModel, originBody, range, insertBody, segmentId) {
1509
+ const { startOffset, endOffset, collapsed } = range;
1510
+ const textX = new _univerjs_core.TextX();
1511
+ if (collapsed) {
1512
+ if (startOffset > 0) textX.push({
1513
+ t: _univerjs_core.TextXActionType.RETAIN,
1514
+ len: startOffset
1515
+ });
1516
+ textX.push({
1517
+ t: _univerjs_core.TextXActionType.INSERT,
1518
+ body: insertBody,
1519
+ len: insertBody.dataStream.length
1520
+ });
1521
+ } else textX.push(..._univerjs_core.BuildTextUtils.selection.delete([range], originBody, 0, insertBody));
1522
+ const textActions = _univerjs_core.JSONX.getInstance().editOp(textX.serialize(), (0, _univerjs_core.getRichTextEditPath)(documentDataModel, segmentId));
1523
+ return collapsed ? textActions : appendRemovedDrawingActions(textActions, documentDataModel, originBody, startOffset, endOffset, segmentId);
1524
+ }
1525
+ function appendRemovedDrawingActions(textActions, documentDataModel, body, startOffset, endOffset, segmentId) {
1526
+ return [textActions, ..._univerjs_core.BuildTextUtils.drawing.remove(documentDataModel.getSnapshot(), [{
1527
+ startOffset,
1528
+ endOffset,
1529
+ collapsed: false
1530
+ }], body, segmentId)].reduce((accumulator, action) => _univerjs_core.JSONX.compose(accumulator, action));
1531
+ }
470
1532
  /**
471
1533
  * The command to delete text, mainly used in BACKSPACE and DELETE when collapsed is true. ONLY handle collapsed range!!!
472
1534
  */
@@ -493,6 +1555,7 @@ const DeleteTextCommand = {
493
1555
  id: RichTextEditingMutation.id,
494
1556
  params: {
495
1557
  unitId,
1558
+ segmentId,
496
1559
  actions: [],
497
1560
  textRanges: [{
498
1561
  startOffset: start,
@@ -509,9 +1572,9 @@ const DeleteTextCommand = {
509
1572
  startOffset: start,
510
1573
  endOffset: end + 1,
511
1574
  collapsed: false
512
- }], body));
1575
+ }], body, 0, null, true, docDataModel.getDocumentStyle().documentFlavor));
513
1576
  const path = (0, _univerjs_core.getRichTextEditPath)(docDataModel, segmentId);
514
- doMutation.params.actions = jsonX.editOp(textX.serialize(), path);
1577
+ doMutation.params.actions = appendRemovedDrawingActions(jsonX.editOp(textX.serialize(), path), docDataModel, body, start, end + 1, segmentId);
515
1578
  const result = commandService.syncExecuteCommand(doMutation.id, doMutation.params);
516
1579
  return Boolean(result);
517
1580
  }
@@ -790,6 +1853,235 @@ const SetDocumentNameCommand = {
790
1853
  }
791
1854
  };
792
1855
 
1856
+ //#endregion
1857
+ //#region src/services/permission/permission-point/document/comment.ts
1858
+ var DocumentCommentPermission = class {
1859
+ constructor(unitId) {
1860
+ this.unitId = unitId;
1861
+ _defineProperty(this, "type", _univerjs_protocol.UnitObject.Document);
1862
+ _defineProperty(this, "subType", _univerjs_protocol.UnitAction.Comment);
1863
+ _defineProperty(this, "status", _univerjs_core.PermissionStatus.INIT);
1864
+ _defineProperty(this, "id", void 0);
1865
+ _defineProperty(this, "value", true);
1866
+ this.id = `${this.type}.${this.subType}_${unitId}`;
1867
+ }
1868
+ };
1869
+
1870
+ //#endregion
1871
+ //#region src/services/permission/permission-point/document/copy.ts
1872
+ var DocumentCopyPermission = class {
1873
+ constructor(unitId) {
1874
+ this.unitId = unitId;
1875
+ _defineProperty(this, "type", _univerjs_protocol.UnitObject.Document);
1876
+ _defineProperty(this, "subType", _univerjs_protocol.UnitAction.Copy);
1877
+ _defineProperty(this, "status", _univerjs_core.PermissionStatus.INIT);
1878
+ _defineProperty(this, "id", void 0);
1879
+ _defineProperty(this, "value", true);
1880
+ this.id = `${this.type}.${this.subType}_${unitId}`;
1881
+ }
1882
+ };
1883
+
1884
+ //#endregion
1885
+ //#region src/services/permission/permission-point/document/editable.ts
1886
+ var DocumentEditablePermission = class {
1887
+ constructor(unitId) {
1888
+ this.unitId = unitId;
1889
+ _defineProperty(this, "type", _univerjs_protocol.UnitObject.Document);
1890
+ _defineProperty(this, "subType", _univerjs_protocol.UnitAction.Edit);
1891
+ _defineProperty(this, "status", _univerjs_core.PermissionStatus.INIT);
1892
+ _defineProperty(this, "id", void 0);
1893
+ _defineProperty(this, "value", true);
1894
+ this.id = `${this.type}.${this.subType}_${unitId}`;
1895
+ }
1896
+ };
1897
+
1898
+ //#endregion
1899
+ //#region src/services/permission/permission-point/document/export.ts
1900
+ var DocumentExportPermission = class {
1901
+ constructor(unitId) {
1902
+ this.unitId = unitId;
1903
+ _defineProperty(this, "type", _univerjs_protocol.UnitObject.Document);
1904
+ _defineProperty(this, "subType", _univerjs_protocol.UnitAction.Export);
1905
+ _defineProperty(this, "status", _univerjs_core.PermissionStatus.INIT);
1906
+ _defineProperty(this, "id", void 0);
1907
+ _defineProperty(this, "value", true);
1908
+ this.id = `${this.type}.${this.subType}_${unitId}`;
1909
+ }
1910
+ };
1911
+
1912
+ //#endregion
1913
+ //#region src/services/permission/permission-point/document/print.ts
1914
+ var DocumentPrintPermission = class {
1915
+ constructor(unitId) {
1916
+ this.unitId = unitId;
1917
+ _defineProperty(this, "type", _univerjs_protocol.UnitObject.Document);
1918
+ _defineProperty(this, "subType", _univerjs_protocol.UnitAction.Print);
1919
+ _defineProperty(this, "status", _univerjs_core.PermissionStatus.INIT);
1920
+ _defineProperty(this, "id", void 0);
1921
+ _defineProperty(this, "value", true);
1922
+ this.id = `${this.type}.${this.subType}_${unitId}`;
1923
+ }
1924
+ };
1925
+
1926
+ //#endregion
1927
+ //#region src/services/permission/permission-point/entity/edit.ts
1928
+ var DocumentEntityEditPermission = class {
1929
+ constructor(unitId, objectId) {
1930
+ this.unitId = unitId;
1931
+ this.objectId = objectId;
1932
+ _defineProperty(this, "type", _univerjs_protocol.UnitObject.DocumentEntity);
1933
+ _defineProperty(this, "subType", _univerjs_protocol.UnitAction.Edit);
1934
+ _defineProperty(this, "status", _univerjs_core.PermissionStatus.INIT);
1935
+ _defineProperty(this, "id", void 0);
1936
+ _defineProperty(this, "value", true);
1937
+ this.id = `${this.type}.${this.subType}_${unitId}_${objectId}`;
1938
+ }
1939
+ };
1940
+
1941
+ //#endregion
1942
+ //#region src/services/permission/permission-point/paragraph/edit.ts
1943
+ var DocumentParagraphEditPermission = class {
1944
+ constructor(unitId, objectId) {
1945
+ this.unitId = unitId;
1946
+ this.objectId = objectId;
1947
+ _defineProperty(this, "type", _univerjs_protocol.UnitObject.DocumentParagraph);
1948
+ _defineProperty(this, "subType", _univerjs_protocol.UnitAction.Edit);
1949
+ _defineProperty(this, "status", _univerjs_core.PermissionStatus.INIT);
1950
+ _defineProperty(this, "id", void 0);
1951
+ _defineProperty(this, "value", true);
1952
+ this.id = `${this.type}.${this.subType}_${unitId}_${objectId}`;
1953
+ }
1954
+ };
1955
+
1956
+ //#endregion
1957
+ //#region src/services/permission/permission-point/section/edit.ts
1958
+ var DocumentSectionEditPermission = class {
1959
+ constructor(unitId, objectId) {
1960
+ this.unitId = unitId;
1961
+ this.objectId = objectId;
1962
+ _defineProperty(this, "type", _univerjs_protocol.UnitObject.DocumentSection);
1963
+ _defineProperty(this, "subType", _univerjs_protocol.UnitAction.Edit);
1964
+ _defineProperty(this, "status", _univerjs_core.PermissionStatus.INIT);
1965
+ _defineProperty(this, "id", void 0);
1966
+ _defineProperty(this, "value", true);
1967
+ this.id = `${this.type}.${this.subType}_${unitId}_${objectId}`;
1968
+ }
1969
+ };
1970
+
1971
+ //#endregion
1972
+ //#region src/services/permission/document-permission.ts
1973
+ const DOCUMENT_UNIT_PERMISSION_ACTIONS = [
1974
+ _univerjs_protocol.UnitAction.Edit,
1975
+ _univerjs_protocol.UnitAction.Copy,
1976
+ _univerjs_protocol.UnitAction.Print,
1977
+ _univerjs_protocol.UnitAction.Export,
1978
+ _univerjs_protocol.UnitAction.Comment
1979
+ ];
1980
+ const DOCUMENT_PERMISSION_OBJECT_TYPES = /* @__PURE__ */ new Set([
1981
+ _univerjs_protocol.UnitObject.Document,
1982
+ _univerjs_protocol.UnitObject.DocumentSection,
1983
+ _univerjs_protocol.UnitObject.DocumentParagraph,
1984
+ _univerjs_protocol.UnitObject.DocumentEntity
1985
+ ]);
1986
+ const DOCUMENT_SECTION_PERMISSION_OBJECT_PREFIX = "section/";
1987
+ const DOCUMENT_PARAGRAPH_PERMISSION_OBJECT_PREFIX = "paragraph/";
1988
+ const DOCUMENT_ENTITY_PERMISSION_OBJECT_PREFIX = "entity/";
1989
+ function getDocumentSectionPermissionObjectId(segmentId, sectionId) {
1990
+ return `${DOCUMENT_SECTION_PERMISSION_OBJECT_PREFIX}${encodeURIComponent(segmentId)}/${encodeURIComponent(sectionId)}`;
1991
+ }
1992
+ function getDocumentParagraphPermissionObjectId(segmentId, paragraphId) {
1993
+ return `${DOCUMENT_PARAGRAPH_PERMISSION_OBJECT_PREFIX}${encodeURIComponent(segmentId)}/${encodeURIComponent(paragraphId)}`;
1994
+ }
1995
+ function getDocumentEntityPermissionObjectId(segmentId, entityType, entityId) {
1996
+ return `${DOCUMENT_ENTITY_PERMISSION_OBJECT_PREFIX}${encodeURIComponent(segmentId)}/${encodeURIComponent(entityType)}/${encodeURIComponent(entityId)}`;
1997
+ }
1998
+ function createDocumentPermissionPoint(unitId, objectId, action) {
1999
+ if (objectId === unitId) switch (action) {
2000
+ case _univerjs_protocol.UnitAction.Edit: return new DocumentEditablePermission(unitId);
2001
+ case _univerjs_protocol.UnitAction.Copy: return new DocumentCopyPermission(unitId);
2002
+ case _univerjs_protocol.UnitAction.Print: return new DocumentPrintPermission(unitId);
2003
+ case _univerjs_protocol.UnitAction.Export: return new DocumentExportPermission(unitId);
2004
+ case _univerjs_protocol.UnitAction.Comment: return new DocumentCommentPermission(unitId);
2005
+ default: throw new Error(`Unsupported Document permission action: ${action}`);
2006
+ }
2007
+ if (action !== _univerjs_protocol.UnitAction.Edit) throw new Error(`Document object permissions only support Edit: ${objectId}`);
2008
+ if (objectId.startsWith(DOCUMENT_SECTION_PERMISSION_OBJECT_PREFIX)) return new DocumentSectionEditPermission(unitId, objectId);
2009
+ if (objectId.startsWith(DOCUMENT_PARAGRAPH_PERMISSION_OBJECT_PREFIX)) return new DocumentParagraphEditPermission(unitId, objectId);
2010
+ if (objectId.startsWith(DOCUMENT_ENTITY_PERMISSION_OBJECT_PREFIX)) return new DocumentEntityEditPermission(unitId, objectId);
2011
+ throw new Error(`Unsupported Document permission object: ${objectId}`);
2012
+ }
2013
+ function getDocumentPermissionValue(permissionService, unitId, objectId, action) {
2014
+ var _permissionService$ge;
2015
+ return ((_permissionService$ge = permissionService.getPermissionPoint(createDocumentPermissionPoint(unitId, objectId, action).id)) === null || _permissionService$ge === void 0 ? void 0 : _permissionService$ge.value) ?? true;
2016
+ }
2017
+ function setDocumentPermissionValue(permissionService, unitId, objectId, action, value) {
2018
+ const point = createDocumentPermissionPoint(unitId, objectId, action);
2019
+ if (!permissionService.getPermissionPoint(point.id)) permissionService.addPermissionPoint(point);
2020
+ permissionService.updatePermissionPoint(point.id, value);
2021
+ }
2022
+ function clearDocumentPermissionValuesForUnit(permissionService, unitId) {
2023
+ permissionService.getAllPermissionPoint().forEach((point$, id) => {
2024
+ point$.subscribe((point) => {
2025
+ if (DOCUMENT_PERMISSION_OBJECT_TYPES.has(point.type) && "unitId" in point && point.unitId === unitId) permissionService.deletePermissionPoint(id);
2026
+ }).unsubscribe();
2027
+ });
2028
+ }
2029
+ function canEditDocumentTargets(permissionService, unitId, objectIds) {
2030
+ if (!getDocumentPermissionValue(permissionService, unitId, unitId, _univerjs_protocol.UnitAction.Edit)) return false;
2031
+ for (const objectId of objectIds) if (!getDocumentPermissionValue(permissionService, unitId, objectId, _univerjs_protocol.UnitAction.Edit)) return false;
2032
+ return true;
2033
+ }
2034
+
2035
+ //#endregion
2036
+ //#region src/commands/commands/set-document-permission.command.ts
2037
+ const SetDocumentPermissionCommand = {
2038
+ type: _univerjs_core.CommandType.COMMAND,
2039
+ id: "doc.command.set-permission",
2040
+ async handler(accessor, params) {
2041
+ if (!params || !DOCUMENT_UNIT_PERMISSION_ACTIONS.includes(params.action)) return false;
2042
+ if (params.objectId !== params.unitId && params.action !== _univerjs_protocol.UnitAction.Edit) return false;
2043
+ if (params.policy && (![
2044
+ "all",
2045
+ "owner",
2046
+ "members"
2047
+ ].includes(params.policy.edit) || params.policy.strategies.some((strategy) => !DOCUMENT_UNIT_PERMISSION_ACTIONS.includes(strategy.action) || params.objectId !== params.unitId && strategy.action !== _univerjs_protocol.UnitAction.Edit))) return false;
2048
+ const point = createDocumentPermissionPoint(params.unitId, params.objectId, params.action);
2049
+ const target = {
2050
+ unitId: params.unitId,
2051
+ objectId: params.objectId,
2052
+ objectType: point.type
2053
+ };
2054
+ const service = accessor.get(_univerjs_core.ObjectPermissionService);
2055
+ if (params.remove) await service.remove(target);
2056
+ else if (params.policy) await service.save(target, params.policy);
2057
+ else await service.setPoint(target, point, params.value);
2058
+ return true;
2059
+ }
2060
+ };
2061
+
2062
+ //#endregion
2063
+ //#region src/commands/commands/set-document-permissions.command.ts
2064
+ const SetDocumentPermissionsCommand = {
2065
+ type: _univerjs_core.CommandType.COMMAND,
2066
+ id: "doc.command.set-permissions",
2067
+ async handler(accessor, params) {
2068
+ if (!(params === null || params === void 0 ? void 0 : params.unitId) || !Array.isArray(params.changes) || !params.changes.length || params.changes.some((change) => !(change === null || change === void 0 ? void 0 : change.objectId) || change.objectId === params.unitId || change.policy !== null && (!change.policy || ![
2069
+ "all",
2070
+ "owner",
2071
+ "members"
2072
+ ].includes(change.policy.edit) || !Array.isArray(change.policy.collaborators) || !Array.isArray(change.policy.strategies) || change.policy.strategies.some((strategy) => strategy.action !== _univerjs_protocol.UnitAction.Edit)))) throw new Error("Invalid object permission batch.");
2073
+ return accessor.get(_univerjs_core.ObjectPermissionService).saveMany(params.changes.map((change) => {
2074
+ const point = createDocumentPermissionPoint(params.unitId, change.objectId, _univerjs_protocol.UnitAction.Edit);
2075
+ return {
2076
+ unitId: params.unitId,
2077
+ objectId: change.objectId,
2078
+ objectType: point.type,
2079
+ policy: change.policy
2080
+ };
2081
+ }));
2082
+ }
2083
+ };
2084
+
793
2085
  //#endregion
794
2086
  //#region src/utils/sections.ts
795
2087
  /** Returns document-level section breaks, excluding table-cell and modern-column sentinels. */
@@ -1278,6 +2570,56 @@ function executeSectionTextX(commandService, documentDataModel, textX, trigger)
1278
2570
  }));
1279
2571
  }
1280
2572
 
2573
+ //#endregion
2574
+ //#region src/services/permission/document-permission-rule.model.ts
2575
+ /**
2576
+ * Copyright 2023-present DreamNum Co., Ltd.
2577
+ *
2578
+ * Licensed under the Apache License, Version 2.0 (the "License");
2579
+ * you may not use this file except in compliance with the License.
2580
+ * You may obtain a copy of the License at
2581
+ *
2582
+ * http://www.apache.org/licenses/LICENSE-2.0
2583
+ *
2584
+ * Unless required by applicable law or agreed to in writing, software
2585
+ * distributed under the License is distributed on an "AS IS" BASIS,
2586
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2587
+ * See the License for the specific language governing permissions and
2588
+ * limitations under the License.
2589
+ */
2590
+ let DocumentPermissionRuleModel = class DocumentPermissionRuleModel extends _univerjs_core.ObjectPermissionRuleModel {
2591
+ constructor(resources) {
2592
+ super(resources, "DOC_OBJECT_PERMISSION_PLUGIN", _univerjs_core.UniverInstanceType.UNIVER_DOC, [
2593
+ _univerjs_protocol.UnitObject.DocumentSection,
2594
+ _univerjs_protocol.UnitObject.DocumentParagraph,
2595
+ _univerjs_protocol.UnitObject.DocumentEntity
2596
+ ]);
2597
+ }
2598
+ };
2599
+ DocumentPermissionRuleModel = __decorate([__decorateParam(0, _univerjs_core.IResourceManagerService)], DocumentPermissionRuleModel);
2600
+
2601
+ //#endregion
2602
+ //#region src/commands/mutations/set-document-permission-rule.mutation.ts
2603
+ const SetDocumentPermissionRuleMutation = {
2604
+ id: "doc.mutation.set-permission-rule",
2605
+ type: _univerjs_core.CommandType.MUTATION,
2606
+ handler: (accessor, params) => {
2607
+ if (!params || !accessor.get(_univerjs_core.IUniverInstanceService).getUnit(params.unitId, _univerjs_core.UniverInstanceType.UNIVER_DOC)) return false;
2608
+ return accessor.get(DocumentPermissionRuleModel).setRule(params.unitId, params.objectType, params.objectId, params.rule);
2609
+ }
2610
+ };
2611
+
2612
+ //#endregion
2613
+ //#region src/commands/mutations/set-document-permission-rules.mutation.ts
2614
+ const SetDocumentPermissionRulesMutation = {
2615
+ id: "doc.mutation.set-permission-rules",
2616
+ type: _univerjs_core.CommandType.MUTATION,
2617
+ handler: (accessor, params) => {
2618
+ if (!params || !accessor.get(_univerjs_core.IUniverInstanceService).getUnit(params.unitId, _univerjs_core.UniverInstanceType.UNIVER_DOC)) return false;
2619
+ return accessor.get(DocumentPermissionRuleModel).setRules(params.unitId, params.rules);
2620
+ }
2621
+ };
2622
+
1281
2623
  //#endregion
1282
2624
  //#region src/embed-host-anchor.ts
1283
2625
  const EMBED_DOCS_CUSTOM_BLOCK_DEFAULT_COMPONENT_KEY = "UniverEmbedDocsCustomBlock";
@@ -1439,7 +2781,7 @@ function composeActions(actions) {
1439
2781
  //#endregion
1440
2782
  //#region package.json
1441
2783
  var name = "@univerjs/docs";
1442
- var version = "1.0.0-insiders.20260813-7c9aa50";
2784
+ var version = "1.0.0";
1443
2785
 
1444
2786
  //#endregion
1445
2787
  //#region src/config/config.ts
@@ -1459,7 +2801,7 @@ var version = "1.0.0-insiders.20260813-7c9aa50";
1459
2801
  * limitations under the License.
1460
2802
  */
1461
2803
  const DOCS_PLUGIN_CONFIG_KEY = "docs.config";
1462
- const configSymbol = Symbol(DOCS_PLUGIN_CONFIG_KEY);
2804
+ const configSymbol$1 = Symbol(DOCS_PLUGIN_CONFIG_KEY);
1463
2805
  const defaultPluginConfig = {};
1464
2806
 
1465
2807
  //#endregion
@@ -1497,23 +2839,490 @@ let DocCustomRangeController = class DocCustomRangeController extends _univerjs_
1497
2839
  }
1498
2840
  return selection;
1499
2841
  }
1500
- _initSelectionChange() {
1501
- this.disposeWithMe(this._commandService.onCommandExecuted((commandInfo) => {
1502
- if (commandInfo.id === SetTextSelectionsOperation.id) {
1503
- const { unitId, ranges, isEditing } = commandInfo.params;
1504
- const doc = this._univerInstanceService.getUnit(unitId);
1505
- if (!doc) return;
1506
- const transformedRanges = ranges.map((range) => this._transformCustomRange(doc, range));
1507
- if (transformedRanges.some((range, i) => ranges[i] !== range)) this._textSelectionManagerService.replaceDocRanges(transformedRanges, void 0, isEditing);
1508
- }
1509
- }));
2842
+ _initSelectionChange() {
2843
+ this.disposeWithMe(this._commandService.onCommandExecuted((commandInfo) => {
2844
+ if (commandInfo.id === SetTextSelectionsOperation.id) {
2845
+ const { unitId, ranges, isEditing } = commandInfo.params;
2846
+ const doc = this._univerInstanceService.getUnit(unitId);
2847
+ if (!doc) return;
2848
+ const transformedRanges = ranges.map((range) => this._transformCustomRange(doc, range));
2849
+ if (transformedRanges.some((range, i) => ranges[i] !== range)) this._textSelectionManagerService.replaceDocRanges(transformedRanges, void 0, isEditing);
2850
+ }
2851
+ }));
2852
+ }
2853
+ };
2854
+ DocCustomRangeController = __decorate([
2855
+ __decorateParam(0, _univerjs_core.ICommandService),
2856
+ __decorateParam(1, (0, _univerjs_core.Inject)(DocSelectionManagerService)),
2857
+ __decorateParam(2, _univerjs_core.IUniverInstanceService)
2858
+ ], DocCustomRangeController);
2859
+
2860
+ //#endregion
2861
+ //#region src/services/permission/document-permission-resolver.ts
2862
+ const HEADER_FOOTER_REFERENCE_KEYS = [
2863
+ "defaultHeaderId",
2864
+ "defaultFooterId",
2865
+ "firstPageHeaderId",
2866
+ "firstPageFooterId",
2867
+ "evenPageHeaderId",
2868
+ "evenPageFooterId"
2869
+ ];
2870
+ const documentPermissionResolverIndexCache = /* @__PURE__ */ new WeakMap();
2871
+ function getDocumentPermissionResolverIndex(documentDataModel) {
2872
+ var _getMutationRevision, _snapshot$body;
2873
+ const mutationRevision = ((_getMutationRevision = documentDataModel.getMutationRevision) === null || _getMutationRevision === void 0 ? void 0 : _getMutationRevision.call(documentDataModel)) ?? NaN;
2874
+ const cached = documentPermissionResolverIndexCache.get(documentDataModel);
2875
+ if ((cached === null || cached === void 0 ? void 0 : cached.mutationRevision) === mutationRevision) return cached;
2876
+ const snapshot = documentDataModel.getSnapshot();
2877
+ const topLevelSections = snapshot.body ? getTopLevelSectionBreaks(snapshot.body) : [];
2878
+ const drawingSegmentIds = /* @__PURE__ */ new Map();
2879
+ const addDrawingSegments = (body, segmentId) => {
2880
+ for (const block of (body === null || body === void 0 ? void 0 : body.customBlocks) ?? []) if (!drawingSegmentIds.has(block.blockId)) drawingSegmentIds.set(block.blockId, segmentId);
2881
+ };
2882
+ addDrawingSegments(snapshot.body, "");
2883
+ Object.entries(snapshot.headers ?? {}).forEach(([segmentId, header]) => addDrawingSegments(header.body, segmentId));
2884
+ Object.entries(snapshot.footers ?? {}).forEach(([segmentId, footer]) => addDrawingSegments(footer.body, segmentId));
2885
+ Object.entries(snapshot.notes ?? {}).forEach(([segmentId, footnote]) => addDrawingSegments(footnote.body, segmentId));
2886
+ const footnoteReferenceRanges = /* @__PURE__ */ new Map();
2887
+ for (const reference of ((_snapshot$body = snapshot.body) === null || _snapshot$body === void 0 ? void 0 : _snapshot$body.customRanges) ?? []) {
2888
+ var _reference$properties;
2889
+ if ((reference.rangeType === _univerjs_core.CustomRangeType.FOOTNOTE || reference.rangeType === _univerjs_core.CustomRangeType.ENDNOTE) && typeof ((_reference$properties = reference.properties) === null || _reference$properties === void 0 ? void 0 : _reference$properties.noteId) === "string") footnoteReferenceRanges.set(reference.properties.noteId, {
2890
+ startOffset: reference.startIndex,
2891
+ endOffset: reference.endIndex + 1
2892
+ });
2893
+ }
2894
+ const index = {
2895
+ drawingSegmentIds,
2896
+ footnoteReferenceRanges,
2897
+ mutationRevision,
2898
+ segments: /* @__PURE__ */ new Map(),
2899
+ topLevelSections
2900
+ };
2901
+ documentPermissionResolverIndexCache.set(documentDataModel, index);
2902
+ return index;
2903
+ }
2904
+ function getDocumentPermissionSegmentIndex(documentDataModel, segmentId, resolverIndex = getDocumentPermissionResolverIndex(documentDataModel)) {
2905
+ var _documentDataModel$ge, _snapshot$notes;
2906
+ const cached = resolverIndex.segments.get(segmentId);
2907
+ if (cached) return cached;
2908
+ const body = ((_documentDataModel$ge = documentDataModel.getSelfOrHeaderFooterModel(segmentId)) === null || _documentDataModel$ge === void 0 ? void 0 : _documentDataModel$ge.getBody()) ?? null;
2909
+ const snapshot = documentDataModel.getSnapshot();
2910
+ const note = (_snapshot$notes = snapshot.notes) === null || _snapshot$notes === void 0 ? void 0 : _snapshot$notes[segmentId];
2911
+ const drawings = (note ? note.drawings : snapshot.drawings) ?? {};
2912
+ const entities = body == null ? [] : [
2913
+ ...(body.tables ?? []).map((item) => ({
2914
+ type: "table",
2915
+ id: item.tableId,
2916
+ startOffset: item.startIndex,
2917
+ endOffset: item.endIndex
2918
+ })),
2919
+ ...(body.customBlocks ?? []).map((item) => ({
2920
+ type: drawings[item.blockId] ? "drawing" : "custom-block",
2921
+ id: item.blockId,
2922
+ startOffset: item.startIndex,
2923
+ endOffset: item.startIndex + 1
2924
+ })),
2925
+ ...(body.blockRanges ?? []).map((item) => ({
2926
+ type: "block-range",
2927
+ id: item.blockId,
2928
+ startOffset: item.startIndex,
2929
+ endOffset: item.endIndex + 1
2930
+ })),
2931
+ ...(body.customRanges ?? []).map((item) => ({
2932
+ type: "custom-range",
2933
+ id: item.rangeId,
2934
+ startOffset: item.startIndex,
2935
+ endOffset: item.endIndex + 1
2936
+ })),
2937
+ ...(body.columnGroups ?? []).map((item) => ({
2938
+ type: "column-group",
2939
+ id: item.columnGroupId,
2940
+ startOffset: item.startIndex,
2941
+ endOffset: item.endIndex + 1
2942
+ }))
2943
+ ];
2944
+ const entityRanges = new Map(entities.map((entity) => [`${entity.type}:${entity.id}`, {
2945
+ startOffset: entity.startOffset,
2946
+ endOffset: entity.endOffset
2947
+ }]));
2948
+ for (const block of (body === null || body === void 0 ? void 0 : body.customBlocks) ?? []) {
2949
+ const range = {
2950
+ startOffset: block.startIndex,
2951
+ endOffset: block.startIndex + 1
2952
+ };
2953
+ entityRanges.set(`custom-block:${block.blockId}`, range);
2954
+ entityRanges.set(`drawing:${block.blockId}`, range);
2955
+ }
2956
+ const segmentIndex = {
2957
+ body,
2958
+ entities,
2959
+ entityRanges,
2960
+ paragraphContentStartOffsets: body == null ? /* @__PURE__ */ new Map() : (0, _univerjs_core.getParagraphContentStartOffsets)(body),
2961
+ paragraphsById: new Map(((body === null || body === void 0 ? void 0 : body.paragraphs) ?? []).filter((paragraph) => paragraph.paragraphId != null).map((paragraph) => [paragraph.paragraphId, paragraph]))
2962
+ };
2963
+ resolverIndex.segments.set(segmentId, segmentIndex);
2964
+ return segmentIndex;
2965
+ }
2966
+ function getDocumentDrawingSegmentId(documentDataModel, drawingId) {
2967
+ return getDocumentPermissionResolverIndex(documentDataModel).drawingSegmentIds.get(drawingId) ?? "";
2968
+ }
2969
+ function getDocumentEditTargetObjectIds(documentDataModel, segmentId, range) {
2970
+ const resolverIndex = getDocumentPermissionResolverIndex(documentDataModel);
2971
+ const segmentIndex = getDocumentPermissionSegmentIndex(documentDataModel, segmentId, resolverIndex);
2972
+ const { body } = segmentIndex;
2973
+ if (!body) return [];
2974
+ return [
2975
+ ...getSectionPermissionObjectIds(documentDataModel, segmentId, range, resolverIndex),
2976
+ ...getParagraphPermissionObjectIds(body, segmentId, range, segmentIndex),
2977
+ ...getEntityPermissionObjectIds(segmentId, range, segmentIndex)
2978
+ ];
2979
+ }
2980
+ function getDocumentEditTargetObjectIdsFromActions(documentDataModel, segmentId, actions) {
2981
+ const result = /* @__PURE__ */ new Set();
2982
+ if (actions == null) return [];
2983
+ const cursor = _univerjs_core.JSON1.type.readCursor(actions);
2984
+ cursor.traverse(null, () => {
2985
+ const path = cursor.getPath();
2986
+ const edit = cursor.getComponent();
2987
+ const scopedSegment = [
2988
+ "headers",
2989
+ "footers",
2990
+ "notes"
2991
+ ].includes(String(path[0])) && typeof path[1] === "string" ? path[1] : segmentId;
2992
+ if (path[0] === "notes" && typeof path[1] === "string") getSectionPermissionObjectIds(documentDataModel, path[1], {
2993
+ startOffset: 0,
2994
+ endOffset: 0
2995
+ }).forEach((objectId) => result.add(objectId));
2996
+ if (path[0] === "noteSettings") getDocumentPermissionResolverIndex(documentDataModel).topLevelSections.forEach((section) => {
2997
+ result.add(getDocumentSectionPermissionObjectId("", section.sectionId));
2998
+ });
2999
+ if (path[0] === "body" && path[1] === "sectionBreaks" && typeof path[2] === "number" && (path[3] === "noteProperties" || path[3] === "suppressEndnotes")) {
3000
+ var _documentDataModel$ge2;
3001
+ const sectionId = (_documentDataModel$ge2 = documentDataModel.getBody()) === null || _documentDataModel$ge2 === void 0 || (_documentDataModel$ge2 = _documentDataModel$ge2.sectionBreaks) === null || _documentDataModel$ge2 === void 0 || (_documentDataModel$ge2 = _documentDataModel$ge2[path[2]]) === null || _documentDataModel$ge2 === void 0 ? void 0 : _documentDataModel$ge2.sectionId;
3002
+ if (sectionId) result.add(getDocumentSectionPermissionObjectId("", sectionId));
3003
+ }
3004
+ if (path[path.length - 1] !== "body" || (edit === null || edit === void 0 ? void 0 : edit.et) !== _univerjs_core.TextX.id || !Array.isArray(edit.e) || !edit.e.every(isTextXAction)) return;
3005
+ const textActions = edit.e;
3006
+ let offset = 0;
3007
+ const addRange = (startOffset, endOffset) => {
3008
+ getDocumentEditTargetObjectIds(documentDataModel, scopedSegment, {
3009
+ startOffset,
3010
+ endOffset
3011
+ }).forEach((objectId) => result.add(objectId));
3012
+ };
3013
+ textActions.forEach((action) => {
3014
+ if (action.t === _univerjs_core.TextXActionType.INSERT) {
3015
+ addRange(offset, offset);
3016
+ return;
3017
+ }
3018
+ if (action.t === _univerjs_core.TextXActionType.DELETE) {
3019
+ addRange(offset, offset + action.len);
3020
+ offset += action.len;
3021
+ return;
3022
+ }
3023
+ if (action.body !== void 0 || action.oldBody !== void 0 || action.coverType !== void 0) addRange(offset, offset + action.len);
3024
+ offset += action.len;
3025
+ });
3026
+ });
3027
+ getDrawingIdsFromActions(actions).forEach((drawingId) => {
3028
+ var _documentDataModel$ge3, _body$customBlocks;
3029
+ result.add(getDocumentEntityPermissionObjectId(segmentId, "drawing", drawingId));
3030
+ const body = (_documentDataModel$ge3 = documentDataModel.getSelfOrHeaderFooterModel(segmentId)) === null || _documentDataModel$ge3 === void 0 ? void 0 : _documentDataModel$ge3.getBody();
3031
+ const block = body === null || body === void 0 || (_body$customBlocks = body.customBlocks) === null || _body$customBlocks === void 0 ? void 0 : _body$customBlocks.find((item) => item.blockId === drawingId);
3032
+ if (block) getSectionPermissionObjectIds(documentDataModel, segmentId, {
3033
+ startOffset: block.startIndex,
3034
+ endOffset: block.startIndex + 1
3035
+ }).forEach((objectId) => result.add(objectId));
3036
+ });
3037
+ return [...result];
3038
+ }
3039
+ function getDrawingIdsFromActions(actions) {
3040
+ const result = /* @__PURE__ */ new Set();
3041
+ const visit = (value) => {
3042
+ if (Array.isArray(value)) {
3043
+ value.forEach((item, index) => {
3044
+ if (item === "drawings" && typeof value[index + 1] === "string") result.add(value[index + 1]);
3045
+ visit(item);
3046
+ });
3047
+ return;
3048
+ }
3049
+ if (!isRecord$2(value)) return;
3050
+ Object.values(value).forEach(visit);
3051
+ };
3052
+ visit(actions);
3053
+ return [...result];
3054
+ }
3055
+ function isTextXAction(value) {
3056
+ if (!isRecord$2(value) || typeof value.len !== "number") return false;
3057
+ if (value.t === _univerjs_core.TextXActionType.INSERT) return isRecord$2(value.body);
3058
+ return value.t === _univerjs_core.TextXActionType.RETAIN || value.t === _univerjs_core.TextXActionType.DELETE;
3059
+ }
3060
+ function isRecord$2(value) {
3061
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3062
+ }
3063
+ function getDocumentEntityParentPermissionObjectIds(documentDataModel, segmentId, entityType, entityId) {
3064
+ const resolverIndex = getDocumentPermissionResolverIndex(documentDataModel);
3065
+ const range = getDocumentPermissionSegmentIndex(documentDataModel, segmentId, resolverIndex).entityRanges.get(`${entityType}:${entityId}`) ?? null;
3066
+ return range ? getSectionPermissionObjectIds(documentDataModel, segmentId, range, resolverIndex) : [];
3067
+ }
3068
+ function getDocumentParagraphParentPermissionObjectIds(documentDataModel, segmentId, paragraphId) {
3069
+ const resolverIndex = getDocumentPermissionResolverIndex(documentDataModel);
3070
+ const segmentIndex = getDocumentPermissionSegmentIndex(documentDataModel, segmentId, resolverIndex);
3071
+ const { body } = segmentIndex;
3072
+ const paragraph = segmentIndex.paragraphsById.get(paragraphId);
3073
+ if (!body || !paragraph) return [];
3074
+ return getSectionPermissionObjectIds(documentDataModel, segmentId, {
3075
+ startOffset: segmentIndex.paragraphContentStartOffsets.get(paragraph.startIndex) ?? (0, _univerjs_core.getParagraphContentStartOffset)(body, paragraph),
3076
+ endOffset: paragraph.startIndex + 1
3077
+ }, resolverIndex);
3078
+ }
3079
+ function getDocumentSectionPermissionObjectIdsByIds(sectionIds) {
3080
+ return Array.from(sectionIds, (sectionId) => getDocumentSectionPermissionObjectId("", sectionId));
3081
+ }
3082
+ function getDocumentSectionIdsAtOffset(body, offset) {
3083
+ return getSectionsIntersectingRange(getTopLevelSectionBreaks(body), {
3084
+ startOffset: offset,
3085
+ endOffset: offset
3086
+ }).map((section) => section.sectionId);
3087
+ }
3088
+ function getSectionPermissionObjectIds(documentDataModel, segmentId, range, resolverIndex = getDocumentPermissionResolverIndex(documentDataModel)) {
3089
+ if (segmentId) {
3090
+ const referenceRange = resolverIndex.footnoteReferenceRanges.get(segmentId);
3091
+ if (referenceRange) return getDocumentEditTargetObjectIds(documentDataModel, "", referenceRange);
3092
+ return getHeaderFooterOwnerSectionIds(documentDataModel, segmentId, resolverIndex.topLevelSections).map((sectionId) => getDocumentSectionPermissionObjectId("", sectionId));
3093
+ }
3094
+ return getSectionsIntersectingRange(resolverIndex.topLevelSections, range).map((section) => getDocumentSectionPermissionObjectId("", section.sectionId));
3095
+ }
3096
+ function getParagraphPermissionObjectIds(body, segmentId, range, segmentIndex) {
3097
+ const startOffset = Math.min(range.startOffset, range.endOffset);
3098
+ const endOffset = Math.max(range.startOffset, range.endOffset);
3099
+ return (body.paragraphs ?? []).filter((paragraph) => intersectsRange(segmentIndex.paragraphContentStartOffsets.get(paragraph.startIndex) ?? (0, _univerjs_core.getParagraphContentStartOffset)(body, paragraph), paragraph.startIndex + 1, startOffset, endOffset)).flatMap((paragraph) => paragraph.paragraphId ? [getDocumentParagraphPermissionObjectId(segmentId, paragraph.paragraphId)] : []);
3100
+ }
3101
+ function getEntityPermissionObjectIds(segmentId, range, segmentIndex) {
3102
+ const startOffset = Math.min(range.startOffset, range.endOffset);
3103
+ const endOffset = Math.max(range.startOffset, range.endOffset);
3104
+ return segmentIndex.entities.filter((item) => intersectsRange(item.startOffset, item.endOffset, startOffset, endOffset)).map((item) => getDocumentEntityPermissionObjectId(segmentId, item.type, item.id));
3105
+ }
3106
+ function getSectionsIntersectingRange(sections, range) {
3107
+ const startOffset = Math.min(range.startOffset, range.endOffset);
3108
+ const endOffset = Math.max(range.startOffset, range.endOffset);
3109
+ return sections.filter((section, index) => intersectsRange(index === 0 ? 0 : sections[index - 1].startIndex + 1, section.startIndex + 1, startOffset, endOffset));
3110
+ }
3111
+ function intersectsRange(targetStart, targetEnd, rangeStart, rangeEnd) {
3112
+ if (rangeStart === rangeEnd) return rangeStart >= targetStart && rangeStart < targetEnd;
3113
+ return rangeStart < targetEnd && rangeEnd > targetStart;
3114
+ }
3115
+ function getHeaderFooterOwnerSectionIds(documentDataModel, segmentId, sections = getDocumentPermissionResolverIndex(documentDataModel).topLevelSections) {
3116
+ const snapshot = documentDataModel.getSnapshot();
3117
+ const result = /* @__PURE__ */ new Set();
3118
+ sections.forEach((section, sectionIndex) => {
3119
+ if (HEADER_FOOTER_REFERENCE_KEYS.some((key) => (0, _univerjs_core.resolveSectionHeaderFooterReference)(snapshot.documentStyle, sections, sectionIndex, key).segmentId === segmentId)) result.add(section.sectionId);
3120
+ });
3121
+ return [...result];
3122
+ }
3123
+
3124
+ //#endregion
3125
+ //#region src/controllers/doc-permission.controller.ts
3126
+ const NON_EDIT_DOCUMENT_COMMAND_IDS = /* @__PURE__ */ new Set([
3127
+ SetDocumentPermissionCommand.id,
3128
+ SetDocumentPermissionsCommand.id,
3129
+ "doc.command.open-header-footer-panel",
3130
+ "doc.command.close-header-footer",
3131
+ "doc.command.select-all",
3132
+ "doc.command.set-zoom-ratio"
3133
+ ]);
3134
+ const DERIVED_DOCUMENT_MUTATION_IDS = /* @__PURE__ */ new Set(["docs-formula.mutation.set-last-values"]);
3135
+ let DocPermissionController = class DocPermissionController extends _univerjs_core.Disposable {
3136
+ constructor(_injector, _commandService, _permissionService, _univerInstanceService) {
3137
+ super();
3138
+ this._injector = _injector;
3139
+ this._commandService = _commandService;
3140
+ this._permissionService = _permissionService;
3141
+ this._univerInstanceService = _univerInstanceService;
3142
+ this._univerInstanceService.getAllUnitsForType(_univerjs_core.UniverInstanceType.UNIVER_DOC).forEach((unit) => this._registerUnitPermissionPoints(unit.getUnitId()));
3143
+ this.disposeWithMe(this._univerInstanceService.getTypeOfUnitAdded$(_univerjs_core.UniverInstanceType.UNIVER_DOC).subscribe(({ unit }) => this._registerUnitPermissionPoints(unit.getUnitId())));
3144
+ this.disposeWithMe(this._commandService.beforeCommandExecuted((commandInfo, options) => {
3145
+ this._check(commandInfo, options);
3146
+ }));
3147
+ this.disposeWithMe(this._univerInstanceService.getTypeOfUnitDisposed$(_univerjs_core.UniverInstanceType.UNIVER_DOC).subscribe((unit) => {
3148
+ this._injector.get(_univerjs_core.ObjectPermissionService).clearUnit(unit.getUnitId());
3149
+ clearDocumentPermissionValuesForUnit(this._permissionService, unit.getUnitId());
3150
+ }));
3151
+ }
3152
+ _registerUnitPermissionPoints(unitId) {
3153
+ DOCUMENT_UNIT_PERMISSION_ACTIONS.forEach((action) => {
3154
+ const point = createDocumentPermissionPoint(unitId, unitId, action);
3155
+ if (!this._permissionService.getPermissionPoint(point.id)) this._permissionService.addPermissionPoint(point);
3156
+ });
3157
+ this._injector.get(_univerjs_core.ObjectPermissionService).initializeUnit({
3158
+ unitId,
3159
+ objectId: unitId,
3160
+ objectType: _univerjs_protocol.UnitObject.Document
3161
+ });
3162
+ }
3163
+ _check(commandInfo, options) {
3164
+ var _this$_univerInstance;
3165
+ if ((options === null || options === void 0 ? void 0 : options.fromCollab) || (options === null || options === void 0 ? void 0 : options.fromChangeset)) return;
3166
+ const unitAction = getDocumentUnitAction(commandInfo.id);
3167
+ const unitId = getUnitId(commandInfo, options) ?? (unitAction ? (_this$_univerInstance = this._univerInstanceService.getCurrentUnitOfType(_univerjs_core.UniverInstanceType.UNIVER_DOC)) === null || _this$_univerInstance === void 0 ? void 0 : _this$_univerInstance.getUnitId() : void 0);
3168
+ if (!unitId || this._univerInstanceService.getUnitType(unitId) !== _univerjs_core.UniverInstanceType.UNIVER_DOC) return;
3169
+ if (unitAction) {
3170
+ if (!getDocumentPermissionValue(this._permissionService, unitId, unitId, unitAction)) {
3171
+ this._injector.get(_univerjs_core.ErrorService).emitPermissionDenied(unitId);
3172
+ throw new _univerjs_core.CustomCommandExecutionError(`Document ${_univerjs_protocol.UnitAction[unitAction]} permission denied.`);
3173
+ }
3174
+ return;
3175
+ }
3176
+ const documentDataModel = this._univerInstanceService.getUnit(unitId, _univerjs_core.UniverInstanceType.UNIVER_DOC);
3177
+ if (!documentDataModel) return;
3178
+ const targetObjectIds = this._resolveTargetObjectIds(documentDataModel, commandInfo);
3179
+ if (targetObjectIds === null) return;
3180
+ if (!canEditDocumentTargets(this._permissionService, unitId, targetObjectIds)) {
3181
+ this._injector.get(_univerjs_core.ErrorService).emitPermissionDenied(unitId, targetObjectIds);
3182
+ throw new _univerjs_core.CustomCommandExecutionError("Document edit permission denied.");
3183
+ }
3184
+ }
3185
+ _resolveTargetObjectIds(documentDataModel, commandInfo) {
3186
+ if (commandInfo.id === RichTextEditingMutation.id) {
3187
+ const params = commandInfo.params;
3188
+ return getDocumentEditTargetObjectIdsFromActions(documentDataModel, params.segmentId ?? "", params.actions);
3189
+ }
3190
+ if (commandInfo.id === DocsRenameMutation.id) return [];
3191
+ if (isDerivedDocumentMutation(commandInfo)) return null;
3192
+ const knownTargets = resolveTextTargets(documentDataModel, commandInfo) ?? resolveSectionTargets(documentDataModel, commandInfo);
3193
+ if (knownTargets) return knownTargets;
3194
+ const entityTargets = resolveEntityTargets(documentDataModel, commandInfo);
3195
+ if (entityTargets.length) return entityTargets;
3196
+ return isDocumentEditCommand(commandInfo.id) || isDocumentDataMutation(commandInfo) ? [] : null;
3197
+ }
3198
+ };
3199
+ DocPermissionController = __decorate([
3200
+ __decorateParam(0, (0, _univerjs_core.Inject)(_univerjs_core.Injector)),
3201
+ __decorateParam(1, _univerjs_core.ICommandService),
3202
+ __decorateParam(2, _univerjs_core.IPermissionService),
3203
+ __decorateParam(3, _univerjs_core.IUniverInstanceService)
3204
+ ], DocPermissionController);
3205
+ function isDocumentEditCommand(id) {
3206
+ if (NON_EDIT_DOCUMENT_COMMAND_IDS.has(id)) return false;
3207
+ return id.startsWith("doc.command.") || id.startsWith("docs.command.") || id.startsWith("doc.command-") || id.startsWith("doc.table.");
3208
+ }
3209
+ function isDocumentDataMutation(commandInfo) {
3210
+ const { id } = commandInfo;
3211
+ if (isDerivedDocumentMutation(commandInfo)) return false;
3212
+ return id.startsWith("doc.mutation.") || id.startsWith("docs.mutation.") || /^docs-[^.]+\.mutation\./.test(id);
3213
+ }
3214
+ function isDerivedDocumentMutation(commandInfo) {
3215
+ const params = isRecord$1(commandInfo.params) ? commandInfo.params : void 0;
3216
+ return DERIVED_DOCUMENT_MUTATION_IDS.has(commandInfo.id) || commandInfo.id === "doc.mutation.update-shape-data" && !!(params === null || params === void 0 ? void 0 : params.formulaLastValueGuard);
3217
+ }
3218
+ function resolveEntityTargets(documentDataModel, commandInfo) {
3219
+ const params = commandInfo.params;
3220
+ if (!isRecord$1(params)) return [];
3221
+ const result = /* @__PURE__ */ new Set();
3222
+ const add = (segmentId, entityType, entityId) => {
3223
+ result.add(getDocumentEntityPermissionObjectId(segmentId, entityType, entityId));
3224
+ getDocumentEntityParentPermissionObjectIds(documentDataModel, segmentId, entityType, entityId).forEach((objectId) => result.add(objectId));
3225
+ };
3226
+ collectEntityReferences(params).forEach(({ entityType, entityId }) => {
3227
+ const explicitSegmentId = params.segmentId;
3228
+ const segmentId = typeof explicitSegmentId === "string" ? explicitSegmentId : entityType === "drawing" || entityType === "custom-block" ? getDocumentDrawingSegmentId(documentDataModel, entityId) : "";
3229
+ add(segmentId, entityType, entityId);
3230
+ });
3231
+ return [...result];
3232
+ }
3233
+ function collectEntityReferences(value) {
3234
+ const result = /* @__PURE__ */ new Map();
3235
+ const typeByKey = {
3236
+ blockId: ["custom-block"],
3237
+ drawingId: ["drawing"],
3238
+ shapeId: ["drawing", "custom-block"],
3239
+ tableId: ["table"],
3240
+ rangeId: ["custom-range"],
3241
+ columnGroupId: ["column-group"]
3242
+ };
3243
+ const visit = (candidate, key = "") => {
3244
+ if (typeof candidate === "string") {
3245
+ var _typeByKey$key;
3246
+ (_typeByKey$key = typeByKey[key]) === null || _typeByKey$key === void 0 || _typeByKey$key.forEach((entityType) => {
3247
+ result.set(`${entityType}\u001F${candidate}`, {
3248
+ entityType,
3249
+ entityId: candidate
3250
+ });
3251
+ });
3252
+ return;
3253
+ }
3254
+ if (Array.isArray(candidate)) {
3255
+ const singularKey = key.endsWith("Ids") ? `${key.slice(0, -3)}Id` : key;
3256
+ candidate.forEach((item) => visit(item, singularKey));
3257
+ return;
3258
+ }
3259
+ if (!isRecord$1(candidate)) return;
3260
+ Object.entries(candidate).forEach(([childKey, child]) => visit(child, childKey));
3261
+ };
3262
+ visit(value);
3263
+ return [...result.values()];
3264
+ }
3265
+ function getUnitId(commandInfo, options) {
3266
+ const params = isRecord$1(commandInfo.params) ? commandInfo.params : void 0;
3267
+ return typeof (params === null || params === void 0 ? void 0 : params.unitId) === "string" ? params.unitId : typeof (options === null || options === void 0 ? void 0 : options.unitId) === "string" ? options.unitId : void 0;
3268
+ }
3269
+ function getDocumentUnitAction(commandId) {
3270
+ if (commandId === "doc.command.copy-current-paragraph" || commandId === "docs-table.command.copy-selection") return _univerjs_protocol.UnitAction.Copy;
3271
+ if (commandId === "docs.operation.print") return _univerjs_protocol.UnitAction.Print;
3272
+ if (commandId === "docs-exchange-client.operation.export-doc") return _univerjs_protocol.UnitAction.Export;
3273
+ if (commandId === "docs.operation.start-add-comment" || commandId === "docs.operation.add-drawing-comment" || commandId.startsWith("docs.command.") && commandId.includes("comment") || commandId.startsWith("thread-comment.command.") || commandId.startsWith("thread-comment.mutation.")) return _univerjs_protocol.UnitAction.Comment;
3274
+ }
3275
+ function resolveTextTargets(documentDataModel, commandInfo) {
3276
+ const { id } = commandInfo;
3277
+ if (id === InsertTextCommand.id || id === UpdateTextCommand.id) {
3278
+ const params = commandInfo.params;
3279
+ return getDocumentEditTargetObjectIds(documentDataModel, params.segmentId ?? "", params.range);
3280
+ }
3281
+ if (id === DeleteTextCommand.id) {
3282
+ const params = commandInfo.params;
3283
+ const isDeleteLeft = params.direction === _univerjs_core.DeleteDirection.LEFT;
3284
+ return getDocumentEditTargetObjectIds(documentDataModel, params.segmentId ?? "", {
3285
+ startOffset: isDeleteLeft ? params.range.startOffset - (params.len ?? 1) : params.range.startOffset,
3286
+ endOffset: isDeleteLeft ? params.range.startOffset : params.range.startOffset + (params.len ?? 1)
3287
+ });
1510
3288
  }
1511
- };
1512
- DocCustomRangeController = __decorate([
1513
- __decorateParam(0, _univerjs_core.ICommandService),
1514
- __decorateParam(1, (0, _univerjs_core.Inject)(DocSelectionManagerService)),
1515
- __decorateParam(2, _univerjs_core.IUniverInstanceService)
1516
- ], DocCustomRangeController);
3289
+ if (id === UpdateDocumentParagraphStyleCommand.id) {
3290
+ const params = commandInfo.params;
3291
+ return getDocumentEditTargetObjectIds(documentDataModel, params.segmentId ?? "", params);
3292
+ }
3293
+ return null;
3294
+ }
3295
+ function resolveSectionTargets(documentDataModel, commandInfo) {
3296
+ const { id } = commandInfo;
3297
+ if (id === UpdateDocumentSectionCommand.id) {
3298
+ const params = commandInfo.params;
3299
+ return getDocumentSectionPermissionObjectIdsByIds(params.updates.map((update) => update.sectionId));
3300
+ }
3301
+ if (id === InsertDocumentSectionBreakCommand.id || id === InsertDocumentColumnBreakCommand.id) {
3302
+ const params = commandInfo.params;
3303
+ const body = documentDataModel.getBody();
3304
+ return body ? getDocumentSectionPermissionObjectIdsByIds(getDocumentSectionIdsAtOffset(body, params.offset)) : [];
3305
+ }
3306
+ if (id === DeleteDocumentSectionBreakCommand.id) {
3307
+ const params = commandInfo.params;
3308
+ const body = documentDataModel.getBody();
3309
+ const sections = body ? getTopLevelSectionBreaks(body) : [];
3310
+ const index = sections.findIndex((section) => section.sectionId === params.sectionId);
3311
+ return getDocumentSectionPermissionObjectIdsByIds([params.sectionId, ...index >= 0 && index + 1 < sections.length ? [sections[index + 1].sectionId] : []]);
3312
+ }
3313
+ if (id === SetSectionHeaderFooterLinkCommand.id) {
3314
+ const params = commandInfo.params;
3315
+ return [getDocumentSectionPermissionObjectId("", params.sectionId)];
3316
+ }
3317
+ if (id === CreateHeaderFooterCommand.id) {
3318
+ const params = commandInfo.params;
3319
+ return params.sectionId ? [getDocumentSectionPermissionObjectId("", params.sectionId)] : [];
3320
+ }
3321
+ return null;
3322
+ }
3323
+ function isRecord$1(value) {
3324
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3325
+ }
1517
3326
 
1518
3327
  //#endregion
1519
3328
  //#region src/services/doc-block-move-validator.service.ts
@@ -1600,6 +3409,20 @@ let DocStateChangeManagerService = class DocStateChangeManagerService extends _u
1600
3409
  this._initialize();
1601
3410
  this._listenDocStateChange();
1602
3411
  }
3412
+ dispose() {
3413
+ if (this._historyTimer != null) {
3414
+ clearTimeout(this._historyTimer);
3415
+ this._historyTimer = null;
3416
+ }
3417
+ if (this._changeStateCacheTimer != null) {
3418
+ clearTimeout(this._changeStateCacheTimer);
3419
+ this._changeStateCacheTimer = null;
3420
+ }
3421
+ this._historyStateCache.clear();
3422
+ this._changeStateCache.clear();
3423
+ this._docStateChange$.complete();
3424
+ super.dispose();
3425
+ }
1603
3426
  getStateCache(unitId) {
1604
3427
  return {
1605
3428
  history: this._historyStateCache.get(unitId) ?? [],
@@ -1610,6 +3433,13 @@ let DocStateChangeManagerService = class DocStateChangeManagerService extends _u
1610
3433
  this._historyStateCache.set(unitId, cache.history);
1611
3434
  this._changeStateCache.set(unitId, cache.collaboration);
1612
3435
  }
3436
+ clearHistory(unitId) {
3437
+ this._historyStateCache.delete(unitId);
3438
+ }
3439
+ flushPendingChanges(unitId) {
3440
+ this._pushHistory(unitId);
3441
+ this._emitChangeState(unitId);
3442
+ }
1613
3443
  _setChangeState(changeState) {
1614
3444
  this._cacheChangeState(changeState, "history");
1615
3445
  this._cacheChangeState(changeState, "collaboration");
@@ -1648,18 +3478,19 @@ let DocStateChangeManagerService = class DocStateChangeManagerService extends _u
1648
3478
  const cacheStates = stateCache.get(unitId);
1649
3479
  cacheStates === null || cacheStates === void 0 || cacheStates.push(changeState);
1650
3480
  } else stateCache.set(unitId, [changeState]);
1651
- if (debounce) if (type === "history") {
1652
- if (this._historyTimer) clearTimeout(this._historyTimer);
1653
- this._historyTimer = setTimeout(() => {
1654
- cb(unitId);
1655
- }, DEBOUNCE_DELAY);
1656
- } else {
1657
- if (this._changeStateCacheTimer) clearTimeout(this._changeStateCacheTimer);
1658
- this._changeStateCacheTimer = setTimeout(() => {
1659
- cb(unitId);
1660
- }, DEBOUNCE_DELAY);
1661
- }
1662
- else cb(unitId);
3481
+ if (debounce) {
3482
+ if (type === "history") {
3483
+ if (this._historyTimer) clearTimeout(this._historyTimer);
3484
+ this._historyTimer = setTimeout(() => {
3485
+ cb(unitId);
3486
+ }, DEBOUNCE_DELAY);
3487
+ } else {
3488
+ if (this._changeStateCacheTimer) clearTimeout(this._changeStateCacheTimer);
3489
+ this._changeStateCacheTimer = setTimeout(() => {
3490
+ cb(unitId);
3491
+ }, DEBOUNCE_DELAY);
3492
+ }
3493
+ } else cb(unitId);
1663
3494
  }
1664
3495
  _pushHistory(unitId) {
1665
3496
  const undoRedoService = this._undoRedoService;
@@ -1671,6 +3502,8 @@ let DocStateChangeManagerService = class DocStateChangeManagerService extends _u
1671
3502
  const lastState = cacheStates[len - 1];
1672
3503
  const redoParams = {
1673
3504
  unitId,
3505
+ trigger: _univerjs_core.RedoCommandId,
3506
+ ...lastState.redoState.layoutState === void 0 ? {} : { layoutState: lastState.redoState.layoutState },
1674
3507
  actions: cacheStates.reduce((acc, cur) => _univerjs_core.JSONX.compose(acc, cur.redoState.actions), null),
1675
3508
  textRanges: lastState.redoState.textRanges,
1676
3509
  segmentId: lastState.segmentId,
@@ -1679,6 +3512,8 @@ let DocStateChangeManagerService = class DocStateChangeManagerService extends _u
1679
3512
  };
1680
3513
  const undoParams = {
1681
3514
  unitId,
3515
+ trigger: _univerjs_core.UndoCommandId,
3516
+ ...firstState.undoState.layoutState === void 0 ? {} : { layoutState: firstState.undoState.layoutState },
1682
3517
  actions: cacheStates.reverse().reduce((acc, cur) => _univerjs_core.JSONX.compose(acc, cur.undoState.actions), null),
1683
3518
  textRanges: firstState.undoState.textRanges,
1684
3519
  segmentId: firstState.segmentId,
@@ -1826,8 +3661,31 @@ let UniverDocsPlugin = class UniverDocsPlugin extends _univerjs_core.Plugin {
1826
3661
  this._configService.setConfig(DOCS_PLUGIN_CONFIG_KEY, rest);
1827
3662
  }
1828
3663
  onStarting() {
3664
+ this._injector.add([DocumentPermissionRuleModel]);
3665
+ this.disposeWithMe(this._injector.get(_univerjs_core.ICommandService).registerCommand(SetDocumentPermissionRuleMutation));
3666
+ this.disposeWithMe(this._injector.get(_univerjs_core.ICommandService).registerCommand(SetDocumentPermissionRulesMutation));
3667
+ this.disposeWithMe(this._injector.get(_univerjs_core.ObjectPermissionService).registerRuleModel(_univerjs_protocol.UnitObject.Document, this._injector.get(DocumentPermissionRuleModel), SetDocumentPermissionRuleMutation.id, SetDocumentPermissionRulesMutation.id));
1829
3668
  this._initializeDependencies();
1830
3669
  this._initializeCommands();
3670
+ this._initializeWordResources();
3671
+ }
3672
+ _initializeWordResources() {
3673
+ for (const pluginName of ["DOC_WORD_STYLES_PLUGIN", "DOC_NOTE_PLUGIN"]) {
3674
+ const resources = /* @__PURE__ */ new Map();
3675
+ this.disposeWithMe({ dispose: () => resources.clear() });
3676
+ this.disposeWithMe(this._injector.get(_univerjs_core.IResourceManagerService).registerPluginResource({
3677
+ pluginName,
3678
+ businesses: [_univerjs_core.UniverInstanceType.UNIVER_DOC],
3679
+ parseJson: (data) => data,
3680
+ onLoad: (unitId, data) => {
3681
+ resources.set(unitId, data);
3682
+ },
3683
+ onUnLoad: (unitId) => {
3684
+ resources.delete(unitId);
3685
+ },
3686
+ toJson: (unitId) => resources.get(unitId) ?? ""
3687
+ }));
3688
+ }
1831
3689
  }
1832
3690
  _initializeCommands() {
1833
3691
  [
@@ -1835,6 +3693,8 @@ let UniverDocsPlugin = class UniverDocsPlugin extends _univerjs_core.Plugin {
1835
3693
  DeleteTextCommand,
1836
3694
  UpdateTextCommand,
1837
3695
  CreateHeaderFooterCommand,
3696
+ SetDocumentPermissionCommand,
3697
+ SetDocumentPermissionsCommand,
1838
3698
  SetDocumentDefaultParagraphStyleCommand,
1839
3699
  SetDocumentNameCommand,
1840
3700
  SetSectionHeaderFooterLinkCommand,
@@ -1857,13 +3717,16 @@ let UniverDocsPlugin = class UniverDocsPlugin extends _univerjs_core.Plugin {
1857
3717
  [DocStateChangeManagerService],
1858
3718
  [DocBlockMoveValidatorService],
1859
3719
  [DocContentInsertService],
3720
+ [DocLayoutExecutorService],
1860
3721
  [DocTextResolverService],
1861
- [DocCustomRangeController]
3722
+ [DocCustomRangeController],
3723
+ [DocPermissionController]
1862
3724
  ].forEach((d) => this._injector.add(d));
1863
3725
  }
1864
3726
  onReady() {
1865
3727
  this._injector.get(DocStateChangeManagerService);
1866
3728
  this._injector.get(DocCustomRangeController);
3729
+ this._injector.get(DocPermissionController);
1867
3730
  }
1868
3731
  };
1869
3732
  _defineProperty(UniverDocsPlugin, "pluginName", "DOCS_PLUGIN");
@@ -1871,6 +3734,739 @@ _defineProperty(UniverDocsPlugin, "packageName", name);
1871
3734
  _defineProperty(UniverDocsPlugin, "version", version);
1872
3735
  UniverDocsPlugin = __decorate([__decorateParam(1, (0, _univerjs_core.Inject)(_univerjs_core.Injector)), __decorateParam(2, _univerjs_core.IConfigService)], UniverDocsPlugin);
1873
3736
 
3737
+ //#endregion
3738
+ //#region src/layout-worker/config/config.ts
3739
+ /**
3740
+ * Copyright 2023-present DreamNum Co., Ltd.
3741
+ *
3742
+ * Licensed under the Apache License, Version 2.0 (the "License");
3743
+ * you may not use this file except in compliance with the License.
3744
+ * You may obtain a copy of the License at
3745
+ *
3746
+ * http://www.apache.org/licenses/LICENSE-2.0
3747
+ *
3748
+ * Unless required by applicable law or agreed to in writing, software
3749
+ * distributed under the License is distributed on an "AS IS" BASIS,
3750
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3751
+ * See the License for the specific language governing permissions and
3752
+ * limitations under the License.
3753
+ */
3754
+ const DOCS_LAYOUT_WORKER_PLUGIN_CONFIG_KEY = "docs-layout-worker.config";
3755
+ const configSymbol = Symbol(DOCS_LAYOUT_WORKER_PLUGIN_CONFIG_KEY);
3756
+ const DEFAULT_DOCS_LAYOUT_WORKER_REQUEST_TIMEOUT_MS = 15e3;
3757
+ const defaultPluginDocsLayoutWorkerConfig = { requestTimeoutMs: DEFAULT_DOCS_LAYOUT_WORKER_REQUEST_TIMEOUT_MS };
3758
+
3759
+ //#endregion
3760
+ //#region src/layout-worker/document-font-metrics.ts
3761
+ /**
3762
+ * Copyright 2023-present DreamNum Co., Ltd.
3763
+ *
3764
+ * Licensed under the Apache License, Version 2.0 (the "License");
3765
+ * you may not use this file except in compliance with the License.
3766
+ * You may obtain a copy of the License at
3767
+ *
3768
+ * http://www.apache.org/licenses/LICENSE-2.0
3769
+ *
3770
+ * Unless required by applicable law or agreed to in writing, software
3771
+ * distributed under the License is distributed on an "AS IS" BASIS,
3772
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3773
+ * See the License for the specific language governing permissions and
3774
+ * limitations under the License.
3775
+ */
3776
+ /** Collect once from the snapshot, then only from mutation payloads (including JSON1 font replacements). */
3777
+ function collectDocumentFontFamilies(value, families) {
3778
+ if (value == null || typeof value !== "object") return;
3779
+ if (Array.isArray(value)) {
3780
+ for (let index = 0; index < value.length; index++) {
3781
+ const item = value[index];
3782
+ if (value[index - 1] === "ff" && item != null && typeof item === "object" && typeof item.i === "string") families.add(item.i);
3783
+ collectDocumentFontFamilies(item, families);
3784
+ }
3785
+ return;
3786
+ }
3787
+ const textStyle = value;
3788
+ if (typeof textStyle.eastAsiaFontFamily === "string" && textStyle.eastAsiaFontFamily.trim()) {
3789
+ const primary = typeof textStyle.ff === "string" && textStyle.ff.trim() ? textStyle.ff : _univerjs_core.DEFAULT_STYLES.ff;
3790
+ families.add(`${primary}, ${textStyle.eastAsiaFontFamily.trim()}`);
3791
+ families.add(`${textStyle.eastAsiaFontFamily.trim()}, ${primary}, ${textStyle.eastAsiaFontFamily.trim()}`);
3792
+ }
3793
+ for (const [key, item] of Object.entries(value)) if (key === "ff" && typeof item === "string") families.add(item);
3794
+ else collectDocumentFontFamilies(item, families);
3795
+ }
3796
+ function measureDocumentFontFamilies(families) {
3797
+ _univerjs_engine_render.FontCache.getNormalLineHeight((0, _univerjs_engine_render.getFontStyleString)());
3798
+ for (const ff of ["", ...families]) for (const bl of [_univerjs_core.BooleanNumber.FALSE, _univerjs_core.BooleanNumber.TRUE]) for (const it of [_univerjs_core.BooleanNumber.FALSE, _univerjs_core.BooleanNumber.TRUE]) _univerjs_engine_render.FontCache.getNormalLineHeight((0, _univerjs_engine_render.getFontStyleString)({
3799
+ ff,
3800
+ bl,
3801
+ it
3802
+ }));
3803
+ return _univerjs_engine_render.FontCache.getNormalLineHeightCache();
3804
+ }
3805
+
3806
+ //#endregion
3807
+ //#region src/layout-worker/font-loader.ts
3808
+ /** Owns the same explicitly supplied font faces in the rendering and layout realms. */
3809
+ var DocsLayoutFontLoader = class extends _univerjs_core.Disposable {
3810
+ constructor(..._args) {
3811
+ super(..._args);
3812
+ _defineProperty(this, "_loading", null);
3813
+ _defineProperty(this, "_fontSet", void 0);
3814
+ _defineProperty(this, "_faces", []);
3815
+ }
3816
+ load(fonts) {
3817
+ this._loading ??= this._load(fonts);
3818
+ return this._loading;
3819
+ }
3820
+ dispose() {
3821
+ for (const face of this._faces) {
3822
+ var _this$_fontSet;
3823
+ (_this$_fontSet = this._fontSet) === null || _this$_fontSet === void 0 || _this$_fontSet.delete(face);
3824
+ }
3825
+ if (this._faces.length > 0) _univerjs_engine_render.FontCache.invalidateMetrics(() => true);
3826
+ this._faces = [];
3827
+ this._fontSet = void 0;
3828
+ super.dispose();
3829
+ }
3830
+ async _load(fonts) {
3831
+ this.ensureNotDisposed();
3832
+ if (fonts.length === 0) return;
3833
+ const fontSet = typeof document === "undefined" ? globalThis.fonts : document.fonts;
3834
+ if (typeof FontFace === "undefined" || fontSet == null) throw new Error("Document layout requires FontFace support to load the configured fonts.");
3835
+ try {
3836
+ const faces = fonts.map(({ family, source, descriptors }) => {
3837
+ if (!family.trim() || (typeof source === "string" ? !source.trim() : source.byteLength === 0)) throw new TypeError("Document layout font family and source must not be empty.");
3838
+ return new FontFace(family, source, descriptors);
3839
+ });
3840
+ await Promise.all(faces.map((face) => face.load()));
3841
+ this.ensureNotDisposed();
3842
+ this._fontSet = fontSet;
3843
+ this._faces = faces;
3844
+ for (const face of faces) fontSet.add(face);
3845
+ _univerjs_engine_render.FontCache.invalidateMetrics(() => true);
3846
+ } catch (error) {
3847
+ this.dispose();
3848
+ throw error;
3849
+ }
3850
+ }
3851
+ };
3852
+
3853
+ //#endregion
3854
+ //#region src/layout-worker/performance-tracker.ts
3855
+ const PERFORMANCE_SAMPLE_LIMIT = 2048;
3856
+ function isRecord(value) {
3857
+ return typeof value === "object" && value != null;
3858
+ }
3859
+ function getRequest(message) {
3860
+ if (!isRecord(message) || typeof message.method !== "string" || !Array.isArray(message.args)) return null;
3861
+ const request = message.args[0];
3862
+ return isRecord(request) ? {
3863
+ method: message.method,
3864
+ request
3865
+ } : null;
3866
+ }
3867
+ function getPublicationResult(message) {
3868
+ if (!isRecord(message) || !isRecord(message.data)) return null;
3869
+ const result = message.data;
3870
+ if (isRecord(result.step)) return result.step;
3871
+ return result;
3872
+ }
3873
+ function createTransferMetrics() {
3874
+ return {
3875
+ mutationTransferMs: [],
3876
+ patchTransferMs: [],
3877
+ snapshotTransferMs: []
3878
+ };
3879
+ }
3880
+ var DocsLayoutWorkerPerformanceTracker = class {
3881
+ constructor() {
3882
+ _defineProperty(this, "_metrics", /* @__PURE__ */ new Map());
3883
+ }
3884
+ recordRequest(message, durationMs) {
3885
+ const requestInfo = getRequest(message);
3886
+ const unitId = requestInfo === null || requestInfo === void 0 ? void 0 : requestInfo.request.unitId;
3887
+ if (requestInfo == null || typeof unitId !== "string") return;
3888
+ if (requestInfo.method === "createSession") {
3889
+ this._append(unitId, "snapshotTransferMs", durationMs);
3890
+ return;
3891
+ }
3892
+ if (requestInfo.method === "startLayout" && Array.isArray(requestInfo.request.mutations) && requestInfo.request.mutations.length > 0) this._append(unitId, "mutationTransferMs", durationMs);
3893
+ }
3894
+ recordResponse(message, durationMs) {
3895
+ const result = getPublicationResult(message);
3896
+ if (result == null || typeof result.unitId !== "string" || result.publication == null) return;
3897
+ this._append(result.unitId, "patchTransferMs", durationMs);
3898
+ }
3899
+ getMetrics(unitId) {
3900
+ const metrics = this._metrics.get(unitId) ?? createTransferMetrics();
3901
+ return {
3902
+ mutationTransferMs: [...metrics.mutationTransferMs],
3903
+ patchTransferMs: [...metrics.patchTransferMs],
3904
+ snapshotTransferMs: [...metrics.snapshotTransferMs]
3905
+ };
3906
+ }
3907
+ reset(unitId) {
3908
+ this._metrics.delete(unitId);
3909
+ }
3910
+ resetAll() {
3911
+ this._metrics.clear();
3912
+ }
3913
+ _append(unitId, metric, durationMs) {
3914
+ const metrics = this._metrics.get(unitId) ?? createTransferMetrics();
3915
+ const samples = metrics[metric];
3916
+ samples.push(durationMs);
3917
+ if (samples.length > PERFORMANCE_SAMPLE_LIMIT) samples.splice(0, samples.length - PERFORMANCE_SAMPLE_LIMIT);
3918
+ this._metrics.set(unitId, metrics);
3919
+ }
3920
+ };
3921
+
3922
+ //#endregion
3923
+ //#region src/layout-worker/protocol.ts
3924
+ const DOCS_LAYOUT_WORKER_CHANNEL = "univer.docs-layout-worker";
3925
+
3926
+ //#endregion
3927
+ //#region src/layout-worker/worker.ts
3928
+ const FONT_PROBE_CONTENT = "Univer 文档 Worker 0123456789";
3929
+ const FONT_PROBE_STYLE = "16px Arial";
3930
+ const WORKER_LAYOUT_INTERRUPT_INTERVAL = 8;
3931
+ function yieldForWorkerMessage() {
3932
+ return new Promise((resolve) => {
3933
+ (0, _univerjs_core.requestImmediateMacroTask)(() => resolve());
3934
+ });
3935
+ }
3936
+ function createDocsLayoutWorkerMessageProtocol$1(performanceTracker) {
3937
+ return {
3938
+ send(message) {
3939
+ const startedAt = _univerjs_core.Tools.now();
3940
+ postMessage(message);
3941
+ performanceTracker.recordResponse(message, _univerjs_core.Tools.now() - startedAt);
3942
+ },
3943
+ onMessage: new rxjs.Observable((subscriber) => {
3944
+ const handler = (event) => subscriber.next(event.data);
3945
+ addEventListener("message", handler);
3946
+ return () => removeEventListener("message", handler);
3947
+ }).pipe((0, rxjs.shareReplay)({
3948
+ bufferSize: 1,
3949
+ refCount: true
3950
+ }))
3951
+ };
3952
+ }
3953
+ function getCustomRangePresentationKey(entry) {
3954
+ return JSON.stringify([entry.segmentId, entry.rangeId]);
3955
+ }
3956
+ function applyRecordPatch(target, patch) {
3957
+ if (patch == null) return;
3958
+ for (const key of patch.removals) delete target[key];
3959
+ Object.assign(target, patch.upserts);
3960
+ }
3961
+ var DocsLayoutWorkerRuntime = class {
3962
+ constructor(_performanceTracker = new DocsLayoutWorkerPerformanceTracker()) {
3963
+ this._performanceTracker = _performanceTracker;
3964
+ _defineProperty(this, "_sessions", /* @__PURE__ */ new Map());
3965
+ _defineProperty(this, "_fontLoader", new DocsLayoutFontLoader());
3966
+ _defineProperty(this, "type", "worker");
3967
+ }
3968
+ initialize(fontFaces = []) {
3969
+ return this._fontLoader.load(fontFaces);
3970
+ }
3971
+ async getCapabilities() {
3972
+ const metrics = _univerjs_engine_render.FontCache.getMeasureText(FONT_PROBE_CONTENT, FONT_PROBE_STYLE);
3973
+ return {
3974
+ protocolVersion: 5,
3975
+ executor: "worker",
3976
+ offscreenCanvas: typeof OffscreenCanvas !== "undefined",
3977
+ structuredClone: typeof structuredClone === "function",
3978
+ fontProbe: {
3979
+ content: FONT_PROBE_CONTENT,
3980
+ font: FONT_PROBE_STYLE,
3981
+ width: metrics.width,
3982
+ actualBoundingBoxAscent: metrics.actualBoundingBoxAscent,
3983
+ actualBoundingBoxDescent: metrics.actualBoundingBoxDescent
3984
+ }
3985
+ };
3986
+ }
3987
+ async recover() {
3988
+ for (const session of this._sessions.values()) for (const mount of session.layoutSessions.values()) mount.layoutSession.dispose();
3989
+ this._sessions.clear();
3990
+ }
3991
+ async createSession(request) {
3992
+ if (typeof OffscreenCanvas === "undefined") throw new Error("Document layout Worker requires OffscreenCanvas text measurement support.");
3993
+ const currentSession = this._sessions.get(request.unitId);
3994
+ if (currentSession != null && request.sessionEpoch < currentSession.sessionEpoch) return;
3995
+ this._disposeSession(request.unitId);
3996
+ _univerjs_engine_render.FontCache.setNormalLineHeightCache(request.normalFontLineHeights ?? {});
3997
+ const dataModel = new _univerjs_core.DocumentDataModel(request.snapshot);
3998
+ const localeService = new _univerjs_core.LocaleService();
3999
+ if (request.localeData != null) localeService.load({ [request.locale]: request.localeData });
4000
+ localeService.setLocale(request.locale);
4001
+ localeService.setDirection(request.direction);
4002
+ this._sessions.set(request.unitId, {
4003
+ sessionEpoch: request.sessionEpoch,
4004
+ dataModel,
4005
+ layoutSessions: /* @__PURE__ */ new Map(),
4006
+ localeService,
4007
+ modelRevision: request.modelRevision,
4008
+ customRangePresentations: /* @__PURE__ */ new Map()
4009
+ });
4010
+ }
4011
+ async startLayout(request) {
4012
+ const session = this._sessions.get(request.unitId);
4013
+ if (session == null) return { status: "not-found" };
4014
+ if (session.modelRevision !== request.baseRevision) return {
4015
+ status: "resnapshot-required",
4016
+ modelRevision: session.modelRevision
4017
+ };
4018
+ if (!this._applyMutations(session, request)) return {
4019
+ status: "resnapshot-required",
4020
+ modelRevision: session.modelRevision
4021
+ };
4022
+ _univerjs_engine_render.FontCache.setNormalLineHeightCache(request.normalFontLineHeights ?? {});
4023
+ this._updateCustomRangePresentations(session, request);
4024
+ this._applyCustomRangePresentations(session.dataModel, Array.from(session.customRangePresentations.values()));
4025
+ let mount = session.layoutSessions.get(request.mountId);
4026
+ if (mount != null && (request.mountEpoch < mount.mountEpoch || request.mountEpoch === mount.mountEpoch && request.viewportEpoch < mount.viewportEpoch)) return { status: "superseded" };
4027
+ if (mount != null && request.mountEpoch > mount.mountEpoch) {
4028
+ mount.layoutSession.dispose();
4029
+ session.layoutSessions.delete(request.mountId);
4030
+ mount = void 0;
4031
+ }
4032
+ if (mount == null) {
4033
+ const customBlockViewports = { ...request.customBlockViewports };
4034
+ applyRecordPatch(customBlockViewports, request.customBlockViewportPatch);
4035
+ mount = {
4036
+ mountId: request.mountId,
4037
+ layoutSession: new _univerjs_engine_render.DocumentLayoutSession(session.dataModel, session.localeService),
4038
+ customBlockViewports,
4039
+ metricsRevision: request.metricsRevision,
4040
+ mountEpoch: request.mountEpoch,
4041
+ viewportEpoch: request.viewportEpoch,
4042
+ activeGeneration: null,
4043
+ cancelledGeneration: null
4044
+ };
4045
+ session.layoutSessions.set(request.mountId, mount);
4046
+ } else {
4047
+ if (request.customBlockViewports != null) mount.customBlockViewports = { ...request.customBlockViewports };
4048
+ applyRecordPatch(mount.customBlockViewports, request.customBlockViewportPatch);
4049
+ mount.metricsRevision = request.metricsRevision;
4050
+ mount.viewportEpoch = request.viewportEpoch;
4051
+ }
4052
+ const generation = mount.layoutSession.start({
4053
+ waitForHyphenationPatterns: true,
4054
+ reason: request.reason,
4055
+ anchor: request.anchor,
4056
+ priorityAnchor: request.priorityAnchor,
4057
+ invalidation: request.invalidation,
4058
+ modernPageWidth: request.modernPageWidth,
4059
+ modernHorizontalMargin: request.modernHorizontalMargin
4060
+ });
4061
+ mount.activeGeneration = generation;
4062
+ mount.cancelledGeneration = null;
4063
+ return {
4064
+ status: "accepted",
4065
+ step: await this._runLayoutStep(session, mount, generation, request.budgetMs)
4066
+ };
4067
+ }
4068
+ _applyMutations(session, request) {
4069
+ for (const mutation of request.mutations) {
4070
+ if (mutation.baseRevision !== session.modelRevision || mutation.modelRevision !== mutation.baseRevision + 1) return false;
4071
+ session.dataModel.apply(mutation.actions);
4072
+ session.modelRevision = mutation.modelRevision;
4073
+ }
4074
+ if (session.modelRevision !== request.modelRevision) return false;
4075
+ if (request.mutations.length > 0) for (const mount of session.layoutSessions.values()) {
4076
+ mount.activeGeneration = null;
4077
+ mount.cancelledGeneration = null;
4078
+ mount.layoutSession.resetDataModel(session.dataModel);
4079
+ }
4080
+ return true;
4081
+ }
4082
+ _applyCustomRangePresentations(dataModel, presentations) {
4083
+ const rangeMaps = /* @__PURE__ */ new Map();
4084
+ const segmentModels = [
4085
+ ["", dataModel],
4086
+ ...dataModel.headerModelMap,
4087
+ ...dataModel.footerModelMap
4088
+ ];
4089
+ for (const [segmentId, segmentModel] of segmentModels) {
4090
+ var _segmentModel$getBody;
4091
+ const rangeMap = /* @__PURE__ */ new Map();
4092
+ for (const range of ((_segmentModel$getBody = segmentModel.getBody()) === null || _segmentModel$getBody === void 0 ? void 0 : _segmentModel$getBody.customRanges) ?? []) {
4093
+ const workerRange = range;
4094
+ delete workerRange.active;
4095
+ delete workerRange.glyphAscentEm;
4096
+ delete workerRange.glyphDescentEm;
4097
+ delete workerRange.glyphWidthEm;
4098
+ delete workerRange.show;
4099
+ if (!rangeMap.has(range.rangeId)) rangeMap.set(range.rangeId, workerRange);
4100
+ }
4101
+ rangeMaps.set(segmentId, rangeMap);
4102
+ }
4103
+ for (const { segmentId, rangeId, presentation } of presentations ?? []) {
4104
+ const rangeMap = rangeMaps.get(segmentId);
4105
+ const range = rangeMap === null || rangeMap === void 0 ? void 0 : rangeMap.get(rangeId);
4106
+ if (range != null) {
4107
+ Object.assign(range, presentation);
4108
+ rangeMap === null || rangeMap === void 0 || rangeMap.delete(rangeId);
4109
+ }
4110
+ }
4111
+ }
4112
+ _updateCustomRangePresentations(session, request) {
4113
+ var _request$customRangeP, _request$customRangeP2;
4114
+ if (request.customRangePresentations != null) {
4115
+ session.customRangePresentations.clear();
4116
+ for (const entry of request.customRangePresentations) {
4117
+ const key = getCustomRangePresentationKey(entry);
4118
+ if (!session.customRangePresentations.has(key)) session.customRangePresentations.set(key, entry);
4119
+ }
4120
+ }
4121
+ for (const removal of ((_request$customRangeP = request.customRangePresentationPatch) === null || _request$customRangeP === void 0 ? void 0 : _request$customRangeP.removals) ?? []) session.customRangePresentations.delete(getCustomRangePresentationKey(removal));
4122
+ for (const entry of ((_request$customRangeP2 = request.customRangePresentationPatch) === null || _request$customRangeP2 === void 0 ? void 0 : _request$customRangeP2.upserts) ?? []) session.customRangePresentations.set(getCustomRangePresentationKey(entry), entry);
4123
+ }
4124
+ async stepLayout(request) {
4125
+ const session = this._getSession(request.unitId);
4126
+ const mount = this._getLayoutMount(session, request);
4127
+ return await this._runLayoutStep(session, mount, request.generation, request.budgetMs);
4128
+ }
4129
+ async publishBacklog(request) {
4130
+ const session = this._getSession(request.unitId);
4131
+ const mount = this._getLayoutMount(session, request);
4132
+ return this._runWithCustomBlockViewports(session, mount, () => ({
4133
+ ...mount.layoutSession.publishBacklog(request.generation),
4134
+ unitId: request.unitId,
4135
+ mountId: request.mountId,
4136
+ mountEpoch: mount.mountEpoch,
4137
+ viewportEpoch: mount.viewportEpoch,
4138
+ modelRevision: session.modelRevision,
4139
+ metricsRevision: mount.metricsRevision
4140
+ }));
4141
+ }
4142
+ async getLayoutPage(request) {
4143
+ const session = this._getSession(request.unitId);
4144
+ const mount = this._getLayoutMount(session, request);
4145
+ return {
4146
+ ...request,
4147
+ modelRevision: session.modelRevision,
4148
+ metricsRevision: mount.metricsRevision,
4149
+ page: mount.layoutSession.getPage(request.pageIndex)
4150
+ };
4151
+ }
4152
+ async cancelLayout(request) {
4153
+ var _this$_sessions$get;
4154
+ const mount = (_this$_sessions$get = this._sessions.get(request.unitId)) === null || _this$_sessions$get === void 0 ? void 0 : _this$_sessions$get.layoutSessions.get(request.mountId);
4155
+ if ((mount === null || mount === void 0 ? void 0 : mount.mountEpoch) === request.mountEpoch && mount.viewportEpoch === request.viewportEpoch) {
4156
+ if (request.generation == null || request.generation === mount.activeGeneration) mount.cancelledGeneration = request.generation ?? mount.activeGeneration;
4157
+ mount.layoutSession.cancel(request.generation);
4158
+ }
4159
+ }
4160
+ async getPerformanceMetrics(unitId) {
4161
+ return this._performanceTracker.getMetrics(unitId);
4162
+ }
4163
+ async resetPerformanceMetrics(unitId) {
4164
+ this._performanceTracker.reset(unitId);
4165
+ }
4166
+ async disposeLayoutMount(request) {
4167
+ const session = this._sessions.get(request.unitId);
4168
+ const mount = session === null || session === void 0 ? void 0 : session.layoutSessions.get(request.mountId);
4169
+ if (session == null || mount == null || mount.mountEpoch !== request.mountEpoch || mount.viewportEpoch !== request.viewportEpoch) return;
4170
+ session.layoutSessions.delete(request.mountId);
4171
+ mount.activeGeneration = null;
4172
+ mount.layoutSession.dispose();
4173
+ }
4174
+ async disposeSession(request) {
4175
+ const session = this._sessions.get(request.unitId);
4176
+ if ((session === null || session === void 0 ? void 0 : session.sessionEpoch) !== request.sessionEpoch) return;
4177
+ this._disposeSession(request.unitId);
4178
+ this._performanceTracker.reset(request.unitId);
4179
+ }
4180
+ dispose() {
4181
+ this._fontLoader.dispose();
4182
+ for (const unitId of this._sessions.keys()) this._disposeSession(unitId);
4183
+ this._performanceTracker.resetAll();
4184
+ }
4185
+ _getSession(unitId) {
4186
+ const session = this._sessions.get(unitId);
4187
+ if (session == null) throw new Error(`Document layout Worker session not found for unit "${unitId}".`);
4188
+ return session;
4189
+ }
4190
+ _getLayoutMount(session, request) {
4191
+ const mount = session.layoutSessions.get(request.mountId);
4192
+ if (mount == null) throw new Error(`Document layout Worker mount not found: "${request.mountId}".`);
4193
+ if (mount.mountEpoch !== request.mountEpoch || mount.viewportEpoch !== request.viewportEpoch) throw new Error(`Document layout Worker rejected a stale mount publication: "${request.mountId}".`);
4194
+ return mount;
4195
+ }
4196
+ async _runLayoutStep(session, mount, generation, budgetMs) {
4197
+ const result = this._runWithCustomBlockViewports(session, mount, () => ({
4198
+ ...mount.layoutSession.step(generation, budgetMs, WORKER_LAYOUT_INTERRUPT_INTERVAL),
4199
+ unitId: session.dataModel.getUnitId(),
4200
+ mountId: mount.mountId,
4201
+ mountEpoch: mount.mountEpoch,
4202
+ viewportEpoch: mount.viewportEpoch,
4203
+ modelRevision: session.modelRevision,
4204
+ metricsRevision: mount.metricsRevision
4205
+ }));
4206
+ await yieldForWorkerMessage();
4207
+ if (mount.activeGeneration === generation && mount.cancelledGeneration !== generation) return result;
4208
+ return this._runWithCustomBlockViewports(session, mount, () => ({
4209
+ ...mount.layoutSession.step(generation, 0, 1),
4210
+ unitId: session.dataModel.getUnitId(),
4211
+ mountId: mount.mountId,
4212
+ mountEpoch: mount.mountEpoch,
4213
+ viewportEpoch: mount.viewportEpoch,
4214
+ modelRevision: session.modelRevision,
4215
+ metricsRevision: mount.metricsRevision
4216
+ }));
4217
+ }
4218
+ _runWithCustomBlockViewports(session, mount, run) {
4219
+ const unregister = (0, _univerjs_engine_render.setDocsCustomBlockRenderViewportProvider)((unitId, blockId) => unitId === session.dataModel.getUnitId() ? mount.customBlockViewports[blockId] : null);
4220
+ try {
4221
+ return run();
4222
+ } finally {
4223
+ unregister();
4224
+ }
4225
+ }
4226
+ _disposeSession(unitId) {
4227
+ const session = this._sessions.get(unitId);
4228
+ if (session == null) return;
4229
+ this._sessions.delete(unitId);
4230
+ for (const mount of session.layoutSessions.values()) {
4231
+ mount.activeGeneration = null;
4232
+ mount.layoutSession.dispose();
4233
+ }
4234
+ session.layoutSessions.clear();
4235
+ session.dataModel.dispose();
4236
+ session.localeService.dispose();
4237
+ }
4238
+ };
4239
+ var DocsLayoutWorkerChannelService = class extends _univerjs_rpc.ChannelService {
4240
+ constructor(protocol, _runtime) {
4241
+ super(protocol);
4242
+ this._runtime = _runtime;
4243
+ }
4244
+ dispose() {
4245
+ this._runtime.dispose();
4246
+ super.dispose();
4247
+ }
4248
+ };
4249
+ function startDocsLayoutWorker() {
4250
+ const performanceTracker = new DocsLayoutWorkerPerformanceTracker();
4251
+ const runtime = new DocsLayoutWorkerRuntime(performanceTracker);
4252
+ const channelService = new DocsLayoutWorkerChannelService(createDocsLayoutWorkerMessageProtocol$1(performanceTracker), runtime);
4253
+ channelService.registerChannel(DOCS_LAYOUT_WORKER_CHANNEL, (0, _univerjs_rpc.fromModule)(runtime));
4254
+ return channelService;
4255
+ }
4256
+
4257
+ //#endregion
4258
+ //#region src/layout-worker/index.ts
4259
+ const FONT_METRICS_TOLERANCE = 1;
4260
+ var DocsLayoutWorkerCapabilityError = class extends Error {
4261
+ constructor(message) {
4262
+ super(message);
4263
+ this.name = "DocsLayoutWorkerCapabilityError";
4264
+ }
4265
+ };
4266
+ function createDocsLayoutWorkerMessageProtocol(worker, performanceTracker) {
4267
+ return {
4268
+ send(message) {
4269
+ const startedAt = _univerjs_core.Tools.now();
4270
+ worker.postMessage(message);
4271
+ performanceTracker.recordRequest(message, _univerjs_core.Tools.now() - startedAt);
4272
+ },
4273
+ onMessage: new rxjs.Observable((subscriber) => {
4274
+ const handler = (event) => subscriber.next(event.data);
4275
+ worker.addEventListener("message", handler);
4276
+ return () => worker.removeEventListener("message", handler);
4277
+ }).pipe((0, rxjs.shareReplay)({
4278
+ bufferSize: 1,
4279
+ refCount: true
4280
+ }))
4281
+ };
4282
+ }
4283
+ var DocsLayoutWorkerClientService = class extends _univerjs_core.Disposable {
4284
+ constructor(_workerFactory, _requestTimeoutMs = DEFAULT_DOCS_LAYOUT_WORKER_REQUEST_TIMEOUT_MS, _fontFaces = []) {
4285
+ super();
4286
+ this._workerFactory = _workerFactory;
4287
+ this._requestTimeoutMs = _requestTimeoutMs;
4288
+ this._fontFaces = _fontFaces;
4289
+ _defineProperty(this, "type", "worker");
4290
+ _defineProperty(this, "_worker", null);
4291
+ _defineProperty(this, "_channelService", null);
4292
+ _defineProperty(this, "_runtime", null);
4293
+ _defineProperty(this, "_initialization", void 0);
4294
+ _defineProperty(this, "_initialized", false);
4295
+ _defineProperty(this, "_performanceTracker", new DocsLayoutWorkerPerformanceTracker());
4296
+ _defineProperty(this, "_fontFamilies", /* @__PURE__ */ new Map());
4297
+ _defineProperty(this, "_fontLoader", new DocsLayoutFontLoader());
4298
+ this.disposeWithMe(this._fontLoader);
4299
+ this._initialization = this._replaceRuntime();
4300
+ }
4301
+ initialize() {
4302
+ return this._initialization;
4303
+ }
4304
+ get renderingFontsReady() {
4305
+ return this._fontFaces.length > 0 ? this._initialization : void 0;
4306
+ }
4307
+ async getCapabilities() {
4308
+ await this._initialization;
4309
+ return this._getRuntime().getCapabilities();
4310
+ }
4311
+ async recover() {
4312
+ this._initialization = this._replaceRuntime();
4313
+ await this._initialization;
4314
+ }
4315
+ createSession(request) {
4316
+ const families = /* @__PURE__ */ new Set();
4317
+ collectDocumentFontFamilies(request.snapshot, families);
4318
+ this._fontFamilies.set(request.unitId, families);
4319
+ const measuredRequest = {
4320
+ ...request,
4321
+ normalFontLineHeights: measureDocumentFontFamilies(families)
4322
+ };
4323
+ if (this._initialized) return this._withTimeout(this._getRuntime().createSession(measuredRequest), "create session");
4324
+ const capturedRequest = _univerjs_core.Tools.deepClone(measuredRequest);
4325
+ return this._initialization.then(() => this._withTimeout(this._getRuntime().createSession(capturedRequest), "create session"));
4326
+ }
4327
+ async startLayout(request) {
4328
+ await this._initialization;
4329
+ const families = this._fontFamilies.get(request.unitId);
4330
+ if (families != null) collectDocumentFontFamilies(request.mutations, families);
4331
+ const measuredRequest = families == null ? request : {
4332
+ ...request,
4333
+ normalFontLineHeights: measureDocumentFontFamilies(families)
4334
+ };
4335
+ return this._withTimeout(this._getRuntime().startLayout(measuredRequest), "start layout");
4336
+ }
4337
+ async stepLayout(request) {
4338
+ await this._initialization;
4339
+ return this._withTimeout(this._getRuntime().stepLayout(request), "step layout");
4340
+ }
4341
+ async publishBacklog(request) {
4342
+ await this._initialization;
4343
+ return this._withTimeout(this._getRuntime().publishBacklog(request), "publish layout backlog");
4344
+ }
4345
+ async getLayoutPage(request) {
4346
+ await this._initialization;
4347
+ return this._withTimeout(this._getRuntime().getLayoutPage(request), "get layout page");
4348
+ }
4349
+ async cancelLayout(request) {
4350
+ await this._initialization;
4351
+ return this._withTimeout(this._getRuntime().cancelLayout(request), "cancel layout");
4352
+ }
4353
+ async getPerformanceMetrics(unitId) {
4354
+ await this._initialization;
4355
+ const workerMetrics = await this._withTimeout(this._getRuntime().getPerformanceMetrics(unitId), "read performance metrics");
4356
+ const clientMetrics = this._performanceTracker.getMetrics(unitId);
4357
+ return {
4358
+ mutationTransferMs: clientMetrics.mutationTransferMs,
4359
+ patchTransferMs: workerMetrics.patchTransferMs,
4360
+ snapshotTransferMs: clientMetrics.snapshotTransferMs
4361
+ };
4362
+ }
4363
+ async resetPerformanceMetrics(unitId) {
4364
+ await this._initialization;
4365
+ await this._withTimeout(this._getRuntime().resetPerformanceMetrics(unitId), "reset performance metrics");
4366
+ this._performanceTracker.reset(unitId);
4367
+ }
4368
+ async disposeLayoutMount(request) {
4369
+ await this._initialization;
4370
+ return this._withTimeout(this._getRuntime().disposeLayoutMount(request), "dispose layout mount");
4371
+ }
4372
+ async disposeSession(request) {
4373
+ await this._initialization;
4374
+ await this._withTimeout(this._getRuntime().disposeSession(request), "dispose session");
4375
+ this._performanceTracker.reset(request.unitId);
4376
+ this._fontFamilies.delete(request.unitId);
4377
+ }
4378
+ dispose() {
4379
+ this._disposeRuntime();
4380
+ super.dispose();
4381
+ }
4382
+ async _replaceRuntime() {
4383
+ this._initialized = false;
4384
+ this._disposeRuntime();
4385
+ await this._withTimeout(this._fontLoader.load(this._fontFaces), "load rendering fonts");
4386
+ this.ensureNotDisposed();
4387
+ const worker = this._workerFactory();
4388
+ const channelService = new _univerjs_rpc.ChannelService(createDocsLayoutWorkerMessageProtocol(worker, this._performanceTracker));
4389
+ this._worker = worker;
4390
+ this._channelService = channelService;
4391
+ this._runtime = (0, _univerjs_rpc.toModule)(channelService.requestChannel(DOCS_LAYOUT_WORKER_CHANNEL));
4392
+ try {
4393
+ await this._withTimeout(this._runtime.initialize(this._fontFaces), "load Worker fonts");
4394
+ await this._withTimeout(this._verifyCapabilities(), "verify capabilities");
4395
+ this.ensureNotDisposed();
4396
+ this._initialized = true;
4397
+ } catch (error) {
4398
+ if (this._worker === worker) this._disposeRuntime();
4399
+ throw error;
4400
+ }
4401
+ }
4402
+ _disposeRuntime() {
4403
+ var _this$_channelService, _this$_worker;
4404
+ this._fontFamilies.clear();
4405
+ this._initialized = false;
4406
+ (_this$_channelService = this._channelService) === null || _this$_channelService === void 0 || _this$_channelService.dispose();
4407
+ this._channelService = null;
4408
+ this._runtime = null;
4409
+ (_this$_worker = this._worker) === null || _this$_worker === void 0 || _this$_worker.terminate();
4410
+ this._worker = null;
4411
+ this._performanceTracker.resetAll();
4412
+ }
4413
+ _getRuntime() {
4414
+ if (this._runtime == null) throw new Error("Document layout Worker runtime is unavailable.");
4415
+ return this._runtime;
4416
+ }
4417
+ _withTimeout(task, operation) {
4418
+ let timeoutId = null;
4419
+ const timeout = new Promise((_resolve, reject) => {
4420
+ timeoutId = setTimeout(() => {
4421
+ reject(/* @__PURE__ */ new Error(`Document layout Worker timed out while attempting to ${operation}.`));
4422
+ }, this._requestTimeoutMs);
4423
+ });
4424
+ return Promise.race([task, timeout]).finally(() => {
4425
+ if (timeoutId != null) clearTimeout(timeoutId);
4426
+ });
4427
+ }
4428
+ async _verifyCapabilities() {
4429
+ const capabilities = await this._getRuntime().getCapabilities();
4430
+ if (capabilities.protocolVersion !== 5) throw new DocsLayoutWorkerCapabilityError("Document layout Worker protocol version mismatch.");
4431
+ if (!capabilities.offscreenCanvas || !capabilities.structuredClone) throw new DocsLayoutWorkerCapabilityError("Document layout Worker requires OffscreenCanvas and structured clone support.");
4432
+ const mainMetrics = _univerjs_engine_render.FontCache.getMeasureText(capabilities.fontProbe.content, capabilities.fontProbe.font);
4433
+ if ([
4434
+ [mainMetrics.width, capabilities.fontProbe.width],
4435
+ [mainMetrics.actualBoundingBoxAscent, capabilities.fontProbe.actualBoundingBoxAscent],
4436
+ [mainMetrics.actualBoundingBoxDescent, capabilities.fontProbe.actualBoundingBoxDescent]
4437
+ ].some(([mainValue, workerValue]) => !Number.isFinite(mainValue) || !Number.isFinite(workerValue) || Math.abs(mainValue - workerValue) > FONT_METRICS_TOLERANCE)) throw new DocsLayoutWorkerCapabilityError("Document layout Worker font metrics differ from the main rendering context.");
4438
+ }
4439
+ };
4440
+ let UniverDocsLayoutWorkerPlugin = class UniverDocsLayoutWorkerPlugin extends _univerjs_core.Plugin {
4441
+ constructor(_config = defaultPluginDocsLayoutWorkerConfig, _injector, _layoutExecutorService, _configService) {
4442
+ super();
4443
+ this._config = _config;
4444
+ this._injector = _injector;
4445
+ this._layoutExecutorService = _layoutExecutorService;
4446
+ this._configService = _configService;
4447
+ const { ...rest } = (0, _univerjs_core.merge)({}, defaultPluginDocsLayoutWorkerConfig, this._config);
4448
+ this._configService.setConfig(DOCS_LAYOUT_WORKER_PLUGIN_CONFIG_KEY, rest);
4449
+ }
4450
+ onStarting() {
4451
+ if (typeof this._config.workerFactory !== "function") throw new TypeError("[UniverDocsLayoutWorkerPlugin]: workerFactory is required.");
4452
+ const requestTimeoutMs = this._config.requestTimeoutMs ?? 15e3;
4453
+ if (!Number.isFinite(requestTimeoutMs) || requestTimeoutMs <= 0) throw new RangeError("[UniverDocsLayoutWorkerPlugin]: requestTimeoutMs must be a positive finite number.");
4454
+ const client = new DocsLayoutWorkerClientService(this._config.workerFactory, requestTimeoutMs, this._config.fontFaces);
4455
+ this._injector.add([DocsLayoutWorkerClientService, { useValue: client }]);
4456
+ this.disposeWithMe(client);
4457
+ this.disposeWithMe(this._layoutExecutorService.register(client));
4458
+ }
4459
+ };
4460
+ _defineProperty(UniverDocsLayoutWorkerPlugin, "pluginName", "DOCS_LAYOUT_WORKER_PLUGIN");
4461
+ _defineProperty(UniverDocsLayoutWorkerPlugin, "packageName", name);
4462
+ _defineProperty(UniverDocsLayoutWorkerPlugin, "version", version);
4463
+ UniverDocsLayoutWorkerPlugin = __decorate([
4464
+ (0, _univerjs_core.DependentOn)(UniverDocsPlugin),
4465
+ __decorateParam(1, (0, _univerjs_core.Inject)(_univerjs_core.Injector)),
4466
+ __decorateParam(2, (0, _univerjs_core.Inject)(DocLayoutExecutorService)),
4467
+ __decorateParam(3, _univerjs_core.IConfigService)
4468
+ ], UniverDocsLayoutWorkerPlugin);
4469
+
1874
4470
  //#endregion
1875
4471
  //#region src/services/doc-interceptor/interceptor-const.ts
1876
4472
  const CUSTOM_RANGE = (0, _univerjs_core.createInterceptorKey)("CUSTOM_RANGE");
@@ -1918,7 +4514,8 @@ let DocInterceptorService = class DocInterceptorService extends _univerjs_core.D
1918
4514
  }
1919
4515
  fetchThroughInterceptors(name) {
1920
4516
  const key = name;
1921
- return (0, _univerjs_core.composeInterceptors)(this._interceptorsByName.get(key) || []);
4517
+ const interceptors = this._interceptorsByName.get(key);
4518
+ return (0, _univerjs_core.composeInterceptors)(interceptors || []);
1922
4519
  }
1923
4520
  interceptDocumentViewModel(viewModel) {
1924
4521
  const disposableCollection = new _univerjs_core.DisposableCollection();
@@ -1927,6 +4524,7 @@ let DocInterceptorService = class DocInterceptorService extends _univerjs_core.D
1927
4524
  return this.fetchThroughInterceptors(DOC_INTERCEPTOR_POINT.CUSTOM_RANGE)(viewModel.getCustomRangeRaw(index), {
1928
4525
  index,
1929
4526
  unitId: viewModel.getDataModel().getUnitId(),
4527
+ body: viewModel.getDataModel().getBody(),
1930
4528
  customRanges: viewModel.getDataModel().getCustomRanges() ?? []
1931
4529
  });
1932
4530
  },
@@ -2189,18 +4787,29 @@ function normalizeTextRange(textRange) {
2189
4787
 
2190
4788
  //#endregion
2191
4789
  exports.CreateHeaderFooterCommand = CreateHeaderFooterCommand;
4790
+ exports.DOCUMENT_UNIT_PERMISSION_ACTIONS = DOCUMENT_UNIT_PERMISSION_ACTIONS;
2192
4791
  exports.DOC_INTERCEPTOR_POINT = DOC_INTERCEPTOR_POINT;
2193
4792
  exports.DOC_SELECTION_OPTION_PRESERVE_CARET = DOC_SELECTION_OPTION_PRESERVE_CARET;
2194
4793
  exports.DeleteDocumentSectionBreakCommand = DeleteDocumentSectionBreakCommand;
2195
4794
  exports.DeleteTextCommand = DeleteTextCommand;
2196
4795
  exports.DocBlockMoveValidatorService = DocBlockMoveValidatorService;
2197
4796
  exports.DocContentInsertService = DocContentInsertService;
4797
+ exports.DocHistoryAction = DocHistoryAction;
2198
4798
  Object.defineProperty(exports, 'DocInterceptorService', {
2199
4799
  enumerable: true,
2200
4800
  get: function () {
2201
4801
  return DocInterceptorService;
2202
4802
  }
2203
4803
  });
4804
+ Object.defineProperty(exports, 'DocLayoutExecutorService', {
4805
+ enumerable: true,
4806
+ get: function () {
4807
+ return DocLayoutExecutorService;
4808
+ }
4809
+ });
4810
+ exports.DocLayoutExecutorState = DocLayoutExecutorState;
4811
+ exports.DocLayoutExecutorType = DocLayoutExecutorType;
4812
+ exports.DocLayoutSessionStatus = DocLayoutSessionStatus;
2204
4813
  Object.defineProperty(exports, 'DocSelectionManagerService', {
2205
4814
  enumerable: true,
2206
4815
  get: function () {
@@ -2221,6 +4830,8 @@ Object.defineProperty(exports, 'DocStateChangeManagerService', {
2221
4830
  });
2222
4831
  exports.DocStateEmitService = DocStateEmitService;
2223
4832
  exports.DocTextResolverService = DocTextResolverService;
4833
+ exports.DocsLayoutWorkerCapabilityError = DocsLayoutWorkerCapabilityError;
4834
+ exports.DocsLayoutWorkerClientService = DocsLayoutWorkerClientService;
2224
4835
  exports.EMBED_DOCS_CUSTOM_BLOCK_DEFAULT_COMPONENT_KEY = EMBED_DOCS_CUSTOM_BLOCK_DEFAULT_COMPONENT_KEY;
2225
4836
  exports.HeaderFooterType = HeaderFooterType;
2226
4837
  exports.IDocStateChangeInterceptorService = IDocStateChangeInterceptorService;
@@ -2230,8 +4841,18 @@ exports.InsertTextCommand = InsertTextCommand;
2230
4841
  exports.RichTextEditingMutation = RichTextEditingMutation;
2231
4842
  exports.SetDocumentDefaultParagraphStyleCommand = SetDocumentDefaultParagraphStyleCommand;
2232
4843
  exports.SetDocumentNameCommand = SetDocumentNameCommand;
4844
+ exports.SetDocumentPermissionCommand = SetDocumentPermissionCommand;
4845
+ exports.SetDocumentPermissionRuleMutation = SetDocumentPermissionRuleMutation;
4846
+ exports.SetDocumentPermissionRulesMutation = SetDocumentPermissionRulesMutation;
4847
+ exports.SetDocumentPermissionsCommand = SetDocumentPermissionsCommand;
2233
4848
  exports.SetSectionHeaderFooterLinkCommand = SetSectionHeaderFooterLinkCommand;
2234
4849
  exports.SetTextSelectionsOperation = SetTextSelectionsOperation;
4850
+ Object.defineProperty(exports, 'UniverDocsLayoutWorkerPlugin', {
4851
+ enumerable: true,
4852
+ get: function () {
4853
+ return UniverDocsLayoutWorkerPlugin;
4854
+ }
4855
+ });
2235
4856
  Object.defineProperty(exports, 'UniverDocsPlugin', {
2236
4857
  enumerable: true,
2237
4858
  get: function () {
@@ -2244,10 +4865,12 @@ exports.UpdateTextCommand = UpdateTextCommand;
2244
4865
  exports.addCustomRangeBySelectionFactory = addCustomRangeBySelectionFactory;
2245
4866
  exports.addCustomRangeFactory = addCustomRangeFactory;
2246
4867
  exports.buildDocTransform = buildDocTransform;
4868
+ exports.canEditDocumentTargets = canEditDocumentTargets;
2247
4869
  exports.consumeContentInsertRange = consumeContentInsertRange;
2248
4870
  exports.createDocsCustomBlockDrawing = createDocsCustomBlockDrawing;
2249
4871
  exports.createDocsCustomBlockInsertMutation = createDocsCustomBlockInsertMutation;
2250
4872
  exports.createDocsCustomBlockRemoveMutation = createDocsCustomBlockRemoveMutation;
4873
+ exports.createDocumentPermissionPoint = createDocumentPermissionPoint;
2251
4874
  exports.createEmbedDocsCustomBlockData = createEmbedDocsCustomBlockData;
2252
4875
  exports.createInsertCustomBlockActions = createInsertCustomBlockActions;
2253
4876
  exports.createRemoveCustomBlockActions = createRemoveCustomBlockActions;
@@ -2256,6 +4879,14 @@ exports.deleteCustomRangeFactory = deleteCustomRangeFactory;
2256
4879
  exports.docDrawingPositionToTransform = docDrawingPositionToTransform;
2257
4880
  exports.generateParagraphs = generateParagraphs;
2258
4881
  exports.getContentInsertRange = getContentInsertRange;
4882
+ exports.getDocumentDrawingSegmentId = getDocumentDrawingSegmentId;
4883
+ exports.getDocumentEditTargetObjectIds = getDocumentEditTargetObjectIds;
4884
+ exports.getDocumentEntityParentPermissionObjectIds = getDocumentEntityParentPermissionObjectIds;
4885
+ exports.getDocumentEntityPermissionObjectId = getDocumentEntityPermissionObjectId;
4886
+ exports.getDocumentParagraphParentPermissionObjectIds = getDocumentParagraphParentPermissionObjectIds;
4887
+ exports.getDocumentParagraphPermissionObjectId = getDocumentParagraphPermissionObjectId;
4888
+ exports.getDocumentPermissionValue = getDocumentPermissionValue;
4889
+ exports.getDocumentSectionPermissionObjectId = getDocumentSectionPermissionObjectId;
2259
4890
  exports.getEffectiveSectionPageSetup = getEffectiveSectionPageSetup;
2260
4891
  exports.getSectionContentWidth = getSectionContentWidth;
2261
4892
  exports.getTopLevelSectionBreaks = getTopLevelSectionBreaks;
@@ -2265,5 +4896,8 @@ exports.isSheetLikeDocsCustomBlockChildType = isSheetLikeDocsCustomBlockChildTyp
2265
4896
  exports.normalizeTextRange = normalizeTextRange;
2266
4897
  exports.replaceSelectionFactory = replaceSelectionFactory;
2267
4898
  exports.resolveDocsCustomBlockSize = resolveDocsCustomBlockSize;
4899
+ exports.setDocumentPermissionValue = setDocumentPermissionValue;
2268
4900
  exports.shouldUseInlineTextSelectionForDocsCustomBlockDrawing = shouldUseInlineTextSelectionForDocsCustomBlockDrawing;
4901
+ exports.startDocsLayoutWorker = startDocsLayoutWorker;
4902
+ exports.transformDocumentTextRanges = transformDocumentTextRanges;
2269
4903
  exports.transformToDocDrawingPosition = transformToDocDrawingPosition;