easy-richtextarea 4.0.34 → 4.0.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/example.js +93 -1563
- package/lib/browser.js +1 -37
- package/lib/main.js +4 -45
- package/lib/mixins/event.js +11 -10
- package/lib/richTextarea.js +31 -156
- package/lib/selection.js +7 -146
- package/package.json +1 -3
- package/src/browser.js +0 -11
- package/src/main.js +0 -12
- package/src/mixins/event.js +3 -4
- package/src/richTextarea.js +22 -239
- package/src/selection.js +4 -154
- package/lib/constants.js +0 -22
- package/lib/contentCompare.js +0 -34
- package/lib/eventTypes.js +0 -49
- package/lib/keyCodes.js +0 -13
- package/lib/operation/delete.js +0 -290
- package/lib/operation/empty.js +0 -116
- package/lib/operation/insert.js +0 -245
- package/lib/operations/fromJSON.js +0 -40
- package/lib/operations/generate.js +0 -42
- package/lib/operations/toJSON.js +0 -17
- package/lib/transform/content.js +0 -19
- package/lib/transform/operations.js +0 -31
- package/lib/transform/selection.js +0 -19
- package/lib/types.js +0 -34
- package/lib/undoBuffer.js +0 -145
- package/src/constants.js +0 -4
- package/src/contentCompare.js +0 -34
- package/src/eventTypes.js +0 -15
- package/src/keyCodes.js +0 -3
- package/src/operation/delete.js +0 -285
- package/src/operation/empty.js +0 -76
- package/src/operation/insert.js +0 -221
- package/src/operations/fromJSON.js +0 -34
- package/src/operations/generate.js +0 -46
- package/src/operations/toJSON.js +0 -5
- package/src/transform/content.js +0 -11
- package/src/transform/operations.js +0 -57
- package/src/transform/selection.js +0 -11
- package/src/types.js +0 -11
- package/src/undoBuffer.js +0 -119
- package/test/content/transform.js +0 -57
- package/test/helpers.js +0 -91
- package/test/operation/delete.js +0 -390
- package/test/operation/empty.js +0 -101
- package/test/operation/insert.js +0 -306
- package/test/operations/generate.js +0 -78
- package/test/operations/transform.js +0 -69
package/src/operation/insert.js
DELETED
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import contentCompare from "../contentCompare";
|
|
4
|
-
import DeleteOperation from "../operation/delete";
|
|
5
|
-
|
|
6
|
-
import { INSERT_TYPE, DELETE_TYPE, EMPTY_TYPE } from "../types";
|
|
7
|
-
|
|
8
|
-
export default class InsertOperation {
|
|
9
|
-
constructor(type, content, position) {
|
|
10
|
-
this.type = type;
|
|
11
|
-
this.content = content;
|
|
12
|
-
this.position = position;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
getType() {
|
|
16
|
-
return this.type;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
getContent() {
|
|
20
|
-
return this.content;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
getPosition() {
|
|
24
|
-
return this.position;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
transformContent(content) {
|
|
28
|
-
let start,
|
|
29
|
-
end;
|
|
30
|
-
|
|
31
|
-
start = 0;
|
|
32
|
-
|
|
33
|
-
end = this.position;
|
|
34
|
-
|
|
35
|
-
const leftContent = content.substring(start, end);
|
|
36
|
-
|
|
37
|
-
start = this.position;
|
|
38
|
-
|
|
39
|
-
const rightContent = content.substring(start),
|
|
40
|
-
transformedContent = leftContent + this.content + rightContent;
|
|
41
|
-
|
|
42
|
-
return transformedContent;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
transformOperation(operation) {
|
|
46
|
-
const type = operation.getType();
|
|
47
|
-
|
|
48
|
-
switch (type) {
|
|
49
|
-
case INSERT_TYPE:
|
|
50
|
-
return ((tau, rho) => {
|
|
51
|
-
|
|
52
|
-
if (tau.position < rho.position) {
|
|
53
|
-
return [tau.clone()];
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (tau.position === rho.position) {
|
|
57
|
-
if (tau.content === rho.content) {
|
|
58
|
-
return [tau.clone()];
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (tau.content !== rho.content) {
|
|
62
|
-
if (contentCompare(rho.content, tau.content)) {
|
|
63
|
-
return [rho.shift(tau)];
|
|
64
|
-
} else {
|
|
65
|
-
return [tau.clone()];
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (tau.position > rho.position) {
|
|
71
|
-
return [rho.shift(tau)];
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
})(operation, this);
|
|
75
|
-
|
|
76
|
-
case DELETE_TYPE:
|
|
77
|
-
return ((tau, rho) => {
|
|
78
|
-
|
|
79
|
-
if (tau.position + tau.content.length <= rho.position) {
|
|
80
|
-
return [tau.clone()];
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (tau.position < rho.position) {
|
|
84
|
-
return [rho.left(tau), rho.left(tau).shift(rho.shift(rho.right(tau)))];
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (tau.position >= rho.position) {
|
|
88
|
-
return [rho.shift(tau)];
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
})(operation, this);
|
|
92
|
-
|
|
93
|
-
case EMPTY_TYPE:
|
|
94
|
-
return ((tau, rho) => {
|
|
95
|
-
|
|
96
|
-
return [tau.clone()];
|
|
97
|
-
|
|
98
|
-
})(operation, this);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
transformSelection(selection) {
|
|
103
|
-
let transformedSelection;
|
|
104
|
-
|
|
105
|
-
const selectionStartPosition = selection.getStartPosition(),
|
|
106
|
-
selectionEndPosition = selection.getEndPosition(), ///
|
|
107
|
-
contentLength = this.content.length,
|
|
108
|
-
startPosition = this.position; ///
|
|
109
|
-
|
|
110
|
-
if (false) {
|
|
111
|
-
///
|
|
112
|
-
} else if (selectionStartPosition >= startPosition) {
|
|
113
|
-
const offset = contentLength; ///
|
|
114
|
-
|
|
115
|
-
transformedSelection = selection.shifted(offset);
|
|
116
|
-
} else if (selectionEndPosition > startPosition) {
|
|
117
|
-
const contentLength = this.content.length,
|
|
118
|
-
endOffset = contentLength; ///
|
|
119
|
-
|
|
120
|
-
transformedSelection = selection.endPositionShifted(endOffset);
|
|
121
|
-
} else {
|
|
122
|
-
transformedSelection = selection.clone();
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return transformedSelection;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
shifted(offset) {
|
|
129
|
-
const content = this.content,
|
|
130
|
-
position = this.position + offset,
|
|
131
|
-
insertOperation = InsertOperation.fromContentAndPosition(content, position);
|
|
132
|
-
|
|
133
|
-
return insertOperation;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
shift(operation) {
|
|
137
|
-
const length = this.content.length,
|
|
138
|
-
offset = length, ///
|
|
139
|
-
shiftedOperation = operation.shifted(offset);
|
|
140
|
-
|
|
141
|
-
return shiftedOperation;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
left(deleteOperation) {
|
|
145
|
-
let content = deleteOperation.getContent();
|
|
146
|
-
|
|
147
|
-
const position = deleteOperation.getPosition(),
|
|
148
|
-
contentLength = this.position - position,
|
|
149
|
-
start = 0,
|
|
150
|
-
end = contentLength; ///
|
|
151
|
-
|
|
152
|
-
content = content.substring(start, end);
|
|
153
|
-
|
|
154
|
-
deleteOperation = DeleteOperation.fromContentAndPosition(content, position);
|
|
155
|
-
|
|
156
|
-
return deleteOperation;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
right(deleteOperation) {
|
|
160
|
-
let content = deleteOperation.getContent(),
|
|
161
|
-
position = deleteOperation.getPosition();
|
|
162
|
-
|
|
163
|
-
const start = this.position - position;
|
|
164
|
-
|
|
165
|
-
position = this.position;
|
|
166
|
-
|
|
167
|
-
content = content.substring(start);
|
|
168
|
-
|
|
169
|
-
deleteOperation = DeleteOperation.fromContentAndPosition(content, position);
|
|
170
|
-
|
|
171
|
-
return deleteOperation;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
invert(InsertOperation, DeleteOperation) {
|
|
175
|
-
const deleteOperation = DeleteOperation.fromContentAndPosition(this.content, this.position);
|
|
176
|
-
|
|
177
|
-
return deleteOperation;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
clone() {
|
|
181
|
-
const insertOperation = InsertOperation.fromContentAndPosition(this.content, this.position);
|
|
182
|
-
|
|
183
|
-
return insertOperation;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
toJSON() {
|
|
187
|
-
const type = this.type,
|
|
188
|
-
content = this.content,
|
|
189
|
-
position = this.position,
|
|
190
|
-
json = {
|
|
191
|
-
type,
|
|
192
|
-
content,
|
|
193
|
-
position
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
return json;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
static fromJSON(json) {
|
|
200
|
-
const { type, content, position } = json,
|
|
201
|
-
insertOperation = new InsertOperation(type, content, position);
|
|
202
|
-
|
|
203
|
-
return insertOperation;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
static fromContentAndPosition(content, position) {
|
|
207
|
-
const type = INSERT_TYPE, ///
|
|
208
|
-
insertOperation = new InsertOperation(type, content, position);
|
|
209
|
-
|
|
210
|
-
return insertOperation;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
static fromContentAndSelection(content, selection) {
|
|
214
|
-
const startPosition = selection.getStartPosition(),
|
|
215
|
-
type = INSERT_TYPE, ///
|
|
216
|
-
position = startPosition, ///
|
|
217
|
-
insertOperation = new InsertOperation(type, content, position);
|
|
218
|
-
|
|
219
|
-
return insertOperation;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import EmptyOperation from "../operation/empty";
|
|
4
|
-
import DeleteOperation from "../operation/delete";
|
|
5
|
-
import InsertOperation from "../operation/insert";
|
|
6
|
-
|
|
7
|
-
import { EMPTY_TYPE, DELETE_TYPE, INSERT_TYPE } from "../types";
|
|
8
|
-
|
|
9
|
-
export default function operationsFromJSON(operationsJSON) {
|
|
10
|
-
const operations = operationsJSON.map((operationJSON) => {
|
|
11
|
-
let operation;
|
|
12
|
-
|
|
13
|
-
const json = operationJSON, ///
|
|
14
|
-
{ type } = json;
|
|
15
|
-
|
|
16
|
-
switch (type) {
|
|
17
|
-
case EMPTY_TYPE:
|
|
18
|
-
operation = EmptyOperation.fromJSON(json);
|
|
19
|
-
break;
|
|
20
|
-
|
|
21
|
-
case DELETE_TYPE:
|
|
22
|
-
operation = DeleteOperation.fromJSON(json);
|
|
23
|
-
break;
|
|
24
|
-
|
|
25
|
-
case INSERT_TYPE:
|
|
26
|
-
operation = InsertOperation.fromJSON(json);
|
|
27
|
-
break;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return operation;
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
return operations;
|
|
34
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import InsertOperation from "../operation/insert";
|
|
4
|
-
import DeleteOperation from "../operation/delete";
|
|
5
|
-
|
|
6
|
-
export default function generateOperations(contentA, contentB) {
|
|
7
|
-
const operations = [],
|
|
8
|
-
contentALength = contentA.length,
|
|
9
|
-
contentBLength = contentB.length;
|
|
10
|
-
|
|
11
|
-
let left, right;
|
|
12
|
-
|
|
13
|
-
for (left = 0; (left < contentALength) && (left < contentBLength); left++) {
|
|
14
|
-
if (contentA[left] !== contentB[left]) {
|
|
15
|
-
break;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
for (right = 0; (right < contentALength - left) && (right < contentBLength - left); right++) {
|
|
20
|
-
if (contentA[contentALength - right - 1] !== contentB[contentBLength - right - 1]) {
|
|
21
|
-
break;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (left + right !== contentALength) {
|
|
26
|
-
const start = left, ///
|
|
27
|
-
end = contentALength - right,
|
|
28
|
-
content = contentA.substring(start, end),
|
|
29
|
-
position = left, ///
|
|
30
|
-
deleteOperation = DeleteOperation.fromContentAndPosition(content, position);
|
|
31
|
-
|
|
32
|
-
operations.push(deleteOperation);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (left + right !== contentBLength) {
|
|
36
|
-
const start = left, ///
|
|
37
|
-
end = contentBLength - right,
|
|
38
|
-
content = contentB.substring(start, end),
|
|
39
|
-
position = left, ///
|
|
40
|
-
insertOperation = InsertOperation.fromContentAndPosition(content, position);
|
|
41
|
-
|
|
42
|
-
operations.push(insertOperation);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return operations;
|
|
46
|
-
}
|
package/src/operations/toJSON.js
DELETED
package/src/transform/content.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { arrayUtilities } from "necessary";
|
|
4
|
-
|
|
5
|
-
const { first, head, tail } = arrayUtilities;
|
|
6
|
-
|
|
7
|
-
export default function transformOperations(tau, rho) {
|
|
8
|
-
if ((tau.length === 0) || (rho.length === 0)) {
|
|
9
|
-
return tau;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const tau1 = head(tau),
|
|
13
|
-
tau2 = tail(tau),
|
|
14
|
-
rho1 = head(rho),
|
|
15
|
-
rho2 = tail(rho);
|
|
16
|
-
|
|
17
|
-
if (tau.length > 1 && rho.length > 1) {
|
|
18
|
-
return (
|
|
19
|
-
transformOperations(
|
|
20
|
-
transformOperations(tau1, rho1),
|
|
21
|
-
rho2
|
|
22
|
-
).concat(
|
|
23
|
-
transformOperations(
|
|
24
|
-
transformOperations(
|
|
25
|
-
tau2,
|
|
26
|
-
transformOperations(rho1, tau1)
|
|
27
|
-
),
|
|
28
|
-
transformOperations(
|
|
29
|
-
rho2,
|
|
30
|
-
transformOperations(tau1, rho1)
|
|
31
|
-
)
|
|
32
|
-
)
|
|
33
|
-
)
|
|
34
|
-
);
|
|
35
|
-
} else if ((tau.length > 1) && (rho.length === 1)) {
|
|
36
|
-
return (
|
|
37
|
-
transformOperations(tau1, rho).concat(
|
|
38
|
-
transformOperations(
|
|
39
|
-
tau2,
|
|
40
|
-
transformOperations(rho, tau1)
|
|
41
|
-
)
|
|
42
|
-
)
|
|
43
|
-
);
|
|
44
|
-
} else if ((tau.length === 1) && (rho.length > 1)) {
|
|
45
|
-
return (
|
|
46
|
-
transformOperations(
|
|
47
|
-
transformOperations(tau, rho1),
|
|
48
|
-
rho2
|
|
49
|
-
)
|
|
50
|
-
);
|
|
51
|
-
} else {
|
|
52
|
-
tau = first(tau); ///
|
|
53
|
-
rho = first(rho); ///
|
|
54
|
-
|
|
55
|
-
return rho.transformOperation(tau);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
export default function transformSelection(selection, operations) {
|
|
4
|
-
operations.forEach((operation) => {
|
|
5
|
-
const transformedSelection = operation.transformSelection(selection);
|
|
6
|
-
|
|
7
|
-
selection = transformedSelection; ///
|
|
8
|
-
})
|
|
9
|
-
|
|
10
|
-
return selection;
|
|
11
|
-
}
|
package/src/types.js
DELETED
package/src/undoBuffer.js
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { arrayUtilities } from "necessary";
|
|
4
|
-
|
|
5
|
-
import EmptyOperation from "./operation/empty";
|
|
6
|
-
import InsertOperation from "./operation/insert";
|
|
7
|
-
import DeleteOperation from "./operation/delete";
|
|
8
|
-
import transformOperations from "./transform/operations";
|
|
9
|
-
|
|
10
|
-
const { clear, filter, unshift } = arrayUtilities;
|
|
11
|
-
|
|
12
|
-
export default class UndoBuffer {
|
|
13
|
-
constructor(undoOperations, redoOperations) {
|
|
14
|
-
this.undoOperations = undoOperations;
|
|
15
|
-
this.redoOperations = redoOperations;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
getUndoOperations() {
|
|
19
|
-
return this.undoOperations;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
getRedoOperations() {
|
|
23
|
-
return this.redoOperations;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
undo() {
|
|
27
|
-
let undoOperation = null;
|
|
28
|
-
|
|
29
|
-
const undoOperationsLength = this.undoOperations.length;
|
|
30
|
-
|
|
31
|
-
if (undoOperationsLength > 0) {
|
|
32
|
-
undoOperation = this.undoOperations.shift();
|
|
33
|
-
|
|
34
|
-
const invertedUndoOperation = undoOperation.invert(InsertOperation, DeleteOperation),
|
|
35
|
-
redoOperation = invertedUndoOperation; ///
|
|
36
|
-
|
|
37
|
-
this.redoOperations.unshift(redoOperation);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return undoOperation;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
redo() {
|
|
44
|
-
let redoOperation = null;
|
|
45
|
-
|
|
46
|
-
const redoOperationsLength = this.redoOperations.length;
|
|
47
|
-
|
|
48
|
-
if (redoOperationsLength > 0) {
|
|
49
|
-
redoOperation = this.redoOperations.shift();
|
|
50
|
-
|
|
51
|
-
const invertedRedoOperation = redoOperation.invert(InsertOperation, DeleteOperation),
|
|
52
|
-
undoOperation = invertedRedoOperation; ///
|
|
53
|
-
|
|
54
|
-
this.undoOperations.unshift(undoOperation);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return redoOperation;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
transform(operations) {
|
|
61
|
-
this.undoOperations = transformOperations(this.undoOperations, operations);
|
|
62
|
-
|
|
63
|
-
this.redoOperations = transformOperations(this.redoOperations, operations);
|
|
64
|
-
|
|
65
|
-
filterEmptyOperations(this.undoOperations);
|
|
66
|
-
|
|
67
|
-
filterEmptyOperations(this.redoOperations);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
addOperations(operations) {
|
|
71
|
-
const invertedOperations = invertOperations(operations),
|
|
72
|
-
reversedInvertedOperations = reverseOperations(invertedOperations),
|
|
73
|
-
undoOperations = reversedInvertedOperations; ///
|
|
74
|
-
|
|
75
|
-
unshift(this.undoOperations, undoOperations);
|
|
76
|
-
|
|
77
|
-
clear(this.redoOperations);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
static fromNothing() {
|
|
81
|
-
const undoOperations = [],
|
|
82
|
-
redoOperations = [],
|
|
83
|
-
undoBuffer = new UndoBuffer(undoOperations, redoOperations);
|
|
84
|
-
|
|
85
|
-
return undoBuffer;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function invertOperations(operations) {
|
|
90
|
-
const invertedOperations = operations.map((operation) => {
|
|
91
|
-
const invertedOperation = operation.invert(InsertOperation, DeleteOperation);
|
|
92
|
-
|
|
93
|
-
return invertedOperation;
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
return invertedOperations;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function reverseOperations(operations) {
|
|
100
|
-
const reversedOperations = operations.reduce((reversedOperations, operation) => {
|
|
101
|
-
const reversedOperation = operation; ///
|
|
102
|
-
|
|
103
|
-
reversedOperations.unshift(reversedOperation);
|
|
104
|
-
|
|
105
|
-
return reversedOperations;
|
|
106
|
-
}, []);
|
|
107
|
-
|
|
108
|
-
return reversedOperations;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function filterEmptyOperations(operations) {
|
|
112
|
-
filter(operations, (operation) => {
|
|
113
|
-
const operationEmptyOperation = (operation instanceof EmptyOperation);
|
|
114
|
-
|
|
115
|
-
if (!operationEmptyOperation) {
|
|
116
|
-
return true;
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const { assert } = require("chai"),
|
|
4
|
-
{ DeleteOperation, InsertOperation, transformContent, generateOperations } = require("../../lib/browser"); ///
|
|
5
|
-
|
|
6
|
-
describe("transformContent", () => {
|
|
7
|
-
describe("the array of operations is of zero length", () => {
|
|
8
|
-
it("leaves the content unchanged", () => {
|
|
9
|
-
const content = "jik8h",
|
|
10
|
-
operations = [],
|
|
11
|
-
transformedContent = transformContent(content, operations),
|
|
12
|
-
expectedContent = content; ///
|
|
13
|
-
|
|
14
|
-
assert.equal(transformedContent, expectedContent);
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
describe("the array of operations is contains a single delete operation", () => {
|
|
19
|
-
it("deletes the requisite characters", () => {
|
|
20
|
-
const content = "jhUngfrcD",
|
|
21
|
-
deleteOperation = DeleteOperation.fromContentAndPosition("ngfr", 3),
|
|
22
|
-
operations = [
|
|
23
|
-
deleteOperation
|
|
24
|
-
],
|
|
25
|
-
transformedContent = transformContent(content, operations),
|
|
26
|
-
expectedContent = "jhUcD";
|
|
27
|
-
|
|
28
|
-
assert.equal(transformedContent, expectedContent);
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
describe("the array of operations is contains a single insert operation", () => {
|
|
33
|
-
it("inserts the requisite characters", () => {
|
|
34
|
-
const content = "jubfEDf",
|
|
35
|
-
insertOperation = InsertOperation.fromContentAndPosition("avTgd", 2),
|
|
36
|
-
operations = [
|
|
37
|
-
insertOperation
|
|
38
|
-
],
|
|
39
|
-
transformedContent = transformContent(content, operations),
|
|
40
|
-
expectedContent = "juavTgdbfEDf";
|
|
41
|
-
|
|
42
|
-
assert.equal(transformedContent, expectedContent);
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
describe("the array of operations is generated", () => {
|
|
47
|
-
it("returns the result of applying those operations", () => {
|
|
48
|
-
const contentA = "8hUjy",
|
|
49
|
-
contentB = "ABV8hUjykmj",
|
|
50
|
-
operations = generateOperations(contentA, contentB),
|
|
51
|
-
transformedContentA = transformContent(contentA, operations),
|
|
52
|
-
expectedContent = contentB; ///
|
|
53
|
-
|
|
54
|
-
assert.equal(transformedContentA, expectedContent);
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
});
|
package/test/helpers.js
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const randomSeed = require("random-seed");
|
|
4
|
-
|
|
5
|
-
const { EmptyOperation, InsertOperation, DeleteOperation } = require("../lib/browser"); ///
|
|
6
|
-
|
|
7
|
-
const DEFAULT_CONTENT_LENGTH = 4,
|
|
8
|
-
DEFAULT_NUMBER_OF_OPERATIONS = 2,
|
|
9
|
-
MAXIMUM_INSERT_OPERATION_LENGTH = 4;
|
|
10
|
-
|
|
11
|
-
const random = randomSeed.create(".");
|
|
12
|
-
|
|
13
|
-
function content(length = DEFAULT_CONTENT_LENGTH) {
|
|
14
|
-
const content = generateContent(length);
|
|
15
|
-
|
|
16
|
-
return content;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function operations(content, numberOfOperations = DEFAULT_NUMBER_OF_OPERATIONS) {
|
|
20
|
-
const operations = [];
|
|
21
|
-
|
|
22
|
-
for (let i = 0; i < numberOfOperations; i++) {
|
|
23
|
-
const operation = generateOperation(content);
|
|
24
|
-
|
|
25
|
-
operations.push(operation);
|
|
26
|
-
|
|
27
|
-
content = operation.transformContent(content);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return operations;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
module.exports = {
|
|
34
|
-
content,
|
|
35
|
-
operations
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
function generateContent(length) {
|
|
39
|
-
let content = "";
|
|
40
|
-
|
|
41
|
-
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
42
|
-
|
|
43
|
-
for (let index = 0; index < length; index++) {
|
|
44
|
-
content += characters.charAt(random(characters.length));
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return content;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function generateOperation(content) {
|
|
51
|
-
if (content === "") {
|
|
52
|
-
return [
|
|
53
|
-
generateEmptyOperation,
|
|
54
|
-
generateInsertOperation
|
|
55
|
-
][random(2)](content);
|
|
56
|
-
} else {
|
|
57
|
-
return [
|
|
58
|
-
generateEmptyOperation,
|
|
59
|
-
generateInsertOperation,
|
|
60
|
-
generateDeleteOperation
|
|
61
|
-
][random(3)](content);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function generateEmptyOperation(content) {
|
|
66
|
-
return EmptyOperation.fromNothing();
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function generateInsertOperation(content) {
|
|
70
|
-
const contentLength = content.length,
|
|
71
|
-
position = random(contentLength + 1);
|
|
72
|
-
|
|
73
|
-
content = generateContent(MAXIMUM_INSERT_OPERATION_LENGTH); ///
|
|
74
|
-
|
|
75
|
-
return InsertOperation.fromContentAndPosition(content, position);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function generateDeleteOperation(content) {
|
|
79
|
-
let contentLength = content.length;
|
|
80
|
-
|
|
81
|
-
const position = random(contentLength);
|
|
82
|
-
|
|
83
|
-
contentLength = random(contentLength - position) + 1;
|
|
84
|
-
|
|
85
|
-
const start = position,
|
|
86
|
-
end = start + contentLength;
|
|
87
|
-
|
|
88
|
-
content = content.substring(start, end);
|
|
89
|
-
|
|
90
|
-
return DeleteOperation.fromContentAndPosition(content, position);
|
|
91
|
-
}
|