@univerjs/docs 1.0.0-alpha.1 → 1.0.0-alpha.3

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 (32) hide show
  1. package/lib/cjs/facade.js +1156 -868
  2. package/lib/cjs/index.js +723 -18
  3. package/lib/es/facade.js +1154 -867
  4. package/lib/es/index.js +701 -19
  5. package/lib/facade.js +1154 -867
  6. package/lib/index.js +701 -19
  7. package/lib/types/commands/commands/create-header-footer.command.d.ts +45 -0
  8. package/lib/types/commands/commands/set-document-default-paragraph-style.command.d.ts +24 -0
  9. package/lib/types/commands/commands/set-section-header-footer-link.command.d.ts +26 -0
  10. package/lib/types/commands/commands/update-document-section.command.d.ts +38 -0
  11. package/lib/types/embed-host-anchor.d.ts +61 -0
  12. package/lib/types/facade/f-document-paragraph.d.ts +87 -100
  13. package/lib/types/facade/f-document-section.d.ts +281 -0
  14. package/lib/types/facade/f-document-text-range.d.ts +136 -0
  15. package/lib/types/facade/f-document.d.ts +316 -26
  16. package/lib/types/facade/f-enum.d.ts +32 -0
  17. package/lib/types/facade/f-types.d.ts +16 -0
  18. package/lib/types/facade/index.d.ts +11 -6
  19. package/lib/types/facade/utils.d.ts +15 -1
  20. package/lib/types/index.d.ts +15 -1
  21. package/lib/types/utils/paragraphs.d.ts +18 -0
  22. package/lib/types/utils/section-columns.d.ts +18 -0
  23. package/lib/types/utils/sections.d.ts +18 -0
  24. package/lib/types/utils/util.d.ts +19 -0
  25. package/lib/umd/facade.js +3 -1
  26. package/lib/umd/index.js +2 -1
  27. package/package.json +5 -5
  28. package/lib/types/facade/f-document-block-range.d.ts +0 -132
  29. package/lib/types/facade/f-document-body.d.ts +0 -276
  30. package/lib/types/facade/f-document-custom-block.d.ts +0 -57
  31. package/lib/types/facade/f-document-element.d.ts +0 -193
  32. package/lib/types/facade/f-document-table.d.ts +0 -57
package/lib/es/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { BuildTextUtils, CommandType, DOCS_FORMULA_BAR_EDITOR_UNIT_ID_KEY, DOCS_NORMAL_EDITOR_UNIT_ID_KEY, DeleteDirection, Disposable, DisposableCollection, ICommandService, IConfigService, IUndoRedoService, IUniverInstanceService, Inject, Injector, JSONX, LocaleService, Optional, Plugin, RedoCommandId, RxDisposable, TextX, TextXActionType, UndoCommandId, UniverInstanceType, composeInterceptors, createIdentifier, createInterceptorKey, getRichTextEditPath, isInternalEditorID, merge, remove, toDisposable } from "@univerjs/core";
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";
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
 
@@ -315,6 +315,27 @@ var DocStateEmitService = class extends RxDisposable {
315
315
  //#endregion
316
316
  //#region src/commands/mutations/core-editing.mutation.ts
317
317
  const RichTextEditingMutationId = "doc.mutation.rich-text-editing";
318
+ function getSegmentType(documentDataModel, segmentId) {
319
+ if (!segmentId) return "body";
320
+ const { headers, footers } = documentDataModel.getSnapshot();
321
+ if (headers === null || headers === void 0 ? void 0 : headers[segmentId]) return "header";
322
+ if (footers === null || footers === void 0 ? void 0 : footers[segmentId]) return "footer";
323
+ return "body";
324
+ }
325
+ function assertValidDocBodyStructure(documentDataModel, segmentId) {
326
+ const segmentModel = documentDataModel.getSelfOrHeaderFooterModel(segmentId);
327
+ const body = segmentModel === null || segmentModel === void 0 ? void 0 : segmentModel.getBody();
328
+ if (!body) return;
329
+ const segmentType = getSegmentType(documentDataModel, segmentId);
330
+ const issues = validateDocBodyStructure(body, {
331
+ segmentType,
332
+ segmentId: segmentId || void 0
333
+ });
334
+ if (!issues.length) return;
335
+ const detail = issues.map((issue) => `${issue.code}${issue.index == null ? "" : `@${issue.index}`}`).join(", ");
336
+ const segmentLabel = segmentId ? `${segmentType} ${segmentId}` : segmentType;
337
+ throw new Error(`[DocStructure] ${segmentLabel}: ${detail}`);
338
+ }
318
339
  /**
319
340
  * The core mutator to change rich text actions. The execution result would be undo mutation params. Could be directly
320
341
  * send to undo redo service (will be used by the triggering command).
@@ -342,6 +363,12 @@ const RichTextEditingMutation = {
342
363
  };
343
364
  const undoActions = JSONX.invertWithDoc(actions, documentDataModel.getSnapshot());
344
365
  documentDataModel.apply(actions);
366
+ try {
367
+ assertValidDocBodyStructure(documentDataModel, segmentId);
368
+ } catch (error) {
369
+ documentDataModel.apply(undoActions);
370
+ throw error;
371
+ }
345
372
  documentViewModel === null || documentViewModel === void 0 || documentViewModel.reset(documentDataModel);
346
373
  if (!noNeedSetTextRange && textRanges && trigger != null && !isSync) queueMicrotask(() => {
347
374
  docSelectionManagerService.replaceDocRanges(textRanges, {
@@ -386,14 +413,16 @@ const InsertTextCommand = {
386
413
  id: "doc.command.insert-text",
387
414
  type: CommandType.COMMAND,
388
415
  handler: (accessor, params) => {
389
- var _activeRange$segmentI;
416
+ var _ref, _ref2, _docDataModel$getSelf;
390
417
  const commandService = accessor.get(ICommandService);
391
418
  const { range, segmentId, body, unitId, cursorOffset } = params;
392
419
  const docSelectionManagerService = accessor.get(DocSelectionManagerService);
393
420
  const docDataModel = accessor.get(IUniverInstanceService).getUnit(unitId, UniverInstanceType.UNIVER_DOC);
394
421
  if (docDataModel == null) return false;
395
422
  const activeRange = docSelectionManagerService.getActiveTextRange();
396
- const originBody = docDataModel.getSelfOrHeaderFooterModel((_activeRange$segmentI = activeRange === null || activeRange === void 0 ? void 0 : activeRange.segmentId) !== null && _activeRange$segmentI !== void 0 ? _activeRange$segmentI : "").getBody();
423
+ 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 : "";
425
+ const originBody = (_docDataModel$getSelf = docDataModel.getSelfOrHeaderFooterModel(targetSegmentId)) === null || _docDataModel$getSelf === void 0 ? void 0 : _docDataModel$getSelf.getBody();
397
426
  if (originBody == null) return false;
398
427
  const { startOffset, collapsed } = range;
399
428
  const cursorMove = cursorOffset !== null && cursorOffset !== void 0 ? cursorOffset : body.dataStream.length;
@@ -446,12 +475,12 @@ const DeleteTextCommand = {
446
475
  id: "doc.command.delete-text",
447
476
  type: CommandType.COMMAND,
448
477
  handler: (accessor, params) => {
449
- var _body$customRanges;
478
+ var _docDataModel$getSelf2, _body$customRanges;
450
479
  const commandService = accessor.get(ICommandService);
451
480
  const univerInstanceService = accessor.get(IUniverInstanceService);
452
481
  const { range, segmentId, unitId, direction, len = 1 } = params;
453
482
  const docDataModel = univerInstanceService.getUnit(unitId, UniverInstanceType.UNIVER_DOC);
454
- const body = docDataModel === null || docDataModel === void 0 ? void 0 : docDataModel.getSelfOrHeaderFooterModel(segmentId).getBody();
483
+ const body = docDataModel === null || docDataModel === void 0 || (_docDataModel$getSelf2 = docDataModel.getSelfOrHeaderFooterModel(segmentId)) === null || _docDataModel$getSelf2 === void 0 ? void 0 : _docDataModel$getSelf2.getBody();
455
484
  if (docDataModel == null || body == null) return false;
456
485
  const { startOffset } = range;
457
486
  let start = direction === DeleteDirection.LEFT ? startOffset - len : startOffset;
@@ -476,14 +505,12 @@ const DeleteTextCommand = {
476
505
  };
477
506
  const textX = new TextX();
478
507
  const jsonX = JSONX.getInstance();
479
- textX.push({
480
- t: TextXActionType.RETAIN,
481
- len: start - 0
482
- });
483
- textX.push({
484
- t: TextXActionType.DELETE,
485
- len: end - start + 1
486
- });
508
+ textX.push(...BuildTextUtils.selection.delete([{
509
+ ...range,
510
+ startOffset: start,
511
+ endOffset: end + 1,
512
+ collapsed: false
513
+ }], body));
487
514
  const path = getRichTextEditPath(docDataModel, segmentId);
488
515
  doMutation.params.actions = jsonX.editOp(textX.serialize(), path);
489
516
  const result = commandService.syncExecuteCommand(doMutation.id, doMutation.params);
@@ -499,7 +526,7 @@ const UpdateTextCommand = {
499
526
  handler: (accessor, params) => {
500
527
  const { range, segmentId, updateBody, coverType, unitId, textRanges } = params;
501
528
  const commandService = accessor.get(ICommandService);
502
- const docDataModel = accessor.get(IUniverInstanceService).getCurrentUniverDocInstance();
529
+ const docDataModel = accessor.get(IUniverInstanceService).getCurrentUnitOfType(UniverInstanceType.UNIVER_DOC);
503
530
  if (docDataModel == null) return false;
504
531
  const doMutation = {
505
532
  id: RichTextEditingMutation.id,
@@ -529,10 +556,601 @@ const UpdateTextCommand = {
529
556
  }
530
557
  };
531
558
 
559
+ //#endregion
560
+ //#region src/commands/commands/create-header-footer.command.ts
561
+ let HeaderFooterType = /* @__PURE__ */ function(HeaderFooterType) {
562
+ HeaderFooterType[HeaderFooterType["FIRST_PAGE_HEADER"] = 0] = "FIRST_PAGE_HEADER";
563
+ HeaderFooterType[HeaderFooterType["FIRST_PAGE_FOOTER"] = 1] = "FIRST_PAGE_FOOTER";
564
+ HeaderFooterType[HeaderFooterType["DEFAULT_HEADER"] = 2] = "DEFAULT_HEADER";
565
+ HeaderFooterType[HeaderFooterType["DEFAULT_FOOTER"] = 3] = "DEFAULT_FOOTER";
566
+ HeaderFooterType[HeaderFooterType["EVEN_PAGE_HEADER"] = 4] = "EVEN_PAGE_HEADER";
567
+ HeaderFooterType[HeaderFooterType["EVEN_PAGE_FOOTER"] = 5] = "EVEN_PAGE_FOOTER";
568
+ return HeaderFooterType;
569
+ }({});
570
+ function getEmptyHeaderFooterBody() {
571
+ return {
572
+ dataStream: "\r\n",
573
+ textRuns: [{
574
+ st: 0,
575
+ ed: 0,
576
+ ts: { fs: 9 }
577
+ }],
578
+ customBlocks: [],
579
+ paragraphs: [{
580
+ startIndex: 0,
581
+ paragraphId: createParagraphId(/* @__PURE__ */ new Set()),
582
+ paragraphStyle: {
583
+ spaceAbove: { v: 0 },
584
+ lineSpacing: 1.5,
585
+ spaceBelow: { v: 0 }
586
+ }
587
+ }],
588
+ sectionBreaks: [{
589
+ sectionId: createSectionId(/* @__PURE__ */ new Set()),
590
+ startIndex: 1
591
+ }]
592
+ };
593
+ }
594
+ function createHeaderFooterAction(segmentId, createType, headerFooterConfig, actions, createMode = "single", configPath = ["documentStyle"]) {
595
+ const jsonX = JSONX.getInstance();
596
+ const ID_LEN = 6;
597
+ const firstSegmentId = segmentId !== null && segmentId !== void 0 ? segmentId : generateRandomId(ID_LEN);
598
+ const isHeader = createType === 2 || createType === 0 || createType === 4;
599
+ const insertAction = jsonX.insertOp([isHeader ? "headers" : "footers", firstSegmentId], {
600
+ [isHeader ? "headerId" : "footerId"]: firstSegmentId,
601
+ body: getEmptyHeaderFooterBody()
602
+ });
603
+ actions.push(insertAction);
604
+ let key = "defaultHeaderId";
605
+ let pairKey = "defaultFooterId";
606
+ switch (createType) {
607
+ case 2:
608
+ key = "defaultHeaderId";
609
+ pairKey = "defaultFooterId";
610
+ break;
611
+ case 3:
612
+ key = "defaultFooterId";
613
+ pairKey = "defaultHeaderId";
614
+ break;
615
+ case 0:
616
+ key = "firstPageHeaderId";
617
+ pairKey = "firstPageFooterId";
618
+ break;
619
+ case 1:
620
+ key = "firstPageFooterId";
621
+ pairKey = "firstPageHeaderId";
622
+ break;
623
+ case 4:
624
+ key = "evenPageHeaderId";
625
+ pairKey = "evenPageFooterId";
626
+ break;
627
+ case 5:
628
+ key = "evenPageFooterId";
629
+ pairKey = "evenPageHeaderId";
630
+ break;
631
+ default: throw new Error(`Unknown header footer type: ${createType}`);
632
+ }
633
+ const linkedSegmentIds = [[key, firstSegmentId]];
634
+ if (createMode === "pair" && pairKey != null) {
635
+ const secondSegmentId = generateRandomId(ID_LEN);
636
+ const insertPairAction = jsonX.insertOp([isHeader ? "footers" : "headers", secondSegmentId], {
637
+ [isHeader ? "footerId" : "headerId"]: secondSegmentId,
638
+ body: getEmptyHeaderFooterBody()
639
+ });
640
+ actions.push(insertPairAction);
641
+ linkedSegmentIds.push([pairKey, secondSegmentId]);
642
+ }
643
+ for (const [k, id] of linkedSegmentIds) if (headerFooterConfig[k] != null) {
644
+ const replaceAction = jsonX.replaceOp([...configPath, k], headerFooterConfig[k], id);
645
+ actions.push(replaceAction);
646
+ } else {
647
+ const insertAction = jsonX.insertOp([...configPath, k], id);
648
+ actions.push(insertAction);
649
+ }
650
+ return actions;
651
+ }
652
+ const CreateHeaderFooterCommand = {
653
+ id: "doc.command.create-header-footer",
654
+ type: CommandType.COMMAND,
655
+ handler: (accessor, params) => {
656
+ var _body$sectionBreaks$f, _body$sectionBreaks, _body$sectionBreaks2;
657
+ const commandService = accessor.get(ICommandService);
658
+ const univerInstanceService = accessor.get(IUniverInstanceService);
659
+ const { unitId, segmentId, createType, headerFooterProps, createMode = "single", sectionId } = params;
660
+ const docDataModel = univerInstanceService.getUnit(unitId, UniverInstanceType.UNIVER_DOC);
661
+ if (docDataModel == null) return false;
662
+ const { documentStyle, body } = docDataModel.getSnapshot();
663
+ if (documentStyle.documentFlavor === DocumentFlavor.MODERN) return false;
664
+ const rawActions = [];
665
+ 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;
667
+ 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
+ if (sectionId != null && !sectionBreak) return false;
669
+ const headerFooterConfig = sectionBreak !== null && sectionBreak !== void 0 ? sectionBreak : documentStyle;
670
+ const configPath = sectionId == null ? ["documentStyle"] : [
671
+ "body",
672
+ "sectionBreaks",
673
+ sectionIndex
674
+ ];
675
+ if (createType != null) createHeaderFooterAction(segmentId, createType, headerFooterConfig, rawActions, createMode, configPath);
676
+ if (headerFooterProps != null) Object.keys(headerFooterProps).forEach((key) => {
677
+ const value = headerFooterProps[key];
678
+ const oldValue = headerFooterConfig[key];
679
+ if (value === oldValue) return;
680
+ const action = oldValue === void 0 ? jsonX.insertOp([...configPath, key], value) : jsonX.replaceOp([...configPath, key], oldValue, value);
681
+ rawActions.push(action);
682
+ });
683
+ if (rawActions.length === 0) return false;
684
+ const doMutation = {
685
+ id: RichTextEditingMutation.id,
686
+ params: {
687
+ unitId,
688
+ actions: rawActions.reduce((acc, cur) => JSONX.compose(acc, cur), null),
689
+ textRanges: [{
690
+ startOffset: 0,
691
+ endOffset: 0,
692
+ collapsed: true
693
+ }],
694
+ debounce: true
695
+ }
696
+ };
697
+ if ((headerFooterProps === null || headerFooterProps === void 0 ? void 0 : headerFooterProps.marginFooter) != null || (headerFooterProps === null || headerFooterProps === void 0 ? void 0 : headerFooterProps.marginHeader) != null) doMutation.params.noNeedSetTextRange = true;
698
+ const result = commandService.syncExecuteCommand(doMutation.id, doMutation.params);
699
+ return Boolean(result);
700
+ }
701
+ };
702
+
703
+ //#endregion
704
+ //#region src/commands/commands/set-document-default-paragraph-style.command.ts
705
+ const SetDocumentDefaultParagraphStyleCommand = {
706
+ id: "doc.command.set-default-paragraph-style",
707
+ type: CommandType.COMMAND,
708
+ handler: (accessor, params) => {
709
+ if (params == null) return false;
710
+ const commandService = accessor.get(ICommandService);
711
+ const documentDataModel = accessor.get(IUniverInstanceService).getUnit(params.unitId, UniverInstanceType.UNIVER_DOC);
712
+ if (documentDataModel == null) return false;
713
+ const oldStyle = documentDataModel.getSnapshot().documentStyle.defaultParagraphStyle;
714
+ const jsonX = JSONX.getInstance();
715
+ const path = ["documentStyle", "defaultParagraphStyle"];
716
+ const rawActions = [];
717
+ if (params.defaultParagraphStyle == null) {
718
+ if (oldStyle != null) rawActions.push(jsonX.removeOp(path, oldStyle));
719
+ } else if (oldStyle == null) {
720
+ const newStyle = Object.fromEntries(Object.entries(params.defaultParagraphStyle).filter(([, value]) => value != null).map(([key, value]) => [key, Tools.deepClone(value)]));
721
+ if (Object.keys(newStyle).length > 0) rawActions.push(jsonX.insertOp(path, newStyle));
722
+ } else Object.entries(params.defaultParagraphStyle).forEach(([key, value]) => {
723
+ const oldValue = oldStyle[key];
724
+ const propertyPath = [...path, key];
725
+ if (value == null) {
726
+ if (oldValue != null) rawActions.push(jsonX.removeOp(propertyPath, oldValue));
727
+ } else if (oldValue == null) rawActions.push(jsonX.insertOp(propertyPath, Tools.deepClone(value)));
728
+ else rawActions.push(jsonX.replaceOp(propertyPath, oldValue, Tools.deepClone(value)));
729
+ });
730
+ const actions = rawActions.reduce((acc, action) => JSONX.compose(acc, action), null);
731
+ if (rawActions.length === 0 || JSONX.isNoop(actions)) return false;
732
+ const mutation = {
733
+ id: RichTextEditingMutation.id,
734
+ params: {
735
+ unitId: params.unitId,
736
+ actions,
737
+ textRanges: null,
738
+ noNeedSetTextRange: true,
739
+ debounce: true,
740
+ isEditing: false
741
+ }
742
+ };
743
+ return Boolean(commandService.syncExecuteCommand(mutation.id, mutation.params));
744
+ }
745
+ };
746
+
747
+ //#endregion
748
+ //#region src/utils/sections.ts
749
+ /** Returns document-level section breaks, excluding table-cell and modern-column sentinels. */
750
+ 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]));
753
+ const result = [];
754
+ let tableCellDepth = 0;
755
+ let columnDepth = 0;
756
+ for (let index = 0; index < body.dataStream.length; index++) {
757
+ const token = body.dataStream[index];
758
+ if (token === DataStreamTreeTokenType.TABLE_CELL_START) tableCellDepth++;
759
+ else if (token === DataStreamTreeTokenType.TABLE_CELL_END) tableCellDepth = Math.max(0, tableCellDepth - 1);
760
+ else if (token === DataStreamTreeTokenType.COLUMN_START) columnDepth++;
761
+ else if (token === DataStreamTreeTokenType.COLUMN_END) columnDepth = Math.max(0, columnDepth - 1);
762
+ else if (token === DataStreamTreeTokenType.SECTION_BREAK && tableCellDepth === 0 && columnDepth === 0) {
763
+ const sectionBreak = sectionBreakByIndex.get(index);
764
+ if (sectionBreak) result.push(sectionBreak);
765
+ }
766
+ }
767
+ return result;
768
+ }
769
+
770
+ //#endregion
771
+ //#region src/commands/commands/set-section-header-footer-link.command.ts
772
+ const SetSectionHeaderFooterLinkCommand = {
773
+ id: "doc.command.set-section-header-footer-link",
774
+ type: CommandType.COMMAND,
775
+ handler: (accessor, params) => {
776
+ var _snapshot$body$sectio, _snapshot$body$sectio2;
777
+ if (!params) return false;
778
+ const instanceService = accessor.get(IUniverInstanceService);
779
+ const commandService = accessor.get(ICommandService);
780
+ const documentDataModel = instanceService.getUnit(params.unitId, UniverInstanceType.UNIVER_DOC);
781
+ const snapshot = documentDataModel === null || documentDataModel === void 0 ? void 0 : documentDataModel.getSnapshot();
782
+ if (!documentDataModel || !(snapshot === null || snapshot === void 0 ? void 0 : snapshot.body) || snapshot.documentStyle.documentFlavor !== DocumentFlavor.TRADITIONAL) return false;
783
+ const sections = getTopLevelSectionBreaks(snapshot.body);
784
+ const sectionIndex = sections.findIndex((section) => section.sectionId === params.sectionId);
785
+ 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;
787
+ if (storageIndex < 0) return false;
788
+ const context = {
789
+ snapshot,
790
+ sections,
791
+ sectionIndex,
792
+ storageIndex,
793
+ key: getSectionHeaderFooterReferenceKey(params.kind, params.variant)
794
+ };
795
+ const rawActions = params.linkedToPrevious ? buildLinkActions(context, params.kind) : buildUnlinkActions(context, params.kind, params.segmentId);
796
+ if (!rawActions) return false;
797
+ const mutation = {
798
+ id: RichTextEditingMutation.id,
799
+ params: {
800
+ unitId: params.unitId,
801
+ actions: rawActions.reduce((actions, action) => JSONX.compose(actions, action), null),
802
+ textRanges: null,
803
+ noNeedSetTextRange: true,
804
+ debounce: true,
805
+ isEditing: false,
806
+ trigger: SetSectionHeaderFooterLinkCommand.id
807
+ }
808
+ };
809
+ return Boolean(commandService.syncExecuteCommand(mutation.id, mutation.params));
810
+ }
811
+ };
812
+ function buildLinkActions(context, kind) {
813
+ const { snapshot, sections, sectionIndex, storageIndex, key } = context;
814
+ const section = sections[sectionIndex];
815
+ const explicitSegmentId = section[key];
816
+ if (typeof explicitSegmentId !== "string" || !explicitSegmentId) return null;
817
+ const jsonX = JSONX.getInstance();
818
+ const actions = [jsonX.removeOp([
819
+ "body",
820
+ "sectionBreaks",
821
+ storageIndex,
822
+ key
823
+ ], explicitSegmentId)];
824
+ const referenceKeys = kind === "header" ? [
825
+ "defaultHeaderId",
826
+ "firstPageHeaderId",
827
+ "evenPageHeaderId"
828
+ ] : [
829
+ "defaultFooterId",
830
+ "firstPageFooterId",
831
+ "evenPageFooterId"
832
+ ];
833
+ const referencedByDocument = referenceKeys.some((referenceKey) => snapshot.documentStyle[referenceKey] === explicitSegmentId);
834
+ const referencedBySection = sections.some((item) => referenceKeys.some((referenceKey) => !(item.sectionId === section.sectionId && referenceKey === key) && item[referenceKey] === explicitSegmentId));
835
+ const resources = kind === "header" ? snapshot.headers : snapshot.footers;
836
+ if (!referencedByDocument && !referencedBySection && (resources === null || resources === void 0 ? void 0 : resources[explicitSegmentId])) actions.push(jsonX.removeOp([kind === "header" ? "headers" : "footers", explicitSegmentId], resources[explicitSegmentId]));
837
+ return actions;
838
+ }
839
+ function buildUnlinkActions(context, kind, requestedSegmentId) {
840
+ const { snapshot, sections, sectionIndex, storageIndex, key } = context;
841
+ const explicitSegmentId = sections[sectionIndex][key];
842
+ if (typeof explicitSegmentId === "string" && explicitSegmentId) return null;
843
+ const sourceSegmentId = resolveSectionHeaderFooterReference(snapshot.documentStyle, sections, sectionIndex - 1, key).segmentId;
844
+ const segmentId = requestedSegmentId !== null && requestedSegmentId !== void 0 ? requestedSegmentId : generateRandomId(6);
845
+ const resources = kind === "header" ? snapshot.headers : snapshot.footers;
846
+ if (resources === null || resources === void 0 ? void 0 : resources[segmentId]) return null;
847
+ const source = sourceSegmentId ? resources === null || resources === void 0 ? void 0 : resources[sourceSegmentId] : void 0;
848
+ const idKey = kind === "header" ? "headerId" : "footerId";
849
+ const resource = source ? {
850
+ ...Tools.deepClone(source),
851
+ [idKey]: segmentId
852
+ } : {
853
+ [idKey]: segmentId,
854
+ body: getEmptyHeaderFooterBody()
855
+ };
856
+ const jsonX = JSONX.getInstance();
857
+ return [jsonX.insertOp([kind === "header" ? "headers" : "footers", segmentId], resource), jsonX.insertOp([
858
+ "body",
859
+ "sectionBreaks",
860
+ storageIndex,
861
+ key
862
+ ], segmentId)];
863
+ }
864
+
865
+ //#endregion
866
+ //#region src/commands/commands/update-document-section.command.ts
867
+ const UpdateDocumentSectionCommand = {
868
+ id: "doc.command.update-section",
869
+ type: CommandType.COMMAND,
870
+ handler: (accessor, params) => {
871
+ if (!(params === null || params === void 0 ? void 0 : params.updates.length) || params.updates.some(({ sectionId, config }) => !sectionId || Object.keys(config).length === 0)) return false;
872
+ const instanceService = accessor.get(IUniverInstanceService);
873
+ const commandService = accessor.get(ICommandService);
874
+ const documentDataModel = instanceService.getUnit(params.unitId, UniverInstanceType.UNIVER_DOC);
875
+ if (!documentDataModel || documentDataModel.getDocumentStyle().documentFlavor !== DocumentFlavor.TRADITIONAL) return false;
876
+ const body = documentDataModel.getBody();
877
+ if (!body) return false;
878
+ const updates = new Map(params.updates.map(({ sectionId, config }) => [sectionId, config]));
879
+ if (updates.size !== params.updates.length) return false;
880
+ const selectedIds = new Set(updates.keys());
881
+ const sections = getTopLevelSectionBreaks(body).filter((section) => selectedIds.has(section.sectionId)).sort((left, right) => left.startIndex - right.startIndex);
882
+ if (sections.length !== selectedIds.size) return false;
883
+ const cursor = new MemoryCursor();
884
+ const textX = new TextX();
885
+ for (const section of sections) {
886
+ textX.push({
887
+ t: TextXActionType.RETAIN,
888
+ len: section.startIndex - cursor.cursor
889
+ });
890
+ textX.push({
891
+ t: TextXActionType.RETAIN,
892
+ len: 1,
893
+ coverType: UpdateDocsAttributeType.REPLACE,
894
+ body: {
895
+ dataStream: "",
896
+ sectionBreaks: [{
897
+ ...Tools.deepClone(section),
898
+ ...Tools.deepClone(updates.get(section.sectionId)),
899
+ sectionId: section.sectionId,
900
+ startIndex: 0
901
+ }]
902
+ }
903
+ });
904
+ cursor.moveCursorTo(section.startIndex + 1);
905
+ }
906
+ const jsonX = JSONX.getInstance();
907
+ const mutation = {
908
+ id: RichTextEditingMutation.id,
909
+ params: {
910
+ unitId: params.unitId,
911
+ actions: jsonX.editOp(textX.serialize(), getRichTextEditPath(documentDataModel)),
912
+ textRanges: null,
913
+ noNeedSetTextRange: true,
914
+ debounce: true,
915
+ isEditing: false,
916
+ trigger: UpdateDocumentSectionCommand.id
917
+ }
918
+ };
919
+ return Boolean(commandService.syncExecuteCommand(mutation.id, mutation.params));
920
+ }
921
+ };
922
+ const InsertDocumentSectionBreakCommand = {
923
+ id: "doc.command.insert-section-break",
924
+ type: CommandType.COMMAND,
925
+ handler: (accessor, params) => {
926
+ var _body$sectionBreaks, _body$tables, _body$columnGroups, _body$blockRanges, _params$config;
927
+ if (!params) return false;
928
+ const context = getTraditionalDocumentContext(accessor, params.unitId);
929
+ if (!context || !params.sectionId || !Number.isInteger(params.offset)) return false;
930
+ 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;
932
+ const textX = new TextX();
933
+ textX.retain(params.offset);
934
+ textX.insert(1, {
935
+ dataStream: DataStreamTreeTokenType.SECTION_BREAK,
936
+ sectionBreaks: [{
937
+ ...Tools.deepClone((_params$config = params.config) !== null && _params$config !== void 0 ? _params$config : {}),
938
+ sectionId: params.sectionId,
939
+ startIndex: 0
940
+ }]
941
+ });
942
+ return executeSectionTextX(commandService, documentDataModel, textX, InsertDocumentSectionBreakCommand.id);
943
+ }
944
+ };
945
+ const DeleteDocumentSectionBreakCommand = {
946
+ id: "doc.command.delete-section-break",
947
+ type: CommandType.COMMAND,
948
+ handler: (accessor, params) => {
949
+ if (!params) return false;
950
+ const context = getTraditionalDocumentContext(accessor, params.unitId);
951
+ if (!context || !params.sectionId) return false;
952
+ const sections = getTopLevelSectionBreaks(context.body);
953
+ if (sections.length <= 1) return false;
954
+ const section = sections.find((item) => item.sectionId === params.sectionId);
955
+ if (!section) return false;
956
+ const textX = new TextX();
957
+ textX.retain(section.startIndex);
958
+ textX.delete(1);
959
+ return executeSectionTextX(context.commandService, context.documentDataModel, textX, DeleteDocumentSectionBreakCommand.id);
960
+ }
961
+ };
962
+ function getTraditionalDocumentContext(accessor, unitId) {
963
+ if (!unitId) return null;
964
+ const documentDataModel = accessor.get(IUniverInstanceService).getUnit(unitId, UniverInstanceType.UNIVER_DOC);
965
+ const body = documentDataModel === null || documentDataModel === void 0 ? void 0 : documentDataModel.getBody();
966
+ if (!documentDataModel || !body || documentDataModel.getDocumentStyle().documentFlavor !== DocumentFlavor.TRADITIONAL) return null;
967
+ return {
968
+ body,
969
+ documentDataModel,
970
+ commandService: accessor.get(ICommandService)
971
+ };
972
+ }
973
+ function executeSectionTextX(commandService, documentDataModel, textX, trigger) {
974
+ const actions = JSONX.getInstance().editOp(textX.serialize(), getRichTextEditPath(documentDataModel));
975
+ return Boolean(commandService.syncExecuteCommand(RichTextEditingMutation.id, {
976
+ unitId: documentDataModel.getUnitId(),
977
+ actions,
978
+ textRanges: null,
979
+ noNeedSetTextRange: true,
980
+ debounce: true,
981
+ isEditing: false,
982
+ trigger
983
+ }));
984
+ }
985
+
986
+ //#endregion
987
+ //#region src/embed-host-anchor.ts
988
+ const EMBED_DOCS_CUSTOM_BLOCK_DEFAULT_COMPONENT_KEY = "UniverEmbedDocsCustomBlock";
989
+ const DEFAULT_CUSTOM_BLOCK_SIZE = {
990
+ width: 720,
991
+ height: 360
992
+ };
993
+ const SHEET_LIKE_CUSTOM_BLOCK_SIZE = {
994
+ width: 960,
995
+ height: 480
996
+ };
997
+ const SLIDE_CUSTOM_BLOCK_SIZE = {
998
+ width: 720,
999
+ height: 405
1000
+ };
1001
+ function createDocsCustomBlockInsertMutation(params) {
1002
+ return createRichTextMutation(params.unitId, params.segmentId, createInsertCustomBlockActions(params));
1003
+ }
1004
+ function createDocsCustomBlockRemoveMutation(params) {
1005
+ return createRichTextMutation(params.unitId, params.segmentId, createRemoveCustomBlockActions(params));
1006
+ }
1007
+ function createInsertCustomBlockActions(params) {
1008
+ const textX = new TextX();
1009
+ if (params.startIndex > 0) textX.push({
1010
+ t: TextXActionType.RETAIN,
1011
+ len: params.startIndex
1012
+ });
1013
+ textX.push({
1014
+ t: TextXActionType.INSERT,
1015
+ body: {
1016
+ dataStream: "\b",
1017
+ customBlocks: [{
1018
+ startIndex: 0,
1019
+ blockId: params.blockId
1020
+ }]
1021
+ },
1022
+ len: 1
1023
+ });
1024
+ return composeActions([toBodyEditActions(textX, params.segmentId), createDrawingInsertActions(params)]);
1025
+ }
1026
+ function createRemoveCustomBlockActions(params) {
1027
+ const textX = new TextX();
1028
+ if (params.startIndex > 0) textX.push({
1029
+ t: TextXActionType.RETAIN,
1030
+ len: params.startIndex
1031
+ });
1032
+ textX.push({
1033
+ t: TextXActionType.DELETE,
1034
+ len: 1
1035
+ });
1036
+ return composeActions([toBodyEditActions(textX, params.segmentId), createDrawingRemoveActions(params)]);
1037
+ }
1038
+ function createDocsCustomBlockDrawing(params) {
1039
+ var _params$componentKey;
1040
+ const size = resolveDocsCustomBlockSize(params.childType);
1041
+ const isInline = params.interactionMode === "inline";
1042
+ return {
1043
+ unitId: params.unitId,
1044
+ subUnitId: params.unitId,
1045
+ drawingId: params.blockId,
1046
+ drawingType: DrawingTypeEnum.DRAWING_DOM,
1047
+ componentKey: (_params$componentKey = params.componentKey) !== null && _params$componentKey !== void 0 ? _params$componentKey : EMBED_DOCS_CUSTOM_BLOCK_DEFAULT_COMPONENT_KEY,
1048
+ data: createEmbedDocsCustomBlockData(params),
1049
+ title: params.blockId,
1050
+ description: "Univer embedded unit custom block",
1051
+ layoutType: isInline ? PositionedObjectLayoutType.INLINE : PositionedObjectLayoutType.WRAP_TOP_AND_BOTTOM,
1052
+ allowTransform: false,
1053
+ docTransform: {
1054
+ size: {
1055
+ width: size.width,
1056
+ height: size.height
1057
+ },
1058
+ positionH: {
1059
+ relativeFrom: isInline ? ObjectRelativeFromH.PAGE : ObjectRelativeFromH.COLUMN,
1060
+ ...isInline ? { posOffset: 0 } : { align: AlignTypeH.LEFT }
1061
+ },
1062
+ positionV: {
1063
+ relativeFrom: isInline ? ObjectRelativeFromV.PAGE : ObjectRelativeFromV.PARAGRAPH,
1064
+ posOffset: 0
1065
+ },
1066
+ angle: 0
1067
+ },
1068
+ transform: {
1069
+ left: 0,
1070
+ top: 0,
1071
+ width: size.width,
1072
+ height: size.height
1073
+ }
1074
+ };
1075
+ }
1076
+ function resolveDocsCustomBlockSize(childType) {
1077
+ if (childType === UniverInstanceType.UNIVER_SHEET || childType === UniverInstanceType.UNIVER_BASE) return SHEET_LIKE_CUSTOM_BLOCK_SIZE;
1078
+ if (childType === UniverInstanceType.UNIVER_SLIDE) return SLIDE_CUSTOM_BLOCK_SIZE;
1079
+ return DEFAULT_CUSTOM_BLOCK_SIZE;
1080
+ }
1081
+ function isSheetLikeDocsCustomBlockChildType(childType) {
1082
+ return childType === UniverInstanceType.UNIVER_SHEET || childType === UniverInstanceType.UNIVER_BASE;
1083
+ }
1084
+ function createEmbedDocsCustomBlockData(params) {
1085
+ var _params$embedId, _params$interactionMo;
1086
+ return {
1087
+ version: 1,
1088
+ embedId: (_params$embedId = params.embedId) !== null && _params$embedId !== void 0 ? _params$embedId : params.blockId,
1089
+ hostUnitId: params.unitId,
1090
+ hostAnchorId: params.blockId,
1091
+ childUnitId: params.childUnitId,
1092
+ childType: params.childType,
1093
+ interactionMode: (_params$interactionMo = params.interactionMode) !== null && _params$interactionMo !== void 0 ? _params$interactionMo : "block"
1094
+ };
1095
+ }
1096
+ function isEmbedDocsCustomBlockData(data) {
1097
+ if (!data || typeof data !== "object") return false;
1098
+ const candidate = data;
1099
+ return candidate.version === 1 && typeof candidate.embedId === "string" && typeof candidate.hostAnchorId === "string";
1100
+ }
1101
+ function shouldUseInlineTextSelectionForDocsCustomBlockDrawing(drawing) {
1102
+ const data = drawing && typeof drawing === "object" ? drawing.data : void 0;
1103
+ if (!isEmbedDocsCustomBlockData(data)) return true;
1104
+ return data.interactionMode === "inline";
1105
+ }
1106
+ function createRichTextMutation(unitId, segmentId, actions) {
1107
+ return {
1108
+ id: RichTextEditingMutation.id,
1109
+ params: {
1110
+ unitId,
1111
+ segmentId,
1112
+ actions,
1113
+ textRanges: [],
1114
+ isEditing: false,
1115
+ noNeedSetTextRange: true
1116
+ }
1117
+ };
1118
+ }
1119
+ function toBodyEditActions(textX, segmentId) {
1120
+ const action = JSONX.getInstance().editOp(textX.serialize(), segmentId ? [
1121
+ "headers",
1122
+ segmentId,
1123
+ "body"
1124
+ ] : ["body"]);
1125
+ return action !== null && action !== void 0 ? action : [];
1126
+ }
1127
+ function createDrawingInsertActions(params) {
1128
+ var _jsonX$insertOp, _jsonX$insertOp2, _params$drawingOrderI;
1129
+ if (params.segmentId) return [];
1130
+ const jsonX = JSONX.getInstance();
1131
+ 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 : []]);
1133
+ }
1134
+ function createDrawingRemoveActions(params) {
1135
+ var _jsonX$removeOp, _jsonX$removeOp2, _params$drawingOrderI2;
1136
+ if (params.segmentId) return [];
1137
+ const jsonX = JSONX.getInstance();
1138
+ 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 : []]);
1140
+ }
1141
+ function composeActions(actions) {
1142
+ return actions.reduce((composed, action) => {
1143
+ var _JSONX$compose;
1144
+ if (!action || JSONX.isNoop(action) || action.length === 0) return composed;
1145
+ 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 : [];
1147
+ }, []);
1148
+ }
1149
+
532
1150
  //#endregion
533
1151
  //#region package.json
534
1152
  var name = "@univerjs/docs";
535
- var version = "1.0.0-alpha.1";
1153
+ var version = "1.0.0-alpha.3";
536
1154
 
537
1155
  //#endregion
538
1156
  //#region src/commands/mutations/docs-rename.mutation.ts
@@ -724,7 +1342,7 @@ let DocStateChangeManagerService = class DocStateChangeManagerService extends Rx
724
1342
  _initialize() {
725
1343
  this.disposeWithMe(this._commandService.beforeCommandExecuted((command) => {
726
1344
  if (command.id === UndoCommandId || command.id === RedoCommandId) {
727
- const univerDoc = this._univerInstanceService.getCurrentUniverDocInstance();
1345
+ const univerDoc = this._univerInstanceService.getCurrentUnitOfType(UniverInstanceType.UNIVER_DOC);
728
1346
  if (univerDoc == null) return;
729
1347
  const unitId = univerDoc.getUnitId();
730
1348
  this._pushHistory(unitId);
@@ -854,6 +1472,12 @@ let UniverDocsPlugin = class UniverDocsPlugin extends Plugin {
854
1472
  InsertTextCommand,
855
1473
  DeleteTextCommand,
856
1474
  UpdateTextCommand,
1475
+ CreateHeaderFooterCommand,
1476
+ SetDocumentDefaultParagraphStyleCommand,
1477
+ SetSectionHeaderFooterLinkCommand,
1478
+ UpdateDocumentSectionCommand,
1479
+ InsertDocumentSectionBreakCommand,
1480
+ DeleteDocumentSectionBreakCommand,
857
1481
  RichTextEditingMutation,
858
1482
  DocsRenameMutation,
859
1483
  SetTextSelectionsOperation
@@ -983,7 +1607,7 @@ function addCustomRangeFactory(accessor, param, body) {
983
1607
  return doMutation;
984
1608
  }
985
1609
  function addCustomRangeBySelectionFactory(accessor, param) {
986
- var _selections$;
1610
+ var _selections$, _documentDataModel$ge;
987
1611
  const { rangeId, rangeType, wholeEntity, properties, unitId, selections: propSelection } = param;
988
1612
  const docSelectionManagerService = accessor.get(DocSelectionManagerService);
989
1613
  const univerInstanceService = accessor.get(IUniverInstanceService);
@@ -995,7 +1619,7 @@ function addCustomRangeBySelectionFactory(accessor, param) {
995
1619
  if (!(selections === null || selections === void 0 ? void 0 : selections.length)) return false;
996
1620
  const documentDataModel = univerInstanceService.getUnit(unitId, UniverInstanceType.UNIVER_DOC);
997
1621
  if (!documentDataModel) return false;
998
- const body = documentDataModel.getSelfOrHeaderFooterModel(segmentId).getBody();
1622
+ const body = (_documentDataModel$ge = documentDataModel.getSelfOrHeaderFooterModel(segmentId)) === null || _documentDataModel$ge === void 0 ? void 0 : _documentDataModel$ge.getBody();
999
1623
  if (!body) return false;
1000
1624
  const textX = BuildTextUtils.customRange.add({
1001
1625
  ranges: selections,
@@ -1049,6 +1673,35 @@ function deleteCustomRangeFactory(accessor, params) {
1049
1673
  return doMutation;
1050
1674
  }
1051
1675
 
1676
+ //#endregion
1677
+ //#region src/utils/paragraphs.ts
1678
+ /** Builds paragraph metadata for inserted paragraph tokens, including horizontal-rule borders. */
1679
+ function generateParagraphs(dataStream, prevParagraph, borderBottom, existingParagraphIds = []) {
1680
+ const paragraphs = [];
1681
+ const existingIds = new Set(existingParagraphIds);
1682
+ for (let i = 0, len = dataStream.length; i < len; i++) {
1683
+ if (dataStream[i] !== DataStreamTreeTokenType.PARAGRAPH) continue;
1684
+ paragraphs.push({
1685
+ startIndex: i,
1686
+ paragraphId: createParagraphId(existingIds)
1687
+ });
1688
+ }
1689
+ for (const paragraph of paragraphs) {
1690
+ if (prevParagraph === null || prevParagraph === void 0 ? void 0 : prevParagraph.bullet) paragraph.bullet = Tools.deepClone(prevParagraph.bullet);
1691
+ if (prevParagraph === null || prevParagraph === void 0 ? void 0 : prevParagraph.paragraphStyle) {
1692
+ paragraph.paragraphStyle = Tools.deepClone(prevParagraph.paragraphStyle);
1693
+ delete paragraph.paragraphStyle.borderBottom;
1694
+ if (prevParagraph.paragraphStyle.headingId) paragraph.paragraphStyle.headingId = generateRandomId(6);
1695
+ }
1696
+ if (borderBottom) {
1697
+ var _paragraph$paragraphS;
1698
+ (_paragraph$paragraphS = paragraph.paragraphStyle) !== null && _paragraph$paragraphS !== void 0 || (paragraph.paragraphStyle = {});
1699
+ paragraph.paragraphStyle.borderBottom = Tools.deepClone(borderBottom);
1700
+ }
1701
+ }
1702
+ return paragraphs;
1703
+ }
1704
+
1052
1705
  //#endregion
1053
1706
  //#region src/utils/replace-selection-factory.ts
1054
1707
  function replaceSelectionFactory(accessor, params) {
@@ -1092,4 +1745,33 @@ function replaceSelectionFactory(accessor, params) {
1092
1745
  }
1093
1746
 
1094
1747
  //#endregion
1095
- export { DOC_INTERCEPTOR_POINT, DeleteTextCommand, DocBlockMoveValidatorService, DocContentInsertService, DocInterceptorService, DocSelectionManagerService, DocSkeletonManagerService, DocStateChangeManagerService, DocStateEmitService, IDocStateChangeInterceptorService, InsertTextCommand, RichTextEditingMutation, SetTextSelectionsOperation, UniverDocsPlugin, UpdateTextCommand, addCustomRangeBySelectionFactory, addCustomRangeFactory, deleteCustomRangeFactory, replaceSelectionFactory };
1748
+ //#region src/utils/section-columns.ts
1749
+ /** Creates explicit OOXML section columns from a count, gap, and optional widths. */
1750
+ function createSectionColumnProperties(documentStyle, section, columnCount, gap, widths) {
1751
+ var _ref, _section$pageSize$wid, _section$pageSize, _documentStyle$pageSi, _ref2, _section$marginLeft, _ref3, _section$marginRight;
1752
+ if (columnCount <= 1) return [];
1753
+ const safeGap = Math.max(0, gap);
1754
+ 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;
1755
+ 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));
1756
+ const availableWidth = Math.max(0, contentWidth - safeGap * (columnCount - 1));
1757
+ return (widths !== null && widths !== void 0 ? widths : Array.from({ length: columnCount }, () => availableWidth / columnCount)).map((width, index) => ({
1758
+ width: Math.max(0, width),
1759
+ paddingEnd: index === columnCount - 1 ? 0 : safeGap
1760
+ }));
1761
+ }
1762
+
1763
+ //#endregion
1764
+ //#region src/utils/util.ts
1765
+ function consumeContentInsertRange(accessor, unitId) {
1766
+ try {
1767
+ return accessor.get(DocContentInsertService).consumeInsertRange(unitId);
1768
+ } catch {
1769
+ return null;
1770
+ }
1771
+ }
1772
+ function isHeaderFooterSelection(range) {
1773
+ return Boolean(range === null || range === void 0 ? void 0 : range.segmentId);
1774
+ }
1775
+
1776
+ //#endregion
1777
+ 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, consumeContentInsertRange, createDocsCustomBlockDrawing, createDocsCustomBlockInsertMutation, createDocsCustomBlockRemoveMutation, createEmbedDocsCustomBlockData, createInsertCustomBlockActions, createRemoveCustomBlockActions, createSectionColumnProperties, deleteCustomRangeFactory, generateParagraphs, getTopLevelSectionBreaks, isEmbedDocsCustomBlockData, isHeaderFooterSelection, isSheetLikeDocsCustomBlockChildType, replaceSelectionFactory, resolveDocsCustomBlockSize, shouldUseInlineTextSelectionForDocsCustomBlockDrawing };