@univerjs/docs 1.0.0-insiders.20260809-70eefdd → 1.0.0-rc.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 (53) hide show
  1. package/LICENSE +176 -0
  2. package/README.md +0 -1
  3. package/lib/cjs/facade.js +331 -60
  4. package/lib/cjs/index.js +2472 -102
  5. package/lib/es/facade.js +326 -62
  6. package/lib/es/index.js +2419 -85
  7. package/lib/facade.js +326 -62
  8. package/lib/index.js +2419 -85
  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 +20 -1
  14. package/lib/types/commands/mutations/doc-structure-mutation-validation.d.ts +17 -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 +15 -2
  21. package/lib/types/facade/f-document-text-range.d.ts +3 -1
  22. package/lib/types/facade/f-document.d.ts +34 -2
  23. package/lib/types/facade/f-univer.d.ts +4 -3
  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 +24 -0
  28. package/lib/types/layout-worker/document-font-metrics.d.ts +18 -0
  29. package/lib/types/layout-worker/index.d.ts +70 -0
  30. package/lib/types/layout-worker/performance-tracker.d.ts +27 -0
  31. package/lib/types/layout-worker/protocol.d.ts +35 -0
  32. package/lib/types/layout-worker/worker.d.ts +49 -0
  33. package/lib/types/services/doc-interceptor/interceptor-const.d.ts +2 -1
  34. package/lib/types/services/doc-layout-executor.service.d.ts +218 -0
  35. package/lib/types/services/doc-selection-manager.service.d.ts +7 -1
  36. package/lib/types/services/doc-skeleton-manager.service.d.ts +6 -1
  37. package/lib/types/services/doc-state-change-manager.service.d.ts +1 -0
  38. package/lib/types/services/doc-state-emit.service.d.ts +4 -0
  39. package/lib/types/services/document-layout-snapshot.d.ts +22 -0
  40. package/lib/types/services/permission/document-permission-resolver.d.ts +27 -0
  41. package/lib/types/services/permission/document-permission-rule.model.d.ts +19 -0
  42. package/lib/types/services/permission/document-permission.d.ts +35 -0
  43. package/lib/types/services/permission/permission-point/document/comment.d.ts +27 -0
  44. package/lib/types/services/permission/permission-point/document/copy.d.ts +27 -0
  45. package/lib/types/services/permission/permission-point/document/editable.d.ts +27 -0
  46. package/lib/types/services/permission/permission-point/document/export.d.ts +27 -0
  47. package/lib/types/services/permission/permission-point/document/print.d.ts +27 -0
  48. package/lib/types/services/permission/permission-point/entity/edit.d.ts +28 -0
  49. package/lib/types/services/permission/permission-point/paragraph/edit.d.ts +28 -0
  50. package/lib/types/services/permission/permission-point/section/edit.d.ts +28 -0
  51. package/lib/umd/facade.js +3 -3
  52. package/lib/umd/index.js +2 -2
  53. 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 = {
@@ -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,645 @@ 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, ...layoutSnapshot } = snapshot;
296
+ return {
297
+ ...layoutSnapshot,
298
+ ...body == null ? {} : { body: projectDocumentBody(body) },
299
+ ...headers == null ? {} : { headers: Object.fromEntries(Object.entries(headers).map(([headerId, header]) => [headerId, projectHeader(header)])) },
300
+ ...footers == null ? {} : { footers: Object.fromEntries(Object.entries(footers).map(([footerId, footer]) => [footerId, projectFooter(footer)])) }
301
+ };
302
+ }
303
+
304
+ //#endregion
305
+ //#region src/services/doc-layout-executor.service.ts
306
+ var _DocLayoutExecutorService;
307
+ let DocLayoutExecutorType = /* @__PURE__ */ function(DocLayoutExecutorType) {
308
+ DocLayoutExecutorType["MAIN_THREAD"] = "main-thread";
309
+ DocLayoutExecutorType["WORKER"] = "worker";
310
+ return DocLayoutExecutorType;
311
+ }({});
312
+ let DocLayoutSessionStatus = /* @__PURE__ */ function(DocLayoutSessionStatus) {
313
+ DocLayoutSessionStatus["ACCEPTED"] = "accepted";
314
+ DocLayoutSessionStatus["NOT_FOUND"] = "not-found";
315
+ DocLayoutSessionStatus["RESNAPSHOT_REQUIRED"] = "resnapshot-required";
316
+ DocLayoutSessionStatus["SUPERSEDED"] = "superseded";
317
+ return DocLayoutSessionStatus;
318
+ }({});
319
+ let DocLayoutExecutorState = /* @__PURE__ */ function(DocLayoutExecutorState) {
320
+ DocLayoutExecutorState["UNREGISTERED"] = "unregistered";
321
+ DocLayoutExecutorState["INITIALIZING"] = "initializing";
322
+ DocLayoutExecutorState["ACTIVE"] = "active";
323
+ DocLayoutExecutorState["RECOVERING"] = "recovering";
324
+ DocLayoutExecutorState["FAILED"] = "failed";
325
+ return DocLayoutExecutorState;
326
+ }({});
327
+ function areShallowRecordsEqual(left, right) {
328
+ const leftRecord = left;
329
+ const rightRecord = right;
330
+ const leftKeys = Object.keys(leftRecord);
331
+ const rightKeys = Object.keys(rightRecord);
332
+ return leftKeys.length === rightKeys.length && leftKeys.every((key) => leftRecord[key] === rightRecord[key]);
333
+ }
334
+ function createRecordPatch(previous, current) {
335
+ const upserts = {};
336
+ const removals = [];
337
+ for (const [key, value] of Object.entries(current)) if (previous[key] == null || !areShallowRecordsEqual(previous[key], value)) upserts[key] = value;
338
+ for (const key of Object.keys(previous)) if (current[key] == null) removals.push(key);
339
+ return {
340
+ removals,
341
+ upserts
342
+ };
343
+ }
344
+ function getCustomRangePresentationKey$1(entry) {
345
+ return JSON.stringify([entry.segmentId, entry.rangeId]);
346
+ }
347
+ function toCustomRangePresentationMap(entries) {
348
+ return new Map(entries.map((entry) => [getCustomRangePresentationKey$1(entry), entry]));
349
+ }
350
+ function createCustomRangePresentationPatch(previous, current) {
351
+ const upserts = [];
352
+ const removals = [];
353
+ for (const [key, entry] of current) {
354
+ const previousEntry = previous.get(key);
355
+ if (previousEntry == null || !areShallowRecordsEqual(previousEntry.presentation, entry.presentation)) upserts.push(entry);
356
+ }
357
+ for (const [key, entry] of previous) if (!current.has(key)) removals.push({
358
+ segmentId: entry.segmentId,
359
+ rangeId: entry.rangeId
360
+ });
361
+ return {
362
+ removals,
363
+ upserts
364
+ };
365
+ }
366
+ function isRichTextEditingMutationParams(value) {
367
+ return typeof value === "object" && value != null && "unitId" in value && typeof value.unitId === "string" && "actions" in value;
368
+ }
369
+ function collectCustomBlockViewports(dataModel) {
370
+ var _snapshot$body;
371
+ const snapshot = dataModel.getSnapshot();
372
+ const documentStyle = snapshot.documentStyle;
373
+ const viewports = {};
374
+ for (const customBlock of ((_snapshot$body = snapshot.body) === null || _snapshot$body === void 0 ? void 0 : _snapshot$body.customBlocks) ?? []) {
375
+ var _snapshot$drawings, _documentStyle$pageSi;
376
+ const drawing = (_snapshot$drawings = snapshot.drawings) === null || _snapshot$drawings === void 0 ? void 0 : _snapshot$drawings[customBlock.blockId];
377
+ if (drawing == null) continue;
378
+ const viewport = (0, _univerjs_engine_render.getDocsCustomBlockRenderViewport)(dataModel.getUnitId(), customBlock.blockId, {
379
+ fallbackHeight: drawing.docTransform.size.height ?? 0,
380
+ fallbackWidth: drawing.docTransform.size.width ?? 0,
381
+ pageMarginLeft: documentStyle.marginLeft,
382
+ pageMarginRight: documentStyle.marginRight,
383
+ pageWidth: (_documentStyle$pageSi = documentStyle.pageSize) === null || _documentStyle$pageSi === void 0 ? void 0 : _documentStyle$pageSi.width
384
+ });
385
+ if (viewport != null) viewports[customBlock.blockId] = { ...viewport };
386
+ }
387
+ return viewports;
388
+ }
389
+ let DocLayoutExecutorService = _DocLayoutExecutorService = class DocLayoutExecutorService extends _univerjs_core.Disposable {
390
+ constructor(_univerInstanceService, _commandService, _localeService, _logService) {
391
+ super();
392
+ this._univerInstanceService = _univerInstanceService;
393
+ this._commandService = _commandService;
394
+ this._localeService = _localeService;
395
+ this._logService = _logService;
396
+ _defineProperty(this, "_executor", null);
397
+ _defineProperty(this, "_executorReady", null);
398
+ _defineProperty(this, "_recoveryFailure", null);
399
+ _defineProperty(this, "_sessionEpoch", 0);
400
+ _defineProperty(this, "_sessions", /* @__PURE__ */ new Map());
401
+ _defineProperty(this, "_hydrationSamples", /* @__PURE__ */ new Map());
402
+ _defineProperty(this, "_customRangePresentationProviders", /* @__PURE__ */ new Set());
403
+ _defineProperty(this, "_executorStatus$", new rxjs.BehaviorSubject({
404
+ state: "unregistered",
405
+ executor: null,
406
+ diagnostic: null,
407
+ recoveryUnitId: null
408
+ }));
409
+ _defineProperty(this, "executorStatus$", this._executorStatus$.asObservable());
410
+ this.disposeWithMe(this._univerInstanceService.getTypeOfUnitAdded$(_univerjs_core.UniverInstanceType.UNIVER_DOC).subscribe(({ unit }) => this._createSessionIfEligible(unit)));
411
+ this.disposeWithMe(this._univerInstanceService.getTypeOfUnitDisposed$(_univerjs_core.UniverInstanceType.UNIVER_DOC).subscribe((unit) => this._disposeSession(unit.getUnitId())));
412
+ this.disposeWithMe(this._commandService.onCommandExecuted((command) => {
413
+ if (command.id !== "doc.mutation.rich-text-editing") return;
414
+ const params = command.params;
415
+ if (!isRichTextEditingMutationParams(params)) {
416
+ this._logService.warn("[DocLayoutExecutorService]: ignored malformed document mutation parameters.");
417
+ return;
418
+ }
419
+ this._enqueueCommittedMutation(params);
420
+ }));
421
+ this.disposeWithMe(this._localeService.localeChanged$.subscribe(() => {
422
+ for (const unitId of this._sessions.keys()) {
423
+ const dataModel = this._getEligibleModel(unitId);
424
+ if (dataModel != null) this._replaceSession(dataModel).catch((error) => {
425
+ this._logService.error("[DocLayoutExecutorService]: failed to refresh Worker locale.", error);
426
+ });
427
+ }
428
+ }));
429
+ }
430
+ register(executor) {
431
+ if (this._executor != null) throw new Error("A document layout executor is already registered.");
432
+ this._executor = executor;
433
+ this._recoveryFailure = null;
434
+ this._executorStatus$.next({
435
+ state: "initializing",
436
+ executor: executor.type,
437
+ diagnostic: null,
438
+ recoveryUnitId: null
439
+ });
440
+ const executorReady = executor.initialize();
441
+ this._executorReady = executorReady;
442
+ executorReady.then(() => {
443
+ if (this._executor === executor) this._executorStatus$.next({
444
+ state: "active",
445
+ executor: executor.type,
446
+ diagnostic: null,
447
+ recoveryUnitId: null
448
+ });
449
+ }).catch((error) => {
450
+ if (this._executor !== executor) return;
451
+ this._executor = null;
452
+ this._executorReady = null;
453
+ this._disposeManagedSessions();
454
+ this._sessions.clear();
455
+ const diagnostic = error instanceof Error ? error.message : String(error);
456
+ this._executorStatus$.next({
457
+ state: "failed",
458
+ executor: executor.type,
459
+ diagnostic,
460
+ recoveryUnitId: null
461
+ });
462
+ this._logService.error("[DocLayoutExecutorService]: document layout executor initialization failed.", error);
463
+ });
464
+ for (const unit of this._univerInstanceService.getAllUnitsForType(_univerjs_core.UniverInstanceType.UNIVER_DOC)) this._createSessionIfEligible(unit);
465
+ return (0, _univerjs_core.toDisposable)(() => {
466
+ if (this._executor === executor) {
467
+ this._executor = null;
468
+ this._executorReady = null;
469
+ this._disposeManagedSessions();
470
+ this._sessions.clear();
471
+ this._executorStatus$.next({
472
+ state: "unregistered",
473
+ executor: null,
474
+ diagnostic: null,
475
+ recoveryUnitId: null
476
+ });
477
+ }
478
+ });
479
+ }
480
+ getExecutor() {
481
+ return this._executor;
482
+ }
483
+ getExecutorStatus() {
484
+ return this._executorStatus$.value;
485
+ }
486
+ registerCustomRangePresentationProvider(provider) {
487
+ this._customRangePresentationProviders.add(provider);
488
+ return (0, _univerjs_core.toDisposable)(() => this._customRangePresentationProviders.delete(provider));
489
+ }
490
+ async getPerformanceMetrics(unitId) {
491
+ var _this$_executor;
492
+ const executorMetrics = await ((_this$_executor = this._executor) === null || _this$_executor === void 0 ? void 0 : _this$_executor.getPerformanceMetrics(unitId));
493
+ return {
494
+ hydrationMs: [...this._hydrationSamples.get(unitId) ?? []],
495
+ mutationTransferMs: [...(executorMetrics === null || executorMetrics === void 0 ? void 0 : executorMetrics.mutationTransferMs) ?? []],
496
+ patchTransferMs: [...(executorMetrics === null || executorMetrics === void 0 ? void 0 : executorMetrics.patchTransferMs) ?? []],
497
+ snapshotTransferMs: [...(executorMetrics === null || executorMetrics === void 0 ? void 0 : executorMetrics.snapshotTransferMs) ?? []]
498
+ };
499
+ }
500
+ async resetPerformanceMetrics(unitId) {
501
+ var _this$_executor2;
502
+ this._hydrationSamples.delete(unitId);
503
+ await ((_this$_executor2 = this._executor) === null || _this$_executor2 === void 0 ? void 0 : _this$_executor2.resetPerformanceMetrics(unitId));
504
+ }
505
+ recordHydrationDuration(unitId, durationMs) {
506
+ this._appendPerformanceSample(this._hydrationSamples, unitId, durationMs);
507
+ }
508
+ async recoverExecutor(unitId, diagnostic) {
509
+ const executor = this._requireExecutor();
510
+ this._executorStatus$.next({
511
+ state: "recovering",
512
+ executor: executor.type,
513
+ diagnostic,
514
+ recoveryUnitId: unitId
515
+ });
516
+ for (const session of this._sessions.values()) this._markSessionDisposed(session);
517
+ this._sessions.clear();
518
+ this._hydrationSamples.clear();
519
+ try {
520
+ const executorReady = executor.recover();
521
+ this._executorReady = executorReady;
522
+ await executorReady;
523
+ } catch (error) {
524
+ const recoveryDiagnostic = error instanceof Error ? error.message : String(error);
525
+ this._executor = null;
526
+ this._executorReady = null;
527
+ this._recoveryFailure = {
528
+ diagnostic: recoveryDiagnostic,
529
+ unitId
530
+ };
531
+ this._executorStatus$.next({
532
+ state: "recovering",
533
+ executor: executor.type,
534
+ diagnostic: recoveryDiagnostic,
535
+ recoveryUnitId: unitId
536
+ });
537
+ throw error;
538
+ }
539
+ }
540
+ completeRecovery(unitId) {
541
+ var _this$_recoveryFailur;
542
+ const status = this._executorStatus$.value;
543
+ if (status.state !== "recovering" || status.recoveryUnitId !== unitId) return;
544
+ const recoveryFailure = ((_this$_recoveryFailur = this._recoveryFailure) === null || _this$_recoveryFailur === void 0 ? void 0 : _this$_recoveryFailur.unitId) === unitId ? this._recoveryFailure : null;
545
+ this._recoveryFailure = null;
546
+ this._executorStatus$.next({
547
+ state: recoveryFailure == null ? "active" : "failed",
548
+ executor: status.executor,
549
+ diagnostic: (recoveryFailure === null || recoveryFailure === void 0 ? void 0 : recoveryFailure.diagnostic) ?? null,
550
+ recoveryUnitId: null
551
+ });
552
+ }
553
+ async startLayout(identity, options, budgetMs) {
554
+ const { unitId } = identity;
555
+ const executor = this._executor;
556
+ const dataModel = this._getEligibleModel(unitId);
557
+ if (executor == null || dataModel == null) return null;
558
+ let session = this._sessions.get(unitId);
559
+ if (session != null && session.sourceMutationRevision !== dataModel.getMutationRevision()) session.needsResnapshot = true;
560
+ if (session == null || session.needsResnapshot) session = await this._replaceSession(dataModel);
561
+ let result = await this._startSynchronizedLayout(executor, session, identity, options, budgetMs);
562
+ if (result.status === "not-found" || result.status === "resnapshot-required") {
563
+ session = await this._replaceSession(dataModel);
564
+ result = await this._startSynchronizedLayout(executor, session, identity, options, budgetMs);
565
+ }
566
+ return result;
567
+ }
568
+ stepLayout(request) {
569
+ return this._requireExecutor().stepLayout(request);
570
+ }
571
+ publishBacklog(request) {
572
+ return this._requireExecutor().publishBacklog(request);
573
+ }
574
+ getLayoutPage(request) {
575
+ return this._requireExecutor().getLayoutPage(request);
576
+ }
577
+ cancelLayout(request) {
578
+ const executor = this._executor;
579
+ return executor == null ? Promise.resolve() : executor.cancelLayout(request);
580
+ }
581
+ disposeLayoutMount(request) {
582
+ const executor = this._executor;
583
+ const session = this._sessions.get(request.unitId);
584
+ const latestStart = session === null || session === void 0 ? void 0 : session.latestStarts.get(request.mountId);
585
+ if ((latestStart === null || latestStart === void 0 ? void 0 : latestStart.mountEpoch) === request.mountEpoch && latestStart.viewportEpoch === request.viewportEpoch) {
586
+ session === null || session === void 0 || session.latestStarts.delete(request.mountId);
587
+ session === null || session === void 0 || session.customBlockViewportsByMount.delete(request.mountId);
588
+ }
589
+ return executor == null ? Promise.resolve() : executor.disposeLayoutMount(request);
590
+ }
591
+ dispose() {
592
+ const executor = this._executor;
593
+ if (executor != null) for (const [unitId, session] of this._sessions) {
594
+ this._markSessionDisposed(session);
595
+ executor.disposeSession({
596
+ unitId,
597
+ sessionEpoch: session.sessionEpoch
598
+ }).catch((error) => {
599
+ this._logService.error("[DocLayoutExecutorService]: failed to dispose a Worker session.", error);
600
+ });
601
+ }
602
+ this._sessions.clear();
603
+ this._executor = null;
604
+ this._executorReady = null;
605
+ this._recoveryFailure = null;
606
+ this._executorStatus$.complete();
607
+ this._customRangePresentationProviders.clear();
608
+ super.dispose();
609
+ }
610
+ _createSessionIfEligible(dataModel) {
611
+ if (this._executor == null || !this._isEligible(dataModel) || this._sessions.has(dataModel.getUnitId())) return;
612
+ this._replaceSession(dataModel).catch((error) => {
613
+ this._logService.error("[DocLayoutExecutorService]: failed to create a Worker session.", error);
614
+ });
615
+ }
616
+ _enqueueCommittedMutation(params) {
617
+ const executor = this._executor;
618
+ const dataModel = this._getEligibleModel(params.unitId);
619
+ if (executor == null || dataModel == null) return;
620
+ const session = this._sessions.get(params.unitId);
621
+ if (session == null) {
622
+ this._replaceSession(dataModel).catch((error) => {
623
+ this._logService.error("[DocLayoutExecutorService]: failed to snapshot a document mutation.", error);
624
+ });
625
+ return;
626
+ }
627
+ if (_univerjs_core.JSONX.isNoop(params.actions)) return;
628
+ const sourceMutationRevision = dataModel.getMutationRevision();
629
+ if (sourceMutationRevision !== session.sourceMutationRevision + 1) {
630
+ session.needsResnapshot = true;
631
+ return;
632
+ }
633
+ const baseRevision = session.modelRevision;
634
+ const modelRevision = baseRevision + 1;
635
+ session.modelRevision = modelRevision;
636
+ session.sourceMutationRevision = sourceMutationRevision;
637
+ session.pendingMutations.push({
638
+ baseRevision,
639
+ modelRevision,
640
+ actions: params.actions
641
+ });
642
+ }
643
+ async _startSynchronizedLayout(executor, session, identity, options, budgetMs) {
644
+ var _session$latestStarts;
645
+ const { unitId, mountId } = identity;
646
+ const startId = (((_session$latestStarts = session.latestStarts.get(mountId)) === null || _session$latestStarts === void 0 ? void 0 : _session$latestStarts.startId) ?? 0) + 1;
647
+ const startIdentity = {
648
+ startId,
649
+ mountEpoch: identity.mountEpoch,
650
+ viewportEpoch: identity.viewportEpoch
651
+ };
652
+ session.latestStarts.set(mountId, startIdentity);
653
+ const startTask = session.queue.then(async () => {
654
+ if (session.disposed || this._executor !== executor) return { status: "not-found" };
655
+ const currentModel = this._getEligibleModel(unitId);
656
+ if (currentModel == null || currentModel.getMutationRevision() !== session.sourceMutationRevision) {
657
+ session.needsResnapshot = true;
658
+ return {
659
+ status: "resnapshot-required",
660
+ modelRevision: session.workerRevision
661
+ };
662
+ }
663
+ if (session.latestStarts.get(mountId) !== startIdentity) return { status: "superseded" };
664
+ const mutations = session.pendingMutations.slice();
665
+ const projections = this._createLayoutProjectionPayload(session, identity, this._getRequiredModel(unitId));
666
+ const request = {
667
+ ...identity,
668
+ metricsRevision: startId,
669
+ baseRevision: session.workerRevision,
670
+ modelRevision: session.modelRevision,
671
+ mutations,
672
+ ...projections.request,
673
+ budgetMs,
674
+ ...options
675
+ };
676
+ const result = await executor.startLayout(request);
677
+ if (result.status === "accepted") {
678
+ session.workerRevision = request.modelRevision;
679
+ session.pendingMutations.splice(0, mutations.length);
680
+ session.customBlockViewportsByMount.set(mountId, {
681
+ mountEpoch: identity.mountEpoch,
682
+ value: projections.customBlockViewports
683
+ });
684
+ session.customRangePresentations = projections.customRangePresentations;
685
+ } else session.needsResnapshot = true;
686
+ return result;
687
+ });
688
+ session.queue = startTask.then(() => void 0, (error) => {
689
+ session.needsResnapshot = true;
690
+ this._logService.error("[DocLayoutExecutorService]: synchronized layout start failed.", error);
691
+ });
692
+ return startTask;
693
+ }
694
+ _createLayoutProjectionPayload(session, identity, dataModel) {
695
+ const customBlockViewports = collectCustomBlockViewports(dataModel);
696
+ const previousCustomBlockViewports = session.customBlockViewportsByMount.get(identity.mountId);
697
+ const customRangePresentations = this._collectCustomRangePresentations(dataModel);
698
+ const customRangePresentationMap = toCustomRangePresentationMap(customRangePresentations);
699
+ const request = {};
700
+ if (previousCustomBlockViewports == null || previousCustomBlockViewports.mountEpoch !== identity.mountEpoch) request.customBlockViewports = customBlockViewports;
701
+ else {
702
+ const patch = createRecordPatch(previousCustomBlockViewports.value, customBlockViewports);
703
+ if (patch.removals.length > 0 || Object.keys(patch.upserts).length > 0) request.customBlockViewportPatch = patch;
704
+ }
705
+ if (session.customRangePresentations == null) request.customRangePresentations = customRangePresentations;
706
+ else {
707
+ const patch = createCustomRangePresentationPatch(session.customRangePresentations, customRangePresentationMap);
708
+ if (patch.removals.length > 0 || patch.upserts.length > 0) request.customRangePresentationPatch = patch;
709
+ }
710
+ return {
711
+ request,
712
+ customBlockViewports,
713
+ customRangePresentations: customRangePresentationMap
714
+ };
715
+ }
716
+ async _replaceSession(dataModel) {
717
+ const executor = this._requireExecutor();
718
+ const unitId = dataModel.getUnitId();
719
+ const previous = this._sessions.get(unitId);
720
+ if (previous != null) this._markSessionDisposed(previous);
721
+ const modelRevision = (previous === null || previous === void 0 ? void 0 : previous.modelRevision) ?? 0;
722
+ const session = {
723
+ sessionEpoch: ++this._sessionEpoch,
724
+ modelRevision,
725
+ sourceMutationRevision: dataModel.getMutationRevision(),
726
+ workerRevision: modelRevision,
727
+ pendingMutations: [],
728
+ latestStarts: /* @__PURE__ */ new Map(),
729
+ customBlockViewportsByMount: /* @__PURE__ */ new Map(),
730
+ customRangePresentations: null,
731
+ queue: Promise.resolve(),
732
+ needsResnapshot: false,
733
+ disposed: false,
734
+ cancelPendingCreateTask: null
735
+ };
736
+ const createTask = this._createSessionOnNextMacroTask(executor, session, dataModel);
737
+ session.queue = createTask;
738
+ this._sessions.set(unitId, session);
739
+ try {
740
+ await createTask;
741
+ } catch (error) {
742
+ session.needsResnapshot = true;
743
+ throw error;
744
+ }
745
+ return session;
746
+ }
747
+ _disposeSession(unitId) {
748
+ var _this$_executor3;
749
+ const session = this._sessions.get(unitId);
750
+ if (session == null) return;
751
+ this._markSessionDisposed(session);
752
+ this._sessions.delete(unitId);
753
+ this._hydrationSamples.delete(unitId);
754
+ (_this$_executor3 = this._executor) === null || _this$_executor3 === void 0 || _this$_executor3.disposeSession({
755
+ unitId,
756
+ sessionEpoch: session.sessionEpoch
757
+ }).catch((error) => {
758
+ this._logService.error("[DocLayoutExecutorService]: failed to dispose a Worker session.", error);
759
+ });
760
+ }
761
+ _getEligibleModel(unitId) {
762
+ const dataModel = this._univerInstanceService.getUnit(unitId, _univerjs_core.UniverInstanceType.UNIVER_DOC);
763
+ return dataModel != null && this._isEligible(dataModel) ? dataModel : null;
764
+ }
765
+ _getRequiredModel(unitId) {
766
+ const dataModel = this._getEligibleModel(unitId);
767
+ if (dataModel == null) throw new Error(`Eligible document model not found for Worker layout: "${unitId}".`);
768
+ return dataModel;
769
+ }
770
+ _collectCustomRangePresentations(dataModel) {
771
+ const presentations = [];
772
+ const providers = Array.from(this._customRangePresentationProviders).reverse();
773
+ if (providers.length === 0) return presentations;
774
+ const collectSegment = (segmentId, body) => {
775
+ if (body == null) return;
776
+ const seenRangeIds = /* @__PURE__ */ new Set();
777
+ for (const range of body.customRanges ?? []) {
778
+ if (seenRangeIds.has(range.rangeId)) continue;
779
+ seenRangeIds.add(range.rangeId);
780
+ for (const provider of providers) {
781
+ const presentation = provider(dataModel.getUnitId(), range, {
782
+ segmentId,
783
+ body
784
+ });
785
+ if (presentation != null) {
786
+ presentations.push({
787
+ segmentId,
788
+ rangeId: range.rangeId,
789
+ presentation: { ...presentation }
790
+ });
791
+ break;
792
+ }
793
+ }
794
+ }
795
+ };
796
+ collectSegment("", dataModel.getBody());
797
+ for (const [segmentId, headerModel] of dataModel.headerModelMap) collectSegment(segmentId, headerModel.getBody());
798
+ for (const [segmentId, footerModel] of dataModel.footerModelMap) collectSegment(segmentId, footerModel.getBody());
799
+ return presentations;
800
+ }
801
+ _isEligible(dataModel) {
802
+ if ((0, _univerjs_core.isInternalEditorID)(dataModel.getUnitId())) return false;
803
+ const flavor = dataModel.getSnapshot().documentStyle.documentFlavor;
804
+ return flavor === _univerjs_core.DocumentFlavor.TRADITIONAL || flavor === _univerjs_core.DocumentFlavor.MODERN;
805
+ }
806
+ _requireExecutor() {
807
+ if (this._executor == null) throw new Error("No document layout executor is registered.");
808
+ return this._executor;
809
+ }
810
+ _appendPerformanceSample(target, unitId, durationMs) {
811
+ const samples = target.get(unitId) ?? [];
812
+ samples.push(durationMs);
813
+ if (samples.length > _DocLayoutExecutorService._performanceSampleLimit) samples.splice(0, samples.length - _DocLayoutExecutorService._performanceSampleLimit);
814
+ target.set(unitId, samples);
815
+ }
816
+ _createSessionOnNextMacroTask(executor, session, dataModel) {
817
+ return new Promise((resolve, reject) => {
818
+ const cancelTask = (0, _univerjs_core.requestImmediateMacroTask)(() => {
819
+ session.cancelPendingCreateTask = null;
820
+ const unitId = dataModel.getUnitId();
821
+ if (session.disposed || this._executor !== executor || this._sessions.get(unitId) !== session) {
822
+ resolve();
823
+ return;
824
+ }
825
+ const executorReady = this._executorReady;
826
+ if (executorReady == null) {
827
+ resolve();
828
+ return;
829
+ }
830
+ executorReady.then(() => {
831
+ if (session.disposed || this._executor !== executor || this._sessions.get(unitId) !== session || this._getEligibleModel(unitId) !== dataModel) {
832
+ resolve();
833
+ return;
834
+ }
835
+ session.sourceMutationRevision = dataModel.getMutationRevision();
836
+ session.workerRevision = session.modelRevision;
837
+ session.pendingMutations.length = 0;
838
+ const request = {
839
+ unitId,
840
+ sessionEpoch: session.sessionEpoch,
841
+ snapshot: createDocumentLayoutSnapshot(dataModel.getSnapshot()),
842
+ modelRevision: session.modelRevision,
843
+ locale: this._localeService.getCurrentLocale(),
844
+ localeData: this._localeService.getLocales(),
845
+ direction: this._localeService.getDirection()
846
+ };
847
+ executor.createSession(request).then(resolve, reject);
848
+ }, reject);
849
+ });
850
+ session.cancelPendingCreateTask = () => {
851
+ cancelTask();
852
+ session.cancelPendingCreateTask = null;
853
+ resolve();
854
+ };
855
+ });
856
+ }
857
+ _markSessionDisposed(session) {
858
+ var _session$cancelPendin;
859
+ session.disposed = true;
860
+ (_session$cancelPendin = session.cancelPendingCreateTask) === null || _session$cancelPendin === void 0 || _session$cancelPendin.call(session);
861
+ session.cancelPendingCreateTask = null;
862
+ }
863
+ _disposeManagedSessions() {
864
+ for (const session of this._sessions.values()) this._markSessionDisposed(session);
865
+ }
866
+ };
867
+ _defineProperty(DocLayoutExecutorService, "_performanceSampleLimit", 2048);
868
+ DocLayoutExecutorService = _DocLayoutExecutorService = __decorate([
869
+ __decorateParam(0, _univerjs_core.IUniverInstanceService),
870
+ __decorateParam(1, _univerjs_core.ICommandService),
871
+ __decorateParam(2, (0, _univerjs_core.Inject)(_univerjs_core.LocaleService)),
872
+ __decorateParam(3, _univerjs_core.ILogService)
873
+ ], DocLayoutExecutorService);
874
+
229
875
  //#endregion
230
876
  //#region src/services/doc-skeleton-manager.service.ts
231
877
  let DocSkeletonManagerService = class DocSkeletonManagerService extends _univerjs_core.RxDisposable {
232
- constructor(_context, _localeService, _univerInstanceService) {
878
+ constructor(_context, _localeService, _univerInstanceService, _docLayoutExecutorService) {
233
879
  super();
234
880
  this._context = _context;
235
881
  this._localeService = _localeService;
236
882
  this._univerInstanceService = _univerInstanceService;
883
+ this._docLayoutExecutorService = _docLayoutExecutorService;
237
884
  _defineProperty(this, "_skeleton", void 0);
238
885
  _defineProperty(this, "_docViewModel", void 0);
239
886
  _defineProperty(this, "_currentSkeleton$", new rxjs.BehaviorSubject(null));
@@ -258,12 +905,23 @@ let DocSkeletonManagerService = class DocSkeletonManagerService extends _univerj
258
905
  getViewModel() {
259
906
  return this._docViewModel;
260
907
  }
908
+ getLayoutPerformanceMetrics() {
909
+ return this._docLayoutExecutorService.getPerformanceMetrics(this._context.unitId);
910
+ }
911
+ supportsIncrementalLayout() {
912
+ var _this$_context$unit$g;
913
+ 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;
914
+ return this._docLayoutExecutorService.getExecutor() != null && !(0, _univerjs_core.isInternalEditorID)(this._context.unitId) && (documentFlavor === _univerjs_core.DocumentFlavor.TRADITIONAL || documentFlavor === _univerjs_core.DocumentFlavor.MODERN);
915
+ }
261
916
  recalculate() {
262
917
  const skeleton = this._skeleton;
263
918
  skeleton.calculate();
919
+ this._publishSkeleton(skeleton);
920
+ return skeleton;
921
+ }
922
+ _publishSkeleton(skeleton) {
264
923
  this._currentSkeletonBefore$.next(skeleton);
265
924
  this._currentSkeleton$.next(skeleton);
266
- return skeleton;
267
925
  }
268
926
  _init() {
269
927
  const documentDataModel = this._context.unit;
@@ -277,7 +935,8 @@ let DocSkeletonManagerService = class DocSkeletonManagerService extends _univerj
277
935
  this._context.unit = documentDataModel;
278
936
  } else if (!this._docViewModel) this._docViewModel = this._buildDocViewModel(documentDataModel);
279
937
  if (!this._skeleton) this._skeleton = this._buildSkeleton(this._docViewModel);
280
- this.recalculate();
938
+ if (this.supportsIncrementalLayout()) this._publishSkeleton(this._skeleton);
939
+ else this.recalculate();
281
940
  this._currentViewModel$.next(this._docViewModel);
282
941
  }
283
942
  _buildSkeleton(documentViewModel) {
@@ -287,7 +946,11 @@ let DocSkeletonManagerService = class DocSkeletonManagerService extends _univerj
287
946
  return new _univerjs_engine_render.DocumentViewModel(documentDataModel);
288
947
  }
289
948
  };
290
- DocSkeletonManagerService = __decorate([__decorateParam(1, (0, _univerjs_core.Inject)(_univerjs_core.LocaleService)), __decorateParam(2, _univerjs_core.IUniverInstanceService)], DocSkeletonManagerService);
949
+ DocSkeletonManagerService = __decorate([
950
+ __decorateParam(1, (0, _univerjs_core.Inject)(_univerjs_core.LocaleService)),
951
+ __decorateParam(2, _univerjs_core.IUniverInstanceService),
952
+ __decorateParam(3, (0, _univerjs_core.Inject)(DocLayoutExecutorService))
953
+ ], DocSkeletonManagerService);
291
954
 
292
955
  //#endregion
293
956
  //#region src/services/doc-state-emit.service.ts
@@ -307,21 +970,113 @@ var DocStateEmitService = class extends _univerjs_core.RxDisposable {
307
970
  };
308
971
 
309
972
  //#endregion
310
- //#region src/commands/mutations/core-editing.mutation.ts
311
- const RichTextEditingMutationId = "doc.mutation.rich-text-editing";
973
+ //#region src/commands/mutations/doc-structure-mutation-validation.ts
974
+ const STRUCTURAL_BODY_FIELDS = [
975
+ "paragraphs",
976
+ "sectionBreaks",
977
+ "customBlocks",
978
+ "docxRawCustomBlocks",
979
+ "docxRawBlocks",
980
+ "docxExportExcludedRanges",
981
+ "tables",
982
+ "columnGroups",
983
+ "blockRanges"
984
+ ];
985
+ const STRUCTURAL_DATA_STREAM_TOKENS = /* @__PURE__ */ new Set([
986
+ _univerjs_core.DataStreamTreeTokenType.PARAGRAPH,
987
+ _univerjs_core.DataStreamTreeTokenType.SECTION_BREAK,
988
+ _univerjs_core.DataStreamTreeTokenType.TABLE_START,
989
+ _univerjs_core.DataStreamTreeTokenType.TABLE_ROW_START,
990
+ _univerjs_core.DataStreamTreeTokenType.TABLE_CELL_START,
991
+ _univerjs_core.DataStreamTreeTokenType.TABLE_CELL_END,
992
+ _univerjs_core.DataStreamTreeTokenType.TABLE_ROW_END,
993
+ _univerjs_core.DataStreamTreeTokenType.TABLE_END,
994
+ _univerjs_core.DataStreamTreeTokenType.COLUMN_GROUP_START,
995
+ _univerjs_core.DataStreamTreeTokenType.COLUMN_START,
996
+ _univerjs_core.DataStreamTreeTokenType.COLUMN_END,
997
+ _univerjs_core.DataStreamTreeTokenType.COLUMN_GROUP_END,
998
+ _univerjs_core.DataStreamTreeTokenType.BLOCK_START,
999
+ _univerjs_core.DataStreamTreeTokenType.BLOCK_END,
1000
+ _univerjs_core.DataStreamTreeTokenType.CUSTOM_BLOCK
1001
+ ]);
1002
+ const NON_STRUCTURAL_ROOT_FIELDS = /* @__PURE__ */ new Set([
1003
+ "disabled",
1004
+ "documentStyle",
1005
+ "drawings",
1006
+ "drawingsOrder",
1007
+ "lists",
1008
+ "locale",
1009
+ "resources",
1010
+ "rev",
1011
+ "settings",
1012
+ "styles",
1013
+ "tableSource",
1014
+ "title"
1015
+ ]);
1016
+ function isRecord$3(value) {
1017
+ return typeof value === "object" && value != null && !Array.isArray(value);
1018
+ }
1019
+ function containsStructuralToken(dataStream) {
1020
+ for (let index = 0; index < dataStream.length; index++) if (STRUCTURAL_DATA_STREAM_TOKENS.has(dataStream[index])) return true;
1021
+ return false;
1022
+ }
1023
+ function isStructurePreservingBody(value) {
1024
+ if (!isRecord$3(value)) return false;
1025
+ const dataStream = value.dataStream;
1026
+ if (dataStream != null && (typeof dataStream !== "string" || containsStructuralToken(dataStream))) return false;
1027
+ return STRUCTURAL_BODY_FIELDS.every((field) => {
1028
+ const metadata = value[field];
1029
+ return metadata == null || Array.isArray(metadata) && metadata.length === 0;
1030
+ });
1031
+ }
1032
+ function isStructurePreservingTextXEdit(value) {
1033
+ if (!Array.isArray(value)) return false;
1034
+ return value.every((action) => {
1035
+ if (!isRecord$3(action) || typeof action.len !== "number" || !Number.isFinite(action.len)) return false;
1036
+ if (action.t === _univerjs_core.TextXActionType.DELETE) return true;
1037
+ if (action.t === _univerjs_core.TextXActionType.INSERT) return isStructurePreservingBody(action.body);
1038
+ return action.t === _univerjs_core.TextXActionType.RETAIN && (action.body == null || isStructurePreservingBody(action.body));
1039
+ });
1040
+ }
1041
+ function pathsEqual(left, right) {
1042
+ return left.length === right.length && left.every((item, index) => item === right[index]);
1043
+ }
1044
+ function isStructurePreservingJSONXEdit(actions, expectedPath) {
1045
+ const cursor = _univerjs_core.JSON1.type.readCursor(actions);
1046
+ let hasComponent = false;
1047
+ let isStructurePreserving = true;
1048
+ cursor.traverse(null, (component) => {
1049
+ if (!isStructurePreserving) return;
1050
+ const path = cursor.getPath();
1051
+ hasComponent = true;
1052
+ if (NON_STRUCTURAL_ROOT_FIELDS.has(String(path[0]))) return;
1053
+ const componentKeys = Object.keys(component);
1054
+ if (component.et !== _univerjs_core.TextX.id || componentKeys.some((key) => key !== "et" && key !== "e") || !pathsEqual(path, expectedPath)) {
1055
+ isStructurePreserving = false;
1056
+ return;
1057
+ }
1058
+ const edit = component.e;
1059
+ isStructurePreserving = isStructurePreservingTextXEdit(edit);
1060
+ });
1061
+ return hasComponent && isStructurePreserving;
1062
+ }
312
1063
  function getSegmentType(documentDataModel, segmentId) {
1064
+ var _documentDataModel$ge;
313
1065
  if (!segmentId) return "body";
314
1066
  const { headers, footers } = documentDataModel.getSnapshot();
315
1067
  if (headers === null || headers === void 0 ? void 0 : headers[segmentId]) return "header";
316
1068
  if (footers === null || footers === void 0 ? void 0 : footers[segmentId]) return "footer";
1069
+ if ((_documentDataModel$ge = documentDataModel.getSnapshot().notes) === null || _documentDataModel$ge === void 0 ? void 0 : _documentDataModel$ge[segmentId]) return "note";
317
1070
  return "body";
318
1071
  }
319
1072
  function assertValidDocBodyStructure(documentDataModel, segmentId) {
1073
+ var _documentDataModel$ge2;
320
1074
  const segmentModel = documentDataModel.getSelfOrHeaderFooterModel(segmentId);
321
1075
  const body = segmentModel === null || segmentModel === void 0 ? void 0 : segmentModel.getBody();
322
1076
  if (!body) return;
323
1077
  const segmentType = getSegmentType(documentDataModel, segmentId);
324
- const issues = (0, _univerjs_core.validateDocBodyStructure)(body, {
1078
+ const note = (_documentDataModel$ge2 = documentDataModel.getSnapshot().notes) === null || _documentDataModel$ge2 === void 0 ? void 0 : _documentDataModel$ge2[segmentId];
1079
+ const issues = note ? (0, _univerjs_core.validateDocumentStructure)({ notes: { [segmentId]: note } }) : (0, _univerjs_core.validateDocBodyStructure)(body, {
325
1080
  segmentType,
326
1081
  segmentId: segmentId || void 0
327
1082
  });
@@ -330,17 +1085,175 @@ function assertValidDocBodyStructure(documentDataModel, segmentId) {
330
1085
  const segmentLabel = segmentId ? `${segmentType} ${segmentId}` : segmentType;
331
1086
  throw new Error(`[DocStructure] ${segmentLabel}: ${detail}`);
332
1087
  }
1088
+ function validateDocStructureMutation(documentDataModel, segmentId, actions, undoActions) {
1089
+ const editPath = (0, _univerjs_core.getRichTextEditPath)(documentDataModel, segmentId);
1090
+ const preservesStructure = isStructurePreservingJSONXEdit(actions, editPath) && isStructurePreservingJSONXEdit(undoActions, editPath);
1091
+ let changesFootnoteStructure = false;
1092
+ const cursor = _univerjs_core.JSON1.type.readCursor(actions);
1093
+ cursor.traverse(null, (component) => {
1094
+ const path = cursor.getPath();
1095
+ if (path[0] === "notes" && (path.length <= 2 || path[2] !== "body") || path.includes("customRanges")) changesFootnoteStructure = true;
1096
+ if (component.et === _univerjs_core.TextX.id && Array.isArray(component.e)) for (const action of component.e) {
1097
+ const ranges = isRecord$3(action) && isRecord$3(action.body) ? action.body.customRanges : void 0;
1098
+ if (Array.isArray(ranges) && ranges.some((range) => isRecord$3(range) && (range.rangeType === _univerjs_core.CustomRangeType.FOOTNOTE || range.rangeType === _univerjs_core.CustomRangeType.ENDNOTE))) changesFootnoteStructure = true;
1099
+ }
1100
+ });
1101
+ if (changesFootnoteStructure) {
1102
+ const issues = (0, _univerjs_core.validateDocumentStructure)(documentDataModel.getSnapshot());
1103
+ if (issues.length > 0) throw new Error(`[DocStructure] ${issues.map((issue) => `${issue.code}@${issue.index ?? issue.segmentId ?? ""}`).join(", ")}`);
1104
+ } else if (!preservesStructure) assertValidDocBodyStructure(documentDataModel, segmentId);
1105
+ return preservesStructure && !changesFootnoteStructure;
1106
+ }
1107
+
1108
+ //#endregion
1109
+ //#region src/commands/mutations/core-editing.mutation.ts
1110
+ let DocHistoryAction = /* @__PURE__ */ function(DocHistoryAction) {
1111
+ DocHistoryAction["DeleteChart"] = "delete-chart";
1112
+ DocHistoryAction["DeleteDivider"] = "delete-divider";
1113
+ DocHistoryAction["DeleteImage"] = "delete-image";
1114
+ DocHistoryAction["DeleteShape"] = "delete-shape";
1115
+ DocHistoryAction["EditTableCell"] = "edit-table-cell";
1116
+ DocHistoryAction["FormatParagraph"] = "format-paragraph";
1117
+ DocHistoryAction["InsertCustomRange"] = "insert-custom-range";
1118
+ DocHistoryAction["UpdateImage"] = "update-image";
1119
+ DocHistoryAction["UpdatePageLayout"] = "update-page-layout";
1120
+ return DocHistoryAction;
1121
+ }({});
1122
+ function extractDocumentBodyActions(actions, segmentId) {
1123
+ if (!Array.isArray(actions)) return;
1124
+ const bodyActions = actions.indexOf("body") > -1 ? actions : actions.find((action) => Array.isArray(action) && action.indexOf("body") > -1);
1125
+ if (!Array.isArray(bodyActions)) return;
1126
+ const bodyIndex = bodyActions.indexOf("body");
1127
+ if (bodyIndex === -1) return;
1128
+ return (bodyIndex === 0 ? "" : bodyActions[bodyIndex - 1]) === segmentId ? bodyActions.slice(bodyIndex) : void 0;
1129
+ }
1130
+ /**
1131
+ * Transforms document selections through the same JSONX actions applied by a rich-text mutation.
1132
+ * Collaboration and rendering use this shared offset rule so the Main interaction window follows
1133
+ * the transformed local caret before an authoritative background layout is published.
1134
+ */
1135
+ function transformDocumentTextRanges(actions, textRanges, priority = "right") {
1136
+ if (textRanges.length === 0) return [];
1137
+ const bodyActions = extractDocumentBodyActions(actions, textRanges[0].segmentId ?? "");
1138
+ if (bodyActions == null) return textRanges;
1139
+ return textRanges.map((textRange) => {
1140
+ const startOffset = _univerjs_core.JSONX.transformPosition(bodyActions, textRange.startOffset, priority);
1141
+ const endOffset = _univerjs_core.JSONX.transformPosition(bodyActions, textRange.endOffset, priority);
1142
+ return {
1143
+ ...textRange,
1144
+ startOffset,
1145
+ endOffset,
1146
+ collapsed: startOffset === endOffset
1147
+ };
1148
+ });
1149
+ }
1150
+ function canRemoveFootnoteReference(actions, references) {
1151
+ let canRemove = false;
1152
+ const cursor = _univerjs_core.JSON1.type.readCursor(actions);
1153
+ cursor.traverse(null, (component) => {
1154
+ const path = cursor.getPath();
1155
+ if (path.length === 0) canRemove = true;
1156
+ if (canRemove || path[0] !== "body") return;
1157
+ if (path.length === 1 && component.et === _univerjs_core.TextX.id && Array.isArray(component.e)) {
1158
+ let offset = 0;
1159
+ for (const action of component.e) {
1160
+ var _action$body;
1161
+ if (action.t === _univerjs_core.TextXActionType.DELETE && references.some((reference) => offset <= reference.endIndex && offset + action.len > reference.startIndex)) {
1162
+ canRemove = true;
1163
+ return;
1164
+ }
1165
+ if (action.t === _univerjs_core.TextXActionType.RETAIN && ((_action$body = action.body) === null || _action$body === void 0 ? void 0 : _action$body.customRanges) != null) {
1166
+ canRemove = true;
1167
+ return;
1168
+ }
1169
+ if (action.t !== _univerjs_core.TextXActionType.INSERT) offset += action.len;
1170
+ }
1171
+ } else if (path.length === 1 || path[1] === "customRanges" || path[1] === "dataStream") canRemove = true;
1172
+ });
1173
+ return canRemove;
1174
+ }
1175
+ function includeFootnoteCleanup(before, actions) {
1176
+ var _before$body, _after$body;
1177
+ if (!before.notes) return actions;
1178
+ 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)) ?? [];
1179
+ if (references.length === 0 || !canRemoveFootnoteReference(actions, references)) return actions;
1180
+ const after = _univerjs_core.JSONX.apply(_univerjs_core.Tools.deepClone(before), actions);
1181
+ 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) => {
1182
+ var _range$properties;
1183
+ return (_range$properties = range.properties) === null || _range$properties === void 0 ? void 0 : _range$properties.noteId;
1184
+ }));
1185
+ let cleanup = null;
1186
+ const previousIds = new Set(references.map((reference) => {
1187
+ var _reference$properties;
1188
+ return (_reference$properties = reference.properties) === null || _reference$properties === void 0 ? void 0 : _reference$properties.noteId;
1189
+ }));
1190
+ for (const id of previousIds) {
1191
+ var _after$notes;
1192
+ 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]));
1193
+ }
1194
+ return _univerjs_core.JSONX.isNoop(cleanup) ? actions : _univerjs_core.JSONX.compose(actions, cleanup);
1195
+ }
1196
+ function applyValidatedDocumentActions(documentDataModel, segmentId, actions) {
1197
+ const before = documentDataModel.getSnapshot();
1198
+ const appliedActions = includeFootnoteCleanup(before, actions);
1199
+ const undoActions = _univerjs_core.JSONX.invertWithDoc(appliedActions, before);
1200
+ documentDataModel.apply(appliedActions);
1201
+ try {
1202
+ return {
1203
+ actions: appliedActions,
1204
+ undoActions,
1205
+ preservesStructure: validateDocStructureMutation(documentDataModel, segmentId, appliedActions, undoActions)
1206
+ };
1207
+ } catch (error) {
1208
+ documentDataModel.apply(undoActions);
1209
+ throw error;
1210
+ }
1211
+ }
1212
+ function resetDocumentViewModel(documentViewModel, documentDataModel, segmentId, actions, preservesStructure) {
1213
+ var _documentViewModel$re, _documentViewModel$re2;
1214
+ if (documentViewModel == null) return;
1215
+ 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);
1216
+ }
1217
+ function scheduleDocumentSelectionUpdate(selectionManager, params, isSync) {
1218
+ const { unitId, textRanges, trigger, noNeedSetTextRange, isEditing = true } = params;
1219
+ if (noNeedSetTextRange || textRanges == null || textRanges.length === 0 || trigger == null || isSync) return;
1220
+ const selectionTarget = {
1221
+ unitId,
1222
+ subUnitId: unitId
1223
+ };
1224
+ const currentSelection = selectionManager.getSelectionInfo(selectionTarget);
1225
+ const logicalTextRanges = textRanges.map((textRange, index) => ({
1226
+ ...textRange,
1227
+ segmentId: textRange.segmentId ?? params.segmentId ?? "",
1228
+ collapsed: textRange.startOffset === textRange.endOffset,
1229
+ isActive: index === textRanges.length - 1
1230
+ }));
1231
+ if (currentSelection != null) selectionManager.replaceSelectionInfoWithoutRefresh({
1232
+ ...currentSelection,
1233
+ segmentId: logicalTextRanges[logicalTextRanges.length - 1].segmentId,
1234
+ textRanges: logicalTextRanges,
1235
+ rectRanges: [],
1236
+ isEditing,
1237
+ options: params.options
1238
+ }, selectionTarget);
1239
+ const updatedSelection = selectionManager.getSelectionInfo(selectionTarget);
1240
+ queueMicrotask(() => {
1241
+ if (selectionManager.getSelectionInfo(selectionTarget) !== updatedSelection) return;
1242
+ if (updatedSelection == null) selectionManager.replaceDocRanges(logicalTextRanges, selectionTarget, isEditing, params.options);
1243
+ else selectionManager.refreshSelection(selectionTarget, isEditing);
1244
+ });
1245
+ }
333
1246
  /**
334
1247
  * The core mutator to change rich text actions. The execution result would be undo mutation params. Could be directly
335
1248
  * send to undo redo service (will be used by the triggering command).
336
1249
  */
337
1250
  const RichTextEditingMutation = {
338
- id: RichTextEditingMutationId,
1251
+ id: RICH_TEXT_EDITING_MUTATION_ID,
339
1252
  type: _univerjs_core.CommandType.MUTATION,
340
1253
  handler: (accessor, params, options) => {
341
1254
  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);
1255
+ const { unitId, segmentId = "", actions, textRanges, prevTextRanges, trigger, noHistory, isCompositionEnd, debounce, isEditing = true, isSync: paramsIsSync, syncer } = params;
1256
+ const isSync = Boolean(paramsIsSync || (options === null || options === void 0 ? void 0 : options.fromCollab) || (options === null || options === void 0 ? void 0 : options.fromChangeset));
344
1257
  const univerInstanceService = accessor.get(_univerjs_core.IUniverInstanceService);
345
1258
  const renderManagerService = accessor.get(_univerjs_engine_render.IRenderManagerService);
346
1259
  const docStateEmitService = accessor.get(DocStateEmitService);
@@ -349,41 +1262,35 @@ const RichTextEditingMutation = {
349
1262
  if (documentDataModel == null) throw new Error(`DocumentDataModel not found for unitId: ${unitId}`);
350
1263
  const docSelectionManagerService = accessor.get(DocSelectionManagerService);
351
1264
  const docRanges = docSelectionManagerService.getDocRanges() ?? [];
1265
+ const selectionInfo = docSelectionManagerService.getSelectionInfo();
352
1266
  const disabled = !!documentDataModel.getSnapshot().disabled;
353
1267
  if (_univerjs_core.JSONX.isNoop(actions) || actions && actions.length === 0 || disabled) return {
354
1268
  unitId,
355
1269
  actions: [],
356
1270
  textRanges: docRanges
357
1271
  };
358
- const undoActions = _univerjs_core.JSONX.invertWithDoc(actions, documentDataModel.getSnapshot());
359
- documentDataModel.apply(actions);
360
- try {
361
- assertValidDocBodyStructure(documentDataModel, segmentId);
362
- } catch (error) {
363
- documentDataModel.apply(undoActions);
364
- throw error;
365
- }
366
- documentViewModel === null || documentViewModel === void 0 || documentViewModel.reset(documentDataModel);
367
- if (!noNeedSetTextRange && textRanges && trigger != null && !isSync) queueMicrotask(() => {
368
- docSelectionManagerService.replaceDocRanges(textRanges, {
369
- unitId,
370
- subUnitId: unitId
371
- }, isEditing, params.options);
372
- });
1272
+ const { actions: appliedActions, undoActions, preservesStructure } = applyValidatedDocumentActions(documentDataModel, segmentId, actions);
1273
+ params.actions = appliedActions;
1274
+ resetDocumentViewModel(documentViewModel, documentDataModel, segmentId, appliedActions, preservesStructure);
1275
+ scheduleDocumentSelectionUpdate(docSelectionManagerService, params, isSync);
373
1276
  const changeState = {
374
- commandId: RichTextEditingMutationId,
1277
+ commandId: RICH_TEXT_EDITING_MUTATION_ID,
375
1278
  unitId,
376
1279
  segmentId,
377
1280
  trigger,
378
1281
  noHistory,
379
1282
  debounce,
380
1283
  redoState: {
381
- actions,
382
- textRanges
1284
+ actions: appliedActions,
1285
+ textRanges,
1286
+ options: params.options,
1287
+ isEditing
383
1288
  },
384
1289
  undoState: {
385
1290
  actions: undoActions,
386
- textRanges: prevTextRanges ?? docRanges
1291
+ textRanges: prevTextRanges ?? docRanges,
1292
+ options: selectionInfo === null || selectionInfo === void 0 ? void 0 : selectionInfo.options,
1293
+ isEditing: selectionInfo === null || selectionInfo === void 0 ? void 0 : selectionInfo.isEditing
387
1294
  },
388
1295
  isCompositionEnd,
389
1296
  isSync,
@@ -409,59 +1316,63 @@ const InsertTextCommand = {
409
1316
  handler: (accessor, params) => {
410
1317
  var _docDataModel$getSelf;
411
1318
  const commandService = accessor.get(_univerjs_core.ICommandService);
412
- const { range, segmentId, body, unitId, cursorOffset } = params;
1319
+ const { range, segmentId, body, unitId, cursorOffset, debounce = true, textRanges, noNeedSetTextRange, isEditing } = params;
413
1320
  const docSelectionManagerService = accessor.get(DocSelectionManagerService);
414
1321
  const docDataModel = accessor.get(_univerjs_core.IUniverInstanceService).getUnit(unitId, _univerjs_core.UniverInstanceType.UNIVER_DOC);
415
1322
  if (docDataModel == null) return false;
416
1323
  const activeRange = docSelectionManagerService.getActiveTextRange();
417
- const rangeSegmentId = "segmentId" in range ? range.segmentId : void 0;
1324
+ const rangeSegmentId = "segmentId" in range && typeof range.segmentId === "string" ? range.segmentId : void 0;
418
1325
  const targetSegmentId = segmentId ?? rangeSegmentId ?? (activeRange === null || activeRange === void 0 ? void 0 : activeRange.segmentId) ?? "";
419
1326
  const originBody = (_docDataModel$getSelf = docDataModel.getSelfOrHeaderFooterModel(targetSegmentId)) === null || _docDataModel$getSelf === void 0 ? void 0 : _docDataModel$getSelf.getBody();
420
1327
  if (originBody == null) return false;
421
1328
  const { startOffset, collapsed } = range;
422
1329
  const cursorMove = cursorOffset ?? body.dataStream.length;
423
- const textRanges = [{
1330
+ const mutationTextRanges = textRanges ?? [{
424
1331
  startOffset: startOffset + cursorMove,
425
1332
  endOffset: startOffset + cursorMove,
426
- style: activeRange === null || activeRange === void 0 ? void 0 : activeRange.style,
427
1333
  collapsed
428
1334
  }];
429
1335
  const doMutation = {
430
1336
  id: RichTextEditingMutation.id,
431
1337
  params: {
432
1338
  unitId,
1339
+ segmentId: targetSegmentId,
433
1340
  actions: [],
434
- textRanges,
435
- debounce: true
1341
+ textRanges: mutationTextRanges,
1342
+ debounce,
1343
+ noNeedSetTextRange,
1344
+ isEditing
436
1345
  }
437
1346
  };
438
- const textX = new _univerjs_core.TextX();
439
- const jsonX = _univerjs_core.JSONX.getInstance();
440
- if (collapsed) {
441
- if (startOffset > 0) textX.push({
442
- t: _univerjs_core.TextXActionType.RETAIN,
443
- len: startOffset
444
- });
445
- textX.push({
446
- t: _univerjs_core.TextXActionType.INSERT,
447
- body,
448
- len: body.dataStream.length
449
- });
450
- } else {
451
- const dos = _univerjs_core.BuildTextUtils.selection.delete([range], originBody, 0, body);
452
- textX.push(...dos);
453
- }
454
- doMutation.params.textRanges = [{
455
- startOffset: startOffset + cursorMove,
456
- endOffset: startOffset + cursorMove,
457
- collapsed
458
- }];
459
- const path = (0, _univerjs_core.getRichTextEditPath)(docDataModel, segmentId);
460
- doMutation.params.actions = jsonX.editOp(textX.serialize(), path);
1347
+ doMutation.params.actions = buildInsertTextActions(docDataModel, originBody, range, body, targetSegmentId);
461
1348
  const result = commandService.syncExecuteCommand(doMutation.id, doMutation.params);
462
1349
  return Boolean(result);
463
1350
  }
464
1351
  };
1352
+ function buildInsertTextActions(documentDataModel, originBody, range, insertBody, segmentId) {
1353
+ const { startOffset, endOffset, collapsed } = range;
1354
+ const textX = new _univerjs_core.TextX();
1355
+ if (collapsed) {
1356
+ if (startOffset > 0) textX.push({
1357
+ t: _univerjs_core.TextXActionType.RETAIN,
1358
+ len: startOffset
1359
+ });
1360
+ textX.push({
1361
+ t: _univerjs_core.TextXActionType.INSERT,
1362
+ body: insertBody,
1363
+ len: insertBody.dataStream.length
1364
+ });
1365
+ } else textX.push(..._univerjs_core.BuildTextUtils.selection.delete([range], originBody, 0, insertBody));
1366
+ const textActions = _univerjs_core.JSONX.getInstance().editOp(textX.serialize(), (0, _univerjs_core.getRichTextEditPath)(documentDataModel, segmentId));
1367
+ return collapsed ? textActions : appendRemovedDrawingActions(textActions, documentDataModel, originBody, startOffset, endOffset, segmentId);
1368
+ }
1369
+ function appendRemovedDrawingActions(textActions, documentDataModel, body, startOffset, endOffset, segmentId) {
1370
+ return [textActions, ..._univerjs_core.BuildTextUtils.drawing.remove(documentDataModel.getSnapshot(), [{
1371
+ startOffset,
1372
+ endOffset,
1373
+ collapsed: false
1374
+ }], body, segmentId)].reduce((accumulator, action) => _univerjs_core.JSONX.compose(accumulator, action));
1375
+ }
465
1376
  /**
466
1377
  * The command to delete text, mainly used in BACKSPACE and DELETE when collapsed is true. ONLY handle collapsed range!!!
467
1378
  */
@@ -488,6 +1399,7 @@ const DeleteTextCommand = {
488
1399
  id: RichTextEditingMutation.id,
489
1400
  params: {
490
1401
  unitId,
1402
+ segmentId,
491
1403
  actions: [],
492
1404
  textRanges: [{
493
1405
  startOffset: start,
@@ -506,7 +1418,7 @@ const DeleteTextCommand = {
506
1418
  collapsed: false
507
1419
  }], body));
508
1420
  const path = (0, _univerjs_core.getRichTextEditPath)(docDataModel, segmentId);
509
- doMutation.params.actions = jsonX.editOp(textX.serialize(), path);
1421
+ doMutation.params.actions = appendRemovedDrawingActions(jsonX.editOp(textX.serialize(), path), docDataModel, body, start, end + 1, segmentId);
510
1422
  const result = commandService.syncExecuteCommand(doMutation.id, doMutation.params);
511
1423
  return Boolean(result);
512
1424
  }
@@ -785,6 +1697,235 @@ const SetDocumentNameCommand = {
785
1697
  }
786
1698
  };
787
1699
 
1700
+ //#endregion
1701
+ //#region src/services/permission/permission-point/document/comment.ts
1702
+ var DocumentCommentPermission = class {
1703
+ constructor(unitId) {
1704
+ this.unitId = unitId;
1705
+ _defineProperty(this, "type", _univerjs_protocol.UnitObject.Document);
1706
+ _defineProperty(this, "subType", _univerjs_protocol.UnitAction.Comment);
1707
+ _defineProperty(this, "status", _univerjs_core.PermissionStatus.INIT);
1708
+ _defineProperty(this, "id", void 0);
1709
+ _defineProperty(this, "value", true);
1710
+ this.id = `${this.type}.${this.subType}_${unitId}`;
1711
+ }
1712
+ };
1713
+
1714
+ //#endregion
1715
+ //#region src/services/permission/permission-point/document/copy.ts
1716
+ var DocumentCopyPermission = class {
1717
+ constructor(unitId) {
1718
+ this.unitId = unitId;
1719
+ _defineProperty(this, "type", _univerjs_protocol.UnitObject.Document);
1720
+ _defineProperty(this, "subType", _univerjs_protocol.UnitAction.Copy);
1721
+ _defineProperty(this, "status", _univerjs_core.PermissionStatus.INIT);
1722
+ _defineProperty(this, "id", void 0);
1723
+ _defineProperty(this, "value", true);
1724
+ this.id = `${this.type}.${this.subType}_${unitId}`;
1725
+ }
1726
+ };
1727
+
1728
+ //#endregion
1729
+ //#region src/services/permission/permission-point/document/editable.ts
1730
+ var DocumentEditablePermission = class {
1731
+ constructor(unitId) {
1732
+ this.unitId = unitId;
1733
+ _defineProperty(this, "type", _univerjs_protocol.UnitObject.Document);
1734
+ _defineProperty(this, "subType", _univerjs_protocol.UnitAction.Edit);
1735
+ _defineProperty(this, "status", _univerjs_core.PermissionStatus.INIT);
1736
+ _defineProperty(this, "id", void 0);
1737
+ _defineProperty(this, "value", true);
1738
+ this.id = `${this.type}.${this.subType}_${unitId}`;
1739
+ }
1740
+ };
1741
+
1742
+ //#endregion
1743
+ //#region src/services/permission/permission-point/document/export.ts
1744
+ var DocumentExportPermission = class {
1745
+ constructor(unitId) {
1746
+ this.unitId = unitId;
1747
+ _defineProperty(this, "type", _univerjs_protocol.UnitObject.Document);
1748
+ _defineProperty(this, "subType", _univerjs_protocol.UnitAction.Export);
1749
+ _defineProperty(this, "status", _univerjs_core.PermissionStatus.INIT);
1750
+ _defineProperty(this, "id", void 0);
1751
+ _defineProperty(this, "value", true);
1752
+ this.id = `${this.type}.${this.subType}_${unitId}`;
1753
+ }
1754
+ };
1755
+
1756
+ //#endregion
1757
+ //#region src/services/permission/permission-point/document/print.ts
1758
+ var DocumentPrintPermission = class {
1759
+ constructor(unitId) {
1760
+ this.unitId = unitId;
1761
+ _defineProperty(this, "type", _univerjs_protocol.UnitObject.Document);
1762
+ _defineProperty(this, "subType", _univerjs_protocol.UnitAction.Print);
1763
+ _defineProperty(this, "status", _univerjs_core.PermissionStatus.INIT);
1764
+ _defineProperty(this, "id", void 0);
1765
+ _defineProperty(this, "value", true);
1766
+ this.id = `${this.type}.${this.subType}_${unitId}`;
1767
+ }
1768
+ };
1769
+
1770
+ //#endregion
1771
+ //#region src/services/permission/permission-point/entity/edit.ts
1772
+ var DocumentEntityEditPermission = class {
1773
+ constructor(unitId, objectId) {
1774
+ this.unitId = unitId;
1775
+ this.objectId = objectId;
1776
+ _defineProperty(this, "type", _univerjs_protocol.UnitObject.DocumentEntity);
1777
+ _defineProperty(this, "subType", _univerjs_protocol.UnitAction.Edit);
1778
+ _defineProperty(this, "status", _univerjs_core.PermissionStatus.INIT);
1779
+ _defineProperty(this, "id", void 0);
1780
+ _defineProperty(this, "value", true);
1781
+ this.id = `${this.type}.${this.subType}_${unitId}_${objectId}`;
1782
+ }
1783
+ };
1784
+
1785
+ //#endregion
1786
+ //#region src/services/permission/permission-point/paragraph/edit.ts
1787
+ var DocumentParagraphEditPermission = class {
1788
+ constructor(unitId, objectId) {
1789
+ this.unitId = unitId;
1790
+ this.objectId = objectId;
1791
+ _defineProperty(this, "type", _univerjs_protocol.UnitObject.DocumentParagraph);
1792
+ _defineProperty(this, "subType", _univerjs_protocol.UnitAction.Edit);
1793
+ _defineProperty(this, "status", _univerjs_core.PermissionStatus.INIT);
1794
+ _defineProperty(this, "id", void 0);
1795
+ _defineProperty(this, "value", true);
1796
+ this.id = `${this.type}.${this.subType}_${unitId}_${objectId}`;
1797
+ }
1798
+ };
1799
+
1800
+ //#endregion
1801
+ //#region src/services/permission/permission-point/section/edit.ts
1802
+ var DocumentSectionEditPermission = class {
1803
+ constructor(unitId, objectId) {
1804
+ this.unitId = unitId;
1805
+ this.objectId = objectId;
1806
+ _defineProperty(this, "type", _univerjs_protocol.UnitObject.DocumentSection);
1807
+ _defineProperty(this, "subType", _univerjs_protocol.UnitAction.Edit);
1808
+ _defineProperty(this, "status", _univerjs_core.PermissionStatus.INIT);
1809
+ _defineProperty(this, "id", void 0);
1810
+ _defineProperty(this, "value", true);
1811
+ this.id = `${this.type}.${this.subType}_${unitId}_${objectId}`;
1812
+ }
1813
+ };
1814
+
1815
+ //#endregion
1816
+ //#region src/services/permission/document-permission.ts
1817
+ const DOCUMENT_UNIT_PERMISSION_ACTIONS = [
1818
+ _univerjs_protocol.UnitAction.Edit,
1819
+ _univerjs_protocol.UnitAction.Copy,
1820
+ _univerjs_protocol.UnitAction.Print,
1821
+ _univerjs_protocol.UnitAction.Export,
1822
+ _univerjs_protocol.UnitAction.Comment
1823
+ ];
1824
+ const DOCUMENT_PERMISSION_OBJECT_TYPES = /* @__PURE__ */ new Set([
1825
+ _univerjs_protocol.UnitObject.Document,
1826
+ _univerjs_protocol.UnitObject.DocumentSection,
1827
+ _univerjs_protocol.UnitObject.DocumentParagraph,
1828
+ _univerjs_protocol.UnitObject.DocumentEntity
1829
+ ]);
1830
+ const DOCUMENT_SECTION_PERMISSION_OBJECT_PREFIX = "section/";
1831
+ const DOCUMENT_PARAGRAPH_PERMISSION_OBJECT_PREFIX = "paragraph/";
1832
+ const DOCUMENT_ENTITY_PERMISSION_OBJECT_PREFIX = "entity/";
1833
+ function getDocumentSectionPermissionObjectId(segmentId, sectionId) {
1834
+ return `${DOCUMENT_SECTION_PERMISSION_OBJECT_PREFIX}${encodeURIComponent(segmentId)}/${encodeURIComponent(sectionId)}`;
1835
+ }
1836
+ function getDocumentParagraphPermissionObjectId(segmentId, paragraphId) {
1837
+ return `${DOCUMENT_PARAGRAPH_PERMISSION_OBJECT_PREFIX}${encodeURIComponent(segmentId)}/${encodeURIComponent(paragraphId)}`;
1838
+ }
1839
+ function getDocumentEntityPermissionObjectId(segmentId, entityType, entityId) {
1840
+ return `${DOCUMENT_ENTITY_PERMISSION_OBJECT_PREFIX}${encodeURIComponent(segmentId)}/${encodeURIComponent(entityType)}/${encodeURIComponent(entityId)}`;
1841
+ }
1842
+ function createDocumentPermissionPoint(unitId, objectId, action) {
1843
+ if (objectId === unitId) switch (action) {
1844
+ case _univerjs_protocol.UnitAction.Edit: return new DocumentEditablePermission(unitId);
1845
+ case _univerjs_protocol.UnitAction.Copy: return new DocumentCopyPermission(unitId);
1846
+ case _univerjs_protocol.UnitAction.Print: return new DocumentPrintPermission(unitId);
1847
+ case _univerjs_protocol.UnitAction.Export: return new DocumentExportPermission(unitId);
1848
+ case _univerjs_protocol.UnitAction.Comment: return new DocumentCommentPermission(unitId);
1849
+ default: throw new Error(`Unsupported Document permission action: ${action}`);
1850
+ }
1851
+ if (action !== _univerjs_protocol.UnitAction.Edit) throw new Error(`Document object permissions only support Edit: ${objectId}`);
1852
+ if (objectId.startsWith(DOCUMENT_SECTION_PERMISSION_OBJECT_PREFIX)) return new DocumentSectionEditPermission(unitId, objectId);
1853
+ if (objectId.startsWith(DOCUMENT_PARAGRAPH_PERMISSION_OBJECT_PREFIX)) return new DocumentParagraphEditPermission(unitId, objectId);
1854
+ if (objectId.startsWith(DOCUMENT_ENTITY_PERMISSION_OBJECT_PREFIX)) return new DocumentEntityEditPermission(unitId, objectId);
1855
+ throw new Error(`Unsupported Document permission object: ${objectId}`);
1856
+ }
1857
+ function getDocumentPermissionValue(permissionService, unitId, objectId, action) {
1858
+ var _permissionService$ge;
1859
+ return ((_permissionService$ge = permissionService.getPermissionPoint(createDocumentPermissionPoint(unitId, objectId, action).id)) === null || _permissionService$ge === void 0 ? void 0 : _permissionService$ge.value) ?? true;
1860
+ }
1861
+ function setDocumentPermissionValue(permissionService, unitId, objectId, action, value) {
1862
+ const point = createDocumentPermissionPoint(unitId, objectId, action);
1863
+ if (!permissionService.getPermissionPoint(point.id)) permissionService.addPermissionPoint(point);
1864
+ permissionService.updatePermissionPoint(point.id, value);
1865
+ }
1866
+ function clearDocumentPermissionValuesForUnit(permissionService, unitId) {
1867
+ permissionService.getAllPermissionPoint().forEach((point$, id) => {
1868
+ point$.subscribe((point) => {
1869
+ if (DOCUMENT_PERMISSION_OBJECT_TYPES.has(point.type) && "unitId" in point && point.unitId === unitId) permissionService.deletePermissionPoint(id);
1870
+ }).unsubscribe();
1871
+ });
1872
+ }
1873
+ function canEditDocumentTargets(permissionService, unitId, objectIds) {
1874
+ if (!getDocumentPermissionValue(permissionService, unitId, unitId, _univerjs_protocol.UnitAction.Edit)) return false;
1875
+ for (const objectId of objectIds) if (!getDocumentPermissionValue(permissionService, unitId, objectId, _univerjs_protocol.UnitAction.Edit)) return false;
1876
+ return true;
1877
+ }
1878
+
1879
+ //#endregion
1880
+ //#region src/commands/commands/set-document-permission.command.ts
1881
+ const SetDocumentPermissionCommand = {
1882
+ type: _univerjs_core.CommandType.COMMAND,
1883
+ id: "doc.command.set-permission",
1884
+ async handler(accessor, params) {
1885
+ if (!params || !DOCUMENT_UNIT_PERMISSION_ACTIONS.includes(params.action)) return false;
1886
+ if (params.objectId !== params.unitId && params.action !== _univerjs_protocol.UnitAction.Edit) return false;
1887
+ if (params.policy && (![
1888
+ "all",
1889
+ "owner",
1890
+ "members"
1891
+ ].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;
1892
+ const point = createDocumentPermissionPoint(params.unitId, params.objectId, params.action);
1893
+ const target = {
1894
+ unitId: params.unitId,
1895
+ objectId: params.objectId,
1896
+ objectType: point.type
1897
+ };
1898
+ const service = accessor.get(_univerjs_core.ObjectPermissionService);
1899
+ if (params.remove) await service.remove(target);
1900
+ else if (params.policy) await service.save(target, params.policy);
1901
+ else await service.setPoint(target, point, params.value);
1902
+ return true;
1903
+ }
1904
+ };
1905
+
1906
+ //#endregion
1907
+ //#region src/commands/commands/set-document-permissions.command.ts
1908
+ const SetDocumentPermissionsCommand = {
1909
+ type: _univerjs_core.CommandType.COMMAND,
1910
+ id: "doc.command.set-permissions",
1911
+ async handler(accessor, params) {
1912
+ 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 || ![
1913
+ "all",
1914
+ "owner",
1915
+ "members"
1916
+ ].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.");
1917
+ return accessor.get(_univerjs_core.ObjectPermissionService).saveMany(params.changes.map((change) => {
1918
+ const point = createDocumentPermissionPoint(params.unitId, change.objectId, _univerjs_protocol.UnitAction.Edit);
1919
+ return {
1920
+ unitId: params.unitId,
1921
+ objectId: change.objectId,
1922
+ objectType: point.type,
1923
+ policy: change.policy
1924
+ };
1925
+ }));
1926
+ }
1927
+ };
1928
+
788
1929
  //#endregion
789
1930
  //#region src/utils/sections.ts
790
1931
  /** Returns document-level section breaks, excluding table-cell and modern-column sentinels. */
@@ -1194,7 +2335,7 @@ const InsertDocumentColumnBreakCommand = {
1194
2335
  rangeId: `docx-break-${(0, _univerjs_core.generateRandomId)()}`,
1195
2336
  rangeType: _univerjs_core.CustomRangeType.CUSTOM,
1196
2337
  wholeEntity: true,
1197
- properties: { docxBreakType: _univerjs_core.DocxBreakType.COLUMN }
2338
+ properties: { breakType: _univerjs_core.DocxBreakType.COLUMN }
1198
2339
  }]
1199
2340
  });
1200
2341
  return executeSectionTextX(context.commandService, context.documentDataModel, textX, InsertDocumentColumnBreakCommand.id);
@@ -1273,6 +2414,56 @@ function executeSectionTextX(commandService, documentDataModel, textX, trigger)
1273
2414
  }));
1274
2415
  }
1275
2416
 
2417
+ //#endregion
2418
+ //#region src/services/permission/document-permission-rule.model.ts
2419
+ /**
2420
+ * Copyright 2023-present DreamNum Co., Ltd.
2421
+ *
2422
+ * Licensed under the Apache License, Version 2.0 (the "License");
2423
+ * you may not use this file except in compliance with the License.
2424
+ * You may obtain a copy of the License at
2425
+ *
2426
+ * http://www.apache.org/licenses/LICENSE-2.0
2427
+ *
2428
+ * Unless required by applicable law or agreed to in writing, software
2429
+ * distributed under the License is distributed on an "AS IS" BASIS,
2430
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2431
+ * See the License for the specific language governing permissions and
2432
+ * limitations under the License.
2433
+ */
2434
+ let DocumentPermissionRuleModel = class DocumentPermissionRuleModel extends _univerjs_core.ObjectPermissionRuleModel {
2435
+ constructor(resources) {
2436
+ super(resources, "DOC_OBJECT_PERMISSION_PLUGIN", _univerjs_core.UniverInstanceType.UNIVER_DOC, [
2437
+ _univerjs_protocol.UnitObject.DocumentSection,
2438
+ _univerjs_protocol.UnitObject.DocumentParagraph,
2439
+ _univerjs_protocol.UnitObject.DocumentEntity
2440
+ ]);
2441
+ }
2442
+ };
2443
+ DocumentPermissionRuleModel = __decorate([__decorateParam(0, _univerjs_core.IResourceManagerService)], DocumentPermissionRuleModel);
2444
+
2445
+ //#endregion
2446
+ //#region src/commands/mutations/set-document-permission-rule.mutation.ts
2447
+ const SetDocumentPermissionRuleMutation = {
2448
+ id: "doc.mutation.set-permission-rule",
2449
+ type: _univerjs_core.CommandType.MUTATION,
2450
+ handler: (accessor, params) => {
2451
+ if (!params || !accessor.get(_univerjs_core.IUniverInstanceService).getUnit(params.unitId, _univerjs_core.UniverInstanceType.UNIVER_DOC)) return false;
2452
+ return accessor.get(DocumentPermissionRuleModel).setRule(params.unitId, params.objectType, params.objectId, params.rule);
2453
+ }
2454
+ };
2455
+
2456
+ //#endregion
2457
+ //#region src/commands/mutations/set-document-permission-rules.mutation.ts
2458
+ const SetDocumentPermissionRulesMutation = {
2459
+ id: "doc.mutation.set-permission-rules",
2460
+ type: _univerjs_core.CommandType.MUTATION,
2461
+ handler: (accessor, params) => {
2462
+ if (!params || !accessor.get(_univerjs_core.IUniverInstanceService).getUnit(params.unitId, _univerjs_core.UniverInstanceType.UNIVER_DOC)) return false;
2463
+ return accessor.get(DocumentPermissionRuleModel).setRules(params.unitId, params.rules);
2464
+ }
2465
+ };
2466
+
1276
2467
  //#endregion
1277
2468
  //#region src/embed-host-anchor.ts
1278
2469
  const EMBED_DOCS_CUSTOM_BLOCK_DEFAULT_COMPONENT_KEY = "UniverEmbedDocsCustomBlock";
@@ -1434,7 +2625,7 @@ function composeActions(actions) {
1434
2625
  //#endregion
1435
2626
  //#region package.json
1436
2627
  var name = "@univerjs/docs";
1437
- var version = "1.0.0-insiders.20260809-70eefdd";
2628
+ var version = "1.0.0-rc.0";
1438
2629
 
1439
2630
  //#endregion
1440
2631
  //#region src/config/config.ts
@@ -1454,7 +2645,7 @@ var version = "1.0.0-insiders.20260809-70eefdd";
1454
2645
  * limitations under the License.
1455
2646
  */
1456
2647
  const DOCS_PLUGIN_CONFIG_KEY = "docs.config";
1457
- const configSymbol = Symbol(DOCS_PLUGIN_CONFIG_KEY);
2648
+ const configSymbol$1 = Symbol(DOCS_PLUGIN_CONFIG_KEY);
1458
2649
  const defaultPluginConfig = {};
1459
2650
 
1460
2651
  //#endregion
@@ -1476,39 +2667,506 @@ let DocCustomRangeController = class DocCustomRangeController extends _univerjs_
1476
2667
  if (collapsed) return range.startIndex < startOffset && range.endIndex >= endOffset;
1477
2668
  return _univerjs_core.BuildTextUtils.range.isIntersects(startOffset, endOffset - 1, range.startIndex, range.endIndex);
1478
2669
  });
1479
- if (customRanges === null || customRanges === void 0 ? void 0 : customRanges.length) {
1480
- let start = startOffset;
1481
- let end = endOffset;
1482
- customRanges.forEach((range) => {
1483
- start = Math.min(range.startIndex, start);
1484
- end = Math.max(range.endIndex + 1, end);
1485
- });
1486
- return {
1487
- ...selection,
1488
- startOffset: start,
1489
- endOffset: end,
1490
- collapsed: start === end
1491
- };
1492
- }
1493
- return selection;
2670
+ if (customRanges === null || customRanges === void 0 ? void 0 : customRanges.length) {
2671
+ let start = startOffset;
2672
+ let end = endOffset;
2673
+ customRanges.forEach((range) => {
2674
+ start = Math.min(range.startIndex, start);
2675
+ end = Math.max(range.endIndex + 1, end);
2676
+ });
2677
+ return {
2678
+ ...selection,
2679
+ startOffset: start,
2680
+ endOffset: end,
2681
+ collapsed: start === end
2682
+ };
2683
+ }
2684
+ return selection;
2685
+ }
2686
+ _initSelectionChange() {
2687
+ this.disposeWithMe(this._commandService.onCommandExecuted((commandInfo) => {
2688
+ if (commandInfo.id === SetTextSelectionsOperation.id) {
2689
+ const { unitId, ranges, isEditing } = commandInfo.params;
2690
+ const doc = this._univerInstanceService.getUnit(unitId);
2691
+ if (!doc) return;
2692
+ const transformedRanges = ranges.map((range) => this._transformCustomRange(doc, range));
2693
+ if (transformedRanges.some((range, i) => ranges[i] !== range)) this._textSelectionManagerService.replaceDocRanges(transformedRanges, void 0, isEditing);
2694
+ }
2695
+ }));
2696
+ }
2697
+ };
2698
+ DocCustomRangeController = __decorate([
2699
+ __decorateParam(0, _univerjs_core.ICommandService),
2700
+ __decorateParam(1, (0, _univerjs_core.Inject)(DocSelectionManagerService)),
2701
+ __decorateParam(2, _univerjs_core.IUniverInstanceService)
2702
+ ], DocCustomRangeController);
2703
+
2704
+ //#endregion
2705
+ //#region src/services/permission/document-permission-resolver.ts
2706
+ const HEADER_FOOTER_REFERENCE_KEYS = [
2707
+ "defaultHeaderId",
2708
+ "defaultFooterId",
2709
+ "firstPageHeaderId",
2710
+ "firstPageFooterId",
2711
+ "evenPageHeaderId",
2712
+ "evenPageFooterId"
2713
+ ];
2714
+ const documentPermissionResolverIndexCache = /* @__PURE__ */ new WeakMap();
2715
+ function getDocumentPermissionResolverIndex(documentDataModel) {
2716
+ var _getMutationRevision, _snapshot$body;
2717
+ const mutationRevision = ((_getMutationRevision = documentDataModel.getMutationRevision) === null || _getMutationRevision === void 0 ? void 0 : _getMutationRevision.call(documentDataModel)) ?? NaN;
2718
+ const cached = documentPermissionResolverIndexCache.get(documentDataModel);
2719
+ if ((cached === null || cached === void 0 ? void 0 : cached.mutationRevision) === mutationRevision) return cached;
2720
+ const snapshot = documentDataModel.getSnapshot();
2721
+ const topLevelSections = snapshot.body ? getTopLevelSectionBreaks(snapshot.body) : [];
2722
+ const drawingSegmentIds = /* @__PURE__ */ new Map();
2723
+ const addDrawingSegments = (body, segmentId) => {
2724
+ for (const block of (body === null || body === void 0 ? void 0 : body.customBlocks) ?? []) if (!drawingSegmentIds.has(block.blockId)) drawingSegmentIds.set(block.blockId, segmentId);
2725
+ };
2726
+ addDrawingSegments(snapshot.body, "");
2727
+ Object.entries(snapshot.headers ?? {}).forEach(([segmentId, header]) => addDrawingSegments(header.body, segmentId));
2728
+ Object.entries(snapshot.footers ?? {}).forEach(([segmentId, footer]) => addDrawingSegments(footer.body, segmentId));
2729
+ Object.entries(snapshot.notes ?? {}).forEach(([segmentId, footnote]) => addDrawingSegments(footnote.body, segmentId));
2730
+ const footnoteReferenceRanges = /* @__PURE__ */ new Map();
2731
+ for (const reference of ((_snapshot$body = snapshot.body) === null || _snapshot$body === void 0 ? void 0 : _snapshot$body.customRanges) ?? []) {
2732
+ var _reference$properties;
2733
+ 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, {
2734
+ startOffset: reference.startIndex,
2735
+ endOffset: reference.endIndex + 1
2736
+ });
2737
+ }
2738
+ const index = {
2739
+ drawingSegmentIds,
2740
+ footnoteReferenceRanges,
2741
+ mutationRevision,
2742
+ segments: /* @__PURE__ */ new Map(),
2743
+ topLevelSections
2744
+ };
2745
+ documentPermissionResolverIndexCache.set(documentDataModel, index);
2746
+ return index;
2747
+ }
2748
+ function getDocumentPermissionSegmentIndex(documentDataModel, segmentId, resolverIndex = getDocumentPermissionResolverIndex(documentDataModel)) {
2749
+ var _documentDataModel$ge, _snapshot$notes;
2750
+ const cached = resolverIndex.segments.get(segmentId);
2751
+ if (cached) return cached;
2752
+ const body = ((_documentDataModel$ge = documentDataModel.getSelfOrHeaderFooterModel(segmentId)) === null || _documentDataModel$ge === void 0 ? void 0 : _documentDataModel$ge.getBody()) ?? null;
2753
+ const snapshot = documentDataModel.getSnapshot();
2754
+ const note = (_snapshot$notes = snapshot.notes) === null || _snapshot$notes === void 0 ? void 0 : _snapshot$notes[segmentId];
2755
+ const drawings = (note ? note.drawings : snapshot.drawings) ?? {};
2756
+ const entities = body == null ? [] : [
2757
+ ...(body.tables ?? []).map((item) => ({
2758
+ type: "table",
2759
+ id: item.tableId,
2760
+ startOffset: item.startIndex,
2761
+ endOffset: item.endIndex
2762
+ })),
2763
+ ...(body.customBlocks ?? []).map((item) => ({
2764
+ type: drawings[item.blockId] ? "drawing" : "custom-block",
2765
+ id: item.blockId,
2766
+ startOffset: item.startIndex,
2767
+ endOffset: item.startIndex + 1
2768
+ })),
2769
+ ...(body.blockRanges ?? []).map((item) => ({
2770
+ type: "block-range",
2771
+ id: item.blockId,
2772
+ startOffset: item.startIndex,
2773
+ endOffset: item.endIndex + 1
2774
+ })),
2775
+ ...(body.customRanges ?? []).map((item) => ({
2776
+ type: "custom-range",
2777
+ id: item.rangeId,
2778
+ startOffset: item.startIndex,
2779
+ endOffset: item.endIndex + 1
2780
+ })),
2781
+ ...(body.columnGroups ?? []).map((item) => ({
2782
+ type: "column-group",
2783
+ id: item.columnGroupId,
2784
+ startOffset: item.startIndex,
2785
+ endOffset: item.endIndex + 1
2786
+ }))
2787
+ ];
2788
+ const entityRanges = new Map(entities.map((entity) => [`${entity.type}:${entity.id}`, {
2789
+ startOffset: entity.startOffset,
2790
+ endOffset: entity.endOffset
2791
+ }]));
2792
+ for (const block of (body === null || body === void 0 ? void 0 : body.customBlocks) ?? []) {
2793
+ const range = {
2794
+ startOffset: block.startIndex,
2795
+ endOffset: block.startIndex + 1
2796
+ };
2797
+ entityRanges.set(`custom-block:${block.blockId}`, range);
2798
+ entityRanges.set(`drawing:${block.blockId}`, range);
2799
+ }
2800
+ const segmentIndex = {
2801
+ body,
2802
+ entities,
2803
+ entityRanges,
2804
+ paragraphContentStartOffsets: body == null ? /* @__PURE__ */ new Map() : (0, _univerjs_core.getParagraphContentStartOffsets)(body),
2805
+ paragraphsById: new Map(((body === null || body === void 0 ? void 0 : body.paragraphs) ?? []).filter((paragraph) => paragraph.paragraphId != null).map((paragraph) => [paragraph.paragraphId, paragraph]))
2806
+ };
2807
+ resolverIndex.segments.set(segmentId, segmentIndex);
2808
+ return segmentIndex;
2809
+ }
2810
+ function getDocumentDrawingSegmentId(documentDataModel, drawingId) {
2811
+ return getDocumentPermissionResolverIndex(documentDataModel).drawingSegmentIds.get(drawingId) ?? "";
2812
+ }
2813
+ function getDocumentEditTargetObjectIds(documentDataModel, segmentId, range) {
2814
+ const resolverIndex = getDocumentPermissionResolverIndex(documentDataModel);
2815
+ const segmentIndex = getDocumentPermissionSegmentIndex(documentDataModel, segmentId, resolverIndex);
2816
+ const { body } = segmentIndex;
2817
+ if (!body) return [];
2818
+ return [
2819
+ ...getSectionPermissionObjectIds(documentDataModel, segmentId, range, resolverIndex),
2820
+ ...getParagraphPermissionObjectIds(body, segmentId, range, segmentIndex),
2821
+ ...getEntityPermissionObjectIds(segmentId, range, segmentIndex)
2822
+ ];
2823
+ }
2824
+ function getDocumentEditTargetObjectIdsFromActions(documentDataModel, segmentId, actions) {
2825
+ const result = /* @__PURE__ */ new Set();
2826
+ if (actions == null) return [];
2827
+ const cursor = _univerjs_core.JSON1.type.readCursor(actions);
2828
+ cursor.traverse(null, () => {
2829
+ const path = cursor.getPath();
2830
+ const edit = cursor.getComponent();
2831
+ const scopedSegment = [
2832
+ "headers",
2833
+ "footers",
2834
+ "notes"
2835
+ ].includes(String(path[0])) && typeof path[1] === "string" ? path[1] : segmentId;
2836
+ if (path[0] === "notes" && typeof path[1] === "string") getSectionPermissionObjectIds(documentDataModel, path[1], {
2837
+ startOffset: 0,
2838
+ endOffset: 0
2839
+ }).forEach((objectId) => result.add(objectId));
2840
+ if (path[0] === "noteSettings") getDocumentPermissionResolverIndex(documentDataModel).topLevelSections.forEach((section) => {
2841
+ result.add(getDocumentSectionPermissionObjectId("", section.sectionId));
2842
+ });
2843
+ if (path[0] === "body" && path[1] === "sectionBreaks" && typeof path[2] === "number" && (path[3] === "noteProperties" || path[3] === "suppressEndnotes")) {
2844
+ var _documentDataModel$ge2;
2845
+ 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;
2846
+ if (sectionId) result.add(getDocumentSectionPermissionObjectId("", sectionId));
2847
+ }
2848
+ 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;
2849
+ const textActions = edit.e;
2850
+ let offset = 0;
2851
+ const addRange = (startOffset, endOffset) => {
2852
+ getDocumentEditTargetObjectIds(documentDataModel, scopedSegment, {
2853
+ startOffset,
2854
+ endOffset
2855
+ }).forEach((objectId) => result.add(objectId));
2856
+ };
2857
+ textActions.forEach((action) => {
2858
+ if (action.t === _univerjs_core.TextXActionType.INSERT) {
2859
+ addRange(offset, offset);
2860
+ return;
2861
+ }
2862
+ if (action.t === _univerjs_core.TextXActionType.DELETE) {
2863
+ addRange(offset, offset + action.len);
2864
+ offset += action.len;
2865
+ return;
2866
+ }
2867
+ if (action.body !== void 0 || action.oldBody !== void 0 || action.coverType !== void 0) addRange(offset, offset + action.len);
2868
+ offset += action.len;
2869
+ });
2870
+ });
2871
+ getDrawingIdsFromActions(actions).forEach((drawingId) => {
2872
+ var _documentDataModel$ge3, _body$customBlocks;
2873
+ result.add(getDocumentEntityPermissionObjectId(segmentId, "drawing", drawingId));
2874
+ const body = (_documentDataModel$ge3 = documentDataModel.getSelfOrHeaderFooterModel(segmentId)) === null || _documentDataModel$ge3 === void 0 ? void 0 : _documentDataModel$ge3.getBody();
2875
+ 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);
2876
+ if (block) getSectionPermissionObjectIds(documentDataModel, segmentId, {
2877
+ startOffset: block.startIndex,
2878
+ endOffset: block.startIndex + 1
2879
+ }).forEach((objectId) => result.add(objectId));
2880
+ });
2881
+ return [...result];
2882
+ }
2883
+ function getDrawingIdsFromActions(actions) {
2884
+ const result = /* @__PURE__ */ new Set();
2885
+ const visit = (value) => {
2886
+ if (Array.isArray(value)) {
2887
+ value.forEach((item, index) => {
2888
+ if (item === "drawings" && typeof value[index + 1] === "string") result.add(value[index + 1]);
2889
+ visit(item);
2890
+ });
2891
+ return;
2892
+ }
2893
+ if (!isRecord$2(value)) return;
2894
+ Object.values(value).forEach(visit);
2895
+ };
2896
+ visit(actions);
2897
+ return [...result];
2898
+ }
2899
+ function isTextXAction(value) {
2900
+ if (!isRecord$2(value) || typeof value.len !== "number") return false;
2901
+ if (value.t === _univerjs_core.TextXActionType.INSERT) return isRecord$2(value.body);
2902
+ return value.t === _univerjs_core.TextXActionType.RETAIN || value.t === _univerjs_core.TextXActionType.DELETE;
2903
+ }
2904
+ function isRecord$2(value) {
2905
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2906
+ }
2907
+ function getDocumentEntityParentPermissionObjectIds(documentDataModel, segmentId, entityType, entityId) {
2908
+ const resolverIndex = getDocumentPermissionResolverIndex(documentDataModel);
2909
+ const range = getDocumentPermissionSegmentIndex(documentDataModel, segmentId, resolverIndex).entityRanges.get(`${entityType}:${entityId}`) ?? null;
2910
+ return range ? getSectionPermissionObjectIds(documentDataModel, segmentId, range, resolverIndex) : [];
2911
+ }
2912
+ function getDocumentParagraphParentPermissionObjectIds(documentDataModel, segmentId, paragraphId) {
2913
+ const resolverIndex = getDocumentPermissionResolverIndex(documentDataModel);
2914
+ const segmentIndex = getDocumentPermissionSegmentIndex(documentDataModel, segmentId, resolverIndex);
2915
+ const { body } = segmentIndex;
2916
+ const paragraph = segmentIndex.paragraphsById.get(paragraphId);
2917
+ if (!body || !paragraph) return [];
2918
+ return getSectionPermissionObjectIds(documentDataModel, segmentId, {
2919
+ startOffset: segmentIndex.paragraphContentStartOffsets.get(paragraph.startIndex) ?? (0, _univerjs_core.getParagraphContentStartOffset)(body, paragraph),
2920
+ endOffset: paragraph.startIndex + 1
2921
+ }, resolverIndex);
2922
+ }
2923
+ function getDocumentSectionPermissionObjectIdsByIds(sectionIds) {
2924
+ return Array.from(sectionIds, (sectionId) => getDocumentSectionPermissionObjectId("", sectionId));
2925
+ }
2926
+ function getDocumentSectionIdsAtOffset(body, offset) {
2927
+ return getSectionsIntersectingRange(getTopLevelSectionBreaks(body), {
2928
+ startOffset: offset,
2929
+ endOffset: offset
2930
+ }).map((section) => section.sectionId);
2931
+ }
2932
+ function getSectionPermissionObjectIds(documentDataModel, segmentId, range, resolverIndex = getDocumentPermissionResolverIndex(documentDataModel)) {
2933
+ if (segmentId) {
2934
+ const referenceRange = resolverIndex.footnoteReferenceRanges.get(segmentId);
2935
+ if (referenceRange) return getDocumentEditTargetObjectIds(documentDataModel, "", referenceRange);
2936
+ return getHeaderFooterOwnerSectionIds(documentDataModel, segmentId, resolverIndex.topLevelSections).map((sectionId) => getDocumentSectionPermissionObjectId("", sectionId));
2937
+ }
2938
+ return getSectionsIntersectingRange(resolverIndex.topLevelSections, range).map((section) => getDocumentSectionPermissionObjectId("", section.sectionId));
2939
+ }
2940
+ function getParagraphPermissionObjectIds(body, segmentId, range, segmentIndex) {
2941
+ const startOffset = Math.min(range.startOffset, range.endOffset);
2942
+ const endOffset = Math.max(range.startOffset, range.endOffset);
2943
+ 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)] : []);
2944
+ }
2945
+ function getEntityPermissionObjectIds(segmentId, range, segmentIndex) {
2946
+ const startOffset = Math.min(range.startOffset, range.endOffset);
2947
+ const endOffset = Math.max(range.startOffset, range.endOffset);
2948
+ return segmentIndex.entities.filter((item) => intersectsRange(item.startOffset, item.endOffset, startOffset, endOffset)).map((item) => getDocumentEntityPermissionObjectId(segmentId, item.type, item.id));
2949
+ }
2950
+ function getSectionsIntersectingRange(sections, range) {
2951
+ const startOffset = Math.min(range.startOffset, range.endOffset);
2952
+ const endOffset = Math.max(range.startOffset, range.endOffset);
2953
+ return sections.filter((section, index) => intersectsRange(index === 0 ? 0 : sections[index - 1].startIndex + 1, section.startIndex + 1, startOffset, endOffset));
2954
+ }
2955
+ function intersectsRange(targetStart, targetEnd, rangeStart, rangeEnd) {
2956
+ if (rangeStart === rangeEnd) return rangeStart >= targetStart && rangeStart < targetEnd;
2957
+ return rangeStart < targetEnd && rangeEnd > targetStart;
2958
+ }
2959
+ function getHeaderFooterOwnerSectionIds(documentDataModel, segmentId, sections = getDocumentPermissionResolverIndex(documentDataModel).topLevelSections) {
2960
+ const snapshot = documentDataModel.getSnapshot();
2961
+ const result = /* @__PURE__ */ new Set();
2962
+ sections.forEach((section, sectionIndex) => {
2963
+ if (HEADER_FOOTER_REFERENCE_KEYS.some((key) => (0, _univerjs_core.resolveSectionHeaderFooterReference)(snapshot.documentStyle, sections, sectionIndex, key).segmentId === segmentId)) result.add(section.sectionId);
2964
+ });
2965
+ return [...result];
2966
+ }
2967
+
2968
+ //#endregion
2969
+ //#region src/controllers/doc-permission.controller.ts
2970
+ const NON_EDIT_DOCUMENT_COMMAND_IDS = /* @__PURE__ */ new Set([
2971
+ SetDocumentPermissionCommand.id,
2972
+ SetDocumentPermissionsCommand.id,
2973
+ "doc.command.open-header-footer-panel",
2974
+ "doc.command.close-header-footer",
2975
+ "doc.command.select-all",
2976
+ "doc.command.set-zoom-ratio"
2977
+ ]);
2978
+ const DERIVED_DOCUMENT_MUTATION_IDS = /* @__PURE__ */ new Set(["docs-formula.mutation.set-last-values"]);
2979
+ let DocPermissionController = class DocPermissionController extends _univerjs_core.Disposable {
2980
+ constructor(_injector, _commandService, _permissionService, _univerInstanceService) {
2981
+ super();
2982
+ this._injector = _injector;
2983
+ this._commandService = _commandService;
2984
+ this._permissionService = _permissionService;
2985
+ this._univerInstanceService = _univerInstanceService;
2986
+ this._univerInstanceService.getAllUnitsForType(_univerjs_core.UniverInstanceType.UNIVER_DOC).forEach((unit) => this._registerUnitPermissionPoints(unit.getUnitId()));
2987
+ this.disposeWithMe(this._univerInstanceService.getTypeOfUnitAdded$(_univerjs_core.UniverInstanceType.UNIVER_DOC).subscribe(({ unit }) => this._registerUnitPermissionPoints(unit.getUnitId())));
2988
+ this.disposeWithMe(this._commandService.beforeCommandExecuted((commandInfo, options) => {
2989
+ this._check(commandInfo, options);
2990
+ }));
2991
+ this.disposeWithMe(this._univerInstanceService.getTypeOfUnitDisposed$(_univerjs_core.UniverInstanceType.UNIVER_DOC).subscribe((unit) => {
2992
+ this._injector.get(_univerjs_core.ObjectPermissionService).clearUnit(unit.getUnitId());
2993
+ clearDocumentPermissionValuesForUnit(this._permissionService, unit.getUnitId());
2994
+ }));
2995
+ }
2996
+ _registerUnitPermissionPoints(unitId) {
2997
+ DOCUMENT_UNIT_PERMISSION_ACTIONS.forEach((action) => {
2998
+ const point = createDocumentPermissionPoint(unitId, unitId, action);
2999
+ if (!this._permissionService.getPermissionPoint(point.id)) this._permissionService.addPermissionPoint(point);
3000
+ });
3001
+ this._injector.get(_univerjs_core.ObjectPermissionService).initializeUnit({
3002
+ unitId,
3003
+ objectId: unitId,
3004
+ objectType: _univerjs_protocol.UnitObject.Document
3005
+ });
1494
3006
  }
1495
- _initSelectionChange() {
1496
- this.disposeWithMe(this._commandService.onCommandExecuted((commandInfo) => {
1497
- if (commandInfo.id === SetTextSelectionsOperation.id) {
1498
- const { unitId, ranges, isEditing } = commandInfo.params;
1499
- const doc = this._univerInstanceService.getUnit(unitId);
1500
- if (!doc) return;
1501
- const transformedRanges = ranges.map((range) => this._transformCustomRange(doc, range));
1502
- if (transformedRanges.some((range, i) => ranges[i] !== range)) this._textSelectionManagerService.replaceDocRanges(transformedRanges, void 0, isEditing);
3007
+ _check(commandInfo, options) {
3008
+ var _this$_univerInstance;
3009
+ if ((options === null || options === void 0 ? void 0 : options.fromCollab) || (options === null || options === void 0 ? void 0 : options.fromChangeset)) return;
3010
+ const unitAction = getDocumentUnitAction(commandInfo.id);
3011
+ 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);
3012
+ if (!unitId || this._univerInstanceService.getUnitType(unitId) !== _univerjs_core.UniverInstanceType.UNIVER_DOC) return;
3013
+ if (unitAction) {
3014
+ if (!getDocumentPermissionValue(this._permissionService, unitId, unitId, unitAction)) {
3015
+ this._injector.get(_univerjs_core.ErrorService).emitPermissionDenied(unitId);
3016
+ throw new _univerjs_core.CustomCommandExecutionError(`Document ${_univerjs_protocol.UnitAction[unitAction]} permission denied.`);
1503
3017
  }
1504
- }));
3018
+ return;
3019
+ }
3020
+ const documentDataModel = this._univerInstanceService.getUnit(unitId, _univerjs_core.UniverInstanceType.UNIVER_DOC);
3021
+ if (!documentDataModel) return;
3022
+ const targetObjectIds = this._resolveTargetObjectIds(documentDataModel, commandInfo);
3023
+ if (targetObjectIds === null) return;
3024
+ if (!canEditDocumentTargets(this._permissionService, unitId, targetObjectIds)) {
3025
+ this._injector.get(_univerjs_core.ErrorService).emitPermissionDenied(unitId, targetObjectIds);
3026
+ throw new _univerjs_core.CustomCommandExecutionError("Document edit permission denied.");
3027
+ }
3028
+ }
3029
+ _resolveTargetObjectIds(documentDataModel, commandInfo) {
3030
+ if (commandInfo.id === RichTextEditingMutation.id) {
3031
+ const params = commandInfo.params;
3032
+ return getDocumentEditTargetObjectIdsFromActions(documentDataModel, params.segmentId ?? "", params.actions);
3033
+ }
3034
+ if (commandInfo.id === DocsRenameMutation.id) return [];
3035
+ if (isDerivedDocumentMutation(commandInfo)) return null;
3036
+ const knownTargets = resolveTextTargets(documentDataModel, commandInfo) ?? resolveSectionTargets(documentDataModel, commandInfo);
3037
+ if (knownTargets) return knownTargets;
3038
+ const entityTargets = resolveEntityTargets(documentDataModel, commandInfo);
3039
+ if (entityTargets.length) return entityTargets;
3040
+ return isDocumentEditCommand(commandInfo.id) || isDocumentDataMutation(commandInfo) ? [] : null;
1505
3041
  }
1506
3042
  };
1507
- DocCustomRangeController = __decorate([
1508
- __decorateParam(0, _univerjs_core.ICommandService),
1509
- __decorateParam(1, (0, _univerjs_core.Inject)(DocSelectionManagerService)),
1510
- __decorateParam(2, _univerjs_core.IUniverInstanceService)
1511
- ], DocCustomRangeController);
3043
+ DocPermissionController = __decorate([
3044
+ __decorateParam(0, (0, _univerjs_core.Inject)(_univerjs_core.Injector)),
3045
+ __decorateParam(1, _univerjs_core.ICommandService),
3046
+ __decorateParam(2, _univerjs_core.IPermissionService),
3047
+ __decorateParam(3, _univerjs_core.IUniverInstanceService)
3048
+ ], DocPermissionController);
3049
+ function isDocumentEditCommand(id) {
3050
+ if (NON_EDIT_DOCUMENT_COMMAND_IDS.has(id)) return false;
3051
+ return id.startsWith("doc.command.") || id.startsWith("docs.command.") || id.startsWith("doc.command-") || id.startsWith("doc.table.");
3052
+ }
3053
+ function isDocumentDataMutation(commandInfo) {
3054
+ const { id } = commandInfo;
3055
+ if (isDerivedDocumentMutation(commandInfo)) return false;
3056
+ return id.startsWith("doc.mutation.") || id.startsWith("docs.mutation.") || /^docs-[^.]+\.mutation\./.test(id);
3057
+ }
3058
+ function isDerivedDocumentMutation(commandInfo) {
3059
+ const params = isRecord$1(commandInfo.params) ? commandInfo.params : void 0;
3060
+ return DERIVED_DOCUMENT_MUTATION_IDS.has(commandInfo.id) || commandInfo.id === "doc.mutation.update-shape-data" && !!(params === null || params === void 0 ? void 0 : params.formulaLastValueGuard);
3061
+ }
3062
+ function resolveEntityTargets(documentDataModel, commandInfo) {
3063
+ const params = commandInfo.params;
3064
+ if (!isRecord$1(params)) return [];
3065
+ const result = /* @__PURE__ */ new Set();
3066
+ const add = (segmentId, entityType, entityId) => {
3067
+ result.add(getDocumentEntityPermissionObjectId(segmentId, entityType, entityId));
3068
+ getDocumentEntityParentPermissionObjectIds(documentDataModel, segmentId, entityType, entityId).forEach((objectId) => result.add(objectId));
3069
+ };
3070
+ collectEntityReferences(params).forEach(({ entityType, entityId }) => {
3071
+ const explicitSegmentId = params.segmentId;
3072
+ const segmentId = typeof explicitSegmentId === "string" ? explicitSegmentId : entityType === "drawing" || entityType === "custom-block" ? getDocumentDrawingSegmentId(documentDataModel, entityId) : "";
3073
+ add(segmentId, entityType, entityId);
3074
+ });
3075
+ return [...result];
3076
+ }
3077
+ function collectEntityReferences(value) {
3078
+ const result = /* @__PURE__ */ new Map();
3079
+ const typeByKey = {
3080
+ blockId: ["custom-block"],
3081
+ drawingId: ["drawing"],
3082
+ shapeId: ["drawing", "custom-block"],
3083
+ tableId: ["table"],
3084
+ rangeId: ["custom-range"],
3085
+ columnGroupId: ["column-group"]
3086
+ };
3087
+ const visit = (candidate, key = "") => {
3088
+ if (typeof candidate === "string") {
3089
+ var _typeByKey$key;
3090
+ (_typeByKey$key = typeByKey[key]) === null || _typeByKey$key === void 0 || _typeByKey$key.forEach((entityType) => {
3091
+ result.set(`${entityType}\u001F${candidate}`, {
3092
+ entityType,
3093
+ entityId: candidate
3094
+ });
3095
+ });
3096
+ return;
3097
+ }
3098
+ if (Array.isArray(candidate)) {
3099
+ const singularKey = key.endsWith("Ids") ? `${key.slice(0, -3)}Id` : key;
3100
+ candidate.forEach((item) => visit(item, singularKey));
3101
+ return;
3102
+ }
3103
+ if (!isRecord$1(candidate)) return;
3104
+ Object.entries(candidate).forEach(([childKey, child]) => visit(child, childKey));
3105
+ };
3106
+ visit(value);
3107
+ return [...result.values()];
3108
+ }
3109
+ function getUnitId(commandInfo, options) {
3110
+ const params = isRecord$1(commandInfo.params) ? commandInfo.params : void 0;
3111
+ 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;
3112
+ }
3113
+ function getDocumentUnitAction(commandId) {
3114
+ if (commandId === "doc.command.copy-current-paragraph" || commandId === "docs-table.command.copy-selection") return _univerjs_protocol.UnitAction.Copy;
3115
+ if (commandId === "docs.operation.print") return _univerjs_protocol.UnitAction.Print;
3116
+ if (commandId === "docs-exchange-client.operation.export-doc") return _univerjs_protocol.UnitAction.Export;
3117
+ 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;
3118
+ }
3119
+ function resolveTextTargets(documentDataModel, commandInfo) {
3120
+ const { id } = commandInfo;
3121
+ if (id === InsertTextCommand.id || id === UpdateTextCommand.id) {
3122
+ const params = commandInfo.params;
3123
+ return getDocumentEditTargetObjectIds(documentDataModel, params.segmentId ?? "", params.range);
3124
+ }
3125
+ if (id === DeleteTextCommand.id) {
3126
+ const params = commandInfo.params;
3127
+ const isDeleteLeft = params.direction === _univerjs_core.DeleteDirection.LEFT;
3128
+ return getDocumentEditTargetObjectIds(documentDataModel, params.segmentId ?? "", {
3129
+ startOffset: isDeleteLeft ? params.range.startOffset - (params.len ?? 1) : params.range.startOffset,
3130
+ endOffset: isDeleteLeft ? params.range.startOffset : params.range.startOffset + (params.len ?? 1)
3131
+ });
3132
+ }
3133
+ if (id === UpdateDocumentParagraphStyleCommand.id) {
3134
+ const params = commandInfo.params;
3135
+ return getDocumentEditTargetObjectIds(documentDataModel, params.segmentId ?? "", params);
3136
+ }
3137
+ return null;
3138
+ }
3139
+ function resolveSectionTargets(documentDataModel, commandInfo) {
3140
+ const { id } = commandInfo;
3141
+ if (id === UpdateDocumentSectionCommand.id) {
3142
+ const params = commandInfo.params;
3143
+ return getDocumentSectionPermissionObjectIdsByIds(params.updates.map((update) => update.sectionId));
3144
+ }
3145
+ if (id === InsertDocumentSectionBreakCommand.id || id === InsertDocumentColumnBreakCommand.id) {
3146
+ const params = commandInfo.params;
3147
+ const body = documentDataModel.getBody();
3148
+ return body ? getDocumentSectionPermissionObjectIdsByIds(getDocumentSectionIdsAtOffset(body, params.offset)) : [];
3149
+ }
3150
+ if (id === DeleteDocumentSectionBreakCommand.id) {
3151
+ const params = commandInfo.params;
3152
+ const body = documentDataModel.getBody();
3153
+ const sections = body ? getTopLevelSectionBreaks(body) : [];
3154
+ const index = sections.findIndex((section) => section.sectionId === params.sectionId);
3155
+ return getDocumentSectionPermissionObjectIdsByIds([params.sectionId, ...index >= 0 && index + 1 < sections.length ? [sections[index + 1].sectionId] : []]);
3156
+ }
3157
+ if (id === SetSectionHeaderFooterLinkCommand.id) {
3158
+ const params = commandInfo.params;
3159
+ return [getDocumentSectionPermissionObjectId("", params.sectionId)];
3160
+ }
3161
+ if (id === CreateHeaderFooterCommand.id) {
3162
+ const params = commandInfo.params;
3163
+ return params.sectionId ? [getDocumentSectionPermissionObjectId("", params.sectionId)] : [];
3164
+ }
3165
+ return null;
3166
+ }
3167
+ function isRecord$1(value) {
3168
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3169
+ }
1512
3170
 
1513
3171
  //#endregion
1514
3172
  //#region src/services/doc-block-move-validator.service.ts
@@ -1605,6 +3263,9 @@ let DocStateChangeManagerService = class DocStateChangeManagerService extends _u
1605
3263
  this._historyStateCache.set(unitId, cache.history);
1606
3264
  this._changeStateCache.set(unitId, cache.collaboration);
1607
3265
  }
3266
+ clearHistory(unitId) {
3267
+ this._historyStateCache.delete(unitId);
3268
+ }
1608
3269
  _setChangeState(changeState) {
1609
3270
  this._cacheChangeState(changeState, "history");
1610
3271
  this._cacheChangeState(changeState, "collaboration");
@@ -1637,6 +3298,8 @@ let DocStateChangeManagerService = class DocStateChangeManagerService extends _u
1637
3298
  if (type === "history" && (trigger === _univerjs_core.RedoCommandId || trigger === _univerjs_core.UndoCommandId)) return;
1638
3299
  const stateCache = type === "history" ? this._historyStateCache : this._changeStateCache;
1639
3300
  const cb = type === "history" ? this._pushHistory.bind(this) : this._emitChangeState.bind(this);
3301
+ const pendingStates = stateCache.get(unitId);
3302
+ if ((pendingStates === null || pendingStates === void 0 ? void 0 : pendingStates.length) && pendingStates[pendingStates.length - 1].segmentId !== changeState.segmentId) cb(unitId);
1640
3303
  if (stateCache.has(unitId)) {
1641
3304
  const cacheStates = stateCache.get(unitId);
1642
3305
  cacheStates === null || cacheStates === void 0 || cacheStates.push(changeState);
@@ -1665,12 +3328,18 @@ let DocStateChangeManagerService = class DocStateChangeManagerService extends _u
1665
3328
  const redoParams = {
1666
3329
  unitId,
1667
3330
  actions: cacheStates.reduce((acc, cur) => _univerjs_core.JSONX.compose(acc, cur.redoState.actions), null),
1668
- textRanges: lastState.redoState.textRanges
3331
+ textRanges: lastState.redoState.textRanges,
3332
+ segmentId: lastState.segmentId,
3333
+ options: lastState.redoState.options,
3334
+ isEditing: lastState.redoState.isEditing
1669
3335
  };
1670
3336
  const undoParams = {
1671
3337
  unitId,
1672
3338
  actions: cacheStates.reverse().reduce((acc, cur) => _univerjs_core.JSONX.compose(acc, cur.undoState.actions), null),
1673
- textRanges: firstState.undoState.textRanges
3339
+ textRanges: firstState.undoState.textRanges,
3340
+ segmentId: firstState.segmentId,
3341
+ options: firstState.undoState.options,
3342
+ isEditing: firstState.undoState.isEditing
1674
3343
  };
1675
3344
  undoRedoService.pushUndoRedo({
1676
3345
  unitID: unitId,
@@ -1699,12 +3368,18 @@ let DocStateChangeManagerService = class DocStateChangeManagerService extends _u
1699
3368
  redoState: {
1700
3369
  unitId,
1701
3370
  actions: cacheStates.reduce((acc, cur) => _univerjs_core.JSONX.compose(acc, cur.redoState.actions), null),
1702
- textRanges: lastState.redoState.textRanges
3371
+ textRanges: lastState.redoState.textRanges,
3372
+ segmentId: lastState.segmentId,
3373
+ options: lastState.redoState.options,
3374
+ isEditing: lastState.redoState.isEditing
1703
3375
  },
1704
3376
  undoState: {
1705
3377
  unitId,
1706
3378
  actions: cacheStates.reverse().reduce((acc, cur) => _univerjs_core.JSONX.compose(acc, cur.undoState.actions), null),
1707
- textRanges: firstState.undoState.textRanges
3379
+ textRanges: firstState.undoState.textRanges,
3380
+ segmentId: firstState.segmentId,
3381
+ options: firstState.undoState.options,
3382
+ isEditing: firstState.undoState.isEditing
1708
3383
  },
1709
3384
  segmentId,
1710
3385
  noHistory,
@@ -1807,6 +3482,10 @@ let UniverDocsPlugin = class UniverDocsPlugin extends _univerjs_core.Plugin {
1807
3482
  this._configService.setConfig(DOCS_PLUGIN_CONFIG_KEY, rest);
1808
3483
  }
1809
3484
  onStarting() {
3485
+ this._injector.add([DocumentPermissionRuleModel]);
3486
+ this.disposeWithMe(this._injector.get(_univerjs_core.ICommandService).registerCommand(SetDocumentPermissionRuleMutation));
3487
+ this.disposeWithMe(this._injector.get(_univerjs_core.ICommandService).registerCommand(SetDocumentPermissionRulesMutation));
3488
+ this.disposeWithMe(this._injector.get(_univerjs_core.ObjectPermissionService).registerRuleModel(_univerjs_protocol.UnitObject.Document, this._injector.get(DocumentPermissionRuleModel), SetDocumentPermissionRuleMutation.id, SetDocumentPermissionRulesMutation.id));
1810
3489
  this._initializeDependencies();
1811
3490
  this._initializeCommands();
1812
3491
  }
@@ -1816,6 +3495,8 @@ let UniverDocsPlugin = class UniverDocsPlugin extends _univerjs_core.Plugin {
1816
3495
  DeleteTextCommand,
1817
3496
  UpdateTextCommand,
1818
3497
  CreateHeaderFooterCommand,
3498
+ SetDocumentPermissionCommand,
3499
+ SetDocumentPermissionsCommand,
1819
3500
  SetDocumentDefaultParagraphStyleCommand,
1820
3501
  SetDocumentNameCommand,
1821
3502
  SetSectionHeaderFooterLinkCommand,
@@ -1838,13 +3519,16 @@ let UniverDocsPlugin = class UniverDocsPlugin extends _univerjs_core.Plugin {
1838
3519
  [DocStateChangeManagerService],
1839
3520
  [DocBlockMoveValidatorService],
1840
3521
  [DocContentInsertService],
3522
+ [DocLayoutExecutorService],
1841
3523
  [DocTextResolverService],
1842
- [DocCustomRangeController]
3524
+ [DocCustomRangeController],
3525
+ [DocPermissionController]
1843
3526
  ].forEach((d) => this._injector.add(d));
1844
3527
  }
1845
3528
  onReady() {
1846
3529
  this._injector.get(DocStateChangeManagerService);
1847
3530
  this._injector.get(DocCustomRangeController);
3531
+ this._injector.get(DocPermissionController);
1848
3532
  }
1849
3533
  };
1850
3534
  _defineProperty(UniverDocsPlugin, "pluginName", "DOCS_PLUGIN");
@@ -1852,6 +3536,655 @@ _defineProperty(UniverDocsPlugin, "packageName", name);
1852
3536
  _defineProperty(UniverDocsPlugin, "version", version);
1853
3537
  UniverDocsPlugin = __decorate([__decorateParam(1, (0, _univerjs_core.Inject)(_univerjs_core.Injector)), __decorateParam(2, _univerjs_core.IConfigService)], UniverDocsPlugin);
1854
3538
 
3539
+ //#endregion
3540
+ //#region src/layout-worker/config/config.ts
3541
+ /**
3542
+ * Copyright 2023-present DreamNum Co., Ltd.
3543
+ *
3544
+ * Licensed under the Apache License, Version 2.0 (the "License");
3545
+ * you may not use this file except in compliance with the License.
3546
+ * You may obtain a copy of the License at
3547
+ *
3548
+ * http://www.apache.org/licenses/LICENSE-2.0
3549
+ *
3550
+ * Unless required by applicable law or agreed to in writing, software
3551
+ * distributed under the License is distributed on an "AS IS" BASIS,
3552
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3553
+ * See the License for the specific language governing permissions and
3554
+ * limitations under the License.
3555
+ */
3556
+ const DOCS_LAYOUT_WORKER_PLUGIN_CONFIG_KEY = "docs-layout-worker.config";
3557
+ const configSymbol = Symbol(DOCS_LAYOUT_WORKER_PLUGIN_CONFIG_KEY);
3558
+ const DEFAULT_DOCS_LAYOUT_WORKER_REQUEST_TIMEOUT_MS = 15e3;
3559
+ const defaultPluginDocsLayoutWorkerConfig = { requestTimeoutMs: DEFAULT_DOCS_LAYOUT_WORKER_REQUEST_TIMEOUT_MS };
3560
+
3561
+ //#endregion
3562
+ //#region src/layout-worker/document-font-metrics.ts
3563
+ /**
3564
+ * Copyright 2023-present DreamNum Co., Ltd.
3565
+ *
3566
+ * Licensed under the Apache License, Version 2.0 (the "License");
3567
+ * you may not use this file except in compliance with the License.
3568
+ * You may obtain a copy of the License at
3569
+ *
3570
+ * http://www.apache.org/licenses/LICENSE-2.0
3571
+ *
3572
+ * Unless required by applicable law or agreed to in writing, software
3573
+ * distributed under the License is distributed on an "AS IS" BASIS,
3574
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3575
+ * See the License for the specific language governing permissions and
3576
+ * limitations under the License.
3577
+ */
3578
+ /** Collect once from the snapshot, then only from mutation payloads (including JSON1 font replacements). */
3579
+ function collectDocumentFontFamilies(value, families) {
3580
+ if (value == null || typeof value !== "object") return;
3581
+ if (Array.isArray(value)) {
3582
+ for (let index = 0; index < value.length; index++) {
3583
+ const item = value[index];
3584
+ if (value[index - 1] === "ff" && item != null && typeof item === "object" && typeof item.i === "string") families.add(item.i);
3585
+ collectDocumentFontFamilies(item, families);
3586
+ }
3587
+ return;
3588
+ }
3589
+ for (const [key, item] of Object.entries(value)) if (key === "ff" && typeof item === "string") families.add(item);
3590
+ else collectDocumentFontFamilies(item, families);
3591
+ }
3592
+ function measureDocumentFontFamilies(families) {
3593
+ _univerjs_engine_render.FontCache.getNormalLineHeight((0, _univerjs_engine_render.getFontStyleString)());
3594
+ 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)({
3595
+ ff,
3596
+ bl,
3597
+ it
3598
+ }));
3599
+ return _univerjs_engine_render.FontCache.getNormalLineHeightCache();
3600
+ }
3601
+
3602
+ //#endregion
3603
+ //#region src/layout-worker/performance-tracker.ts
3604
+ const PERFORMANCE_SAMPLE_LIMIT = 2048;
3605
+ function isRecord(value) {
3606
+ return typeof value === "object" && value != null;
3607
+ }
3608
+ function getRequest(message) {
3609
+ if (!isRecord(message) || typeof message.method !== "string" || !Array.isArray(message.args)) return null;
3610
+ const request = message.args[0];
3611
+ return isRecord(request) ? {
3612
+ method: message.method,
3613
+ request
3614
+ } : null;
3615
+ }
3616
+ function getPublicationResult(message) {
3617
+ if (!isRecord(message) || !isRecord(message.data)) return null;
3618
+ const result = message.data;
3619
+ if (isRecord(result.step)) return result.step;
3620
+ return result;
3621
+ }
3622
+ function createTransferMetrics() {
3623
+ return {
3624
+ mutationTransferMs: [],
3625
+ patchTransferMs: [],
3626
+ snapshotTransferMs: []
3627
+ };
3628
+ }
3629
+ var DocsLayoutWorkerPerformanceTracker = class {
3630
+ constructor() {
3631
+ _defineProperty(this, "_metrics", /* @__PURE__ */ new Map());
3632
+ }
3633
+ recordRequest(message, durationMs) {
3634
+ const requestInfo = getRequest(message);
3635
+ const unitId = requestInfo === null || requestInfo === void 0 ? void 0 : requestInfo.request.unitId;
3636
+ if (requestInfo == null || typeof unitId !== "string") return;
3637
+ if (requestInfo.method === "createSession") {
3638
+ this._append(unitId, "snapshotTransferMs", durationMs);
3639
+ return;
3640
+ }
3641
+ if (requestInfo.method === "startLayout" && Array.isArray(requestInfo.request.mutations) && requestInfo.request.mutations.length > 0) this._append(unitId, "mutationTransferMs", durationMs);
3642
+ }
3643
+ recordResponse(message, durationMs) {
3644
+ const result = getPublicationResult(message);
3645
+ if (result == null || typeof result.unitId !== "string" || result.publication == null) return;
3646
+ this._append(result.unitId, "patchTransferMs", durationMs);
3647
+ }
3648
+ getMetrics(unitId) {
3649
+ const metrics = this._metrics.get(unitId) ?? createTransferMetrics();
3650
+ return {
3651
+ mutationTransferMs: [...metrics.mutationTransferMs],
3652
+ patchTransferMs: [...metrics.patchTransferMs],
3653
+ snapshotTransferMs: [...metrics.snapshotTransferMs]
3654
+ };
3655
+ }
3656
+ reset(unitId) {
3657
+ this._metrics.delete(unitId);
3658
+ }
3659
+ resetAll() {
3660
+ this._metrics.clear();
3661
+ }
3662
+ _append(unitId, metric, durationMs) {
3663
+ const metrics = this._metrics.get(unitId) ?? createTransferMetrics();
3664
+ const samples = metrics[metric];
3665
+ samples.push(durationMs);
3666
+ if (samples.length > PERFORMANCE_SAMPLE_LIMIT) samples.splice(0, samples.length - PERFORMANCE_SAMPLE_LIMIT);
3667
+ this._metrics.set(unitId, metrics);
3668
+ }
3669
+ };
3670
+
3671
+ //#endregion
3672
+ //#region src/layout-worker/protocol.ts
3673
+ const DOCS_LAYOUT_WORKER_CHANNEL = "univer.docs-layout-worker";
3674
+
3675
+ //#endregion
3676
+ //#region src/layout-worker/worker.ts
3677
+ const FONT_PROBE_CONTENT = "Univer 文档 Worker 0123456789";
3678
+ const FONT_PROBE_STYLE = "16px Arial";
3679
+ const WORKER_LAYOUT_INTERRUPT_INTERVAL = 8;
3680
+ function yieldForWorkerMessage() {
3681
+ return new Promise((resolve) => {
3682
+ (0, _univerjs_core.requestImmediateMacroTask)(() => resolve());
3683
+ });
3684
+ }
3685
+ function createDocsLayoutWorkerMessageProtocol$1(performanceTracker) {
3686
+ return {
3687
+ send(message) {
3688
+ const startedAt = _univerjs_core.Tools.now();
3689
+ postMessage(message);
3690
+ performanceTracker.recordResponse(message, _univerjs_core.Tools.now() - startedAt);
3691
+ },
3692
+ onMessage: new rxjs.Observable((subscriber) => {
3693
+ const handler = (event) => subscriber.next(event.data);
3694
+ addEventListener("message", handler);
3695
+ return () => removeEventListener("message", handler);
3696
+ }).pipe((0, rxjs.shareReplay)({
3697
+ bufferSize: 1,
3698
+ refCount: true
3699
+ }))
3700
+ };
3701
+ }
3702
+ function getCustomRangePresentationKey(entry) {
3703
+ return JSON.stringify([entry.segmentId, entry.rangeId]);
3704
+ }
3705
+ function applyRecordPatch(target, patch) {
3706
+ if (patch == null) return;
3707
+ for (const key of patch.removals) delete target[key];
3708
+ Object.assign(target, patch.upserts);
3709
+ }
3710
+ var DocsLayoutWorkerRuntime = class {
3711
+ constructor(_performanceTracker = new DocsLayoutWorkerPerformanceTracker()) {
3712
+ this._performanceTracker = _performanceTracker;
3713
+ _defineProperty(this, "_sessions", /* @__PURE__ */ new Map());
3714
+ _defineProperty(this, "type", "worker");
3715
+ }
3716
+ initialize() {
3717
+ return Promise.resolve();
3718
+ }
3719
+ async getCapabilities() {
3720
+ const metrics = _univerjs_engine_render.FontCache.getMeasureText(FONT_PROBE_CONTENT, FONT_PROBE_STYLE);
3721
+ return {
3722
+ protocolVersion: 5,
3723
+ executor: "worker",
3724
+ offscreenCanvas: typeof OffscreenCanvas !== "undefined",
3725
+ structuredClone: typeof structuredClone === "function",
3726
+ fontProbe: {
3727
+ content: FONT_PROBE_CONTENT,
3728
+ font: FONT_PROBE_STYLE,
3729
+ width: metrics.width,
3730
+ actualBoundingBoxAscent: metrics.actualBoundingBoxAscent,
3731
+ actualBoundingBoxDescent: metrics.actualBoundingBoxDescent
3732
+ }
3733
+ };
3734
+ }
3735
+ async recover() {
3736
+ for (const session of this._sessions.values()) for (const mount of session.layoutSessions.values()) mount.layoutSession.dispose();
3737
+ this._sessions.clear();
3738
+ }
3739
+ async createSession(request) {
3740
+ if (typeof OffscreenCanvas === "undefined") throw new Error("Document layout Worker requires OffscreenCanvas text measurement support.");
3741
+ const currentSession = this._sessions.get(request.unitId);
3742
+ if (currentSession != null && request.sessionEpoch < currentSession.sessionEpoch) return;
3743
+ this._disposeSession(request.unitId);
3744
+ _univerjs_engine_render.FontCache.setNormalLineHeightCache(request.normalFontLineHeights ?? {});
3745
+ const dataModel = new _univerjs_core.DocumentDataModel(request.snapshot);
3746
+ const localeService = new _univerjs_core.LocaleService();
3747
+ if (request.localeData != null) localeService.load({ [request.locale]: request.localeData });
3748
+ localeService.setLocale(request.locale);
3749
+ localeService.setDirection(request.direction);
3750
+ this._sessions.set(request.unitId, {
3751
+ sessionEpoch: request.sessionEpoch,
3752
+ dataModel,
3753
+ layoutSessions: /* @__PURE__ */ new Map(),
3754
+ localeService,
3755
+ modelRevision: request.modelRevision,
3756
+ customRangePresentations: /* @__PURE__ */ new Map()
3757
+ });
3758
+ }
3759
+ async startLayout(request) {
3760
+ const session = this._sessions.get(request.unitId);
3761
+ if (session == null) return { status: "not-found" };
3762
+ if (session.modelRevision !== request.baseRevision) return {
3763
+ status: "resnapshot-required",
3764
+ modelRevision: session.modelRevision
3765
+ };
3766
+ if (!this._applyMutations(session, request)) return {
3767
+ status: "resnapshot-required",
3768
+ modelRevision: session.modelRevision
3769
+ };
3770
+ _univerjs_engine_render.FontCache.setNormalLineHeightCache(request.normalFontLineHeights ?? {});
3771
+ this._updateCustomRangePresentations(session, request);
3772
+ this._applyCustomRangePresentations(session.dataModel, Array.from(session.customRangePresentations.values()));
3773
+ let mount = session.layoutSessions.get(request.mountId);
3774
+ if (mount != null && (request.mountEpoch < mount.mountEpoch || request.mountEpoch === mount.mountEpoch && request.viewportEpoch < mount.viewportEpoch)) return { status: "superseded" };
3775
+ if (mount != null && request.mountEpoch > mount.mountEpoch) {
3776
+ mount.layoutSession.dispose();
3777
+ session.layoutSessions.delete(request.mountId);
3778
+ mount = void 0;
3779
+ }
3780
+ if (mount == null) {
3781
+ const customBlockViewports = { ...request.customBlockViewports };
3782
+ applyRecordPatch(customBlockViewports, request.customBlockViewportPatch);
3783
+ mount = {
3784
+ mountId: request.mountId,
3785
+ layoutSession: new _univerjs_engine_render.DocumentLayoutSession(session.dataModel, session.localeService),
3786
+ customBlockViewports,
3787
+ metricsRevision: request.metricsRevision,
3788
+ mountEpoch: request.mountEpoch,
3789
+ viewportEpoch: request.viewportEpoch,
3790
+ activeGeneration: null,
3791
+ cancelledGeneration: null
3792
+ };
3793
+ session.layoutSessions.set(request.mountId, mount);
3794
+ } else {
3795
+ if (request.customBlockViewports != null) mount.customBlockViewports = { ...request.customBlockViewports };
3796
+ applyRecordPatch(mount.customBlockViewports, request.customBlockViewportPatch);
3797
+ mount.metricsRevision = request.metricsRevision;
3798
+ mount.viewportEpoch = request.viewportEpoch;
3799
+ }
3800
+ const generation = mount.layoutSession.start({
3801
+ waitForHyphenationPatterns: true,
3802
+ reason: request.reason,
3803
+ anchor: request.anchor,
3804
+ priorityAnchor: request.priorityAnchor,
3805
+ invalidation: request.invalidation
3806
+ });
3807
+ mount.activeGeneration = generation;
3808
+ mount.cancelledGeneration = null;
3809
+ return {
3810
+ status: "accepted",
3811
+ step: await this._runLayoutStep(session, mount, generation, request.budgetMs)
3812
+ };
3813
+ }
3814
+ _applyMutations(session, request) {
3815
+ for (const mutation of request.mutations) {
3816
+ if (mutation.baseRevision !== session.modelRevision || mutation.modelRevision !== mutation.baseRevision + 1) return false;
3817
+ session.dataModel.apply(mutation.actions);
3818
+ session.modelRevision = mutation.modelRevision;
3819
+ }
3820
+ if (session.modelRevision !== request.modelRevision) return false;
3821
+ if (request.mutations.length > 0) for (const mount of session.layoutSessions.values()) {
3822
+ mount.activeGeneration = null;
3823
+ mount.cancelledGeneration = null;
3824
+ mount.layoutSession.resetDataModel(session.dataModel);
3825
+ }
3826
+ return true;
3827
+ }
3828
+ _applyCustomRangePresentations(dataModel, presentations) {
3829
+ const rangeMaps = /* @__PURE__ */ new Map();
3830
+ const segmentModels = [
3831
+ ["", dataModel],
3832
+ ...dataModel.headerModelMap,
3833
+ ...dataModel.footerModelMap
3834
+ ];
3835
+ for (const [segmentId, segmentModel] of segmentModels) {
3836
+ var _segmentModel$getBody;
3837
+ const rangeMap = /* @__PURE__ */ new Map();
3838
+ for (const range of ((_segmentModel$getBody = segmentModel.getBody()) === null || _segmentModel$getBody === void 0 ? void 0 : _segmentModel$getBody.customRanges) ?? []) {
3839
+ const workerRange = range;
3840
+ delete workerRange.active;
3841
+ delete workerRange.glyphAscentEm;
3842
+ delete workerRange.glyphDescentEm;
3843
+ delete workerRange.glyphWidthEm;
3844
+ delete workerRange.show;
3845
+ if (!rangeMap.has(range.rangeId)) rangeMap.set(range.rangeId, workerRange);
3846
+ }
3847
+ rangeMaps.set(segmentId, rangeMap);
3848
+ }
3849
+ for (const { segmentId, rangeId, presentation } of presentations ?? []) {
3850
+ const rangeMap = rangeMaps.get(segmentId);
3851
+ const range = rangeMap === null || rangeMap === void 0 ? void 0 : rangeMap.get(rangeId);
3852
+ if (range != null) {
3853
+ Object.assign(range, presentation);
3854
+ rangeMap === null || rangeMap === void 0 || rangeMap.delete(rangeId);
3855
+ }
3856
+ }
3857
+ }
3858
+ _updateCustomRangePresentations(session, request) {
3859
+ var _request$customRangeP, _request$customRangeP2;
3860
+ if (request.customRangePresentations != null) {
3861
+ session.customRangePresentations.clear();
3862
+ for (const entry of request.customRangePresentations) {
3863
+ const key = getCustomRangePresentationKey(entry);
3864
+ if (!session.customRangePresentations.has(key)) session.customRangePresentations.set(key, entry);
3865
+ }
3866
+ }
3867
+ for (const removal of ((_request$customRangeP = request.customRangePresentationPatch) === null || _request$customRangeP === void 0 ? void 0 : _request$customRangeP.removals) ?? []) session.customRangePresentations.delete(getCustomRangePresentationKey(removal));
3868
+ for (const entry of ((_request$customRangeP2 = request.customRangePresentationPatch) === null || _request$customRangeP2 === void 0 ? void 0 : _request$customRangeP2.upserts) ?? []) session.customRangePresentations.set(getCustomRangePresentationKey(entry), entry);
3869
+ }
3870
+ async stepLayout(request) {
3871
+ const session = this._getSession(request.unitId);
3872
+ const mount = this._getLayoutMount(session, request);
3873
+ return await this._runLayoutStep(session, mount, request.generation, request.budgetMs);
3874
+ }
3875
+ async publishBacklog(request) {
3876
+ const session = this._getSession(request.unitId);
3877
+ const mount = this._getLayoutMount(session, request);
3878
+ return this._runWithCustomBlockViewports(session, mount, () => ({
3879
+ ...mount.layoutSession.publishBacklog(request.generation),
3880
+ unitId: request.unitId,
3881
+ mountId: request.mountId,
3882
+ mountEpoch: mount.mountEpoch,
3883
+ viewportEpoch: mount.viewportEpoch,
3884
+ modelRevision: session.modelRevision,
3885
+ metricsRevision: mount.metricsRevision
3886
+ }));
3887
+ }
3888
+ async getLayoutPage(request) {
3889
+ const session = this._getSession(request.unitId);
3890
+ const mount = this._getLayoutMount(session, request);
3891
+ return {
3892
+ ...request,
3893
+ modelRevision: session.modelRevision,
3894
+ metricsRevision: mount.metricsRevision,
3895
+ page: mount.layoutSession.getPage(request.pageIndex)
3896
+ };
3897
+ }
3898
+ async cancelLayout(request) {
3899
+ var _this$_sessions$get;
3900
+ 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);
3901
+ if ((mount === null || mount === void 0 ? void 0 : mount.mountEpoch) === request.mountEpoch && mount.viewportEpoch === request.viewportEpoch) {
3902
+ if (request.generation == null || request.generation === mount.activeGeneration) mount.cancelledGeneration = request.generation ?? mount.activeGeneration;
3903
+ mount.layoutSession.cancel(request.generation);
3904
+ }
3905
+ }
3906
+ async getPerformanceMetrics(unitId) {
3907
+ return this._performanceTracker.getMetrics(unitId);
3908
+ }
3909
+ async resetPerformanceMetrics(unitId) {
3910
+ this._performanceTracker.reset(unitId);
3911
+ }
3912
+ async disposeLayoutMount(request) {
3913
+ const session = this._sessions.get(request.unitId);
3914
+ const mount = session === null || session === void 0 ? void 0 : session.layoutSessions.get(request.mountId);
3915
+ if (session == null || mount == null || mount.mountEpoch !== request.mountEpoch || mount.viewportEpoch !== request.viewportEpoch) return;
3916
+ session.layoutSessions.delete(request.mountId);
3917
+ mount.activeGeneration = null;
3918
+ mount.layoutSession.dispose();
3919
+ }
3920
+ async disposeSession(request) {
3921
+ const session = this._sessions.get(request.unitId);
3922
+ if ((session === null || session === void 0 ? void 0 : session.sessionEpoch) !== request.sessionEpoch) return;
3923
+ this._disposeSession(request.unitId);
3924
+ this._performanceTracker.reset(request.unitId);
3925
+ }
3926
+ dispose() {
3927
+ for (const unitId of this._sessions.keys()) this._disposeSession(unitId);
3928
+ this._performanceTracker.resetAll();
3929
+ }
3930
+ _getSession(unitId) {
3931
+ const session = this._sessions.get(unitId);
3932
+ if (session == null) throw new Error(`Document layout Worker session not found for unit "${unitId}".`);
3933
+ return session;
3934
+ }
3935
+ _getLayoutMount(session, request) {
3936
+ const mount = session.layoutSessions.get(request.mountId);
3937
+ if (mount == null) throw new Error(`Document layout Worker mount not found: "${request.mountId}".`);
3938
+ if (mount.mountEpoch !== request.mountEpoch || mount.viewportEpoch !== request.viewportEpoch) throw new Error(`Document layout Worker rejected a stale mount publication: "${request.mountId}".`);
3939
+ return mount;
3940
+ }
3941
+ async _runLayoutStep(session, mount, generation, budgetMs) {
3942
+ const result = this._runWithCustomBlockViewports(session, mount, () => ({
3943
+ ...mount.layoutSession.step(generation, budgetMs, WORKER_LAYOUT_INTERRUPT_INTERVAL),
3944
+ unitId: session.dataModel.getUnitId(),
3945
+ mountId: mount.mountId,
3946
+ mountEpoch: mount.mountEpoch,
3947
+ viewportEpoch: mount.viewportEpoch,
3948
+ modelRevision: session.modelRevision,
3949
+ metricsRevision: mount.metricsRevision
3950
+ }));
3951
+ await yieldForWorkerMessage();
3952
+ if (mount.activeGeneration === generation && mount.cancelledGeneration !== generation) return result;
3953
+ return this._runWithCustomBlockViewports(session, mount, () => ({
3954
+ ...mount.layoutSession.step(generation, 0, 1),
3955
+ unitId: session.dataModel.getUnitId(),
3956
+ mountId: mount.mountId,
3957
+ mountEpoch: mount.mountEpoch,
3958
+ viewportEpoch: mount.viewportEpoch,
3959
+ modelRevision: session.modelRevision,
3960
+ metricsRevision: mount.metricsRevision
3961
+ }));
3962
+ }
3963
+ _runWithCustomBlockViewports(session, mount, run) {
3964
+ const unregister = (0, _univerjs_engine_render.setDocsCustomBlockRenderViewportProvider)((unitId, blockId) => unitId === session.dataModel.getUnitId() ? mount.customBlockViewports[blockId] : null);
3965
+ try {
3966
+ return run();
3967
+ } finally {
3968
+ unregister();
3969
+ }
3970
+ }
3971
+ _disposeSession(unitId) {
3972
+ const session = this._sessions.get(unitId);
3973
+ if (session == null) return;
3974
+ this._sessions.delete(unitId);
3975
+ for (const mount of session.layoutSessions.values()) {
3976
+ mount.activeGeneration = null;
3977
+ mount.layoutSession.dispose();
3978
+ }
3979
+ session.layoutSessions.clear();
3980
+ session.dataModel.dispose();
3981
+ session.localeService.dispose();
3982
+ }
3983
+ };
3984
+ function startDocsLayoutWorker() {
3985
+ const performanceTracker = new DocsLayoutWorkerPerformanceTracker();
3986
+ const channelService = new _univerjs_rpc.ChannelService(createDocsLayoutWorkerMessageProtocol$1(performanceTracker));
3987
+ channelService.registerChannel(DOCS_LAYOUT_WORKER_CHANNEL, (0, _univerjs_rpc.fromModule)(new DocsLayoutWorkerRuntime(performanceTracker)));
3988
+ return channelService;
3989
+ }
3990
+
3991
+ //#endregion
3992
+ //#region src/layout-worker/index.ts
3993
+ const FONT_METRICS_TOLERANCE = 1;
3994
+ var DocsLayoutWorkerCapabilityError = class extends Error {
3995
+ constructor(message) {
3996
+ super(message);
3997
+ this.name = "DocsLayoutWorkerCapabilityError";
3998
+ }
3999
+ };
4000
+ function createDocsLayoutWorkerMessageProtocol(worker, performanceTracker) {
4001
+ return {
4002
+ send(message) {
4003
+ const startedAt = _univerjs_core.Tools.now();
4004
+ worker.postMessage(message);
4005
+ performanceTracker.recordRequest(message, _univerjs_core.Tools.now() - startedAt);
4006
+ },
4007
+ onMessage: new rxjs.Observable((subscriber) => {
4008
+ const handler = (event) => subscriber.next(event.data);
4009
+ worker.addEventListener("message", handler);
4010
+ return () => worker.removeEventListener("message", handler);
4011
+ }).pipe((0, rxjs.shareReplay)({
4012
+ bufferSize: 1,
4013
+ refCount: true
4014
+ }))
4015
+ };
4016
+ }
4017
+ var DocsLayoutWorkerClientService = class extends _univerjs_core.Disposable {
4018
+ constructor(_workerFactory, _requestTimeoutMs = DEFAULT_DOCS_LAYOUT_WORKER_REQUEST_TIMEOUT_MS) {
4019
+ super();
4020
+ this._workerFactory = _workerFactory;
4021
+ this._requestTimeoutMs = _requestTimeoutMs;
4022
+ _defineProperty(this, "type", "worker");
4023
+ _defineProperty(this, "_worker", null);
4024
+ _defineProperty(this, "_channelService", null);
4025
+ _defineProperty(this, "_runtime", null);
4026
+ _defineProperty(this, "_initialization", void 0);
4027
+ _defineProperty(this, "_initialized", false);
4028
+ _defineProperty(this, "_performanceTracker", new DocsLayoutWorkerPerformanceTracker());
4029
+ _defineProperty(this, "_fontFamilies", /* @__PURE__ */ new Map());
4030
+ this._initialization = this._replaceRuntime();
4031
+ }
4032
+ initialize() {
4033
+ return this._initialization;
4034
+ }
4035
+ getCapabilities() {
4036
+ return this._getRuntime().getCapabilities();
4037
+ }
4038
+ async recover() {
4039
+ this._initialization = this._replaceRuntime();
4040
+ await this._initialization;
4041
+ }
4042
+ createSession(request) {
4043
+ const families = /* @__PURE__ */ new Set();
4044
+ collectDocumentFontFamilies(request.snapshot, families);
4045
+ this._fontFamilies.set(request.unitId, families);
4046
+ const measuredRequest = {
4047
+ ...request,
4048
+ normalFontLineHeights: measureDocumentFontFamilies(families)
4049
+ };
4050
+ if (this._initialized) return this._withTimeout(this._getRuntime().createSession(measuredRequest), "create session");
4051
+ const capturedRequest = _univerjs_core.Tools.deepClone(measuredRequest);
4052
+ return this._initialization.then(() => this._withTimeout(this._getRuntime().createSession(capturedRequest), "create session"));
4053
+ }
4054
+ async startLayout(request) {
4055
+ await this._initialization;
4056
+ const families = this._fontFamilies.get(request.unitId);
4057
+ if (families != null) collectDocumentFontFamilies(request.mutations, families);
4058
+ const measuredRequest = families == null ? request : {
4059
+ ...request,
4060
+ normalFontLineHeights: measureDocumentFontFamilies(families)
4061
+ };
4062
+ return this._withTimeout(this._getRuntime().startLayout(measuredRequest), "start layout");
4063
+ }
4064
+ async stepLayout(request) {
4065
+ await this._initialization;
4066
+ return this._withTimeout(this._getRuntime().stepLayout(request), "step layout");
4067
+ }
4068
+ async publishBacklog(request) {
4069
+ await this._initialization;
4070
+ return this._withTimeout(this._getRuntime().publishBacklog(request), "publish layout backlog");
4071
+ }
4072
+ async getLayoutPage(request) {
4073
+ await this._initialization;
4074
+ return this._withTimeout(this._getRuntime().getLayoutPage(request), "get layout page");
4075
+ }
4076
+ async cancelLayout(request) {
4077
+ await this._initialization;
4078
+ return this._withTimeout(this._getRuntime().cancelLayout(request), "cancel layout");
4079
+ }
4080
+ async getPerformanceMetrics(unitId) {
4081
+ await this._initialization;
4082
+ const workerMetrics = await this._withTimeout(this._getRuntime().getPerformanceMetrics(unitId), "read performance metrics");
4083
+ const clientMetrics = this._performanceTracker.getMetrics(unitId);
4084
+ return {
4085
+ mutationTransferMs: clientMetrics.mutationTransferMs,
4086
+ patchTransferMs: workerMetrics.patchTransferMs,
4087
+ snapshotTransferMs: clientMetrics.snapshotTransferMs
4088
+ };
4089
+ }
4090
+ async resetPerformanceMetrics(unitId) {
4091
+ await this._initialization;
4092
+ await this._withTimeout(this._getRuntime().resetPerformanceMetrics(unitId), "reset performance metrics");
4093
+ this._performanceTracker.reset(unitId);
4094
+ }
4095
+ async disposeLayoutMount(request) {
4096
+ await this._initialization;
4097
+ return this._withTimeout(this._getRuntime().disposeLayoutMount(request), "dispose layout mount");
4098
+ }
4099
+ async disposeSession(request) {
4100
+ await this._initialization;
4101
+ await this._withTimeout(this._getRuntime().disposeSession(request), "dispose session");
4102
+ this._performanceTracker.reset(request.unitId);
4103
+ this._fontFamilies.delete(request.unitId);
4104
+ }
4105
+ dispose() {
4106
+ this._disposeRuntime();
4107
+ super.dispose();
4108
+ }
4109
+ async _replaceRuntime() {
4110
+ this._initialized = false;
4111
+ this._disposeRuntime();
4112
+ const worker = this._workerFactory();
4113
+ const channelService = new _univerjs_rpc.ChannelService(createDocsLayoutWorkerMessageProtocol(worker, this._performanceTracker));
4114
+ this._worker = worker;
4115
+ this._channelService = channelService;
4116
+ this._runtime = (0, _univerjs_rpc.toModule)(channelService.requestChannel(DOCS_LAYOUT_WORKER_CHANNEL));
4117
+ await this._withTimeout(this._verifyCapabilities(), "verify capabilities");
4118
+ this._initialized = true;
4119
+ }
4120
+ _disposeRuntime() {
4121
+ var _this$_channelService, _this$_worker;
4122
+ this._fontFamilies.clear();
4123
+ this._initialized = false;
4124
+ (_this$_channelService = this._channelService) === null || _this$_channelService === void 0 || _this$_channelService.dispose();
4125
+ this._channelService = null;
4126
+ this._runtime = null;
4127
+ (_this$_worker = this._worker) === null || _this$_worker === void 0 || _this$_worker.terminate();
4128
+ this._worker = null;
4129
+ this._performanceTracker.resetAll();
4130
+ }
4131
+ _getRuntime() {
4132
+ if (this._runtime == null) throw new Error("Document layout Worker runtime is unavailable.");
4133
+ return this._runtime;
4134
+ }
4135
+ _withTimeout(task, operation) {
4136
+ let timeoutId = null;
4137
+ const timeout = new Promise((_resolve, reject) => {
4138
+ timeoutId = setTimeout(() => {
4139
+ reject(/* @__PURE__ */ new Error(`Document layout Worker timed out while attempting to ${operation}.`));
4140
+ }, this._requestTimeoutMs);
4141
+ });
4142
+ return Promise.race([task, timeout]).finally(() => {
4143
+ if (timeoutId != null) clearTimeout(timeoutId);
4144
+ });
4145
+ }
4146
+ async _verifyCapabilities() {
4147
+ const capabilities = await this.getCapabilities();
4148
+ if (capabilities.protocolVersion !== 5) throw new DocsLayoutWorkerCapabilityError("Document layout Worker protocol version mismatch.");
4149
+ if (!capabilities.offscreenCanvas || !capabilities.structuredClone) throw new DocsLayoutWorkerCapabilityError("Document layout Worker requires OffscreenCanvas and structured clone support.");
4150
+ const mainMetrics = _univerjs_engine_render.FontCache.getMeasureText(capabilities.fontProbe.content, capabilities.fontProbe.font);
4151
+ if ([
4152
+ [mainMetrics.width, capabilities.fontProbe.width],
4153
+ [mainMetrics.actualBoundingBoxAscent, capabilities.fontProbe.actualBoundingBoxAscent],
4154
+ [mainMetrics.actualBoundingBoxDescent, capabilities.fontProbe.actualBoundingBoxDescent]
4155
+ ].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.");
4156
+ }
4157
+ };
4158
+ let UniverDocsLayoutWorkerPlugin = class UniverDocsLayoutWorkerPlugin extends _univerjs_core.Plugin {
4159
+ constructor(_config = defaultPluginDocsLayoutWorkerConfig, _injector, _layoutExecutorService, _configService) {
4160
+ super();
4161
+ this._config = _config;
4162
+ this._injector = _injector;
4163
+ this._layoutExecutorService = _layoutExecutorService;
4164
+ this._configService = _configService;
4165
+ const { ...rest } = (0, _univerjs_core.merge)({}, defaultPluginDocsLayoutWorkerConfig, this._config);
4166
+ this._configService.setConfig(DOCS_LAYOUT_WORKER_PLUGIN_CONFIG_KEY, rest);
4167
+ }
4168
+ onStarting() {
4169
+ if (typeof this._config.workerFactory !== "function") throw new TypeError("[UniverDocsLayoutWorkerPlugin]: workerFactory is required.");
4170
+ const requestTimeoutMs = this._config.requestTimeoutMs ?? 15e3;
4171
+ if (!Number.isFinite(requestTimeoutMs) || requestTimeoutMs <= 0) throw new RangeError("[UniverDocsLayoutWorkerPlugin]: requestTimeoutMs must be a positive finite number.");
4172
+ const client = new DocsLayoutWorkerClientService(this._config.workerFactory, requestTimeoutMs);
4173
+ this._injector.add([DocsLayoutWorkerClientService, { useValue: client }]);
4174
+ this.disposeWithMe(client);
4175
+ this.disposeWithMe(this._layoutExecutorService.register(client));
4176
+ }
4177
+ };
4178
+ _defineProperty(UniverDocsLayoutWorkerPlugin, "pluginName", "DOCS_LAYOUT_WORKER_PLUGIN");
4179
+ _defineProperty(UniverDocsLayoutWorkerPlugin, "packageName", name);
4180
+ _defineProperty(UniverDocsLayoutWorkerPlugin, "version", version);
4181
+ UniverDocsLayoutWorkerPlugin = __decorate([
4182
+ (0, _univerjs_core.DependentOn)(UniverDocsPlugin),
4183
+ __decorateParam(1, (0, _univerjs_core.Inject)(_univerjs_core.Injector)),
4184
+ __decorateParam(2, (0, _univerjs_core.Inject)(DocLayoutExecutorService)),
4185
+ __decorateParam(3, _univerjs_core.IConfigService)
4186
+ ], UniverDocsLayoutWorkerPlugin);
4187
+
1855
4188
  //#endregion
1856
4189
  //#region src/services/doc-interceptor/interceptor-const.ts
1857
4190
  const CUSTOM_RANGE = (0, _univerjs_core.createInterceptorKey)("CUSTOM_RANGE");
@@ -1908,6 +4241,7 @@ let DocInterceptorService = class DocInterceptorService extends _univerjs_core.D
1908
4241
  return this.fetchThroughInterceptors(DOC_INTERCEPTOR_POINT.CUSTOM_RANGE)(viewModel.getCustomRangeRaw(index), {
1909
4242
  index,
1910
4243
  unitId: viewModel.getDataModel().getUnitId(),
4244
+ body: viewModel.getDataModel().getBody(),
1911
4245
  customRanges: viewModel.getDataModel().getCustomRanges() ?? []
1912
4246
  });
1913
4247
  },
@@ -2170,18 +4504,29 @@ function normalizeTextRange(textRange) {
2170
4504
 
2171
4505
  //#endregion
2172
4506
  exports.CreateHeaderFooterCommand = CreateHeaderFooterCommand;
4507
+ exports.DOCUMENT_UNIT_PERMISSION_ACTIONS = DOCUMENT_UNIT_PERMISSION_ACTIONS;
2173
4508
  exports.DOC_INTERCEPTOR_POINT = DOC_INTERCEPTOR_POINT;
2174
4509
  exports.DOC_SELECTION_OPTION_PRESERVE_CARET = DOC_SELECTION_OPTION_PRESERVE_CARET;
2175
4510
  exports.DeleteDocumentSectionBreakCommand = DeleteDocumentSectionBreakCommand;
2176
4511
  exports.DeleteTextCommand = DeleteTextCommand;
2177
4512
  exports.DocBlockMoveValidatorService = DocBlockMoveValidatorService;
2178
4513
  exports.DocContentInsertService = DocContentInsertService;
4514
+ exports.DocHistoryAction = DocHistoryAction;
2179
4515
  Object.defineProperty(exports, 'DocInterceptorService', {
2180
4516
  enumerable: true,
2181
4517
  get: function () {
2182
4518
  return DocInterceptorService;
2183
4519
  }
2184
4520
  });
4521
+ Object.defineProperty(exports, 'DocLayoutExecutorService', {
4522
+ enumerable: true,
4523
+ get: function () {
4524
+ return DocLayoutExecutorService;
4525
+ }
4526
+ });
4527
+ exports.DocLayoutExecutorState = DocLayoutExecutorState;
4528
+ exports.DocLayoutExecutorType = DocLayoutExecutorType;
4529
+ exports.DocLayoutSessionStatus = DocLayoutSessionStatus;
2185
4530
  Object.defineProperty(exports, 'DocSelectionManagerService', {
2186
4531
  enumerable: true,
2187
4532
  get: function () {
@@ -2202,6 +4547,8 @@ Object.defineProperty(exports, 'DocStateChangeManagerService', {
2202
4547
  });
2203
4548
  exports.DocStateEmitService = DocStateEmitService;
2204
4549
  exports.DocTextResolverService = DocTextResolverService;
4550
+ exports.DocsLayoutWorkerCapabilityError = DocsLayoutWorkerCapabilityError;
4551
+ exports.DocsLayoutWorkerClientService = DocsLayoutWorkerClientService;
2205
4552
  exports.EMBED_DOCS_CUSTOM_BLOCK_DEFAULT_COMPONENT_KEY = EMBED_DOCS_CUSTOM_BLOCK_DEFAULT_COMPONENT_KEY;
2206
4553
  exports.HeaderFooterType = HeaderFooterType;
2207
4554
  exports.IDocStateChangeInterceptorService = IDocStateChangeInterceptorService;
@@ -2211,8 +4558,18 @@ exports.InsertTextCommand = InsertTextCommand;
2211
4558
  exports.RichTextEditingMutation = RichTextEditingMutation;
2212
4559
  exports.SetDocumentDefaultParagraphStyleCommand = SetDocumentDefaultParagraphStyleCommand;
2213
4560
  exports.SetDocumentNameCommand = SetDocumentNameCommand;
4561
+ exports.SetDocumentPermissionCommand = SetDocumentPermissionCommand;
4562
+ exports.SetDocumentPermissionRuleMutation = SetDocumentPermissionRuleMutation;
4563
+ exports.SetDocumentPermissionRulesMutation = SetDocumentPermissionRulesMutation;
4564
+ exports.SetDocumentPermissionsCommand = SetDocumentPermissionsCommand;
2214
4565
  exports.SetSectionHeaderFooterLinkCommand = SetSectionHeaderFooterLinkCommand;
2215
4566
  exports.SetTextSelectionsOperation = SetTextSelectionsOperation;
4567
+ Object.defineProperty(exports, 'UniverDocsLayoutWorkerPlugin', {
4568
+ enumerable: true,
4569
+ get: function () {
4570
+ return UniverDocsLayoutWorkerPlugin;
4571
+ }
4572
+ });
2216
4573
  Object.defineProperty(exports, 'UniverDocsPlugin', {
2217
4574
  enumerable: true,
2218
4575
  get: function () {
@@ -2225,10 +4582,12 @@ exports.UpdateTextCommand = UpdateTextCommand;
2225
4582
  exports.addCustomRangeBySelectionFactory = addCustomRangeBySelectionFactory;
2226
4583
  exports.addCustomRangeFactory = addCustomRangeFactory;
2227
4584
  exports.buildDocTransform = buildDocTransform;
4585
+ exports.canEditDocumentTargets = canEditDocumentTargets;
2228
4586
  exports.consumeContentInsertRange = consumeContentInsertRange;
2229
4587
  exports.createDocsCustomBlockDrawing = createDocsCustomBlockDrawing;
2230
4588
  exports.createDocsCustomBlockInsertMutation = createDocsCustomBlockInsertMutation;
2231
4589
  exports.createDocsCustomBlockRemoveMutation = createDocsCustomBlockRemoveMutation;
4590
+ exports.createDocumentPermissionPoint = createDocumentPermissionPoint;
2232
4591
  exports.createEmbedDocsCustomBlockData = createEmbedDocsCustomBlockData;
2233
4592
  exports.createInsertCustomBlockActions = createInsertCustomBlockActions;
2234
4593
  exports.createRemoveCustomBlockActions = createRemoveCustomBlockActions;
@@ -2237,6 +4596,14 @@ exports.deleteCustomRangeFactory = deleteCustomRangeFactory;
2237
4596
  exports.docDrawingPositionToTransform = docDrawingPositionToTransform;
2238
4597
  exports.generateParagraphs = generateParagraphs;
2239
4598
  exports.getContentInsertRange = getContentInsertRange;
4599
+ exports.getDocumentDrawingSegmentId = getDocumentDrawingSegmentId;
4600
+ exports.getDocumentEditTargetObjectIds = getDocumentEditTargetObjectIds;
4601
+ exports.getDocumentEntityParentPermissionObjectIds = getDocumentEntityParentPermissionObjectIds;
4602
+ exports.getDocumentEntityPermissionObjectId = getDocumentEntityPermissionObjectId;
4603
+ exports.getDocumentParagraphParentPermissionObjectIds = getDocumentParagraphParentPermissionObjectIds;
4604
+ exports.getDocumentParagraphPermissionObjectId = getDocumentParagraphPermissionObjectId;
4605
+ exports.getDocumentPermissionValue = getDocumentPermissionValue;
4606
+ exports.getDocumentSectionPermissionObjectId = getDocumentSectionPermissionObjectId;
2240
4607
  exports.getEffectiveSectionPageSetup = getEffectiveSectionPageSetup;
2241
4608
  exports.getSectionContentWidth = getSectionContentWidth;
2242
4609
  exports.getTopLevelSectionBreaks = getTopLevelSectionBreaks;
@@ -2246,5 +4613,8 @@ exports.isSheetLikeDocsCustomBlockChildType = isSheetLikeDocsCustomBlockChildTyp
2246
4613
  exports.normalizeTextRange = normalizeTextRange;
2247
4614
  exports.replaceSelectionFactory = replaceSelectionFactory;
2248
4615
  exports.resolveDocsCustomBlockSize = resolveDocsCustomBlockSize;
4616
+ exports.setDocumentPermissionValue = setDocumentPermissionValue;
2249
4617
  exports.shouldUseInlineTextSelectionForDocsCustomBlockDrawing = shouldUseInlineTextSelectionForDocsCustomBlockDrawing;
4618
+ exports.startDocsLayoutWorker = startDocsLayoutWorker;
4619
+ exports.transformDocumentTextRanges = transformDocumentTextRanges;
2250
4620
  exports.transformToDocDrawingPosition = transformToDocDrawingPosition;