@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.
- package/lib/cjs/facade.js +1156 -868
- package/lib/cjs/index.js +723 -18
- package/lib/es/facade.js +1154 -867
- package/lib/es/index.js +701 -19
- package/lib/facade.js +1154 -867
- package/lib/index.js +701 -19
- package/lib/types/commands/commands/create-header-footer.command.d.ts +45 -0
- package/lib/types/commands/commands/set-document-default-paragraph-style.command.d.ts +24 -0
- package/lib/types/commands/commands/set-section-header-footer-link.command.d.ts +26 -0
- package/lib/types/commands/commands/update-document-section.command.d.ts +38 -0
- package/lib/types/embed-host-anchor.d.ts +61 -0
- package/lib/types/facade/f-document-paragraph.d.ts +87 -100
- package/lib/types/facade/f-document-section.d.ts +281 -0
- package/lib/types/facade/f-document-text-range.d.ts +136 -0
- package/lib/types/facade/f-document.d.ts +316 -26
- package/lib/types/facade/f-enum.d.ts +32 -0
- package/lib/types/facade/f-types.d.ts +16 -0
- package/lib/types/facade/index.d.ts +11 -6
- package/lib/types/facade/utils.d.ts +15 -1
- package/lib/types/index.d.ts +15 -1
- package/lib/types/utils/paragraphs.d.ts +18 -0
- package/lib/types/utils/section-columns.d.ts +18 -0
- package/lib/types/utils/sections.d.ts +18 -0
- package/lib/types/utils/util.d.ts +19 -0
- package/lib/umd/facade.js +3 -1
- package/lib/umd/index.js +2 -1
- package/package.json +5 -5
- package/lib/types/facade/f-document-block-range.d.ts +0 -132
- package/lib/types/facade/f-document-body.d.ts +0 -276
- package/lib/types/facade/f-document-custom-block.d.ts +0 -57
- package/lib/types/facade/f-document-element.d.ts +0 -193
- 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
|
|
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
|
|
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
|
|
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
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
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).
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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 };
|