Skip to content

Commit

Permalink
fix: transform with REPLACE type
Browse files Browse the repository at this point in the history
  • Loading branch information
Jocs committed Oct 22, 2024
1 parent d0054f3 commit b0194b8
Show file tree
Hide file tree
Showing 5 changed files with 281 additions and 27 deletions.
166 changes: 159 additions & 7 deletions packages/core/src/docs/data-model/text-x/__tests__/apply.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
import type { IDocumentBody } from '../../../../types/interfaces';
import type { TextXAction } from '../action-types';
import { describe, expect, it } from 'vitest';
import { BooleanNumber } from '../../../../types/enum';
import { UpdateDocsAttributeType } from '../../../../shared';
import { BooleanNumber, HorizontalAlign } from '../../../../types/enum';
import { TextXActionType } from '../action-types';
import { TextX } from '../text-x';

Expand Down Expand Up @@ -55,6 +56,28 @@ function getDefaultDocWithLength2() {
return doc;
}

function getDefaultDocWithParagraph() {
const doc: IDocumentBody = {
dataStream: 'w\r\n',
textRuns: [
{
st: 0,
ed: 1,
ts: {
bl: BooleanNumber.TRUE,
},
},
],
paragraphs: [
{
startIndex: 1,
},
],
};

return doc;
}

describe('apply method', () => {
it('should get the same result when apply two actions by order OR composed first case 1', () => {
const actionsA: TextXAction[] = [
Expand Down Expand Up @@ -167,12 +190,6 @@ describe('apply method', () => {
const resultC = TextX.apply(doc3, composedAction1);
const resultD = TextX.apply(doc4, composedAction2);

// console.log(JSON.stringify(resultA, null, 2));
// console.log(JSON.stringify(resultB, null, 2));

// console.log(JSON.stringify(composedAction2, null, 2));
// console.log(JSON.stringify(resultC, null, 2));

expect(resultA).toEqual(resultB);
expect(resultC).toEqual(resultD);
expect(resultA).toEqual(resultC);
Expand Down Expand Up @@ -250,4 +267,139 @@ describe('apply method', () => {
expect(resultA).toEqual(resultC);
expect(composedAction1).toEqual(composedAction2);
});

it('should get the same result when set paragraph align type at 2 clients', () => {
const actionsA: TextXAction[] = [
{
t: TextXActionType.RETAIN,
len: 1,
segmentId: '',
}, {
t: TextXActionType.RETAIN,
len: 1,
segmentId: '',
body: {
dataStream: '',
paragraphs: [{
startIndex: 0,
paragraphStyle: {
horizontalAlign: HorizontalAlign.LEFT,
},
}],
},
},
];

const actionsB: TextXAction[] = [
{
t: TextXActionType.RETAIN,
len: 1,
segmentId: '',
}, {
t: TextXActionType.RETAIN,
len: 1,
segmentId: '',
body: {
dataStream: '',
paragraphs: [{
startIndex: 0,
paragraphStyle: {
horizontalAlign: HorizontalAlign.RIGHT,
},
}],
},
},
];

const doc1 = getDefaultDocWithParagraph();
const doc2 = getDefaultDocWithParagraph();
const doc3 = getDefaultDocWithParagraph();
const doc4 = getDefaultDocWithParagraph();

const resultA = TextX.apply(TextX.apply(doc1, actionsA), TextX.transform(actionsB, actionsA, 'left'));
const resultB = TextX.apply(TextX.apply(doc2, actionsB), TextX.transform(actionsA, actionsB, 'right'));

const composedAction1 = TextX.compose(actionsA, TextX.transform(actionsB, actionsA, 'left'));
const composedAction2 = TextX.compose(actionsB, TextX.transform(actionsA, actionsB, 'right'));

const resultC = TextX.apply(doc3, composedAction1);
const resultD = TextX.apply(doc4, composedAction2);

expect(resultA).toEqual(resultB);
expect(resultC).toEqual(resultD);
expect(resultA).toEqual(resultC);
expect(composedAction1).toEqual(composedAction2);
});

it('should get the same result when set paragraph align with REPLACE cover type at 2 clients', () => {
const actionsA: TextXAction[] = [
{
t: TextXActionType.RETAIN,
len: 1,
segmentId: '',
}, {
t: TextXActionType.RETAIN,
len: 1,
segmentId: '',
coverType: UpdateDocsAttributeType.REPLACE,
body: {
dataStream: '',
paragraphs: [{
startIndex: 0,
paragraphStyle: {
horizontalAlign: HorizontalAlign.LEFT,
},
}],
},
},
];

const actionsB: TextXAction[] = [
{
t: TextXActionType.RETAIN,
len: 1,
segmentId: '',
}, {
t: TextXActionType.RETAIN,
len: 1,
segmentId: '',
coverType: UpdateDocsAttributeType.REPLACE,
body: {
dataStream: '',
paragraphs: [{
startIndex: 0,
paragraphStyle: {
horizontalAlign: HorizontalAlign.RIGHT,
},
}],
},
},
];

const doc1 = getDefaultDocWithParagraph();
const doc2 = getDefaultDocWithParagraph();
const doc3 = getDefaultDocWithParagraph();
const doc4 = getDefaultDocWithParagraph();

const resultA = TextX.apply(TextX.apply(doc1, actionsA), TextX.transform(actionsB, actionsA, 'left'));
const resultB = TextX.apply(TextX.apply(doc2, actionsB), TextX.transform(actionsA, actionsB, 'right'));

const composedAction1 = TextX.compose(actionsA, TextX.transform(actionsB, actionsA, 'left'));
const composedAction2 = TextX.compose(actionsB, TextX.transform(actionsA, actionsB, 'right'));

const resultC = TextX.apply(doc3, composedAction1);
const resultD = TextX.apply(doc4, composedAction2);

// console.log(JSON.stringify(resultA, null, 2));
// console.log(JSON.stringify(resultB, null, 2));

// console.log('composedAction1', JSON.stringify(composedAction1, null, 2));

// console.log(JSON.stringify(resultC, null, 2));

expect(resultA).toEqual(resultB);
expect(resultC).toEqual(resultD);
expect(resultA).toEqual(resultC);
expect(composedAction1).toEqual(composedAction2);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import type { TextXAction } from '../action-types';
import { describe, expect, it } from 'vitest';
import { UpdateDocsAttributeType } from '../../../../shared';
import { BooleanNumber } from '../../../../types/enum';
import { TextXActionType } from '../action-types';
import { TextX } from '../text-x';
Expand Down Expand Up @@ -673,6 +674,93 @@ describe('transform()', () => {
expect(TextX._transform(actionsA, actionsB, 'left')).toEqual(expectedActionsWithPriorityTrue);
});

it('retain + retain with paragraph and REPLACE type', () => {
const actionsA: TextXAction[] = [
{
t: TextXActionType.RETAIN,
len: 1,
segmentId: '',
coverType: UpdateDocsAttributeType.REPLACE,
body: {
dataStream: '',
paragraphs: [
{
startIndex: 0,
paragraphStyle: {
lineSpacing: 1,
},
},
],
},
},
];

const actionsB: TextXAction[] = [
{
t: TextXActionType.RETAIN,
len: 1,
segmentId: '',
coverType: UpdateDocsAttributeType.REPLACE,
body: {
dataStream: '',
paragraphs: [
{
startIndex: 0,
paragraphStyle: {
lineSpacing: 5,
spaceBelow: { v: 6 },
},
},
],
},
},
];

const expectedActionsWithPriorityTrue: TextXAction[] = [
{
t: TextXActionType.RETAIN,
len: 1,
segmentId: '',
coverType: UpdateDocsAttributeType.REPLACE,
body: {
dataStream: '',
paragraphs: [
{
startIndex: 0,
paragraphStyle: {
lineSpacing: 1,
},
},
],
},
},
];

const expectedActionsWithPriorityFalse: TextXAction[] = [
{
t: TextXActionType.RETAIN,
len: 1,
segmentId: '',
coverType: UpdateDocsAttributeType.REPLACE,
body: {
dataStream: '',
paragraphs: [
{
startIndex: 0,
paragraphStyle: {
lineSpacing: 5,
spaceBelow: { v: 6 },
},
},
],
},
},
];

expect(TextX._transform(actionsA, actionsB, 'right')).toEqual(expectedActionsWithPriorityFalse);
expect(TextX._transform(actionsA, actionsB, 'left')).toEqual(expectedActionsWithPriorityTrue);
});

it('insert after the retain attributes', () => {
const actionA: TextXAction[] = [{
t: TextXActionType.RETAIN,
Expand Down
9 changes: 5 additions & 4 deletions packages/core/src/docs/data-model/text-x/text-x.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
* limitations under the License.
*/

import { Tools } from '../../../shared/tools';
import { UpdateDocsAttributeType } from '../../../shared/command-enum';
import type { IDocumentBody } from '../../../types/interfaces/i-document-data';
import { type IDeleteAction, type IInsertAction, type IRetainAction, type TextXAction, TextXActionType } from './action-types';
import { UpdateDocsAttributeType } from '../../../shared/command-enum';
import { Tools } from '../../../shared/tools';
import { ActionIterator } from './action-iterator';
import { composeBody, getBodySlice, isUselessRetainAction } from './utils';
import { type IDeleteAction, type IInsertAction, type IRetainAction, type TextXAction, TextXActionType } from './action-types';
import { textXApply } from './apply';
import { transformBody } from './transform-utils';
import { composeBody, getBodySlice, isUselessRetainAction } from './utils';

function onlyHasDataStream(body: IDocumentBody) {
return Object.keys(body).length === 1;
Expand Down Expand Up @@ -118,6 +118,7 @@ export class TextX {
* 2) If the other body property exists, then execute the TransformBody logic to override it
*/
// priority - if true, this actions takes priority over other, that is, this actions are considered to happen "first".
// thisActions is the target action.
static transform(thisActions: TextXAction[], otherActions: TextXAction[], priority: TPriority = 'right'): TextXAction[] {
return this._transform(otherActions, thisActions, priority === 'left' ? 'right' : 'left');
}
Expand Down
Loading

0 comments on commit b0194b8

Please sign in to comment.