diff --git a/.github/workflows/collaboration-manager.yml b/.github/workflows/collaboration-manager.yml new file mode 100644 index 00000000..b40eca5e --- /dev/null +++ b/.github/workflows/collaboration-manager.yml @@ -0,0 +1,40 @@ +name: Collaboration manager check +on: + pull_request: + merge_group: + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run ESLint check + uses: ./.github/actions/lint + with: + package-name: '@editorjs/collaboration-manager' + + tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - run: yarn + + - name: Build the package + uses: ./.github/actions/build + with: + package-name: '@editorjs/model' + + - name: Run unit tests + uses: ./.github/actions/unit-tests + with: + package-name: '@editorjs/collaboration-manager' + working-directory: './packages/collaboration-manager' + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Build the package + uses: ./.github/actions/build + with: + package-name: '@editorjs/collaboration-manager' diff --git a/packages/collaboration-manager/package.json b/packages/collaboration-manager/package.json index e974fcc6..c3575ce3 100644 --- a/packages/collaboration-manager/package.json +++ b/packages/collaboration-manager/package.json @@ -6,7 +6,7 @@ "types": "dist/index.d.ts", "type": "module", "scripts": { - "build": "tsc --project tsconfig.build.json", + "build": "tsc --build tsconfig.build.json", "dev": "tsc --project tsconfig.build.json --watch", "lint": "eslint ./src", "lint:ci": "yarn lint --max-warnings 0", diff --git a/packages/collaboration-manager/src/CollaborationManager.spec.ts b/packages/collaboration-manager/src/CollaborationManager.spec.ts index b679142f..6637895a 100644 --- a/packages/collaboration-manager/src/CollaborationManager.spec.ts +++ b/packages/collaboration-manager/src/CollaborationManager.spec.ts @@ -7,7 +7,9 @@ import { Operation, OperationType } from './Operation.js'; describe('CollaborationManager', () => { describe('applyOperation', () => { it('should add text on apply Insert Operation', () => { - const model = new EditorJSModel({ + const model = new EditorJSModel(); + + model.initializeDocument({ blocks: [ { name: 'paragraph', data: { @@ -47,7 +49,9 @@ describe('CollaborationManager', () => { it('should remove text on apply Remove Operation', () => { - const model = new EditorJSModel({ + const model = new EditorJSModel(); + + model.initializeDocument({ blocks: [ { name: 'paragraph', data: { @@ -89,7 +93,9 @@ describe('CollaborationManager', () => { describe('undo logic', () => { it('should invert Insert operation', () => { - const model = new EditorJSModel({ + const model = new EditorJSModel(); + + model.initializeDocument({ blocks: [ { name: 'paragraph', data: { @@ -129,7 +135,9 @@ describe('CollaborationManager', () => { }); it('should invert Remove operation', () => { - const model = new EditorJSModel({ + const model = new EditorJSModel(); + + model.initializeDocument({ blocks: [ { name: 'paragraph', data: { @@ -170,7 +178,9 @@ describe('CollaborationManager', () => { }); it('should revert only one operation if stack length is 1', () => { - const model = new EditorJSModel({ + const model = new EditorJSModel(); + + model.initializeDocument({ blocks: [ { name: 'paragraph', data: { @@ -211,7 +221,9 @@ describe('CollaborationManager', () => { }); it('should revert back to original state after undo and redo operations', () => { - const model = new EditorJSModel({ + const model = new EditorJSModel(); + + model.initializeDocument({ blocks: [ { name: 'paragraph', data: { diff --git a/packages/collaboration-manager/src/Transformer.ts b/packages/collaboration-manager/src/Transformer.ts index f8ad60a9..0b449bef 100644 --- a/packages/collaboration-manager/src/Transformer.ts +++ b/packages/collaboration-manager/src/Transformer.ts @@ -1,3 +1,4 @@ +import { IndexBuilder } from '@editorjs/model'; import { Operation, OperationType } from './Operation.js'; /** @@ -10,19 +11,35 @@ export class Transformer { * @param operation - operation to inverse */ public static inverse(operation: Operation): Operation { + const index = operation.index; + switch (operation.type) { case OperationType.Insert: - return new Operation(OperationType.Delete, operation.index, { + + const textRange = index.textRange; + + if (textRange == undefined) { + throw new Error('Unsupported index'); + } + + const [ textRangeStart ] = textRange; + + const newIndex = new IndexBuilder() + .from(index) + .addTextRange([textRangeStart, textRangeStart + operation.data.newValue.length]) + .build(); + + return new Operation(OperationType.Delete, newIndex, { prevValue: operation.data.newValue, newValue: operation.data.prevValue, }); case OperationType.Delete: - return new Operation(OperationType.Insert, operation.index, { + return new Operation(OperationType.Insert, index, { prevValue: operation.data.newValue, newValue: operation.data.prevValue, }); case OperationType.Modify: - return new Operation(OperationType.Modify, operation.index, { + return new Operation(OperationType.Modify, index, { prevValue: operation.data.newValue, newValue: operation.data.prevValue, }); diff --git a/packages/collaboration-manager/tsconfig.build.json b/packages/collaboration-manager/tsconfig.build.json index 832aea87..d59c527a 100644 --- a/packages/collaboration-manager/tsconfig.build.json +++ b/packages/collaboration-manager/tsconfig.build.json @@ -9,5 +9,10 @@ ], "exclude": [ "src/**/*.spec.ts" + ], + "references": [ + { + "path": "../model/tsconfig.build.json" + } ] }