refactor(docs): move core editing commands and facade APIs into docs package (#7007)

This commit is contained in:
wpxp123456
2026-06-02 16:26:07 +08:00
committed by GitHub
parent 6b96f9028a
commit db4a8bfece
56 changed files with 557 additions and 495 deletions
-1
View File
@@ -172,7 +172,6 @@ import '@univerjs/sheets-numfmt-ui/lib/index.css'
import '@univerjs/engine-formula/facade'
import '@univerjs/ui/facade'
import '@univerjs/docs-ui/facade'
import '@univerjs/sheets/facade'
import '@univerjs/sheets-ui/facade'
import '@univerjs/sheets-formula/facade'
-1
View File
@@ -172,7 +172,6 @@ import '@univerjs/sheets-numfmt-ui/lib/index.css'
import '@univerjs/engine-formula/facade'
import '@univerjs/ui/facade'
import '@univerjs/docs-ui/facade'
import '@univerjs/sheets/facade'
import '@univerjs/sheets-ui/facade'
import '@univerjs/sheets-formula/facade'
-1
View File
@@ -173,7 +173,6 @@ import '@univerjs/sheets-numfmt-ui/lib/index.css'
import '@univerjs/engine-formula/facade'
import '@univerjs/ui/facade'
import '@univerjs/docs-ui/facade'
import '@univerjs/sheets/facade'
import '@univerjs/sheets-ui/facade'
import '@univerjs/sheets-formula/facade'
-1
View File
@@ -173,7 +173,6 @@ import '@univerjs/sheets-numfmt-ui/lib/index.css'
import '@univerjs/engine-formula/facade'
import '@univerjs/ui/facade'
import '@univerjs/docs-ui/facade'
import '@univerjs/sheets/facade'
import '@univerjs/sheets-ui/facade'
import '@univerjs/sheets-formula/facade'
-1
View File
@@ -172,7 +172,6 @@ import '@univerjs/sheets-numfmt-ui/lib/index.css'
import '@univerjs/engine-formula/facade'
import '@univerjs/ui/facade'
import '@univerjs/docs-ui/facade'
import '@univerjs/sheets/facade'
import '@univerjs/sheets-ui/facade'
import '@univerjs/sheets-formula/facade'
-1
View File
@@ -172,7 +172,6 @@ import '@univerjs/sheets-numfmt-ui/lib/index.css'
import '@univerjs/engine-formula/facade'
import '@univerjs/ui/facade'
import '@univerjs/docs-ui/facade'
import '@univerjs/sheets/facade'
import '@univerjs/sheets-ui/facade'
import '@univerjs/sheets-formula/facade'
+1
View File
@@ -30,6 +30,7 @@ import { DEFAULT_DOCUMENT_DATA_SIMPLE } from '@univerjs/mockdata';
import zhCN from '@univerjs/mockdata/locales/zh-CN';
import { UniverUIPlugin } from '@univerjs/ui';
import '@univerjs/docs/facade';
import '@univerjs/docs-ui/facade';
import '../global.css';
+1 -1
View File
@@ -39,9 +39,9 @@ import { UniverSheetsZenEditorPlugin } from '@univerjs/sheets-zen-editor';
import { UniverThreadCommentUIPlugin } from '@univerjs/thread-comment-ui';
import { UniverUIPlugin } from '@univerjs/ui';
import { SwitchUnits } from './switch-units';
import '@univerjs/sheets/facade';
import '@univerjs/ui/facade';
import '@univerjs/docs-ui/facade';
import '@univerjs/sheets-ui/facade';
import '@univerjs/sheets-data-validation/facade';
import '@univerjs/engine-formula/facade';
-1
View File
@@ -42,7 +42,6 @@ import { UniverUIPlugin } from '@univerjs/ui';
import '@univerjs/sheets/facade';
import '@univerjs/ui/facade';
import '@univerjs/docs-ui/facade';
import '@univerjs/sheets-ui/facade';
import '@univerjs/sheets-data-validation/facade';
import '@univerjs/engine-formula/facade';
+1
View File
@@ -67,6 +67,7 @@ import ImportCSVButtonPlugin from './custom/import-csv-button';
import '@univerjs/sheets/facade';
import '@univerjs/ui/facade';
import '@univerjs/docs/facade';
import '@univerjs/docs-ui/facade';
import '@univerjs/sheets-ui/facade';
import '@univerjs/sheets-data-validation/facade';
@@ -16,7 +16,8 @@
import { describe, expect, it } from 'vitest';
import { DocumentDataModel } from '../../../document-data-model';
import { addDrawing, getCustomBlockIdsInSelections, getRichTextEditPath } from '../drawings';
import { getRichTextEditPath } from '../../utils';
import { addDrawing, getCustomBlockIdsInSelections } from '../drawings';
describe('drawing build utils', () => {
it('should resolve custom blocks and replace selected drawings in the document body', () => {
@@ -21,6 +21,7 @@ import type { JSONXActions } from '../../json-x/json-x';
import { JSONX } from '../../json-x/json-x';
import { TextXActionType } from '../action-types';
import { TextX } from '../text-x';
import { getRichTextEditPath } from '../utils';
import { deleteSelectionTextX } from './text-x-utils';
export interface IAddDrawingParam {
@@ -52,26 +53,6 @@ export function getCustomBlockIdsInSelections(body: IDocumentBody, selections: I
return customBlockIds;
}
export function getRichTextEditPath(docDataModel: DocumentDataModel, segmentId = '') {
if (!segmentId) {
return ['body'];
}
const { headers, footers } = docDataModel.getSnapshot();
if (headers == null && footers == null) {
throw new Error('Document data model must have headers or footers when update by segment id');
}
if (headers?.[segmentId] != null) {
return ['headers', segmentId, 'body'];
} else if (footers?.[segmentId] != null) {
return ['footers', segmentId, 'body'];
} else {
throw new Error('Segment id not found in headers or footers');
}
}
// eslint-disable-next-line max-lines-per-function
export const addDrawing = (param: IAddDrawingParam) => {
const { selection, documentDataModel, drawings } = param;
@@ -15,6 +15,7 @@
*/
import type { ICustomBlock, ICustomDecoration, ICustomRange, IDocumentBlockRange, IDocumentBody, IParagraph, ISectionBreak, ITextRun } from '../../../types/interfaces/i-document-data';
import type { DocumentDataModel } from '../../data-model';
import type { IRetainAction } from './action-types';
import { UpdateDocsAttributeType } from '../../../shared/command-enum';
import { Tools } from '../../../shared/tools';
@@ -563,3 +564,23 @@ export function isUselessRetainAction(action: IRetainAction): boolean {
return false;
}
export function getRichTextEditPath(docDataModel: DocumentDataModel, segmentId = '') {
if (!segmentId) {
return ['body'];
}
const { headers, footers } = docDataModel.getSnapshot();
if (headers == null && footers == null) {
throw new Error('Document data model must have headers or footers when update by segment id');
}
if (headers?.[segmentId] != null) {
return ['headers', segmentId, 'body'];
} else if (footers?.[segmentId] != null) {
return ['footers', segmentId, 'body'];
} else {
throw new Error('Segment id not found in headers or footers');
}
}
+1
View File
@@ -91,6 +91,7 @@ export {
getCustomDecorationSlice,
getCustomRangeSlice,
getParagraphsSlice,
getRichTextEditPath,
getSectionBreakSlice,
getTableSlice,
getTextRunSlice,
@@ -20,6 +20,7 @@ import type { IInsertDrawingCommandParams } from './interfaces';
import {
BuildTextUtils,
CommandType,
getRichTextEditPath,
ICommandService,
IUniverInstanceService,
JSONX,
@@ -27,7 +28,7 @@ import {
TextXActionType,
} from '@univerjs/core';
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
import { DocContentInsertService, getCustomBlockIdsInSelections, getRichTextEditPath } from '@univerjs/docs-ui';
import { DocContentInsertService, getCustomBlockIdsInSelections } from '@univerjs/docs-ui';
/**
* The command to insert new drawings
@@ -20,6 +20,7 @@ import type { ITextRangeWithStyle } from '@univerjs/engine-render';
import type { IDeleteDrawingCommandParams } from './interfaces';
import {
CommandType,
getRichTextEditPath,
ICommandService,
IUniverInstanceService,
JSONX,
@@ -28,7 +29,7 @@ import {
TextXActionType,
} from '@univerjs/core';
import { RichTextEditingMutation } from '@univerjs/docs';
import { DocSelectionRenderService, getRichTextEditPath } from '@univerjs/docs-ui';
import { DocSelectionRenderService } from '@univerjs/docs-ui';
import { IRenderManagerService } from '@univerjs/engine-render';
/**
@@ -21,6 +21,7 @@ import type { IDocumentSkeletonDrawing, IDocumentSkeletonHeaderFooter, IDocument
import {
BooleanNumber,
CommandType,
getRichTextEditPath,
ICommandService,
IUniverInstanceService,
JSONX,
@@ -32,7 +33,7 @@ import {
Tools,
} from '@univerjs/core';
import { DocSkeletonManagerService, RichTextEditingMutation } from '@univerjs/docs';
import { DocSelectionRenderService, getRichTextEditPath } from '@univerjs/docs-ui';
import { DocSelectionRenderService } from '@univerjs/docs-ui';
import { DocumentEditArea, IRenderManagerService } from '@univerjs/engine-render';
import { DocRefreshDrawingsService } from '../../services/doc-refresh-drawings.service';
@@ -15,9 +15,10 @@
*/
import type { ICommand, IDisposable, IDocumentData, Univer } from '@univerjs/core';
import type { IInsertTextCommandParams } from '@univerjs/docs';
import { awaitTime, CustomRangeType, Direction, ICommandService, IUniverInstanceService } from '@univerjs/core';
import { DocSelectionManagerService, RichTextEditingMutation, SetTextSelectionsOperation } from '@univerjs/docs';
import { DeleteLeftCommand, DocCanvasPopManagerService, InsertCommand, MoveCursorOperation } from '@univerjs/docs-ui';
import { DocSelectionManagerService, InsertTextCommand, RichTextEditingMutation, SetTextSelectionsOperation } from '@univerjs/docs';
import { DeleteLeftCommand, DocCanvasPopManagerService, MoveCursorOperation } from '@univerjs/docs-ui';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { AddDocMentionCommand, DeleteDocMentionCommand } from '../commands/commands/doc-mention.command';
import {
@@ -125,7 +126,7 @@ function setupMentionTestBed(docData: IDocumentData) {
injector.add([DocMentionTriggerController]);
const commandService = get(ICommandService);
commandService.registerCommand(InsertCommand);
commandService.registerCommand(InsertTextCommand);
commandService.registerCommand(MoveCursorOperation);
commandService.registerCommand(SetTextSelectionsOperation);
commandService.registerCommand(ShowMentionEditPopupOperation);
@@ -184,7 +185,7 @@ describe('docs-mention-ui integration', () => {
style: null as never,
}]);
expect(await testBed.commandService.executeCommand(InsertCommand.id, {
expect(await testBed.commandService.executeCommand<IInsertTextCommandParams>(InsertTextCommand.id, {
unitId: 'test-doc',
segmentId: '',
range: { startOffset: 11, endOffset: 11, collapsed: true },
@@ -14,10 +14,10 @@
* limitations under the License.
*/
import type { IInsertCommandParams } from '@univerjs/docs-ui';
import type { IInsertTextCommandParams } from '@univerjs/docs';
import { Disposable, ICommandService, Inject, Tools } from '@univerjs/core';
import { DocSelectionManagerService } from '@univerjs/docs';
import { DeleteLeftCommand, InsertCommand, MoveCursorOperation } from '@univerjs/docs-ui';
import { DocSelectionManagerService, InsertTextCommand } from '@univerjs/docs';
import { DeleteLeftCommand, MoveCursorOperation } from '@univerjs/docs-ui';
import { CloseMentionEditPopupOperation, ShowMentionEditPopupOperation } from '../commands/operations/mention-popup.operation';
import { DocMentionPopupService } from '../services/doc-mention-popup.service';
import { DocMentionService } from '../services/doc-mention.service';
@@ -37,8 +37,8 @@ export class DocMentionTriggerController extends Disposable {
private _initTrigger() {
this.disposeWithMe(
this._commandService.onCommandExecuted((commandInfo) => {
if (commandInfo.id === InsertCommand.id) {
const params = commandInfo.params as IInsertCommandParams;
if (commandInfo.id === InsertTextCommand.id) {
const params = commandInfo.params as IInsertTextCommandParams;
const activeRange = this._textSelectionManagerService.getActiveTextRange();
if (params.body.dataStream === '@' && activeRange && !Tools.isDefine(this._docMentionService.editing)) {
setTimeout(() => {
@@ -15,8 +15,8 @@
*/
import { DeleteDirection, Direction } from '@univerjs/core';
import { RichTextEditingMutation } from '@univerjs/docs';
import { DeleteCommand, DeleteLeftCommand, IMEInputCommand, InsertCommand, MoveCursorOperation } from '@univerjs/docs-ui';
import { DeleteTextCommand, InsertTextCommand, RichTextEditingMutation } from '@univerjs/docs';
import { DeleteLeftCommand, IMEInputCommand, MoveCursorOperation } from '@univerjs/docs-ui';
import { KeyCode } from '@univerjs/ui';
import { describe, expect, it, vi } from 'vitest';
import { CloseQuickInsertPopupOperation, ShowQuickInsertPopupOperation } from '../../commands/operations/quick-insert-popup.operation';
@@ -114,7 +114,7 @@ describe('DocQuickInsertTriggerController', () => {
}));
commandService.emit({
id: InsertCommand.id,
id: InsertTextCommand.id,
params: {
body: { dataStream: '/' },
range: { endOffset: 5 },
@@ -134,7 +134,7 @@ describe('DocQuickInsertTriggerController', () => {
popupService.setEditPopup({ anchor: 4 });
commandService.emit({
id: InsertCommand.id,
id: InsertTextCommand.id,
params: {
body: { dataStream: 'a' },
range: { endOffset: 7 },
@@ -164,7 +164,7 @@ describe('DocQuickInsertTriggerController', () => {
expect(popupService.setInputOffset).toHaveBeenLastCalledWith({ start: 4, end: 9 });
commandService.emit({
id: DeleteCommand.id,
id: DeleteTextCommand.id,
params: {
direction: DeleteDirection.LEFT,
len: 2,
@@ -15,11 +15,11 @@
*/
import type { DocumentDataModel } from '@univerjs/core';
import type { IRichTextEditingMutationParams } from '@univerjs/docs';
import type { IDeleteCommandParams, IIMEInputCommandParams, IInsertCommandParams, IMoveCursorOperationParams } from '@univerjs/docs-ui';
import type { IDeleteTextCommandParams, IInsertTextCommandParams, IRichTextEditingMutationParams } from '@univerjs/docs';
import type { IIMEInputCommandParams, IMoveCursorOperationParams } from '@univerjs/docs-ui';
import { DeleteDirection, Direction, Disposable, ICommandService, Inject, IUniverInstanceService, UniverInstanceType } from '@univerjs/core';
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
import { DeleteCommand, DeleteLeftCommand, IMEInputCommand, InsertCommand, MoveCursorOperation } from '@univerjs/docs-ui';
import { DeleteTextCommand, DocSelectionManagerService, InsertTextCommand, RichTextEditingMutation } from '@univerjs/docs';
import { DeleteLeftCommand, IMEInputCommand, MoveCursorOperation } from '@univerjs/docs-ui';
import { IShortcutService, KeyCode } from '@univerjs/ui';
import { CloseQuickInsertPopupOperation, ShowQuickInsertPopupOperation } from '../commands/operations/quick-insert-popup.operation';
import { builtInMenuCommandIds, textMenu } from '../menu/menu';
@@ -57,8 +57,8 @@ export class DocQuickInsertTriggerController extends Disposable {
return;
}
if (commandInfo.id === InsertCommand.id) {
const params = commandInfo.params as IInsertCommandParams;
if (commandInfo.id === InsertTextCommand.id) {
const params = commandInfo.params as IInsertTextCommandParams;
if (_docQuickInsertPopupService.editPopup) {
_docQuickInsertPopupService.setInputOffset({
start: _docQuickInsertPopupService.inputOffset.start,
@@ -114,8 +114,8 @@ export class DocQuickInsertTriggerController extends Disposable {
}
}
if (commandInfo.id === DeleteCommand.id) {
const params = commandInfo.params as IDeleteCommandParams;
if (commandInfo.id === DeleteTextCommand.id) {
const params = commandInfo.params as IDeleteTextCommandParams;
if (_docQuickInsertPopupService.editPopup && params.direction === DeleteDirection.LEFT) {
const len = params.len ?? 0;
_docQuickInsertPopupService.setInputOffset({ start: _docQuickInsertPopupService.inputOffset.start, end: params.range.endOffset - len });
@@ -15,7 +15,7 @@
*/
import type { DocumentDataModel, IDisposable, Nullable } from '@univerjs/core';
import type { IInsertCommandParams } from '@univerjs/docs-ui';
import type { IInsertTextCommandParams } from '@univerjs/docs';
import type { Documents, DocumentSkeleton, IBoundRectNoAngle, IDocumentSkeletonGlyph, ITextRangeWithStyle } from '@univerjs/engine-render';
import type { Observable } from 'rxjs';
import { Disposable, ICommandService, Inject, IUniverInstanceService, UniverInstanceType } from '@univerjs/core';
@@ -47,7 +47,7 @@ export interface IDocPopup {
keyword: string;
menus$: Observable<DocPopupMenu[]>;
Placeholder?: React.ComponentType;
preconditions?: (params: IInsertCommandParams) => boolean;
preconditions?: (params: IInsertTextCommandParams) => boolean;
}
const noopDisposable = {
@@ -15,21 +15,21 @@
*/
import type { DocumentDataModel, ICommand, IDocumentData, Injector, IStyleBase, Univer } from '@univerjs/core';
import type { IDeleteTextCommandParams, IInsertTextCommandParams, IUpdateTextCommandParams } from '@univerjs/docs';
import {
awaitTime,
BooleanNumber,
CustomRangeType,
DataStreamTreeTokenType,
DeleteDirection,
HorizontalAlign,
ICommandService,
IUniverInstanceService,
UniverInstanceType,
UpdateDocsAttributeType,
} from '@univerjs/core';
import { DocSelectionManagerService, DocSkeletonManagerService, RichTextEditingMutation, SetTextSelectionsOperation } from '@univerjs/docs';
import { DeleteTextCommand, DocSelectionManagerService, DocSkeletonManagerService, InsertTextCommand, RichTextEditingMutation, SetTextSelectionsOperation, UpdateTextCommand } from '@univerjs/docs';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { DeleteDirection } from '../../../types/delete-direction';
import { DeleteCommand, InsertCommand, UpdateCommand } from '../core-editing.command';
import { DeleteLeftCommand, DeleteRightCommand, isDeleteOffsetInsideBlockRange } from '../doc-delete.command';
import { createCommandTestBed } from './create-command-test-bed';
@@ -209,7 +209,7 @@ describe('core editing commands', () => {
function registerDeleteKeyCommands() {
commandService.registerCommand(DeleteLeftCommand);
commandService.registerCommand(DeleteRightCommand);
commandService.registerCommand(UpdateCommand);
commandService.registerCommand(UpdateTextCommand);
commandService.registerCommand(SetTextSelectionsOperation);
commandService.registerCommand(RichTextEditingMutation as unknown as ICommand);
}
@@ -220,9 +220,9 @@ describe('core editing commands', () => {
get = testBed.get;
commandService = get(ICommandService);
commandService.registerCommand(InsertCommand);
commandService.registerCommand(DeleteCommand);
commandService.registerCommand(UpdateCommand);
commandService.registerCommand(InsertTextCommand);
commandService.registerCommand(DeleteTextCommand);
commandService.registerCommand(UpdateTextCommand);
commandService.registerCommand(SetTextSelectionsOperation);
commandService.registerCommand(RichTextEditingMutation as unknown as ICommand);
@@ -239,7 +239,7 @@ describe('core editing commands', () => {
const selectionManager = get(DocSelectionManagerService);
selectionManager.__TEST_ONLY_add([{ startOffset: 5, endOffset: 5, collapsed: true, isActive: true, segmentId: '', style: null as never }]);
await commandService.executeCommand(InsertCommand.id, {
await commandService.executeCommand<IInsertTextCommandParams>(InsertTextCommand.id, {
unitId: 'test-doc',
segmentId: '',
range: { startOffset: 5, endOffset: 5, collapsed: true },
@@ -254,7 +254,7 @@ describe('core editing commands', () => {
});
it('deletes an entire custom range when the selection hits a whole entity', async () => {
await commandService.executeCommand(DeleteCommand.id, {
await commandService.executeCommand<IDeleteTextCommandParams>(DeleteTextCommand.id, {
unitId: 'test-doc',
segmentId: '',
range: { startOffset: 7, endOffset: 7, collapsed: true },
@@ -273,11 +273,11 @@ describe('core editing commands', () => {
univer = testBed.univer;
get = testBed.get;
commandService = get(ICommandService);
commandService.registerCommand(DeleteCommand);
commandService.registerCommand(DeleteTextCommand);
commandService.registerCommand(SetTextSelectionsOperation);
commandService.registerCommand(RichTextEditingMutation as unknown as ICommand);
await commandService.executeCommand(DeleteCommand.id, {
await commandService.executeCommand<IDeleteTextCommandParams>(DeleteTextCommand.id, {
unitId: 'test-doc',
segmentId: '',
range: { startOffset: 0, endOffset: 0, collapsed: true },
@@ -296,11 +296,11 @@ describe('core editing commands', () => {
univer = testBed.univer;
get = testBed.get;
commandService = get(ICommandService);
commandService.registerCommand(DeleteCommand);
commandService.registerCommand(DeleteTextCommand);
commandService.registerCommand(SetTextSelectionsOperation);
commandService.registerCommand(RichTextEditingMutation as unknown as ICommand);
await commandService.executeCommand(DeleteCommand.id, {
await commandService.executeCommand<IDeleteTextCommandParams>(DeleteTextCommand.id, {
unitId: 'test-doc',
segmentId: '',
range: { startOffset: 1, endOffset: 1, collapsed: true },
@@ -411,14 +411,14 @@ describe('core editing commands', () => {
await commandService.executeCommand(DeleteLeftCommand.id);
expect(executeSpy).not.toHaveBeenCalledWith(UpdateCommand.id, expect.anything());
expect(executeSpy).toHaveBeenCalledWith(DeleteCommand.id, expect.objectContaining({
expect(executeSpy).not.toHaveBeenCalledWith(UpdateTextCommand.id, expect.anything());
expect(executeSpy).toHaveBeenCalledWith(DeleteTextCommand.id, expect.objectContaining({
direction: DeleteDirection.LEFT,
}));
});
it('updates text styles through the shared rich text mutation flow', async () => {
await commandService.executeCommand(UpdateCommand.id, {
await commandService.executeCommand<IUpdateTextCommandParams>(UpdateTextCommand.id, {
unitId: 'test-doc',
segmentId: '',
range: { startOffset: 0, endOffset: 5, collapsed: false },
@@ -16,11 +16,10 @@
import type { DocumentDataModel, ICommand, IDocumentBody, IMutationInfo, IParagraph, IParagraphBorder, ITextRangeParam } from '@univerjs/core';
import type { IRichTextEditingMutationParams } from '@univerjs/docs';
import { BuildTextUtils, CommandType, DataStreamTreeTokenType, generateRandomId, ICommandService, IUniverInstanceService, JSONX, PresetListType, TextX, TextXActionType, Tools, UniverInstanceType, UpdateDocsAttributeType } from '@univerjs/core';
import { BuildTextUtils, CommandType, DataStreamTreeTokenType, generateRandomId, getRichTextEditPath, ICommandService, IUniverInstanceService, JSONX, PresetListType, TextX, TextXActionType, Tools, UniverInstanceType, UpdateDocsAttributeType } from '@univerjs/core';
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
import { getTextRunAtPosition } from '../../basics/paragraph';
import { DocMenuStyleService } from '../../services/doc-menu-style.service';
import { getRichTextEditPath } from '../util';
export function generateParagraphs(
dataStream: string,
@@ -31,6 +31,7 @@ import {
BuildTextUtils,
CommandType,
generateRandomId,
getRichTextEditPath,
ICommandService,
IUniverInstanceService,
JSONX,
@@ -42,7 +43,7 @@ import {
} from '@univerjs/core';
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
import { getCustomDecorationAtPosition, getCustomRangeAtPosition } from '../../basics/paragraph';
import { getCommandSkeleton, getRichTextEditPath } from '../util';
import { getCommandSkeleton } from '../util';
import { getDeleteRowContentActionParams, getDeleteRowsActionsParams, getDeleteTableActionParams } from './table/table';
export function getCustomBlockIdsInSelections(body: IDocumentBody, selections: ITextRange[]): string[] {
@@ -15,13 +15,15 @@
*/
import type { DocumentDataModel, ICommand, IDocumentBlockRange, IDocumentBody, IMutationInfo, IParagraph, ITextRange, JSONXActions, Nullable } from '@univerjs/core';
import type { IRichTextEditingMutationParams } from '@univerjs/docs';
import type { IDeleteTextCommandParams, IRichTextEditingMutationParams, IUpdateTextCommandParams } from '@univerjs/docs';
import type { IRectRangeWithStyle, ITextRangeWithStyle } from '@univerjs/engine-render';
import {
BlockType,
BuildTextUtils,
CommandType,
DataStreamTreeTokenType,
DeleteDirection,
getRichTextEditPath,
HorizontalAlign,
ICommandService,
IUniverInstanceService,
@@ -34,14 +36,11 @@ import {
UniverInstanceType,
UpdateDocsAttributeType,
} from '@univerjs/core';
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
import { DeleteTextCommand, DocSelectionManagerService, RichTextEditingMutation, UpdateTextCommand } from '@univerjs/docs';
import { getParagraphByGlyph, hasListGlyph, isFirstGlyph, isIndentByGlyph } from '@univerjs/engine-render';
import { DocAutoFormatService } from '../../services/doc-auto-format.service';
import { DeleteDirection } from '../../types/delete-direction';
import { getCommandSkeleton, getRichTextEditPath } from '../util';
import { getCommandSkeleton } from '../util';
import { CutContentCommand } from './clipboard.inner.command';
import { DeleteCommand, UpdateCommand } from './core-editing.command';
import { getCurrentParagraph } from './util';
export interface IDeleteCustomBlockParams {
@@ -519,14 +518,12 @@ export const DeleteLeftCommand: ICommand = {
const paragraphStyle = paragraph.paragraphStyle;
if (isBullet === true) {
const paragraphStyle = paragraph.paragraphStyle;
if (paragraphStyle) {
updateParagraph.paragraphStyle = paragraphStyle;
updateParagraph.paragraphStyle = { ...paragraphStyle };
// TODO: It maybe need to update codes bellow when we support nested list.
const { hanging } = paragraphStyle;
if (hanging) {
updateParagraph.paragraphStyle.indentStart = hanging;
updateParagraph.paragraphStyle.indentStart = { ...hanging };
updateParagraph.paragraphStyle.hanging = undefined;
}
}
@@ -537,7 +534,7 @@ export const DeleteLeftCommand: ICommand = {
updateParagraph.bullet = bullet;
}
if (paragraphStyle != null) {
if (paragraphStyle) {
updateParagraph.paragraphStyle = { ...paragraphStyle };
delete updateParagraph.paragraphStyle.hanging;
delete updateParagraph.paragraphStyle.indentStart;
@@ -548,11 +545,12 @@ export const DeleteLeftCommand: ICommand = {
{
startOffset: cursor,
endOffset: cursor,
collapsed: true,
style,
},
];
result = await commandService.executeCommand(UpdateCommand.id, {
result = await commandService.executeCommand<IUpdateTextCommandParams>(UpdateTextCommand.id, {
unitId: docDataModel.getUnitId(),
updateBody: {
dataStream: '',
@@ -561,6 +559,7 @@ export const DeleteLeftCommand: ICommand = {
range: {
startOffset: paragraphIndex,
endOffset: paragraphIndex + 1,
collapsed: true,
},
textRanges,
coverType: UpdateDocsAttributeType.REPLACE,
@@ -612,15 +611,7 @@ export const DeleteLeftCommand: ICommand = {
cursor -= preGlyph.count;
cursor -= prePreGlyph.count;
const textRanges = [
{
startOffset: cursor,
endOffset: cursor,
style,
},
];
result = await commandService.executeCommand(DeleteCommand.id, {
result = await commandService.executeCommand<IDeleteTextCommandParams>(DeleteTextCommand.id, {
unitId: docDataModel.getUnitId(),
range: {
...activeRange,
@@ -630,12 +621,11 @@ export const DeleteLeftCommand: ICommand = {
segmentId,
direction: DeleteDirection.LEFT,
len: prePreGlyph.count,
textRanges,
});
}
} else {
cursor -= preGlyph.count;
result = await commandService.executeCommand(DeleteCommand.id, {
result = await commandService.executeCommand<IDeleteTextCommandParams>(DeleteTextCommand.id, {
unitId: docDataModel.getUnitId(),
range: actualRange,
segmentId,
@@ -763,15 +753,7 @@ export const DeleteRightCommand: ICommand = {
return true;
}
const textRanges = [
{
startOffset: startOffset + 1,
endOffset: startOffset + 1,
style,
},
];
result = await commandService.executeCommand(DeleteCommand.id, {
result = await commandService.executeCommand<IDeleteTextCommandParams>(DeleteTextCommand.id, {
unitId: docDataModel.getUnitId(),
range: {
...activeRange,
@@ -780,25 +762,15 @@ export const DeleteRightCommand: ICommand = {
},
segmentId,
direction: DeleteDirection.RIGHT,
textRanges,
len: nextGlyph.count,
});
}
} else {
const textRanges = [
{
startOffset,
endOffset: startOffset,
style,
},
];
result = await commandService.executeCommand(DeleteCommand.id, {
result = await commandService.executeCommand<IDeleteTextCommandParams>(DeleteTextCommand.id, {
unitId: docDataModel.getUnitId(),
range: actualRange,
segmentId,
direction: DeleteDirection.RIGHT,
textRanges,
len: needDeleteGlyph.count,
});
}
@@ -881,7 +853,7 @@ function resetEmptyCenteredParagraphAlignment(
paragraph: IParagraph,
style: ITextRangeWithStyle['style']
) {
return commandService.executeCommand(UpdateCommand.id, {
return commandService.executeCommand<IUpdateTextCommandParams>(UpdateTextCommand.id, {
unitId: docDataModel.getUnitId(),
updateBody: {
dataStream: '',
@@ -897,6 +869,7 @@ function resetEmptyCenteredParagraphAlignment(
range: {
startOffset: paragraph.startIndex,
endOffset: paragraph.startIndex + 1,
collapsed: true,
},
textRanges: [{
startOffset: paragraph.startIndex,
@@ -16,9 +16,8 @@
import type { DocumentDataModel, IAccessor, ICommand, IMutationInfo, IParagraphStyle } from '@univerjs/core';
import type { IRichTextEditingMutationParams } from '@univerjs/docs';
import { BuildTextUtils, CommandType, ICommandService, IUniverInstanceService, JSONX, MemoryCursor, TextX, TextXActionType, UniverInstanceType, UpdateDocsAttributeType } from '@univerjs/core';
import { BuildTextUtils, CommandType, getRichTextEditPath, ICommandService, IUniverInstanceService, JSONX, MemoryCursor, TextX, TextXActionType, UniverInstanceType, UpdateDocsAttributeType } from '@univerjs/core';
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
import { getRichTextEditPath } from '../util';
export interface IDocParagraphSettingCommandParams {
paragraph: Partial<Pick<IParagraphStyle, 'hanging' | 'horizontalAlign' | 'spaceBelow' | 'spaceAbove' | 'indentEnd' | 'indentStart' | 'lineSpacing' | 'indentFirstLine' | 'snapToGrid' | 'spacingRule'>>;
@@ -17,13 +17,12 @@
import type { DocumentDataModel, ICommand, ICommandInfo } from '@univerjs/core';
import type { IRichTextEditingMutationParams } from '@univerjs/docs';
import type { ITextRangeWithStyle } from '@univerjs/engine-render';
import { BuildTextUtils, CommandType, ICommandService, IUniverInstanceService, JSONX, SHEET_EDITOR_UNITS, TextX, TextXActionType, UniverInstanceType } from '@univerjs/core';
import { BuildTextUtils, CommandType, getRichTextEditPath, ICommandService, IUniverInstanceService, JSONX, SHEET_EDITOR_UNITS, TextX, TextXActionType, UniverInstanceType } from '@univerjs/core';
import { RichTextEditingMutation } from '@univerjs/docs';
import { IRenderManagerService } from '@univerjs/engine-render';
import { getCustomDecorationAtPosition, getCustomRangeAtPosition, getTextRunAtPosition } from '../../basics/paragraph';
import { DocIMEInputManagerService } from '../../services/doc-ime-input-manager.service';
import { DocMenuStyleService } from '../../services/doc-menu-style.service';
import { getRichTextEditPath } from '../util';
export interface IIMEInputCommandParams {
unitId: string;
@@ -33,6 +33,7 @@ import {
CommandType,
DOC_RANGE_TYPE,
getBodySlice,
getRichTextEditPath,
ICommandService,
IUniverInstanceService,
JSONX,
@@ -44,7 +45,6 @@ import {
} from '@univerjs/core';
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
import { DocMenuStyleService } from '../../services/doc-menu-style.service';
import { getRichTextEditPath } from '../util';
function handleInlineFormat(
preCommandId: string,
@@ -16,9 +16,8 @@
import type { DocumentDataModel, ICommand, IDocumentBody, IMutationInfo, PresetListType } from '@univerjs/core';
import type { IRichTextEditingMutationParams } from '@univerjs/docs';
import { BuildTextUtils, CommandType, ICommandService, IUniverInstanceService, JSONX, UniverInstanceType } from '@univerjs/core';
import { BuildTextUtils, CommandType, getRichTextEditPath, ICommandService, IUniverInstanceService, JSONX, UniverInstanceType } from '@univerjs/core';
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
import { getRichTextEditPath } from '../../util';
interface IInsertBulletBelowCommandParams {
listType: PresetListType;
@@ -21,6 +21,7 @@ import {
BuildTextUtils,
CommandType,
generateRandomId,
getRichTextEditPath,
ICommandService,
IUniverInstanceService,
JSONX,
@@ -34,7 +35,6 @@ import {
} from '@univerjs/core';
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
import { DocContentInsertService } from '../../services/doc-content-insert.service';
import { getRichTextEditPath } from '../util';
import { getCurrentParagraph } from './util';
interface IListOperationCommandParams {
@@ -20,6 +20,7 @@ import type { IRichTextEditingMutationParams } from '@univerjs/docs';
import {
BuildTextUtils,
CommandType,
getRichTextEditPath,
HorizontalAlign,
ICommandService,
IUniverInstanceService,
@@ -30,7 +31,6 @@ import {
UpdateDocsAttributeType,
} from '@univerjs/core';
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
import { getRichTextEditPath } from '../util';
interface IAlignOperationCommandParams {
alignType: HorizontalAlign;
@@ -17,9 +17,8 @@
import type { DocumentDataModel, ICommand, IDocumentBody, IDocumentData, IMutationInfo, ITextRange, JSONXActions } from '@univerjs/core';
import type { IRichTextEditingMutationParams } from '@univerjs/docs';
import type { ITextRangeWithStyle } from '@univerjs/engine-render';
import { BuildTextUtils, CommandType, ICommandService, IUndoRedoService, IUniverInstanceService, JSONX, TextX, TextXActionType, ThemeService, Tools, UniverInstanceType } from '@univerjs/core';
import { BuildTextUtils, CommandType, getRichTextEditPath, ICommandService, IUndoRedoService, IUniverInstanceService, JSONX, TextX, TextXActionType, ThemeService, Tools, UniverInstanceType } from '@univerjs/core';
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
import { getRichTextEditPath } from '../util';
export interface IReplaceSnapshotCommandParams {
unitId: string;
@@ -17,10 +17,9 @@
import type { DocumentDataModel, ICommand, IMutationInfo, ITextRangeParam } from '@univerjs/core';
import type { IRichTextEditingMutationParams } from '@univerjs/docs';
import type { ITextRangeWithStyle } from '@univerjs/engine-render';
import { BuildTextUtils, CommandType, generateRandomId, ICommandService, IUniverInstanceService, JSONX, NamedStyleType, TextX, TextXActionType, UniverInstanceType } from '@univerjs/core';
import { BuildTextUtils, CommandType, generateRandomId, getRichTextEditPath, ICommandService, IUniverInstanceService, JSONX, NamedStyleType, TextX, TextXActionType, UniverInstanceType } from '@univerjs/core';
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
import { DocContentInsertService } from '../../services/doc-content-insert.service';
import { getRichTextEditPath } from '../util';
export interface ISetParagraphNamedStyleCommandParams {
value: NamedStyleType;
@@ -17,12 +17,12 @@
import type { ICommand, IMutationInfo, JSONXActions } from '@univerjs/core';
import type { IRichTextEditingMutationParams } from '@univerjs/docs';
import type { ITextRangeWithStyle } from '@univerjs/engine-render';
import { CommandType, DataStreamTreeTokenType, ICommandService, IUniverInstanceService, JSONX, TextX, TextXActionType } from '@univerjs/core';
import { CommandType, DataStreamTreeTokenType, getRichTextEditPath, ICommandService, IUniverInstanceService, JSONX, TextX, TextXActionType } from '@univerjs/core';
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
import { getTextRunAtPosition } from '../../../basics/paragraph';
import { DocContentInsertService } from '../../../services/doc-content-insert.service';
import { DocMenuStyleService } from '../../../services/doc-menu-style.service';
import { getCommandSkeleton, getRichTextEditPath } from '../../util';
import { getCommandSkeleton } from '../../util';
import { generateParagraphs } from '../break-line.command';
import { genEmptyTable, genTableSource } from './table';
@@ -17,9 +17,9 @@
import type { ICommand, IMutationInfo, JSONXActions } from '@univerjs/core';
import type { IRichTextEditingMutationParams } from '@univerjs/docs';
import type { ITextRangeWithStyle } from '@univerjs/engine-render';
import { CommandType, ICommandService, IUniverInstanceService, JSONX, TextX, TextXActionType } from '@univerjs/core';
import { CommandType, getRichTextEditPath, ICommandService, IUniverInstanceService, JSONX, TextX, TextXActionType } from '@univerjs/core';
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
import { getCommandSkeleton, getRichTextEditPath } from '../../util';
import { getCommandSkeleton } from '../../util';
import { getDeleteColumnsActionParams, getDeleteRowsActionsParams, getDeleteTableActionParams, getRangeInfoFromRanges } from './table';
export interface IDocTableDeleteRowsCommandParams {}
@@ -17,9 +17,9 @@
import type { DocumentDataModel, ICommand, IMutationInfo, JSONXActions } from '@univerjs/core';
import type { IRichTextEditingMutationParams } from '@univerjs/docs';
import type { ITextRangeWithStyle } from '@univerjs/engine-render';
import { CommandType, ICommandService, IUniverInstanceService, JSONX, TextX, TextXActionType, UniverInstanceType } from '@univerjs/core';
import { CommandType, getRichTextEditPath, ICommandService, IUniverInstanceService, JSONX, TextX, TextXActionType, UniverInstanceType } from '@univerjs/core';
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
import { getCommandSkeleton, getRichTextEditPath } from '../../util';
import { getCommandSkeleton } from '../../util';
import { getColumnWidths, getEmptyTableCell, getEmptyTableRow, getInsertColumnActionsParams, getInsertColumnBody, getInsertRowActionsParams, getInsertRowBody, getRangeInfoFromRanges, getTableColumn, INSERT_COLUMN_POSITION, INSERT_ROW_POSITION } from './table';
// Insert rows and columns are in this file.
+1 -21
View File
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import type { DocumentDataModel, IAccessor } from '@univerjs/core';
import type { IAccessor } from '@univerjs/core';
import { DocSkeletonManagerService } from '@univerjs/docs';
import { IRenderManagerService } from '@univerjs/engine-render';
@@ -27,23 +27,3 @@ export function getCommandSkeleton(accessor: IAccessor, unitId: string) {
const renderManagerService = accessor.get(IRenderManagerService);
return renderManagerService.getRenderById(unitId)?.with(DocSkeletonManagerService);
}
export function getRichTextEditPath(docDataModel: DocumentDataModel, segmentId = '') {
if (!segmentId) {
return ['body'];
}
const { headers, footers } = docDataModel.getSnapshot();
if (headers == null && footers == null) {
throw new Error('Document data model must have headers or footers when update by segment id');
}
if (headers?.[segmentId] != null) {
return ['headers', segmentId, 'body'];
} else if (footers?.[segmentId] != null) {
return ['footers', segmentId, 'body'];
} else {
throw new Error('Segment id not found in headers or footers');
}
}
@@ -15,13 +15,13 @@
*/
import type { DocumentDataModel, Nullable } from '@univerjs/core';
import type { IInsertTextCommandParams } from '@univerjs/docs';
import type { IRenderContext, IRenderModule } from '@univerjs/engine-render';
import type { Subscription } from 'rxjs';
import { Disposable, ICommandService, Inject, SHEET_EDITOR_UNITS } from '@univerjs/core';
import { DocSkeletonManagerService } from '@univerjs/docs';
import { DocSkeletonManagerService, InsertTextCommand } from '@univerjs/docs';
import { getCustomDecorationAtPosition, getCustomRangeAtPosition, getTextRunAtPosition } from '../../basics/paragraph';
import { AfterSpaceCommand } from '../../commands/commands/auto-format.command';
import { InsertCommand } from '../../commands/commands/core-editing.command';
import { DocMenuStyleService } from '../../services/doc-menu-style.service';
import { DocSelectionRenderService } from '../../services/selection/doc-selection-render.service';
@@ -80,7 +80,7 @@ export class DocInputController extends Disposable implements IRenderModule {
const curTextRun = getTextRunAtPosition(originBody, activeRange.endOffset, defaultTextStyle, cacheStyle, SHEET_EDITOR_UNITS.includes(unitId));
const curCustomDecorations = getCustomDecorationAtPosition(originBody?.customDecorations ?? [], activeRange.endOffset);
await this._commandService.executeCommand(InsertCommand.id, {
await this._commandService.executeCommand<IInsertTextCommandParams>(InsertTextCommand.id, {
unitId,
body: {
dataStream: content,
@@ -14,69 +14,44 @@
* limitations under the License.
*/
import type { DocumentDataModel, ICommandService, IDocumentData } from '@univerjs/core';
import { InsertCommand } from '@univerjs/docs-ui';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { FDocument } from '../f-document';
import type { DocumentDataModel, ICommand, IDocumentData, Injector, Univer } from '@univerjs/core';
import { ICommandService, IResourceManagerService, UniverInstanceType } from '@univerjs/core';
import { InsertTextCommand, RichTextEditingMutation } from '@univerjs/docs';
import { FDocument } from '@univerjs/docs/facade';
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import { createTestBed } from './create-test-bed';
describe('Test FDocument', () => {
let commandService: Pick<ICommandService, 'executeCommand'>;
let resourceManagerService: { getResourcesByType: ReturnType<typeof vi.fn> };
let univerInstanceService: { focusUnit: ReturnType<typeof vi.fn> };
let renderManagerService: { getRenderById: ReturnType<typeof vi.fn> };
let documentDataModel: Pick<DocumentDataModel, 'getUnitId' | 'getSnapshot'>;
let univer: Univer;
let get: Injector['get'];
let documentDataModel: DocumentDataModel;
let document: FDocument;
function createDocumentFacade(docData?: IDocumentData) {
const testBed = createTestBed(docData);
univer = testBed.univer;
get = testBed.get;
documentDataModel = testBed.doc;
const commandService = get(ICommandService);
commandService.registerCommand(InsertTextCommand);
commandService.registerCommand(RichTextEditingMutation as unknown as ICommand);
document = univer.__getInjector().createInstance(FDocument, documentDataModel);
}
beforeEach(() => {
commandService = {
executeCommand: vi.fn().mockResolvedValue(true),
};
resourceManagerService = {
getResourcesByType: vi.fn(() => []),
};
univerInstanceService = {
focusUnit: vi.fn(),
};
renderManagerService = {
getRenderById: vi.fn(),
};
documentDataModel = {
getUnitId: () => 'test',
getSnapshot: () => ({
id: 'test',
title: 'Test Document',
documentStyle: {},
body: {
dataStream: 'Hello,\r\n',
},
}),
};
document = new FDocument(
documentDataModel as DocumentDataModel,
{} as never,
univerInstanceService as never,
commandService as ICommandService,
resourceManagerService as never,
renderManagerService as never
);
createDocumentFacade();
});
it('appends text by executing the insert command at the tail of the body', async () => {
afterEach(() => {
univer.dispose();
});
it('appends text at the tail of the body', async () => {
await expect(document.appendText('Univer')).resolves.toBe(true);
expect(commandService.executeCommand).toHaveBeenCalledWith(InsertCommand.id, {
unitId: 'test',
body: {
dataStream: 'Univer',
},
range: {
startOffset: 6,
endOffset: 6,
collapsed: true,
segmentId: '',
},
segmentId: '',
});
expect(document.save().body?.dataStream).toBe('Hello,Univer\r\n');
});
it('inserts text at an explicit document range', async () => {
@@ -86,19 +61,7 @@ describe('Test FDocument', () => {
startOffset: 2,
})).resolves.toBe(true);
expect(commandService.executeCommand).toHaveBeenCalledWith(InsertCommand.id, {
unitId: 'test',
body: {
dataStream: 'Docs',
},
range: {
startOffset: 2,
endOffset: 4,
collapsed: false,
segmentId: '',
},
segmentId: '',
});
expect(document.save().body?.dataStream).toBe('HeDocso,\r\n');
});
it('inserts paragraphs at an explicit document range', async () => {
@@ -108,49 +71,35 @@ describe('Test FDocument', () => {
startOffset: 6,
})).resolves.toBe(true);
expect(commandService.executeCommand).toHaveBeenCalledWith(InsertCommand.id, {
unitId: 'test',
body: {
dataStream: 'Line 1\r\nLine 2\r\n',
},
range: {
startOffset: 6,
endOffset: 6,
collapsed: true,
segmentId: '',
},
segmentId: '',
cursorOffset: 'Line 1\r\nLine 2\r\n'.length,
});
expect(document.save().body?.dataStream).toBe('Hello,Line 1\r\nLine 2\r\n\r\n');
});
it('throws when appending text to a document without a body', () => {
const emptyDocument = new FDocument(
{
getUnitId: () => 'test',
getSnapshot: () => ({ id: 'test' } as IDocumentData),
} as DocumentDataModel,
{} as never,
univerInstanceService as never,
commandService as ICommandService,
resourceManagerService as never,
renderManagerService as never
);
univer.dispose();
createDocumentFacade({
id: 'test',
title: 'Test Document',
documentStyle: {},
});
expect(() => emptyDocument.appendText('Univer')).toThrowError('The document body is empty');
expect(() => document.appendText('Univer')).toThrowError('The document body is empty');
});
it('includes current document resources in snapshots', () => {
resourceManagerService.getResourcesByType.mockReturnValue([
{
name: 'test-resource',
data: '{"value":1}',
},
]);
const resourceManagerService = get(IResourceManagerService);
expect(document.getSnapshot().resources).toEqual([
resourceManagerService.registerPluginResource({
pluginName: 'DOC_TEST_RESOURCE_PLUGIN',
businesses: [UniverInstanceType.UNIVER_DOC],
onLoad: () => undefined,
onUnLoad: () => undefined,
toJson: () => '{"value":1}',
parseJson: (bytes) => JSON.parse(bytes),
});
expect(document.save().resources).toEqual([
{
name: 'test-resource',
name: 'DOC_TEST_RESOURCE_PLUGIN',
data: '{"value":1}',
},
]);
+17 -131
View File
@@ -14,150 +14,30 @@
* limitations under the License.
*/
import type { DocumentDataModel, IDocumentData } from '@univerjs/core';
import {
DOC_RANGE_TYPE,
ICommandService,
Inject,
Injector,
IResourceManagerService,
IUniverInstanceService,
RedoCommand,
UndoCommand,
UniverInstanceType,
} from '@univerjs/core';
import { DocSelectionRenderService, InsertCommand } from '@univerjs/docs-ui';
import { DOC_RANGE_TYPE } from '@univerjs/core';
import { DocSelectionRenderService } from '@univerjs/docs-ui';
import { FDocument } from '@univerjs/docs/facade';
import { IRenderManagerService } from '@univerjs/engine-render';
export interface IDocumentInsertTextFacadeOptions {
startOffset?: number;
endOffset?: number;
segmentId?: string;
cursorOffset?: number;
interface IFDocumentUIMixin {
setSelection(startOffset: number, endOffset: number): void;
}
/**
* @hideconstructor
*/
export class FDocument {
readonly id: string;
constructor(
private readonly _documentDataModel: DocumentDataModel,
@Inject(Injector) protected readonly _injector: Injector,
@IUniverInstanceService private readonly _univerInstanceService: IUniverInstanceService,
@ICommandService private readonly _commandService: ICommandService,
@IResourceManagerService private readonly _resourceManagerService: IResourceManagerService,
@IRenderManagerService private readonly _renderManagerService: IRenderManagerService
) {
this.id = this._documentDataModel.getUnitId();
}
getId(): string {
return this._documentDataModel.getUnitId();
}
getName(): string {
return this.getSnapshot().title || '';
}
getSnapshot(): IDocumentData {
const resources = this._resourceManagerService.getResourcesByType(this.id, UniverInstanceType.UNIVER_DOC);
const snapshot = this._documentDataModel.getSnapshot() as IDocumentData;
snapshot.resources = resources;
return snapshot;
}
undo(): Promise<boolean> {
this._univerInstanceService.focusUnit(this.id);
return this._commandService.executeCommand(UndoCommand.id);
}
redo(): Promise<boolean> {
this._univerInstanceService.focusUnit(this.id);
return this._commandService.executeCommand(RedoCommand.id);
}
/**
* Adds the specified text to the end of this text region.
* @param text - The text to be added to the end of this text region.
*/
appendText(text: string): Promise<boolean> {
const { body } = this.getSnapshot();
if (!body) {
throw new Error('The document body is empty');
}
const lastPosition = body.dataStream.length - 2;
return this.insertText(text, {
startOffset: lastPosition,
endOffset: lastPosition,
segmentId: '',
});
}
/**
* Inserts text at the provided document range. Defaults to appending before the final section break.
* @param text - The text to insert.
* @param options - Optional target range, segment id, and cursor offset.
*/
insertText(text: string, options: IDocumentInsertTextFacadeOptions = {}): Promise<boolean> {
const unitId = this.id;
const { body } = this.getSnapshot();
if (!body) {
throw new Error('The document body is empty');
}
const startOffset = options.startOffset ?? Math.max(0, body.dataStream.length - 2);
const endOffset = options.endOffset ?? startOffset;
const segmentId = options.segmentId ?? '';
const activeRange = {
startOffset,
endOffset,
collapsed: startOffset === endOffset,
segmentId,
};
return this._commandService.executeCommand(InsertCommand.id, {
unitId,
body: {
dataStream: text,
},
range: activeRange,
segmentId,
...(options.cursorOffset == null ? {} : { cursorOffset: options.cursorOffset }),
});
}
/**
* Inserts one or more plain-text paragraphs at the provided document range.
* @param text - Paragraph text. Newlines are normalized to document paragraph separators.
* @param options - Optional target range, segment id, and cursor offset.
*/
insertParagraph(text = '', options: IDocumentInsertTextFacadeOptions = {}): Promise<boolean> {
const dataStream = `${text.replace(/\r\n/g, '\n').replace(/\r/g, '\n').split('\n').join('\r\n')}\r\n`;
return this.insertText(dataStream, {
...options,
cursorOffset: options.cursorOffset ?? dataStream.length,
});
}
export class FDocumentUIMixin extends FDocument implements IFDocumentUIMixin {
/**
* Sets the selection to a specified text range in the document.
* @param startOffset - The starting offset of the selection in the document.
* @param endOffset - The ending offset of the selection in the document.
* @example
* ```typescript
* document.setSelection(10, 20);
* const fDocument = univerAPI.getActiveDocument();
* fDocument.setSelection(10, 20);
* ```
*/
setSelection(startOffset: number, endOffset: number): void {
override setSelection(startOffset: number, endOffset: number): void {
// TODO: @jocs...
const docSelectionRenderService = this._renderManagerService.getRenderById(this.getId())?.with(DocSelectionRenderService);
const renderManagerService = this._injector.get(IRenderManagerService);
const docSelectionRenderService = renderManagerService.getRenderUnitById(this.getId())?.with(DocSelectionRenderService);
docSelectionRenderService?.removeAllRanges();
docSelectionRenderService?.addDocRanges(
[
@@ -171,3 +51,9 @@ export class FDocument {
);
}
}
FDocument.extend(FDocumentUIMixin);
declare module '@univerjs/docs/facade' {
// eslint-disable-next-line ts/naming-convention
interface FDocument extends IFDocumentUIMixin {}
}
+2 -4
View File
@@ -14,8 +14,6 @@
* limitations under the License.
*/
import './f-univer';
import './f-document';
export { FDocument } from './f-document';
export type * from './f-univer';
export type * from './f-document';
+2 -12
View File
@@ -29,16 +29,6 @@ export { DocCopyCommand, DocCutCommand, DocPasteCommand } from './commands/comma
export { CutContentCommand, type IInnerPasteCommandParams, InnerPasteCommand } from './commands/commands/clipboard.inner.command';
export type { IInnerCutCommandParams } from './commands/commands/clipboard.inner.command';
export { getCustomBlockIdsInSelections, getCutActionsFromDocRanges } from './commands/commands/clipboard.inner.command';
export {
DeleteCommand,
EditorInsertTextCommandId,
type ICoverCommandParams,
type IDeleteCommandParams,
type IInsertCommandParams,
InsertCommand,
type IUpdateCommandParams,
UpdateCommand,
} from './commands/commands/core-editing.command';
export { buildMoveDocBlockActions, type IMoveDocBlockCommandParams, MoveDocBlockCommand } from './commands/commands/doc-block-move.command';
export { DeleteCustomBlockCommand, DeleteLeftCommand, DeleteRightCommand, type IDeleteCustomBlockParams, MergeTwoParagraphCommand } from './commands/commands/doc-delete.command';
export { getCursorWhenDelete } from './commands/commands/doc-delete.command';
@@ -46,6 +36,7 @@ export { HorizontalLineCommand } from './commands/commands/doc-horizontal-line.c
export { DocSelectAllCommand } from './commands/commands/doc-select-all.command';
export { type IIMEInputCommandParams, IMEInputCommand } from './commands/commands/ime-input.command';
export {
getStyleInTextRange,
ResetInlineFormatTextBackgroundColorCommand,
SetInlineFormatBoldCommand,
SetInlineFormatCommand,
@@ -59,7 +50,6 @@ export {
SetInlineFormatTextColorCommand,
SetInlineFormatTextFillCommand,
SetInlineFormatUnderlineCommand,
getStyleInTextRange,
} from './commands/commands/inline-format.command';
export { type IInsertCustomRangeCommandParams, InsertCustomRangeCommand } from './commands/commands/insert-custom-range.command';
export {
@@ -117,7 +107,7 @@ export { DocCreateTableOperation } from './commands/operations/doc-create-table.
export { type IMoveCursorOperationParams, MoveSelectionOperation } from './commands/operations/doc-cursor.operation';
export { MoveCursorOperation } from './commands/operations/doc-cursor.operation';
export { type ISetDocZoomRatioOperationParams, SetDocZoomRatioOperation } from './commands/operations/set-doc-zoom-ratio.operation';
export { getCommandSkeleton, getRichTextEditPath } from './commands/util';
export { getCommandSkeleton } from './commands/util';
export type { IUniverDocsUIConfig } from './config/config';
export { DocUIController } from './controllers/doc-ui.controller';
export { DocBackScrollRenderController } from './controllers/render-controllers/back-scroll.render-controller';
-4
View File
@@ -38,7 +38,6 @@ import { AfterSpaceCommand, EnterCommand, TabCommand } from './commands/commands
import { BreakLineCommand } from './commands/commands/break-line.command';
import { DocCopyCommand, DocCopyCurrentParagraphCommand, DocCutCommand, DocCutCurrentParagraphCommand, DocPasteCommand } from './commands/commands/clipboard.command';
import { CutContentCommand, InnerPasteCommand } from './commands/commands/clipboard.inner.command';
import { DeleteCommand, InsertCommand, UpdateCommand } from './commands/commands/core-editing.command';
import { MoveDocBlockCommand } from './commands/commands/doc-block-move.command';
import { DeleteCurrentParagraphCommand, DeleteCustomBlockCommand, DeleteLeftCommand, DeleteRightCommand, MergeTwoParagraphCommand, RemoveHorizontalLineCommand } from './commands/commands/doc-delete.command';
import { CloseHeaderFooterCommand } from './commands/commands/doc-header-footer.command';
@@ -221,11 +220,8 @@ export class UniverDocsUIPlugin extends Plugin {
SetInlineFormatTextBackgroundColorCommand,
SetInlineFormatCommand,
BreakLineCommand,
InsertCommand,
DeleteCommand,
DeleteCustomBlockCommand,
MoveDocBlockCommand,
UpdateCommand,
MergeTwoParagraphCommand,
RemoveHorizontalLineCommand,
SetDocZoomRatioOperation,
+1 -1
View File
@@ -10,7 +10,7 @@
| Package | UMD global | CSS | Locales | Facade entry |
| --- | --- | :---: | :---: | :---: |
| `@univerjs/docs` | `UniverDocs` | No | No | No |
| `@univerjs/docs` | `UniverDocs` | No | No | Yes |
## Installation
+12 -1
View File
@@ -26,7 +26,8 @@
],
"exports": {
".": "./src/index.ts",
"./*": "./src/*"
"./*": "./src/*",
"./facade": "./src/facade/index.ts"
},
"main": "./src/index.ts",
"types": "./lib/types/index.d.ts",
@@ -45,6 +46,16 @@
"require": "./lib/cjs/*",
"types": "./lib/types/index.d.ts"
},
"./facade": {
"import": "./lib/es/facade.js",
"require": "./lib/cjs/facade.js",
"types": "./lib/types/facade/index.d.ts"
},
"./lib/facade": {
"import": "./lib/es/facade.js",
"require": "./lib/cjs/facade.js",
"types": "./lib/types/facade/index.d.ts"
},
"./lib/*": "./lib/*"
}
},
@@ -23,14 +23,24 @@ import type {
ITextRange,
UpdateDocsAttributeType,
} from '@univerjs/core';
import type { IRichTextEditingMutationParams } from '@univerjs/docs';
import type { ITextRangeWithStyle } from '@univerjs/engine-render';
import { BuildTextUtils, CommandType, ICommandService, IUniverInstanceService, JSONX, TextX, TextXActionType, UniverInstanceType } from '@univerjs/core';
import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs';
import { DeleteDirection } from '../../types/delete-direction';
import { getRichTextEditPath } from '../util';
import type { IRichTextEditingMutationParams } from '../mutations/core-editing.mutation';
import {
BuildTextUtils,
CommandType,
DeleteDirection,
getRichTextEditPath,
ICommandService,
IUniverInstanceService,
JSONX,
TextX,
TextXActionType,
UniverInstanceType,
} from '@univerjs/core';
import { DocSelectionManagerService } from '../../services/doc-selection-manager.service';
import { RichTextEditingMutation } from '../mutations/core-editing.mutation';
export interface IInsertCommandParams {
export interface IInsertTextCommandParams {
unitId: string;
body: IDocumentBody;
range: ITextRange;
@@ -38,17 +48,13 @@ export interface IInsertCommandParams {
cursorOffset?: number;
}
export const EditorInsertTextCommandId = 'doc.command.insert-text';
/**
* The command to insert text. The changed range could be non-collapsed, mainly use in line break and normal input.
*/
export const InsertCommand: ICommand<IInsertCommandParams> = {
id: EditorInsertTextCommandId,
export const InsertTextCommand: ICommand<IInsertTextCommandParams> = {
id: 'doc.command.insert-text',
type: CommandType.COMMAND,
handler: async (accessor, params: IInsertCommandParams) => {
handler: async (accessor, params: IInsertTextCommandParams) => {
const commandService = accessor.get(ICommandService);
const { range, segmentId, body, unitId, cursorOffset } = params;
const docSelectionManagerService = accessor.get(DocSelectionManagerService);
@@ -126,7 +132,7 @@ export const InsertCommand: ICommand<IInsertCommandParams> = {
},
};
export interface IDeleteCommandParams {
export interface IDeleteTextCommandParams {
unitId: string;
range: ITextRange;
direction: DeleteDirection;
@@ -137,11 +143,11 @@ export interface IDeleteCommandParams {
/**
* The command to delete text, mainly used in BACKSPACE and DELETE when collapsed is true. ONLY handle collapsed range!!!
*/
export const DeleteCommand: ICommand<IDeleteCommandParams> = {
export const DeleteTextCommand: ICommand<IDeleteTextCommandParams> = {
id: 'doc.command.delete-text',
type: CommandType.COMMAND,
handler: async (accessor, params: IDeleteCommandParams) => {
handler: async (accessor, params: IDeleteTextCommandParams) => {
const commandService = accessor.get(ICommandService);
const univerInstanceService = accessor.get(IUniverInstanceService);
const { range, segmentId, unitId, direction, len = 1 } = params;
@@ -202,7 +208,7 @@ export const DeleteCommand: ICommand<IDeleteCommandParams> = {
},
};
export interface IUpdateCommandParams {
export interface IUpdateTextCommandParams {
unitId: string;
updateBody: IDocumentBody;
range: ITextRange;
@@ -214,12 +220,12 @@ export interface IUpdateCommandParams {
/**
* The command to update text properties, mainly used in BACKSPACE.
*/
export const UpdateCommand: ICommand<IUpdateCommandParams> = {
export const UpdateTextCommand: ICommand<IUpdateTextCommandParams> = {
id: 'doc.command.update-text',
type: CommandType.COMMAND,
handler: async (accessor, params: IUpdateCommandParams) => {
handler: async (accessor, params: IUpdateTextCommandParams) => {
const { range, segmentId, updateBody, coverType, unitId, textRanges } = params;
const commandService = accessor.get(ICommandService);
const univerInstanceService = accessor.get(IUniverInstanceService);
+272
View File
@@ -0,0 +1,272 @@
/**
* Copyright 2023-present DreamNum Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type { DocumentDataModel, IDocumentData } from '@univerjs/core';
import type { IInsertTextCommandParams } from '@univerjs/docs';
import {
ICommandService,
Inject,
Injector,
IResourceLoaderService,
IUniverInstanceService,
RedoCommand,
UndoCommand,
} from '@univerjs/core';
import { FBaseInitialable } from '@univerjs/core/facade';
import { InsertTextCommand } from '@univerjs/docs';
export interface IDocumentInsertTextFacadeOptions {
startOffset?: number;
endOffset?: number;
segmentId?: string;
cursorOffset?: number;
}
/**
* Facade API object bounded to a document. It provides a set of methods to interact with the document.
* @hideconstructor
*/
export class FDocument extends FBaseInitialable {
readonly id: string;
constructor(
private readonly _documentDataModel: DocumentDataModel,
@Inject(Injector) protected override readonly _injector: Injector,
@IUniverInstanceService protected readonly _univerInstanceService: IUniverInstanceService,
@Inject(IResourceLoaderService) protected readonly _resourceLoaderService: IResourceLoaderService,
@ICommandService private readonly _commandService: ICommandService
) {
super(_injector);
this.id = this._documentDataModel.getUnitId();
}
/**
* Get the document data model of the document.
* @returns {DocumentDataModel} The document data model.
* @example
* ```typescript
* const fDocument = univerAPI.getActiveDocument();
* const documentDataModel = fDocument.getDocumentDataModel();
* console.log(documentDataModel);
* ```
*/
getDocumentDataModel(): DocumentDataModel {
return this._documentDataModel;
}
override dispose(): void {
super.dispose();
}
/**
* Get the document id.
* @returns {string} The document id.
* @example
* ```typescript
* const fDocument = univerAPI.getActiveDocument();
* const unitId = fDocument.getId();
* console.log(unitId);
* ```
*/
getId(): string {
return this.id;
}
/**
* Get the document name.
* @returns {string} The document name.
* @example
* ```typescript
* const fDocument = univerAPI.getActiveDocument();
* const name = fDocument.getName();
* console.log(name);
* ```
*/
getName(): string {
return this._documentDataModel.getTitle() || '';
}
/**
* Save the document snapshot data, including the document content and resource data, etc.
* @returns {IDocumentData} The document snapshot data.
* @example
* ```typescript
* const fDocument = univerAPI.getActiveDocument();
* const snapshot = fDocument.save();
* console.log(snapshot);
* ```
*/
save(): IDocumentData {
const snapshot = this._resourceLoaderService.saveUnit<IDocumentData>(this._documentDataModel.getUnitId())!;
return snapshot;
}
/**
* Undo the last operation in the document.
* @returns {Promise<boolean>} A promise that resolves to true if the undo operation was successful, or false if it failed.
* @example
* ```typescript
* const fDocument = univerAPI.getActiveDocument();
* await fDocument.undo();
* ```
*/
undo(): Promise<boolean> {
this._univerInstanceService.focusUnit(this.id);
return this._commandService.executeCommand(UndoCommand.id);
}
/**
* Redo the last undone operation in the document.
* @returns {Promise<boolean>} A promise that resolves to true if the redo operation was successful, or false if it failed.
* @example
* ```typescript
* const fDocument = univerAPI.getActiveDocument();
* await fDocument.redo();
* ```
*/
redo(): Promise<boolean> {
this._univerInstanceService.focusUnit(this.id);
return this._commandService.executeCommand(RedoCommand.id);
}
/**
* Adds the specified text to the end of this text region.
* @param {string} text - The text to be added to the end of this text region.
* @return {Promise<boolean>} A promise that resolves to true if the text was successfully appended, or false if it failed.
* @example
* ```typescript
* const fDocument = univerAPI.getActiveDocument();
* await fDocument.appendText('Hello, world!');
* ```
*/
appendText(text: string): Promise<boolean> {
const { body } = this.save();
if (!body) {
throw new Error('The document body is empty');
}
const lastPosition = body.dataStream.length - 2;
return this.insertText(text, {
startOffset: lastPosition,
endOffset: lastPosition,
segmentId: '',
});
}
/**
* Inserts text at the provided document range. Defaults to appending before the final section break.
* @param {string} text - The text to insert.
* @param {IDocumentInsertTextFacadeOptions} options - Optional target range, segment id, and cursor offset.
* @returns {Promise<boolean>} A promise that resolves to true if the text was successfully inserted, or false if it failed.
* @example
*
* // Insert text at a specific range in the document body
* ```typescript
* const fDocument = univerAPI.getActiveDocument();
* await fDocument.insertText('Hello, world!', {
* startOffset: 5,
* endOffset: 5,
* segmentId: '',
* cursorOffset: 13,
* });
* ```
*
* // Insert text at the beginning of a header or footer segment
* ```typescript
* const fDocument = univerAPI.getActiveDocument();
* const snapshot = fDocument.save();
* const { headers, footers } = snapshot;
*
* if (headers) {
* for (const headerId in headers) {
* if (headerId === 'target-header-id') {
* await fDocument.insertText('Hello, header!', {
* startOffset: 0,
* endOffset: 0,
* segmentId: headerId,
* });
* }
* }
* }
*
* if (footers) {
* for (const footerId in footers) {
* if (footerId === 'target-footer-id') {
* await fDocument.insertText('Hello, footer!', {
* startOffset: 0,
* endOffset: 0,
* segmentId: footerId,
* });
* }
* }
* }
* ```
*/
insertText(text: string, options: IDocumentInsertTextFacadeOptions = {}): Promise<boolean> {
const unitId = this.id;
const { body } = this.save();
if (!body) {
throw new Error('The document body is empty');
}
const startOffset = options.startOffset ?? Math.max(0, body.dataStream.length - 2);
const endOffset = options.endOffset ?? startOffset;
const segmentId = options.segmentId ?? '';
const activeRange = {
startOffset,
endOffset,
collapsed: startOffset === endOffset,
segmentId,
};
return this._commandService.executeCommand<IInsertTextCommandParams>(InsertTextCommand.id, {
unitId,
body: {
dataStream: text,
},
range: activeRange,
segmentId,
...(options.cursorOffset == null ? {} : { cursorOffset: options.cursorOffset }),
});
}
/**
* Inserts one or more plain-text paragraphs at the provided document range.
* @param {string} text - The paragraph text to insert. Newlines are normalized to document paragraph separators.
* @param {IDocumentInsertTextFacadeOptions} options - Optional target range, segment id, and cursor offset.
* @returns {Promise<boolean>} A promise that resolves to true if the paragraphs were successfully inserted, or false if it failed.
* @example
* ```typescript
* const fDocument = univerAPI.getActiveDocument();
* await fDocument.insertParagraph('Hello, world! This is a new paragraph.', {
* startOffset: 5,
* endOffset: 5,
* });
* ```
*/
insertParagraph(text = '', options: IDocumentInsertTextFacadeOptions = {}): Promise<boolean> {
const dataStream = `${text.replace(/\r\n/g, '\n').replace(/\r/g, '\n').split('\n').join('\r\n')}\r\n`;
return this.insertText(dataStream, {
...options,
cursorOffset: options.cursorOffset ?? dataStream.length,
});
}
}
@@ -15,7 +15,7 @@
*/
import type { DocumentDataModel, IDocumentData } from '@univerjs/core';
import { UniverInstanceType } from '@univerjs/core';
import { IUniverInstanceService, UniverInstanceType } from '@univerjs/core';
import { FUniver } from '@univerjs/core/facade';
import { FDocument } from './f-document';
@@ -25,29 +25,44 @@ import { FDocument } from './f-document';
export interface IFUniverDocsUIMixin {
/**
* Create a new document and get the API handler of that document.
*
* @param {Partial<IDocumentData>} data The snapshot of the document.
* @returns {FDocument} FDocument API instance.
* @returns {FDocument} The document API instance.
* @example
* ```typescript
* const fDocument = univerAPI.createUniverDoc({ id: 'document-01', title: 'Document1' });
* console.log(fDocument);
* ```
*/
createUniverDoc(data: Partial<IDocumentData>): FDocument;
/**
* Get the document API handler by the document id.
*
* @param {string} id The document id.
* @returns {FDocument | null} The document API instance.
*/
getUniverDoc(id: string): FDocument | null;
createDocument(data: Partial<IDocumentData>): FDocument;
/**
* Get the currently focused Univer document.
*
* @returns {FDocument | null} The currently focused Univer document.
* @returns {FDocument | null} The currently focused Univer document API instance, or null if there is no focused Univer document.
* @example
* ```typescript
* const fDocument = univerAPI.getActiveDocument();
* console.log(fDocument);
* ```
*/
getActiveDocument(): FDocument | null;
/**
* Get the document API handler by the document id.
* @param {string} id The document id.
* @returns {FDocument | null} The document API instance corresponding to the document id, or null if not found.
* @example
* ```typescript
* const fDocument = univerAPI.getDocument('document-01');
* console.log(fDocument);
* ```
*/
getDocument(id: string): FDocument | null;
}
export class FUniverDocsUIMixin extends FUniver implements IFUniverDocsUIMixin {
override createUniverDoc(data: Partial<IDocumentData>): FDocument {
const document = this._univerInstanceService.createUnit<IDocumentData, DocumentDataModel>(UniverInstanceType.UNIVER_DOC, data);
override createDocument(data: Partial<IDocumentData>): FDocument {
const instanceService = this._injector.get(IUniverInstanceService);
const document = instanceService.createUnit<IDocumentData, DocumentDataModel>(UniverInstanceType.UNIVER_DOC, data);
return this._injector.createInstance(FDocument, document);
}
@@ -60,8 +75,8 @@ export class FUniverDocsUIMixin extends FUniver implements IFUniverDocsUIMixin {
return this._injector.createInstance(FDocument, document);
}
override getUniverDoc(id: string): FDocument | null {
const document = this._univerInstanceService.getUniverDocInstance(id);
override getDocument(id: string): FDocument | null {
const document = this._univerInstanceService.getUnit<DocumentDataModel>(id, UniverInstanceType.UNIVER_DOC);
if (!document) {
return null;
}
@@ -14,7 +14,8 @@
* limitations under the License.
*/
export enum DeleteDirection {
LEFT,
RIGHT,
}
import './f-univer';
export { FDocument } from './f-document';
export type * from './f-univer';
+8
View File
@@ -14,6 +14,14 @@
* limitations under the License.
*/
export {
DeleteTextCommand,
type IDeleteTextCommandParams,
type IInsertTextCommandParams,
InsertTextCommand,
type IUpdateTextCommandParams,
UpdateTextCommand,
} from './commands/commands/core-editing.command';
export { type IRichTextEditingMutationParams, RichTextEditingMutation } from './commands/mutations/core-editing.mutation';
export { type ISetTextSelectionsOperationParams, SetTextSelectionsOperation } from './commands/operations/text-selection.operation';
export type { IUniverDocsConfig } from './config/config';
+4
View File
@@ -25,6 +25,7 @@ import {
Plugin,
} from '@univerjs/core';
import pkg from '../package.json';
import { DeleteTextCommand, InsertTextCommand, UpdateTextCommand } from './commands/commands/core-editing.command';
import { RichTextEditingMutation } from './commands/mutations/core-editing.mutation';
import { DocsRenameMutation } from './commands/mutations/docs-rename.mutation';
import { SetTextSelectionsOperation } from './commands/operations/text-selection.operation';
@@ -63,6 +64,9 @@ export class UniverDocsPlugin extends Plugin {
private _initializeCommands(): void {
(
[
InsertTextCommand,
DeleteTextCommand,
UpdateTextCommand,
RichTextEditingMutation,
DocsRenameMutation,
SetTextSelectionsOperation,
@@ -16,7 +16,7 @@
import type { CustomRangeType, DocumentDataModel, IAccessor, IAddCustomRangeTextXParam, IDocumentBody, IMutationInfo, ITextRange, ITextRangeParam, Nullable, TextX } from '@univerjs/core';
import type { IRichTextEditingMutationParams } from '../commands/mutations/core-editing.mutation';
import { BuildTextUtils, IUniverInstanceService, JSONX, UniverInstanceType } from '@univerjs/core';
import { BuildTextUtils, getRichTextEditPath, IUniverInstanceService, JSONX, UniverInstanceType } from '@univerjs/core';
import { RichTextEditingMutation } from '../commands/mutations/core-editing.mutation';
import { DocSelectionManagerService } from '../services/doc-selection-manager.service';
@@ -24,29 +24,6 @@ interface IAddCustomRangeParam extends IAddCustomRangeTextXParam {
unitId: string;
}
/**
* @deprecated This is a duplication from docs-ui to avoid making too much breaking changes.
*/
export function getRichTextEditPath(docDataModel: DocumentDataModel, segmentId = '') {
if (!segmentId) {
return ['body'];
}
const { headers, footers } = docDataModel.getSnapshot();
if (headers == null && footers == null) {
throw new Error('Document data model must have headers or footers when update by segment id');
}
if (headers?.[segmentId] != null) {
return ['headers', segmentId, 'body'];
} else if (footers?.[segmentId] != null) {
return ['footers', segmentId, 'body'];
} else {
throw new Error('Segment id not found in headers or footers');
}
}
export function addCustomRangeFactory(accessor: IAccessor, param: IAddCustomRangeParam, body: IDocumentBody) {
const { unitId, segmentId } = param;
const univerInstanceService = accessor.get(IUniverInstanceService);
@@ -15,16 +15,13 @@
*/
import type { IDisposable, IExecutionOptions } from '@univerjs/core';
import type { CommentUpdate, IAddCommentCommandParams, IDeleteCommentCommandParams } from '@univerjs/thread-comment';
import type { CommentUpdate, IAddCommentCommandParams, IDeleteCommentCommandParams, IUpdateCommentCommandParams } from '@univerjs/thread-comment';
import { toDisposable } from '@univerjs/core';
import { FWorkbook } from '@univerjs/sheets/facade';
import { AddCommentCommand, DeleteCommentCommand, DeleteCommentTreeCommand, ThreadCommentModel, UpdateCommentCommand } from '@univerjs/thread-comment';
import { filter } from 'rxjs';
import { FThreadComment } from './f-thread-comment';
// eslint-disable-next-line ts/no-explicit-any
type IUpdateCommandParams = any;
/**
* @ignore
*/
@@ -82,7 +79,7 @@ export interface IFWorkbookSheetsThreadCommentMixin {
*/
onBeforeUpdateThreadComment(
this: FWorkbook,
callback: (params: IUpdateCommandParams, options: IExecutionOptions | undefined) => void | false
callback: (params: IUpdateCommentCommandParams, options: IExecutionOptions | undefined) => void | false
): IDisposable;
/**
@@ -154,9 +151,9 @@ export class FWorkbookSheetsThreadCommentMixin extends FWorkbook implements IFWo
* @param callback
* @deprecated
*/
override onBeforeUpdateThreadComment(callback: (params: IUpdateCommandParams, options: IExecutionOptions | undefined) => void | false): IDisposable {
override onBeforeUpdateThreadComment(callback: (params: IUpdateCommentCommandParams, options: IExecutionOptions | undefined) => void | false): IDisposable {
return toDisposable(this._commandService.beforeCommandExecuted((commandInfo, options) => {
const params = commandInfo.params as IUpdateCommandParams;
const params = commandInfo.params as IUpdateCommentCommandParams;
if (commandInfo.id === UpdateCommentCommand.id) {
if (params.unitId !== this._workbook.getUnitId()) {
return;
@@ -15,11 +15,13 @@
*/
import type { ICommandInfo } from '@univerjs/core';
import type { IIMEInputCommandParams, IInsertCommandParams } from '@univerjs/docs-ui';
import type { IInsertTextCommandParams } from '@univerjs/docs';
import type { IIMEInputCommandParams } from '@univerjs/docs-ui';
import type { ISheetPasteParams } from '../../commands/commands/clipboard.command';
import type { IEditorBridgeServiceVisibleParam } from '../../services/editor-bridge.service';
import { Disposable, DisposableCollection, FOCUSING_COMMENT_EDITOR, FOCUSING_EDITOR_STANDALONE, ICommandService, IContextService, Inject, IPermissionService, IUniverInstanceService, LocaleService } from '@univerjs/core';
import { IMEInputCommand, InsertCommand } from '@univerjs/docs-ui';
import { InsertTextCommand } from '@univerjs/docs';
import { IMEInputCommand } from '@univerjs/docs-ui';
import { getSheetCommandTarget, RangeProtectionPermissionEditPoint, RangeProtectionPermissionViewPoint, RangeProtectionRuleModel, SheetPermissionCheckController, WorkbookCopyPermission, WorkbookEditablePermission, WorksheetCopyPermission, WorksheetEditPermission, WorksheetSetCellStylePermission, WorksheetSetCellValuePermission, WorksheetSetColumnStylePermission } from '@univerjs/sheets';
import { IDialogService } from '@univerjs/ui';
import { SheetCopyCommand, SheetCutCommand, SheetPasteColWidthCommand, SheetPasteCommand, SheetPasteShortKeyCommand } from '../../commands/commands/clipboard.command';
@@ -90,13 +92,13 @@ export class SheetPermissionCheckUIController extends Disposable {
let target;
switch (id) {
case InsertCommand.id:
case InsertTextCommand.id:
case IMEInputCommand.id:
if (this._contextService.getContextValue(FOCUSING_EDITOR_STANDALONE) === true || this._contextService.getContextValue(FOCUSING_COMMENT_EDITOR) === true) {
break;
}
params = commandInfo.params as IInsertCommandParams | IIMEInputCommandParams;
params = commandInfo.params as IInsertTextCommandParams | IIMEInputCommandParams;
permission = this._sheetPermissionCheckController.permissionCheckWithoutRange({
workbookTypes: [WorkbookEditablePermission],
+3 -4
View File
@@ -80,13 +80,13 @@ export interface IFUniverSheetsMixin {
* @returns {FWorkbook} The spreadsheet API instance.
* @example
* ```ts
* const fWorkbook = univerAPI.createWorkbook({ id: 'Sheet1', name: 'Sheet1' });
* const fWorkbook = univerAPI.createWorkbook({ id: 'workbook-01', name: 'Workbook1' });
* console.log(fWorkbook);
* ```
*
* Add you can make the workbook not as the active workbook by setting options:
* ```ts
* const fWorkbook = univerAPI.createWorkbook({ id: 'Sheet1', name: 'Sheet1' }, { makeCurrent: false });
* const fWorkbook = univerAPI.createWorkbook({ id: 'workbook-01', name: 'Workbook1' }, { makeCurrent: false });
* console.log(fWorkbook);
* ```
*/
@@ -110,8 +110,7 @@ export interface IFUniverSheetsMixin {
*
* @example
* ```ts
* const unitId = 'workbook-01';
* const fWorkbook = univerAPI.getWorkbook(unitId);
* const fWorkbook = univerAPI.getWorkbook('workbook-01');
* console.log(fWorkbook);
* ```
*/