@univerjs/docs 1.0.0-alpha.7 → 1.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { AlignTypeH, BuildTextUtils, CommandType, DOCS_FORMULA_BAR_EDITOR_UNIT_ID_KEY, DOCS_NORMAL_EDITOR_UNIT_ID_KEY, DataStreamTreeTokenType, DeleteDirection, Disposable, DisposableCollection, DocumentFlavor, DrawingTypeEnum, ICommandService, IConfigService, IUndoRedoService, IUniverInstanceService, Inject, Injector, JSONX, LocaleService, MemoryCursor, ObjectRelativeFromH, ObjectRelativeFromV, Optional, PAGE_SIZE, PaperType, Plugin, PositionedObjectLayoutType, RedoCommandId, RxDisposable, TextX, TextXActionType, Tools, UndoCommandId, UniverInstanceType, UpdateDocsAttributeType, composeInterceptors, containsInteriorInsertionOffset, createIdentifier, createInterceptorKey, createParagraphId, createSectionId, generateRandomId, getBlockRangeInterval, getColumnGroupRangeInterval, getRichTextEditPath, getSectionHeaderFooterReferenceKey, getTableRangeInterval, isInternalEditorID, merge, remove, resolveSectionHeaderFooterReference, toDisposable, validateDocBodyStructure } from "@univerjs/core";
1
+ import { AlignTypeH, BuildTextUtils, ColumnSeparatorType, CommandType, CustomRangeType, DOCS_FORMULA_BAR_EDITOR_UNIT_ID_KEY, DOCS_NORMAL_EDITOR_UNIT_ID_KEY, DataStreamTreeTokenType, DeleteDirection, Disposable, DisposableCollection, DocumentFlavor, DocxBreakType, DrawingTypeEnum, ICommandService, IConfigService, IUndoRedoService, IUniverInstanceService, Inject, Injector, JSONX, LocaleService, MemoryCursor, ObjectRelativeFromH, ObjectRelativeFromV, Optional, PAGE_SIZE, PageOrientType, PaperType, Plugin, PositionedObjectLayoutType, RESTORE_INSERTED_PARAGRAPH_IDS, RedoCommandId, RxDisposable, SectionType, TRADITIONAL_DOCUMENT_DEFAULT_MARGIN, TextX, TextXActionType, Tools, UndoCommandId, UniverInstanceType, UpdateDocsAttributeType, composeInterceptors, containsInteriorInsertionOffset, createIdentifier, createInterceptorKey, createParagraphId, createSectionId, generateRandomId, getBlockRangeInterval, getColumnGroupRangeInterval, getParagraphContentStartOffset, getRichTextEditPath, getSectionHeaderFooterReferenceKey, getTableRangeInterval, isInternalEditorID, merge, remove, resolveSectionHeaderFooterReference, toDisposable, validateDocBodyStructure } from "@univerjs/core";
2
2
  import { DocumentSkeleton, DocumentViewModel, IRenderManagerService, NORMAL_TEXT_SELECTION_PLUGIN_STYLE } from "@univerjs/engine-render";
3
3
  import { BehaviorSubject, Subject, takeUntil } from "rxjs";
4
4
 
@@ -12,7 +12,7 @@ const SetTextSelectionsOperation = {
12
12
  };
13
13
 
14
14
  //#endregion
15
- //#region \0@oxc-project+runtime@0.137.0/helpers/esm/typeof.js
15
+ //#region \0@oxc-project+runtime@0.140.0/helpers/esm/typeof.js
16
16
  function _typeof(o) {
17
17
  "@babel/helpers - typeof";
18
18
  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
@@ -23,7 +23,7 @@ function _typeof(o) {
23
23
  }
24
24
 
25
25
  //#endregion
26
- //#region \0@oxc-project+runtime@0.137.0/helpers/esm/toPrimitive.js
26
+ //#region \0@oxc-project+runtime@0.140.0/helpers/esm/toPrimitive.js
27
27
  function toPrimitive(t, r) {
28
28
  if ("object" != _typeof(t) || !t) return t;
29
29
  var e = t[Symbol.toPrimitive];
@@ -36,14 +36,14 @@ function toPrimitive(t, r) {
36
36
  }
37
37
 
38
38
  //#endregion
39
- //#region \0@oxc-project+runtime@0.137.0/helpers/esm/toPropertyKey.js
39
+ //#region \0@oxc-project+runtime@0.140.0/helpers/esm/toPropertyKey.js
40
40
  function toPropertyKey(t) {
41
41
  var i = toPrimitive(t, "string");
42
42
  return "symbol" == _typeof(i) ? i : i + "";
43
43
  }
44
44
 
45
45
  //#endregion
46
- //#region \0@oxc-project+runtime@0.137.0/helpers/esm/defineProperty.js
46
+ //#region \0@oxc-project+runtime@0.140.0/helpers/esm/defineProperty.js
47
47
  function _defineProperty(e, r, t) {
48
48
  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
49
49
  value: t,
@@ -54,7 +54,7 @@ function _defineProperty(e, r, t) {
54
54
  }
55
55
 
56
56
  //#endregion
57
- //#region \0@oxc-project+runtime@0.137.0/helpers/esm/decorateParam.js
57
+ //#region \0@oxc-project+runtime@0.140.0/helpers/esm/decorateParam.js
58
58
  function __decorateParam(paramIndex, decorator) {
59
59
  return function(target, key) {
60
60
  decorator(target, key, paramIndex);
@@ -62,7 +62,7 @@ function __decorateParam(paramIndex, decorator) {
62
62
  }
63
63
 
64
64
  //#endregion
65
- //#region \0@oxc-project+runtime@0.137.0/helpers/esm/decorate.js
65
+ //#region \0@oxc-project+runtime@0.140.0/helpers/esm/decorate.js
66
66
  function __decorate(decorators, target, key, desc) {
67
67
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
68
68
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -72,6 +72,11 @@ function __decorate(decorators, target, key, desc) {
72
72
 
73
73
  //#endregion
74
74
  //#region src/services/doc-selection-manager.service.ts
75
+ /**
76
+ * Keeps a programmatically restored collapsed caret from being promoted back
77
+ * into a neighboring whole-entity selection by feature-specific UI.
78
+ */
79
+ const DOC_SELECTION_OPTION_PRESERVE_CARET = "preserveCaret";
75
80
  let DocSelectionManagerService = class DocSelectionManagerService extends RxDisposable {
76
81
  constructor(_commandService, _univerInstanceService) {
77
82
  super();
@@ -118,9 +123,8 @@ let DocSelectionManagerService = class DocSelectionManagerService extends RxDisp
118
123
  return (_this$_getTextRanges2 = this._getTextRanges(params)) === null || _this$_getTextRanges2 === void 0 ? void 0 : _this$_getTextRanges2.rectRanges;
119
124
  }
120
125
  getDocRanges(params = this._currentSelection) {
121
- var _this$getTextRanges, _this$getRectRanges;
122
- const textRanges = (_this$getTextRanges = this.getTextRanges(params)) !== null && _this$getTextRanges !== void 0 ? _this$getTextRanges : [];
123
- const rectRanges = (_this$getRectRanges = this.getRectRanges(params)) !== null && _this$getRectRanges !== void 0 ? _this$getRectRanges : [];
126
+ const textRanges = this.getTextRanges(params) ?? [];
127
+ const rectRanges = this.getRectRanges(params) ?? [];
124
128
  return [...textRanges, ...rectRanges].filter((range) => range.startOffset != null && range.endOffset != null).sort((a, b) => {
125
129
  if (a.startOffset > b.startOffset) return 1;
126
130
  else if (a.startOffset < b.startOffset) return -1;
@@ -133,16 +137,6 @@ let DocSelectionManagerService = class DocSelectionManagerService extends RxDisp
133
137
  const { textRanges } = selectionInfo;
134
138
  return textRanges.find((textRange) => textRange.isActive);
135
139
  }
136
- /**
137
- *
138
- * @deprecated
139
- */
140
- getActiveRectRange() {
141
- const selectionInfo = this._getTextRanges(this._currentSelection);
142
- if (selectionInfo == null) return;
143
- const { rectRanges } = selectionInfo;
144
- return rectRanges.find((rectRange) => rectRange.isActive);
145
- }
146
140
  __TEST_ONLY_add(textRanges, isEditing = true) {
147
141
  if (this._currentSelection == null) return;
148
142
  this._addByParam({
@@ -155,12 +149,6 @@ let DocSelectionManagerService = class DocSelectionManagerService extends RxDisp
155
149
  style: NORMAL_TEXT_SELECTION_PLUGIN_STYLE
156
150
  });
157
151
  }
158
- /**
159
- * @deprecated pls use replaceDocRanges.
160
- */
161
- replaceTextRanges(docRanges, isEditing = true, options) {
162
- return this.replaceDocRanges(docRanges, this._currentSelection, isEditing, options);
163
- }
164
152
  replaceDocRanges(docRanges, params = this._currentSelection, isEditing = true, options) {
165
153
  if (params == null) return;
166
154
  const { unitId, subUnitId } = params;
@@ -211,14 +199,15 @@ let DocSelectionManagerService = class DocSelectionManagerService extends RxDisp
211
199
  _refresh(param) {
212
200
  const allTextSelectionInfo = this._getTextRanges(param);
213
201
  if (allTextSelectionInfo == null) return;
214
- const { textRanges, rectRanges } = allTextSelectionInfo;
202
+ const { textRanges, rectRanges, options } = allTextSelectionInfo;
215
203
  const docRanges = [...textRanges, ...rectRanges];
216
204
  const { unitId, subUnitId } = param;
217
205
  this._refreshSelection$.next({
218
206
  unitId,
219
207
  subUnitId,
220
208
  docRanges,
221
- isEditing: false
209
+ isEditing: false,
210
+ options
222
211
  });
223
212
  }
224
213
  _replaceByParam(insertParam) {
@@ -268,6 +257,13 @@ let DocSkeletonManagerService = class DocSkeletonManagerService extends RxDispos
268
257
  getViewModel() {
269
258
  return this._docViewModel;
270
259
  }
260
+ recalculate() {
261
+ const skeleton = this._skeleton;
262
+ skeleton.calculate();
263
+ this._currentSkeletonBefore$.next(skeleton);
264
+ this._currentSkeleton$.next(skeleton);
265
+ return skeleton;
266
+ }
271
267
  _init() {
272
268
  const documentDataModel = this._context.unit;
273
269
  this._update(documentDataModel);
@@ -280,10 +276,7 @@ let DocSkeletonManagerService = class DocSkeletonManagerService extends RxDispos
280
276
  this._context.unit = documentDataModel;
281
277
  } else if (!this._docViewModel) this._docViewModel = this._buildDocViewModel(documentDataModel);
282
278
  if (!this._skeleton) this._skeleton = this._buildSkeleton(this._docViewModel);
283
- const skeleton = this._skeleton;
284
- skeleton.calculate();
285
- this._currentSkeletonBefore$.next(skeleton);
286
- this._currentSkeleton$.next(skeleton);
279
+ this.recalculate();
287
280
  this._currentViewModel$.next(this._docViewModel);
288
281
  }
289
282
  _buildSkeleton(documentViewModel) {
@@ -344,7 +337,7 @@ const RichTextEditingMutation = {
344
337
  id: RichTextEditingMutationId,
345
338
  type: CommandType.MUTATION,
346
339
  handler: (accessor, params, options) => {
347
- var _renderManagerService, _docSelectionManagerS;
340
+ var _renderManagerService;
348
341
  const { unitId, segmentId = "", actions, textRanges, prevTextRanges, trigger, noHistory, isCompositionEnd, noNeedSetTextRange, debounce, isEditing = true, isSync: paramsIsSync, syncer } = params;
349
342
  const isSync = paramsIsSync || (options === null || options === void 0 ? void 0 : options.fromCollab) || (options === null || options === void 0 ? void 0 : options.fromChangeset);
350
343
  const univerInstanceService = accessor.get(IUniverInstanceService);
@@ -354,7 +347,7 @@ const RichTextEditingMutation = {
354
347
  const documentViewModel = (_renderManagerService = renderManagerService.getRenderUnitById(unitId)) === null || _renderManagerService === void 0 ? void 0 : _renderManagerService.with(DocSkeletonManagerService).getViewModel();
355
348
  if (documentDataModel == null) throw new Error(`DocumentDataModel not found for unitId: ${unitId}`);
356
349
  const docSelectionManagerService = accessor.get(DocSelectionManagerService);
357
- const docRanges = (_docSelectionManagerS = docSelectionManagerService.getDocRanges()) !== null && _docSelectionManagerS !== void 0 ? _docSelectionManagerS : [];
350
+ const docRanges = docSelectionManagerService.getDocRanges() ?? [];
358
351
  const disabled = !!documentDataModel.getSnapshot().disabled;
359
352
  if (JSONX.isNoop(actions) || actions && actions.length === 0 || disabled) return {
360
353
  unitId,
@@ -389,7 +382,7 @@ const RichTextEditingMutation = {
389
382
  },
390
383
  undoState: {
391
384
  actions: undoActions,
392
- textRanges: prevTextRanges !== null && prevTextRanges !== void 0 ? prevTextRanges : docRanges
385
+ textRanges: prevTextRanges ?? docRanges
393
386
  },
394
387
  isCompositionEnd,
395
388
  isSync,
@@ -413,7 +406,7 @@ const InsertTextCommand = {
413
406
  id: "doc.command.insert-text",
414
407
  type: CommandType.COMMAND,
415
408
  handler: (accessor, params) => {
416
- var _ref, _ref2, _docDataModel$getSelf;
409
+ var _docDataModel$getSelf;
417
410
  const commandService = accessor.get(ICommandService);
418
411
  const { range, segmentId, body, unitId, cursorOffset } = params;
419
412
  const docSelectionManagerService = accessor.get(DocSelectionManagerService);
@@ -421,11 +414,11 @@ const InsertTextCommand = {
421
414
  if (docDataModel == null) return false;
422
415
  const activeRange = docSelectionManagerService.getActiveTextRange();
423
416
  const rangeSegmentId = "segmentId" in range ? range.segmentId : void 0;
424
- const targetSegmentId = (_ref = (_ref2 = segmentId !== null && segmentId !== void 0 ? segmentId : rangeSegmentId) !== null && _ref2 !== void 0 ? _ref2 : activeRange === null || activeRange === void 0 ? void 0 : activeRange.segmentId) !== null && _ref !== void 0 ? _ref : "";
417
+ const targetSegmentId = segmentId ?? rangeSegmentId ?? (activeRange === null || activeRange === void 0 ? void 0 : activeRange.segmentId) ?? "";
425
418
  const originBody = (_docDataModel$getSelf = docDataModel.getSelfOrHeaderFooterModel(targetSegmentId)) === null || _docDataModel$getSelf === void 0 ? void 0 : _docDataModel$getSelf.getBody();
426
419
  if (originBody == null) return false;
427
420
  const { startOffset, collapsed } = range;
428
- const cursorMove = cursorOffset !== null && cursorOffset !== void 0 ? cursorOffset : body.dataStream.length;
421
+ const cursorMove = cursorOffset ?? body.dataStream.length;
429
422
  const textRanges = [{
430
423
  startOffset: startOffset + cursorMove,
431
424
  endOffset: startOffset + cursorMove,
@@ -594,7 +587,7 @@ function getEmptyHeaderFooterBody() {
594
587
  function createHeaderFooterAction(segmentId, createType, headerFooterConfig, actions, createMode = "single", configPath = ["documentStyle"]) {
595
588
  const jsonX = JSONX.getInstance();
596
589
  const ID_LEN = 6;
597
- const firstSegmentId = segmentId !== null && segmentId !== void 0 ? segmentId : generateRandomId(ID_LEN);
590
+ const firstSegmentId = segmentId ?? generateRandomId(ID_LEN);
598
591
  const isHeader = createType === 2 || createType === 0 || createType === 4;
599
592
  const insertAction = jsonX.insertOp([isHeader ? "headers" : "footers", firstSegmentId], {
600
593
  [isHeader ? "headerId" : "footerId"]: firstSegmentId,
@@ -653,7 +646,7 @@ const CreateHeaderFooterCommand = {
653
646
  id: "doc.command.create-header-footer",
654
647
  type: CommandType.COMMAND,
655
648
  handler: (accessor, params) => {
656
- var _body$sectionBreaks$f, _body$sectionBreaks, _body$sectionBreaks2;
649
+ var _body$sectionBreaks, _body$sectionBreaks2;
657
650
  const commandService = accessor.get(ICommandService);
658
651
  const univerInstanceService = accessor.get(IUniverInstanceService);
659
652
  const { unitId, segmentId, createType, headerFooterProps, createMode = "single", sectionId } = params;
@@ -663,10 +656,10 @@ const CreateHeaderFooterCommand = {
663
656
  if (documentStyle.documentFlavor === DocumentFlavor.MODERN) return false;
664
657
  const rawActions = [];
665
658
  const jsonX = JSONX.getInstance();
666
- const sectionIndex = sectionId == null ? -1 : (_body$sectionBreaks$f = body === null || body === void 0 || (_body$sectionBreaks = body.sectionBreaks) === null || _body$sectionBreaks === void 0 ? void 0 : _body$sectionBreaks.findIndex((section) => section.sectionId === sectionId)) !== null && _body$sectionBreaks$f !== void 0 ? _body$sectionBreaks$f : -1;
659
+ const sectionIndex = sectionId == null ? -1 : (body === null || body === void 0 || (_body$sectionBreaks = body.sectionBreaks) === null || _body$sectionBreaks === void 0 ? void 0 : _body$sectionBreaks.findIndex((section) => section.sectionId === sectionId)) ?? -1;
667
660
  const sectionBreak = sectionIndex < 0 ? void 0 : body === null || body === void 0 || (_body$sectionBreaks2 = body.sectionBreaks) === null || _body$sectionBreaks2 === void 0 ? void 0 : _body$sectionBreaks2[sectionIndex];
668
661
  if (sectionId != null && !sectionBreak) return false;
669
- const headerFooterConfig = sectionBreak !== null && sectionBreak !== void 0 ? sectionBreak : documentStyle;
662
+ const headerFooterConfig = sectionBreak ?? documentStyle;
670
663
  const configPath = sectionId == null ? ["documentStyle"] : [
671
664
  "body",
672
665
  "sectionBreaks",
@@ -748,8 +741,7 @@ const SetDocumentDefaultParagraphStyleCommand = {
748
741
  //#region src/utils/sections.ts
749
742
  /** Returns document-level section breaks, excluding table-cell and modern-column sentinels. */
750
743
  function getTopLevelSectionBreaks(body) {
751
- var _body$sectionBreaks;
752
- const sectionBreakByIndex = new Map(((_body$sectionBreaks = body.sectionBreaks) !== null && _body$sectionBreaks !== void 0 ? _body$sectionBreaks : []).map((sectionBreak) => [sectionBreak.startIndex, sectionBreak]));
744
+ const sectionBreakByIndex = new Map((body.sectionBreaks ?? []).map((sectionBreak) => [sectionBreak.startIndex, sectionBreak]));
753
745
  const result = [];
754
746
  let tableCellDepth = 0;
755
747
  let columnDepth = 0;
@@ -773,7 +765,7 @@ const SetSectionHeaderFooterLinkCommand = {
773
765
  id: "doc.command.set-section-header-footer-link",
774
766
  type: CommandType.COMMAND,
775
767
  handler: (accessor, params) => {
776
- var _snapshot$body$sectio, _snapshot$body$sectio2;
768
+ var _snapshot$body$sectio;
777
769
  if (!params) return false;
778
770
  const instanceService = accessor.get(IUniverInstanceService);
779
771
  const commandService = accessor.get(ICommandService);
@@ -783,7 +775,7 @@ const SetSectionHeaderFooterLinkCommand = {
783
775
  const sections = getTopLevelSectionBreaks(snapshot.body);
784
776
  const sectionIndex = sections.findIndex((section) => section.sectionId === params.sectionId);
785
777
  if (sectionIndex <= 0) return false;
786
- const storageIndex = (_snapshot$body$sectio = (_snapshot$body$sectio2 = snapshot.body.sectionBreaks) === null || _snapshot$body$sectio2 === void 0 ? void 0 : _snapshot$body$sectio2.findIndex((item) => item.sectionId === params.sectionId)) !== null && _snapshot$body$sectio !== void 0 ? _snapshot$body$sectio : -1;
778
+ const storageIndex = ((_snapshot$body$sectio = snapshot.body.sectionBreaks) === null || _snapshot$body$sectio === void 0 ? void 0 : _snapshot$body$sectio.findIndex((item) => item.sectionId === params.sectionId)) ?? -1;
787
779
  if (storageIndex < 0) return false;
788
780
  const context = {
789
781
  snapshot,
@@ -841,7 +833,7 @@ function buildUnlinkActions(context, kind, requestedSegmentId) {
841
833
  const explicitSegmentId = sections[sectionIndex][key];
842
834
  if (typeof explicitSegmentId === "string" && explicitSegmentId) return null;
843
835
  const sourceSegmentId = resolveSectionHeaderFooterReference(snapshot.documentStyle, sections, sectionIndex - 1, key).segmentId;
844
- const segmentId = requestedSegmentId !== null && requestedSegmentId !== void 0 ? requestedSegmentId : generateRandomId(6);
836
+ const segmentId = requestedSegmentId ?? generateRandomId(6);
845
837
  const resources = kind === "header" ? snapshot.headers : snapshot.footers;
846
838
  if (resources === null || resources === void 0 ? void 0 : resources[segmentId]) return null;
847
839
  const source = sourceSegmentId ? resources === null || resources === void 0 ? void 0 : resources[sourceSegmentId] : void 0;
@@ -862,6 +854,174 @@ function buildUnlinkActions(context, kind, requestedSegmentId) {
862
854
  ], segmentId)];
863
855
  }
864
856
 
857
+ //#endregion
858
+ //#region src/commands/commands/update-document-paragraph-style.command.ts
859
+ function isValidParams(params) {
860
+ return Boolean((params === null || params === void 0 ? void 0 : params.unitId) && params.paragraphId && Number.isInteger(params.startOffset) && Number.isInteger(params.endOffset) && params.startOffset >= 0 && params.endOffset >= params.startOffset && params.style && Object.keys(params.style).length > 0);
861
+ }
862
+ function getCurrentParagraph(body, params) {
863
+ const matches = (body.paragraphs ?? []).filter((paragraph) => paragraph.paragraphId === params.paragraphId);
864
+ if (matches.length !== 1) return null;
865
+ const paragraph = matches[0];
866
+ return getParagraphContentStartOffset(body, paragraph) === params.startOffset && paragraph.startIndex === params.endOffset && body.dataStream[params.endOffset] === "\r" ? paragraph : null;
867
+ }
868
+ function createParagraphStyleTextX(body, paragraph, params) {
869
+ const textX = new TextX();
870
+ const initializesTextRuns = Boolean(params.style.textStyle && params.startOffset < params.endOffset && body.textRuns == null);
871
+ if (params.startOffset > 0) textX.push({
872
+ t: TextXActionType.RETAIN,
873
+ len: params.startOffset
874
+ });
875
+ if (params.style.textStyle && params.startOffset < params.endOffset && !initializesTextRuns) textX.push({
876
+ t: TextXActionType.RETAIN,
877
+ len: params.endOffset - params.startOffset,
878
+ coverType: UpdateDocsAttributeType.COVER,
879
+ body: {
880
+ dataStream: "",
881
+ textRuns: [{
882
+ st: 0,
883
+ ed: params.endOffset - params.startOffset,
884
+ ts: Tools.deepClone(params.style.textStyle)
885
+ }]
886
+ }
887
+ });
888
+ else if (params.startOffset < params.endOffset) textX.push({
889
+ t: TextXActionType.RETAIN,
890
+ len: params.endOffset - params.startOffset
891
+ });
892
+ const paragraphBody = {
893
+ dataStream: "",
894
+ paragraphs: [{
895
+ ...Tools.deepClone(paragraph),
896
+ startIndex: 0,
897
+ paragraphStyle: {
898
+ ...Tools.deepClone(paragraph.paragraphStyle ?? {}),
899
+ ...Tools.deepClone(params.style)
900
+ }
901
+ }]
902
+ };
903
+ Object.defineProperty(paragraphBody, RESTORE_INSERTED_PARAGRAPH_IDS, {
904
+ value: true,
905
+ enumerable: true
906
+ });
907
+ textX.push({
908
+ t: TextXActionType.RETAIN,
909
+ len: 1,
910
+ coverType: UpdateDocsAttributeType.REPLACE,
911
+ body: paragraphBody
912
+ });
913
+ return {
914
+ textX,
915
+ initializesTextRuns
916
+ };
917
+ }
918
+ const UpdateDocumentParagraphStyleCommand = {
919
+ id: "doc.command.update-paragraph-style",
920
+ type: CommandType.COMMAND,
921
+ handler: (accessor, params) => {
922
+ var _documentDataModel$ge;
923
+ if (!isValidParams(params)) return false;
924
+ const instanceService = accessor.get(IUniverInstanceService);
925
+ const commandService = accessor.get(ICommandService);
926
+ const documentDataModel = instanceService.getUnit(params.unitId, UniverInstanceType.UNIVER_DOC);
927
+ const segmentId = params.segmentId ?? "";
928
+ const body = documentDataModel === null || documentDataModel === void 0 || (_documentDataModel$ge = documentDataModel.getSelfOrHeaderFooterModel(segmentId)) === null || _documentDataModel$ge === void 0 ? void 0 : _documentDataModel$ge.getBody();
929
+ if (!documentDataModel || !body) return false;
930
+ const paragraph = getCurrentParagraph(body, params);
931
+ if (!paragraph) return false;
932
+ const { textX, initializesTextRuns } = createParagraphStyleTextX(body, paragraph, params);
933
+ const jsonX = JSONX.getInstance();
934
+ const path = getRichTextEditPath(documentDataModel, segmentId);
935
+ let actions = jsonX.editOp(textX.serialize(), path);
936
+ if (initializesTextRuns) {
937
+ const initializeTextRunsActions = jsonX.replaceOp([...path, "textRuns"], void 0, [{
938
+ st: params.startOffset,
939
+ ed: params.endOffset,
940
+ ts: Tools.deepClone(params.style.textStyle)
941
+ }]);
942
+ actions = JSONX.compose(initializeTextRunsActions, actions);
943
+ }
944
+ return Boolean(commandService.syncExecuteCommand(RichTextEditingMutation.id, {
945
+ unitId: params.unitId,
946
+ segmentId,
947
+ actions,
948
+ textRanges: null,
949
+ noNeedSetTextRange: true,
950
+ isEditing: false,
951
+ trigger: UpdateDocumentParagraphStyleCommand.id
952
+ }));
953
+ }
954
+ };
955
+
956
+ //#endregion
957
+ //#region src/utils/section-columns.ts
958
+ function resolveSectionValue(sectionValue, documentValue, fallback) {
959
+ return sectionValue ?? documentValue ?? fallback;
960
+ }
961
+ function getEffectivePageSize(documentStyle, section) {
962
+ var _section$pageSize, _documentStyle$pageSi, _section$pageSize2, _documentStyle$pageSi2;
963
+ const fallback = PAGE_SIZE[PaperType.A4];
964
+ return {
965
+ width: resolveSectionValue(section === null || section === void 0 || (_section$pageSize = section.pageSize) === null || _section$pageSize === void 0 ? void 0 : _section$pageSize.width, documentStyle === null || documentStyle === void 0 || (_documentStyle$pageSi = documentStyle.pageSize) === null || _documentStyle$pageSi === void 0 ? void 0 : _documentStyle$pageSi.width, fallback.width),
966
+ height: resolveSectionValue(section === null || section === void 0 || (_section$pageSize2 = section.pageSize) === null || _section$pageSize2 === void 0 ? void 0 : _section$pageSize2.height, documentStyle === null || documentStyle === void 0 || (_documentStyle$pageSi2 = documentStyle.pageSize) === null || _documentStyle$pageSi2 === void 0 ? void 0 : _documentStyle$pageSi2.height, fallback.height)
967
+ };
968
+ }
969
+ function getEffectiveMargins(documentStyle, section) {
970
+ return {
971
+ top: resolveSectionValue(section === null || section === void 0 ? void 0 : section.marginTop, documentStyle === null || documentStyle === void 0 ? void 0 : documentStyle.marginTop, TRADITIONAL_DOCUMENT_DEFAULT_MARGIN),
972
+ bottom: resolveSectionValue(section === null || section === void 0 ? void 0 : section.marginBottom, documentStyle === null || documentStyle === void 0 ? void 0 : documentStyle.marginBottom, TRADITIONAL_DOCUMENT_DEFAULT_MARGIN),
973
+ left: resolveSectionValue(section === null || section === void 0 ? void 0 : section.marginLeft, documentStyle === null || documentStyle === void 0 ? void 0 : documentStyle.marginLeft, TRADITIONAL_DOCUMENT_DEFAULT_MARGIN),
974
+ right: resolveSectionValue(section === null || section === void 0 ? void 0 : section.marginRight, documentStyle === null || documentStyle === void 0 ? void 0 : documentStyle.marginRight, TRADITIONAL_DOCUMENT_DEFAULT_MARGIN)
975
+ };
976
+ }
977
+ function assertPositivePageSetup(pageSize, contentSize) {
978
+ if (![
979
+ pageSize.width,
980
+ pageSize.height,
981
+ contentSize.width,
982
+ contentSize.height
983
+ ].every((value) => Number.isFinite(value) && value > 0)) throw new RangeError("Effective section page setup must leave a positive content area and use finite positive page dimensions.");
984
+ }
985
+ /** Resolves nominal traditional page geometry without requiring a renderer. */
986
+ function getEffectiveSectionPageSetup(documentStyle, section) {
987
+ const pageSize = getEffectivePageSize(documentStyle, section);
988
+ const margins = getEffectiveMargins(documentStyle, section);
989
+ const contentSize = {
990
+ width: getSectionContentWidth(documentStyle, section),
991
+ height: pageSize.height - margins.top - margins.bottom
992
+ };
993
+ assertPositivePageSetup(pageSize, contentSize);
994
+ const pageNumberStart = (section === null || section === void 0 ? void 0 : section.pageNumberStart) ?? (documentStyle === null || documentStyle === void 0 ? void 0 : documentStyle.pageNumberStart);
995
+ return {
996
+ pageSize,
997
+ pageOrient: resolveSectionValue(section === null || section === void 0 ? void 0 : section.pageOrient, documentStyle === null || documentStyle === void 0 ? void 0 : documentStyle.pageOrient, PageOrientType.PORTRAIT),
998
+ margins,
999
+ contentSize,
1000
+ ...pageNumberStart == null ? {} : { pageNumberStart }
1001
+ };
1002
+ }
1003
+ /** Returns the usable horizontal layout width for a traditional section. */
1004
+ function getSectionContentWidth(documentStyle, section) {
1005
+ var _section$pageSize3, _documentStyle$pageSi3;
1006
+ const pageWidth = resolveSectionValue(section === null || section === void 0 || (_section$pageSize3 = section.pageSize) === null || _section$pageSize3 === void 0 ? void 0 : _section$pageSize3.width, documentStyle === null || documentStyle === void 0 || (_documentStyle$pageSi3 = documentStyle.pageSize) === null || _documentStyle$pageSi3 === void 0 ? void 0 : _documentStyle$pageSi3.width, PAGE_SIZE[PaperType.A4].width);
1007
+ return Math.max(0, pageWidth - resolveSectionValue(section === null || section === void 0 ? void 0 : section.marginLeft, documentStyle === null || documentStyle === void 0 ? void 0 : documentStyle.marginLeft, TRADITIONAL_DOCUMENT_DEFAULT_MARGIN) - resolveSectionValue(section === null || section === void 0 ? void 0 : section.marginRight, documentStyle === null || documentStyle === void 0 ? void 0 : documentStyle.marginRight, TRADITIONAL_DOCUMENT_DEFAULT_MARGIN));
1008
+ }
1009
+ /** Creates explicit OOXML section columns from a count, gap, and optional widths. */
1010
+ function createSectionColumnProperties(documentStyle, section, columnCount, gap, widths) {
1011
+ if (columnCount <= 1) return [];
1012
+ const safeGap = Math.max(0, gap);
1013
+ const contentWidth = getSectionContentWidth(documentStyle, section);
1014
+ const availableWidth = Math.max(0, contentWidth - safeGap * (columnCount - 1));
1015
+ if (widths) {
1016
+ if (widths.some((width) => !Number.isFinite(width) || width < 0)) throw new RangeError("Section column widths must be finite and non-negative.");
1017
+ if (widths.reduce((sum, width) => sum + width, 0) > availableWidth) throw new RangeError("Section columns exceed the available page content width.");
1018
+ }
1019
+ return (widths ?? Array.from({ length: columnCount }, () => availableWidth / columnCount)).map((width, index) => ({
1020
+ width: Math.max(0, width),
1021
+ paddingEnd: index === columnCount - 1 ? 0 : safeGap
1022
+ }));
1023
+ }
1024
+
865
1025
  //#endregion
866
1026
  //#region src/commands/commands/update-document-section.command.ts
867
1027
  const UpdateDocumentSectionCommand = {
@@ -880,6 +1040,11 @@ const UpdateDocumentSectionCommand = {
880
1040
  const selectedIds = new Set(updates.keys());
881
1041
  const sections = getTopLevelSectionBreaks(body).filter((section) => selectedIds.has(section.sectionId)).sort((left, right) => left.startIndex - right.startIndex);
882
1042
  if (sections.length !== selectedIds.size) return false;
1043
+ const documentStyle = documentDataModel.getDocumentStyle();
1044
+ if (sections.some((section) => !isValidSectionConfig({
1045
+ ...section,
1046
+ ...updates.get(section.sectionId)
1047
+ }, documentStyle))) return false;
883
1048
  const cursor = new MemoryCursor();
884
1049
  const textX = new TextX();
885
1050
  for (const section of sections) {
@@ -923,25 +1088,70 @@ const InsertDocumentSectionBreakCommand = {
923
1088
  id: "doc.command.insert-section-break",
924
1089
  type: CommandType.COMMAND,
925
1090
  handler: (accessor, params) => {
926
- var _body$sectionBreaks, _body$tables, _body$columnGroups, _body$blockRanges, _params$config;
1091
+ var _body$sectionBreaks;
927
1092
  if (!params) return false;
928
1093
  const context = getTraditionalDocumentContext(accessor, params.unitId);
929
- if (!context || !params.sectionId || !Number.isInteger(params.offset)) return false;
1094
+ if (!context || !params.sectionId || !Number.isInteger(params.offset) || params.nextSectionType != null && !isValidEnumValue(SectionType, params.nextSectionType)) return false;
930
1095
  const { body, documentDataModel, commandService } = context;
931
- if (params.offset < 0 || params.offset > body.dataStream.length || ((_body$sectionBreaks = body.sectionBreaks) === null || _body$sectionBreaks === void 0 ? void 0 : _body$sectionBreaks.some((section) => section.sectionId === params.sectionId)) || ((_body$tables = body.tables) === null || _body$tables === void 0 ? void 0 : _body$tables.some((range) => containsInteriorInsertionOffset(getTableRangeInterval(range), params.offset))) || ((_body$columnGroups = body.columnGroups) === null || _body$columnGroups === void 0 ? void 0 : _body$columnGroups.some((range) => containsInteriorInsertionOffset(getColumnGroupRangeInterval(range), params.offset))) || ((_body$blockRanges = body.blockRanges) === null || _body$blockRanges === void 0 ? void 0 : _body$blockRanges.some((range) => containsInteriorInsertionOffset(getBlockRangeInterval(range), params.offset)))) return false;
1096
+ const insertedSection = {
1097
+ ...Tools.deepClone(params.config ?? {}),
1098
+ sectionId: params.sectionId,
1099
+ startIndex: params.offset
1100
+ };
1101
+ if (!isValidTopLevelInsertionOffset(body, params.offset) || ((_body$sectionBreaks = body.sectionBreaks) === null || _body$sectionBreaks === void 0 ? void 0 : _body$sectionBreaks.some((section) => section.sectionId === params.sectionId)) || !isValidSectionConfig(insertedSection, documentDataModel.getDocumentStyle())) return false;
1102
+ const nextSection = params.nextSectionType == null ? void 0 : getTopLevelSectionBreaks(body).find((section) => section.startIndex >= params.offset);
1103
+ if (params.nextSectionType != null && !nextSection) return false;
932
1104
  const textX = new TextX();
933
1105
  textX.retain(params.offset);
934
1106
  textX.insert(1, {
935
1107
  dataStream: DataStreamTreeTokenType.SECTION_BREAK,
936
1108
  sectionBreaks: [{
937
- ...Tools.deepClone((_params$config = params.config) !== null && _params$config !== void 0 ? _params$config : {}),
938
- sectionId: params.sectionId,
1109
+ ...insertedSection,
939
1110
  startIndex: 0
940
1111
  }]
941
1112
  });
1113
+ if (nextSection && params.nextSectionType != null) {
1114
+ textX.retain(nextSection.startIndex - params.offset);
1115
+ textX.push({
1116
+ t: TextXActionType.RETAIN,
1117
+ len: 1,
1118
+ coverType: UpdateDocsAttributeType.REPLACE,
1119
+ body: {
1120
+ dataStream: "",
1121
+ sectionBreaks: [{
1122
+ ...Tools.deepClone(nextSection),
1123
+ sectionType: params.nextSectionType,
1124
+ startIndex: 0
1125
+ }]
1126
+ }
1127
+ });
1128
+ }
942
1129
  return executeSectionTextX(commandService, documentDataModel, textX, InsertDocumentSectionBreakCommand.id);
943
1130
  }
944
1131
  };
1132
+ const InsertDocumentColumnBreakCommand = {
1133
+ id: "doc.command.insert-column-break",
1134
+ type: CommandType.COMMAND,
1135
+ handler: (accessor, params) => {
1136
+ if (!params) return false;
1137
+ const context = getTraditionalDocumentContext(accessor, params.unitId);
1138
+ if (!context || !isValidTopLevelInsertionOffset(context.body, params.offset)) return false;
1139
+ const textX = new TextX();
1140
+ textX.retain(params.offset);
1141
+ textX.insert(1, {
1142
+ dataStream: DataStreamTreeTokenType.COLUMN_BREAK,
1143
+ customRanges: [{
1144
+ startIndex: 0,
1145
+ endIndex: 0,
1146
+ rangeId: `docx-break-${generateRandomId()}`,
1147
+ rangeType: CustomRangeType.CUSTOM,
1148
+ wholeEntity: true,
1149
+ properties: { docxBreakType: DocxBreakType.COLUMN }
1150
+ }]
1151
+ });
1152
+ return executeSectionTextX(context.commandService, context.documentDataModel, textX, InsertDocumentColumnBreakCommand.id);
1153
+ }
1154
+ };
945
1155
  const DeleteDocumentSectionBreakCommand = {
946
1156
  id: "doc.command.delete-section-break",
947
1157
  type: CommandType.COMMAND,
@@ -952,7 +1162,7 @@ const DeleteDocumentSectionBreakCommand = {
952
1162
  const sections = getTopLevelSectionBreaks(context.body);
953
1163
  if (sections.length <= 1) return false;
954
1164
  const section = sections.find((item) => item.sectionId === params.sectionId);
955
- if (!section) return false;
1165
+ if (!section || section === sections[sections.length - 1]) return false;
956
1166
  const textX = new TextX();
957
1167
  textX.retain(section.startIndex);
958
1168
  textX.delete(1);
@@ -970,6 +1180,38 @@ function getTraditionalDocumentContext(accessor, unitId) {
970
1180
  commandService: accessor.get(ICommandService)
971
1181
  };
972
1182
  }
1183
+ function isValidTopLevelInsertionOffset(body, offset) {
1184
+ var _body$tables, _body$columnGroups, _body$blockRanges;
1185
+ return Number.isInteger(offset) && offset >= 0 && offset <= body.dataStream.length && !((_body$tables = body.tables) === null || _body$tables === void 0 ? void 0 : _body$tables.some((range) => containsInteriorInsertionOffset(getTableRangeInterval(range), offset))) && !((_body$columnGroups = body.columnGroups) === null || _body$columnGroups === void 0 ? void 0 : _body$columnGroups.some((range) => containsInteriorInsertionOffset(getColumnGroupRangeInterval(range), offset))) && !((_body$blockRanges = body.blockRanges) === null || _body$blockRanges === void 0 ? void 0 : _body$blockRanges.some((range) => containsInteriorInsertionOffset(getBlockRangeInterval(range), offset)));
1186
+ }
1187
+ function isValidSectionConfig(section, documentStyle) {
1188
+ if (section.sectionType != null && !isValidEnumValue(SectionType, section.sectionType)) return false;
1189
+ if (section.pageOrient != null && !isValidEnumValue(PageOrientType, section.pageOrient)) return false;
1190
+ if (section.columnSeparatorType != null && !isValidEnumValue(ColumnSeparatorType, section.columnSeparatorType)) return false;
1191
+ if (section.pageNumberStart != null && (!Number.isInteger(section.pageNumberStart) || section.pageNumberStart < 1)) return false;
1192
+ if (section.pageSize && (!isPositiveFinite(section.pageSize.width) || !isPositiveFinite(section.pageSize.height))) return false;
1193
+ if ([
1194
+ section.marginTop,
1195
+ section.marginBottom,
1196
+ section.marginLeft,
1197
+ section.marginRight
1198
+ ].some((margin) => margin != null && (!Number.isFinite(margin) || margin < 0))) return false;
1199
+ const pageSize = section.pageSize ?? documentStyle.pageSize;
1200
+ const marginTop = section.marginTop ?? documentStyle.marginTop ?? 0;
1201
+ const marginBottom = section.marginBottom ?? documentStyle.marginBottom ?? 0;
1202
+ const marginLeft = section.marginLeft ?? documentStyle.marginLeft ?? 0;
1203
+ const marginRight = section.marginRight ?? documentStyle.marginRight ?? 0;
1204
+ if ((pageSize === null || pageSize === void 0 ? void 0 : pageSize.width) != null && marginLeft + marginRight >= pageSize.width || (pageSize === null || pageSize === void 0 ? void 0 : pageSize.height) != null && marginTop + marginBottom >= pageSize.height) return false;
1205
+ const columns = section.columnProperties ?? [];
1206
+ if (columns.some(({ width, paddingEnd }) => !Number.isFinite(width) || !Number.isFinite(paddingEnd) || width < 0 || paddingEnd < 0)) return false;
1207
+ return columns.reduce((sum, { width, paddingEnd }) => sum + width + paddingEnd, 0) <= getSectionContentWidth(documentStyle, section);
1208
+ }
1209
+ function isPositiveFinite(value) {
1210
+ return value != null && Number.isFinite(value) && value > 0;
1211
+ }
1212
+ function isValidEnumValue(enumObject, value) {
1213
+ return Object.values(enumObject).includes(value);
1214
+ }
973
1215
  function executeSectionTextX(commandService, documentDataModel, textX, trigger) {
974
1216
  const actions = JSONX.getInstance().editOp(textX.serialize(), getRichTextEditPath(documentDataModel));
975
1217
  return Boolean(commandService.syncExecuteCommand(RichTextEditingMutation.id, {
@@ -1036,7 +1278,6 @@ function createRemoveCustomBlockActions(params) {
1036
1278
  return composeActions([toBodyEditActions(textX, params.segmentId), createDrawingRemoveActions(params)]);
1037
1279
  }
1038
1280
  function createDocsCustomBlockDrawing(params) {
1039
- var _params$componentKey;
1040
1281
  const size = resolveDocsCustomBlockSize(params.childType);
1041
1282
  const isInline = params.interactionMode === "inline";
1042
1283
  return {
@@ -1044,7 +1285,7 @@ function createDocsCustomBlockDrawing(params) {
1044
1285
  subUnitId: params.unitId,
1045
1286
  drawingId: params.blockId,
1046
1287
  drawingType: DrawingTypeEnum.DRAWING_DOM,
1047
- componentKey: (_params$componentKey = params.componentKey) !== null && _params$componentKey !== void 0 ? _params$componentKey : EMBED_DOCS_CUSTOM_BLOCK_DEFAULT_COMPONENT_KEY,
1288
+ componentKey: params.componentKey ?? "UniverEmbedDocsCustomBlock",
1048
1289
  data: createEmbedDocsCustomBlockData(params),
1049
1290
  title: params.blockId,
1050
1291
  description: "Univer embedded unit custom block",
@@ -1082,15 +1323,14 @@ function isSheetLikeDocsCustomBlockChildType(childType) {
1082
1323
  return childType === UniverInstanceType.UNIVER_SHEET || childType === UniverInstanceType.UNIVER_BASE;
1083
1324
  }
1084
1325
  function createEmbedDocsCustomBlockData(params) {
1085
- var _params$embedId, _params$interactionMo;
1086
1326
  return {
1087
1327
  version: 1,
1088
- embedId: (_params$embedId = params.embedId) !== null && _params$embedId !== void 0 ? _params$embedId : params.blockId,
1328
+ embedId: params.embedId ?? params.blockId,
1089
1329
  hostUnitId: params.unitId,
1090
1330
  hostAnchorId: params.blockId,
1091
1331
  childUnitId: params.childUnitId,
1092
1332
  childType: params.childType,
1093
- interactionMode: (_params$interactionMo = params.interactionMode) !== null && _params$interactionMo !== void 0 ? _params$interactionMo : "block"
1333
+ interactionMode: params.interactionMode ?? "block"
1094
1334
  };
1095
1335
  }
1096
1336
  function isEmbedDocsCustomBlockData(data) {
@@ -1117,40 +1357,36 @@ function createRichTextMutation(unitId, segmentId, actions) {
1117
1357
  };
1118
1358
  }
1119
1359
  function toBodyEditActions(textX, segmentId) {
1120
- const action = JSONX.getInstance().editOp(textX.serialize(), segmentId ? [
1360
+ return JSONX.getInstance().editOp(textX.serialize(), segmentId ? [
1121
1361
  "headers",
1122
1362
  segmentId,
1123
1363
  "body"
1124
- ] : ["body"]);
1125
- return action !== null && action !== void 0 ? action : [];
1364
+ ] : ["body"]) ?? [];
1126
1365
  }
1127
1366
  function createDrawingInsertActions(params) {
1128
- var _jsonX$insertOp, _jsonX$insertOp2, _params$drawingOrderI;
1129
1367
  if (params.segmentId) return [];
1130
1368
  const jsonX = JSONX.getInstance();
1131
1369
  const drawing = createDocsCustomBlockDrawing(params);
1132
- return composeActions([(_jsonX$insertOp = jsonX.insertOp(["drawings", params.blockId], drawing)) !== null && _jsonX$insertOp !== void 0 ? _jsonX$insertOp : [], (_jsonX$insertOp2 = jsonX.insertOp(["drawingsOrder", (_params$drawingOrderI = params.drawingOrderIndex) !== null && _params$drawingOrderI !== void 0 ? _params$drawingOrderI : 0], params.blockId)) !== null && _jsonX$insertOp2 !== void 0 ? _jsonX$insertOp2 : []]);
1370
+ return composeActions([jsonX.insertOp(["drawings", params.blockId], drawing) ?? [], jsonX.insertOp(["drawingsOrder", params.drawingOrderIndex ?? 0], params.blockId) ?? []]);
1133
1371
  }
1134
1372
  function createDrawingRemoveActions(params) {
1135
- var _jsonX$removeOp, _jsonX$removeOp2, _params$drawingOrderI2;
1136
1373
  if (params.segmentId) return [];
1137
1374
  const jsonX = JSONX.getInstance();
1138
1375
  const drawing = createDocsCustomBlockDrawing(params);
1139
- return composeActions([(_jsonX$removeOp = jsonX.removeOp(["drawings", params.blockId], drawing)) !== null && _jsonX$removeOp !== void 0 ? _jsonX$removeOp : [], (_jsonX$removeOp2 = jsonX.removeOp(["drawingsOrder", (_params$drawingOrderI2 = params.drawingOrderIndex) !== null && _params$drawingOrderI2 !== void 0 ? _params$drawingOrderI2 : 0], params.blockId)) !== null && _jsonX$removeOp2 !== void 0 ? _jsonX$removeOp2 : []]);
1376
+ return composeActions([jsonX.removeOp(["drawings", params.blockId], drawing) ?? [], jsonX.removeOp(["drawingsOrder", params.drawingOrderIndex ?? 0], params.blockId) ?? []]);
1140
1377
  }
1141
1378
  function composeActions(actions) {
1142
1379
  return actions.reduce((composed, action) => {
1143
- var _JSONX$compose;
1144
1380
  if (!action || JSONX.isNoop(action) || action.length === 0) return composed;
1145
1381
  if (!composed || JSONX.isNoop(composed) || composed.length === 0) return action;
1146
- return (_JSONX$compose = JSONX.compose(composed, action)) !== null && _JSONX$compose !== void 0 ? _JSONX$compose : [];
1382
+ return JSONX.compose(composed, action) ?? [];
1147
1383
  }, []);
1148
1384
  }
1149
1385
 
1150
1386
  //#endregion
1151
1387
  //#region package.json
1152
1388
  var name = "@univerjs/docs";
1153
- var version = "1.0.0-alpha.7";
1389
+ var version = "1.0.0-beta.0";
1154
1390
 
1155
1391
  //#endregion
1156
1392
  //#region src/commands/mutations/docs-rename.mutation.ts
@@ -1228,7 +1464,7 @@ let DocCustomRangeController = class DocCustomRangeController extends Disposable
1228
1464
  const doc = this._univerInstanceService.getUnit(unitId);
1229
1465
  if (!doc) return;
1230
1466
  const transformedRanges = ranges.map((range) => this._transformCustomRange(doc, range));
1231
- if (transformedRanges.some((range, i) => ranges[i] !== range)) this._textSelectionManagerService.replaceTextRanges(transformedRanges, isEditing);
1467
+ if (transformedRanges.some((range, i) => ranges[i] !== range)) this._textSelectionManagerService.replaceDocRanges(transformedRanges, void 0, isEditing);
1232
1468
  }
1233
1469
  }));
1234
1470
  }
@@ -1325,10 +1561,9 @@ let DocStateChangeManagerService = class DocStateChangeManagerService extends Rx
1325
1561
  this._listenDocStateChange();
1326
1562
  }
1327
1563
  getStateCache(unitId) {
1328
- var _this$_historyStateCa, _this$_changeStateCac;
1329
1564
  return {
1330
- history: (_this$_historyStateCa = this._historyStateCache.get(unitId)) !== null && _this$_historyStateCa !== void 0 ? _this$_historyStateCa : [],
1331
- collaboration: (_this$_changeStateCac = this._changeStateCache.get(unitId)) !== null && _this$_changeStateCac !== void 0 ? _this$_changeStateCac : []
1565
+ history: this._historyStateCache.get(unitId) ?? [],
1566
+ collaboration: this._changeStateCache.get(unitId) ?? []
1332
1567
  };
1333
1568
  }
1334
1569
  setStateCache(unitId, cache) {
@@ -1352,9 +1587,9 @@ let DocStateChangeManagerService = class DocStateChangeManagerService extends Rx
1352
1587
  }
1353
1588
  _listenDocStateChange() {
1354
1589
  this._docStateEmitService.docStateChangeParams$.pipe(takeUntil(this.dispose$)).subscribe((changeStateInfo) => {
1355
- var _this$_docStateChange, _this$_docStateChange2;
1590
+ var _this$_docStateChange;
1356
1591
  if (changeStateInfo == null) return;
1357
- const interceptedChangeStateInfo = (_this$_docStateChange = (_this$_docStateChange2 = this._docStateChangeInterceptorService) === null || _this$_docStateChange2 === void 0 ? void 0 : _this$_docStateChange2.transformChangeStateInfo(changeStateInfo)) !== null && _this$_docStateChange !== void 0 ? _this$_docStateChange : changeStateInfo;
1592
+ const interceptedChangeStateInfo = ((_this$_docStateChange = this._docStateChangeInterceptorService) === null || _this$_docStateChange === void 0 ? void 0 : _this$_docStateChange.transformChangeStateInfo(changeStateInfo)) ?? changeStateInfo;
1358
1593
  if (interceptedChangeStateInfo == null) return;
1359
1594
  if (interceptedChangeStateInfo.isSync) return;
1360
1595
  const { isCompositionEnd: _isCompositionEnd, isSync: _isSync, syncer: _syncer, ...changeState } = interceptedChangeStateInfo;
@@ -1452,6 +1687,79 @@ DocStateChangeManagerService = __decorate([
1452
1687
  __decorateParam(4, Optional(IDocStateChangeInterceptorService))
1453
1688
  ], DocStateChangeManagerService);
1454
1689
 
1690
+ //#endregion
1691
+ //#region src/services/doc-text-resolver.service.ts
1692
+ /**
1693
+ * Builds a consumer-facing text projection while retaining a mapping back to
1694
+ * the native document offsets.
1695
+ *
1696
+ * Consumers such as find/replace can search the projected text and then use
1697
+ * `characters` to focus the native object that supplied a matching character.
1698
+ * Resolvers must return half-open, non-overlapping replacements.
1699
+ */
1700
+ var DocTextResolverService = class extends Disposable {
1701
+ constructor(..._args) {
1702
+ super(..._args);
1703
+ _defineProperty(this, "_resolvers", /* @__PURE__ */ new Set());
1704
+ _defineProperty(this, "_textChanged$", new Subject());
1705
+ _defineProperty(this, "textChanged$", this._textChanged$.asObservable());
1706
+ }
1707
+ register(resolver) {
1708
+ this._resolvers.add(resolver);
1709
+ return toDisposable(() => this._resolvers.delete(resolver));
1710
+ }
1711
+ notifyTextChanged(unitId) {
1712
+ this._textChanged$.next(unitId);
1713
+ }
1714
+ resolve(unitId, body) {
1715
+ const replacements = this._collectReplacements(unitId, body);
1716
+ const characters = [];
1717
+ let text = "";
1718
+ let sourceOffset = 0;
1719
+ for (const replacement of replacements) {
1720
+ const sourceText = body.dataStream.slice(sourceOffset, replacement.startOffset);
1721
+ text += sourceText;
1722
+ for (let index = sourceOffset; index < replacement.startOffset; index += 1) characters.push({
1723
+ startOffset: index,
1724
+ endOffset: index + 1,
1725
+ replaceable: true
1726
+ });
1727
+ text += replacement.text;
1728
+ for (let index = 0; index < replacement.text.length; index += 1) characters.push({
1729
+ startOffset: replacement.startOffset,
1730
+ endOffset: replacement.endOffset,
1731
+ replaceable: replacement.replaceable ?? false
1732
+ });
1733
+ sourceOffset = replacement.endOffset;
1734
+ }
1735
+ text += body.dataStream.slice(sourceOffset);
1736
+ for (let index = sourceOffset; index < body.dataStream.length; index += 1) characters.push({
1737
+ startOffset: index,
1738
+ endOffset: index + 1,
1739
+ replaceable: true
1740
+ });
1741
+ return {
1742
+ characters,
1743
+ text
1744
+ };
1745
+ }
1746
+ _collectReplacements(unitId, body) {
1747
+ const candidates = [...this._resolvers].flatMap((resolver) => resolver.resolve(unitId, body)).filter((replacement) => Number.isInteger(replacement.startOffset) && Number.isInteger(replacement.endOffset) && replacement.startOffset >= 0 && replacement.endOffset > replacement.startOffset && replacement.endOffset <= body.dataStream.length).sort((left, right) => left.startOffset - right.startOffset || right.endOffset - left.endOffset);
1748
+ const replacements = [];
1749
+ let previousEnd = -1;
1750
+ for (const candidate of candidates) {
1751
+ if (candidate.startOffset < previousEnd) continue;
1752
+ replacements.push(candidate);
1753
+ previousEnd = candidate.endOffset;
1754
+ }
1755
+ return replacements;
1756
+ }
1757
+ dispose() {
1758
+ this._textChanged$.complete();
1759
+ super.dispose();
1760
+ }
1761
+ };
1762
+
1455
1763
  //#endregion
1456
1764
  //#region src/plugin.ts
1457
1765
  let UniverDocsPlugin = class UniverDocsPlugin extends Plugin {
@@ -1475,8 +1783,10 @@ let UniverDocsPlugin = class UniverDocsPlugin extends Plugin {
1475
1783
  CreateHeaderFooterCommand,
1476
1784
  SetDocumentDefaultParagraphStyleCommand,
1477
1785
  SetSectionHeaderFooterLinkCommand,
1786
+ UpdateDocumentParagraphStyleCommand,
1478
1787
  UpdateDocumentSectionCommand,
1479
1788
  InsertDocumentSectionBreakCommand,
1789
+ InsertDocumentColumnBreakCommand,
1480
1790
  DeleteDocumentSectionBreakCommand,
1481
1791
  RichTextEditingMutation,
1482
1792
  DocsRenameMutation,
@@ -1492,6 +1802,7 @@ let UniverDocsPlugin = class UniverDocsPlugin extends Plugin {
1492
1802
  [DocStateChangeManagerService],
1493
1803
  [DocBlockMoveValidatorService],
1494
1804
  [DocContentInsertService],
1805
+ [DocTextResolverService],
1495
1806
  [DocCustomRangeController]
1496
1807
  ].forEach((d) => this._injector.add(d));
1497
1808
  }
@@ -1547,10 +1858,7 @@ let DocInterceptorService = class DocInterceptorService extends Disposable {
1547
1858
  if (!this._interceptorsByName.has(key)) this._interceptorsByName.set(key, []);
1548
1859
  const interceptors = this._interceptorsByName.get(key);
1549
1860
  interceptors.push(interceptor);
1550
- this._interceptorsByName.set(key, interceptors.sort((a, b) => {
1551
- var _b$priority, _a$priority;
1552
- return ((_b$priority = b.priority) !== null && _b$priority !== void 0 ? _b$priority : 0) - ((_a$priority = a.priority) !== null && _a$priority !== void 0 ? _a$priority : 0);
1553
- }));
1861
+ this._interceptorsByName.set(key, interceptors.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0)));
1554
1862
  return this.disposeWithMe(toDisposable(() => remove(this._interceptorsByName.get(key), interceptor)));
1555
1863
  }
1556
1864
  fetchThroughInterceptors(name) {
@@ -1561,19 +1869,17 @@ let DocInterceptorService = class DocInterceptorService extends Disposable {
1561
1869
  const disposableCollection = new DisposableCollection();
1562
1870
  disposableCollection.add(viewModel.registerCustomRangeInterceptor({
1563
1871
  getCustomRange: (index) => {
1564
- var _viewModel$getDataMod;
1565
1872
  return this.fetchThroughInterceptors(DOC_INTERCEPTOR_POINT.CUSTOM_RANGE)(viewModel.getCustomRangeRaw(index), {
1566
1873
  index,
1567
1874
  unitId: viewModel.getDataModel().getUnitId(),
1568
- customRanges: (_viewModel$getDataMod = viewModel.getDataModel().getCustomRanges()) !== null && _viewModel$getDataMod !== void 0 ? _viewModel$getDataMod : []
1875
+ customRanges: viewModel.getDataModel().getCustomRanges() ?? []
1569
1876
  });
1570
1877
  },
1571
1878
  getCustomDecoration: (index) => {
1572
- var _viewModel$getDataMod2;
1573
1879
  return this.fetchThroughInterceptors(DOC_INTERCEPTOR_POINT.CUSTOM_DECORATION)(viewModel.getCustomDecorationRaw(index), {
1574
1880
  index,
1575
1881
  unitId: viewModel.getDataModel().getUnitId(),
1576
- customDecorations: (_viewModel$getDataMod2 = viewModel.getDataModel().getCustomDecorations()) !== null && _viewModel$getDataMod2 !== void 0 ? _viewModel$getDataMod2 : []
1882
+ customDecorations: viewModel.getDataModel().getCustomDecorations() ?? []
1577
1883
  });
1578
1884
  }
1579
1885
  }));
@@ -1611,7 +1917,7 @@ function addCustomRangeBySelectionFactory(accessor, param) {
1611
1917
  const { rangeId, rangeType, wholeEntity, properties, unitId, selections: propSelection } = param;
1612
1918
  const docSelectionManagerService = accessor.get(DocSelectionManagerService);
1613
1919
  const univerInstanceService = accessor.get(IUniverInstanceService);
1614
- const selections = propSelection !== null && propSelection !== void 0 ? propSelection : docSelectionManagerService.getTextRanges({
1920
+ const selections = propSelection ?? docSelectionManagerService.getTextRanges({
1615
1921
  unitId,
1616
1922
  subUnitId: unitId
1617
1923
  });
@@ -1694,8 +2000,7 @@ function generateParagraphs(dataStream, prevParagraph, borderBottom, existingPar
1694
2000
  if (prevParagraph.paragraphStyle.headingId) paragraph.paragraphStyle.headingId = generateRandomId(6);
1695
2001
  }
1696
2002
  if (borderBottom) {
1697
- var _paragraph$paragraphS;
1698
- (_paragraph$paragraphS = paragraph.paragraphStyle) !== null && _paragraph$paragraphS !== void 0 || (paragraph.paragraphStyle = {});
2003
+ paragraph.paragraphStyle ??= {};
1699
2004
  paragraph.paragraphStyle.borderBottom = Tools.deepClone(borderBottom);
1700
2005
  paragraph.paragraphStyle.spaceBelow = { v: 10 };
1701
2006
  }
@@ -1706,7 +2011,7 @@ function generateParagraphs(dataStream, prevParagraph, borderBottom, existingPar
1706
2011
  //#endregion
1707
2012
  //#region src/utils/replace-selection-factory.ts
1708
2013
  function replaceSelectionFactory(accessor, params) {
1709
- var _params$selection, _docDataModel$getSelf, _params$selection2, _params$textRanges;
2014
+ var _params$selection, _docDataModel$getSelf;
1710
2015
  const { unitId, body: insertBody, doc } = params;
1711
2016
  let docDataModel = doc;
1712
2017
  if (!docDataModel) docDataModel = accessor.get(IUniverInstanceService).getUnit(unitId);
@@ -1715,9 +2020,9 @@ function replaceSelectionFactory(accessor, params) {
1715
2020
  const body = (_docDataModel$getSelf = docDataModel.getSelfOrHeaderFooterModel(segmentId)) === null || _docDataModel$getSelf === void 0 ? void 0 : _docDataModel$getSelf.getBody();
1716
2021
  if (!body) return false;
1717
2022
  const docSelectionManagerService = accessor.get(DocSelectionManagerService);
1718
- const selection = (_params$selection2 = params.selection) !== null && _params$selection2 !== void 0 ? _params$selection2 : docSelectionManagerService.getActiveTextRange();
2023
+ const selection = params.selection ?? docSelectionManagerService.getActiveTextRange();
1719
2024
  if (!selection || !body) return false;
1720
- const textRanges = (_params$textRanges = params.textRanges) !== null && _params$textRanges !== void 0 ? _params$textRanges : [{
2025
+ const textRanges = params.textRanges ?? [{
1721
2026
  startOffset: selection.startOffset + insertBody.dataStream.length,
1722
2027
  endOffset: selection.startOffset + insertBody.dataStream.length,
1723
2028
  collapsed: true,
@@ -1745,26 +2050,9 @@ function replaceSelectionFactory(accessor, params) {
1745
2050
  return doMutation;
1746
2051
  }
1747
2052
 
1748
- //#endregion
1749
- //#region src/utils/section-columns.ts
1750
- /** Creates explicit OOXML section columns from a count, gap, and optional widths. */
1751
- function createSectionColumnProperties(documentStyle, section, columnCount, gap, widths) {
1752
- var _ref, _section$pageSize$wid, _section$pageSize, _documentStyle$pageSi, _ref2, _section$marginLeft, _ref3, _section$marginRight;
1753
- if (columnCount <= 1) return [];
1754
- const safeGap = Math.max(0, gap);
1755
- const pageWidth = (_ref = (_section$pageSize$wid = section === null || section === void 0 || (_section$pageSize = section.pageSize) === null || _section$pageSize === void 0 ? void 0 : _section$pageSize.width) !== null && _section$pageSize$wid !== void 0 ? _section$pageSize$wid : documentStyle === null || documentStyle === void 0 || (_documentStyle$pageSi = documentStyle.pageSize) === null || _documentStyle$pageSi === void 0 ? void 0 : _documentStyle$pageSi.width) !== null && _ref !== void 0 ? _ref : PAGE_SIZE[PaperType.A4].width;
1756
- const contentWidth = Math.max(0, pageWidth - ((_ref2 = (_section$marginLeft = section === null || section === void 0 ? void 0 : section.marginLeft) !== null && _section$marginLeft !== void 0 ? _section$marginLeft : documentStyle === null || documentStyle === void 0 ? void 0 : documentStyle.marginLeft) !== null && _ref2 !== void 0 ? _ref2 : 72) - ((_ref3 = (_section$marginRight = section === null || section === void 0 ? void 0 : section.marginRight) !== null && _section$marginRight !== void 0 ? _section$marginRight : documentStyle === null || documentStyle === void 0 ? void 0 : documentStyle.marginRight) !== null && _ref3 !== void 0 ? _ref3 : 72));
1757
- const availableWidth = Math.max(0, contentWidth - safeGap * (columnCount - 1));
1758
- return (widths !== null && widths !== void 0 ? widths : Array.from({ length: columnCount }, () => availableWidth / columnCount)).map((width, index) => ({
1759
- width: Math.max(0, width),
1760
- paddingEnd: index === columnCount - 1 ? 0 : safeGap
1761
- }));
1762
- }
1763
-
1764
2053
  //#endregion
1765
2054
  //#region src/utils/transform-position.ts
1766
2055
  function buildDocTransform(width, height, position) {
1767
- var _position$left, _position$top;
1768
2056
  return {
1769
2057
  size: {
1770
2058
  width,
@@ -1772,11 +2060,11 @@ function buildDocTransform(width, height, position) {
1772
2060
  },
1773
2061
  positionH: {
1774
2062
  relativeFrom: ObjectRelativeFromH.PAGE,
1775
- posOffset: (_position$left = position === null || position === void 0 ? void 0 : position.left) !== null && _position$left !== void 0 ? _position$left : 0
2063
+ posOffset: (position === null || position === void 0 ? void 0 : position.left) ?? 0
1776
2064
  },
1777
2065
  positionV: {
1778
2066
  relativeFrom: ObjectRelativeFromV.PARAGRAPH,
1779
- posOffset: (_position$top = position === null || position === void 0 ? void 0 : position.top) !== null && _position$top !== void 0 ? _position$top : 0
2067
+ posOffset: (position === null || position === void 0 ? void 0 : position.top) ?? 0
1780
2068
  },
1781
2069
  angle: 0
1782
2070
  };
@@ -1822,7 +2110,7 @@ function consumeContentInsertRange(accessor, unitId) {
1822
2110
  }
1823
2111
  function getContentInsertRange(accessor, unitId) {
1824
2112
  var _accessor$get$getCurr;
1825
- const _unitId = unitId !== null && unitId !== void 0 ? unitId : (_accessor$get$getCurr = accessor.get(IUniverInstanceService).getCurrentUnitOfType(UniverInstanceType.UNIVER_DOC)) === null || _accessor$get$getCurr === void 0 ? void 0 : _accessor$get$getCurr.getUnitId();
2113
+ const _unitId = unitId ?? ((_accessor$get$getCurr = accessor.get(IUniverInstanceService).getCurrentUnitOfType(UniverInstanceType.UNIVER_DOC)) === null || _accessor$get$getCurr === void 0 ? void 0 : _accessor$get$getCurr.getUnitId());
1826
2114
  if (!_unitId) return null;
1827
2115
  const insertRange = consumeContentInsertRange(accessor, _unitId);
1828
2116
  if (!insertRange) return null;
@@ -1835,15 +2123,14 @@ function isHeaderFooterSelection(range) {
1835
2123
  return Boolean(range === null || range === void 0 ? void 0 : range.segmentId);
1836
2124
  }
1837
2125
  function normalizeTextRange(textRange) {
1838
- var _textRange$endOffset, _textRange$collapsed, _textRange$segmentId;
1839
- const endOffset = (_textRange$endOffset = textRange.endOffset) !== null && _textRange$endOffset !== void 0 ? _textRange$endOffset : textRange.startOffset;
2126
+ const endOffset = textRange.endOffset ?? textRange.startOffset;
1840
2127
  return {
1841
2128
  ...textRange,
1842
2129
  endOffset,
1843
- collapsed: (_textRange$collapsed = textRange.collapsed) !== null && _textRange$collapsed !== void 0 ? _textRange$collapsed : textRange.startOffset === endOffset,
1844
- segmentId: (_textRange$segmentId = textRange.segmentId) !== null && _textRange$segmentId !== void 0 ? _textRange$segmentId : ""
2130
+ collapsed: textRange.collapsed ?? textRange.startOffset === endOffset,
2131
+ segmentId: textRange.segmentId ?? ""
1845
2132
  };
1846
2133
  }
1847
2134
 
1848
2135
  //#endregion
1849
- export { CreateHeaderFooterCommand, DOC_INTERCEPTOR_POINT, DeleteDocumentSectionBreakCommand, DeleteTextCommand, DocBlockMoveValidatorService, DocContentInsertService, DocInterceptorService, DocSelectionManagerService, DocSkeletonManagerService, DocStateChangeManagerService, DocStateEmitService, EMBED_DOCS_CUSTOM_BLOCK_DEFAULT_COMPONENT_KEY, HeaderFooterType, IDocStateChangeInterceptorService, InsertDocumentSectionBreakCommand, InsertTextCommand, RichTextEditingMutation, SetDocumentDefaultParagraphStyleCommand, SetSectionHeaderFooterLinkCommand, SetTextSelectionsOperation, UniverDocsPlugin, UpdateDocumentSectionCommand, UpdateTextCommand, addCustomRangeBySelectionFactory, addCustomRangeFactory, buildDocTransform, consumeContentInsertRange, createDocsCustomBlockDrawing, createDocsCustomBlockInsertMutation, createDocsCustomBlockRemoveMutation, createEmbedDocsCustomBlockData, createInsertCustomBlockActions, createRemoveCustomBlockActions, createSectionColumnProperties, deleteCustomRangeFactory, docDrawingPositionToTransform, generateParagraphs, getContentInsertRange, getTopLevelSectionBreaks, isEmbedDocsCustomBlockData, isHeaderFooterSelection, isSheetLikeDocsCustomBlockChildType, normalizeTextRange, replaceSelectionFactory, resolveDocsCustomBlockSize, shouldUseInlineTextSelectionForDocsCustomBlockDrawing, transformToDocDrawingPosition };
2136
+ export { CreateHeaderFooterCommand, DOC_INTERCEPTOR_POINT, DOC_SELECTION_OPTION_PRESERVE_CARET, DeleteDocumentSectionBreakCommand, DeleteTextCommand, DocBlockMoveValidatorService, DocContentInsertService, DocInterceptorService, DocSelectionManagerService, DocSkeletonManagerService, DocStateChangeManagerService, DocStateEmitService, DocTextResolverService, EMBED_DOCS_CUSTOM_BLOCK_DEFAULT_COMPONENT_KEY, HeaderFooterType, IDocStateChangeInterceptorService, InsertDocumentColumnBreakCommand, InsertDocumentSectionBreakCommand, InsertTextCommand, RichTextEditingMutation, SetDocumentDefaultParagraphStyleCommand, SetSectionHeaderFooterLinkCommand, SetTextSelectionsOperation, UniverDocsPlugin, UpdateDocumentParagraphStyleCommand, UpdateDocumentSectionCommand, UpdateTextCommand, addCustomRangeBySelectionFactory, addCustomRangeFactory, buildDocTransform, consumeContentInsertRange, createDocsCustomBlockDrawing, createDocsCustomBlockInsertMutation, createDocsCustomBlockRemoveMutation, createEmbedDocsCustomBlockData, createInsertCustomBlockActions, createRemoveCustomBlockActions, createSectionColumnProperties, deleteCustomRangeFactory, docDrawingPositionToTransform, generateParagraphs, getContentInsertRange, getEffectiveSectionPageSetup, getSectionContentWidth, getTopLevelSectionBreaks, isEmbedDocsCustomBlockData, isHeaderFooterSelection, isSheetLikeDocsCustomBlockChildType, normalizeTextRange, replaceSelectionFactory, resolveDocsCustomBlockSize, shouldUseInlineTextSelectionForDocsCustomBlockDrawing, transformToDocDrawingPosition };