easy-richtextarea 4.0.3 → 4.0.5

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.
Files changed (52) hide show
  1. package/README.md +0 -8
  2. package/example.js +1535 -1039
  3. package/lib/browser.js +9 -5
  4. package/lib/constants.js +13 -4
  5. package/lib/contentCompare.js +34 -0
  6. package/lib/example/richTextarea.js +2 -2
  7. package/lib/example/view.js +18 -9
  8. package/lib/keyCodes.js +13 -0
  9. package/lib/main.js +9 -5
  10. package/lib/operation/delete.js +101 -52
  11. package/lib/operation/empty.js +21 -6
  12. package/lib/operation/insert.js +78 -31
  13. package/lib/operations/fromJSON.js +4 -4
  14. package/lib/operations/generate.js +3 -3
  15. package/lib/richTextarea.js +258 -153
  16. package/lib/selection.js +55 -13
  17. package/lib/transform/content.js +19 -0
  18. package/lib/{operations/transform.js → transform/operations.js} +3 -7
  19. package/lib/transform/selection.js +19 -0
  20. package/lib/types.js +13 -13
  21. package/lib/undoBuffer.js +140 -0
  22. package/package.json +3 -2
  23. package/src/browser.js +3 -3
  24. package/src/constants.js +1 -0
  25. package/src/contentCompare.js +34 -0
  26. package/src/example/richTextarea.js +11 -9
  27. package/src/example/view.js +28 -10
  28. package/src/keyCodes.js +3 -0
  29. package/src/main.js +3 -2
  30. package/src/operation/delete.js +135 -58
  31. package/src/operation/empty.js +19 -14
  32. package/src/operation/insert.js +97 -39
  33. package/src/operations/fromJSON.js +4 -4
  34. package/src/operations/generate.js +8 -4
  35. package/src/richTextarea.js +343 -181
  36. package/src/selection.js +53 -9
  37. package/src/transform/content.js +11 -0
  38. package/src/{operations/transform.js → transform/operations.js} +3 -3
  39. package/src/transform/selection.js +11 -0
  40. package/src/types.js +6 -6
  41. package/src/undoBuffer.js +105 -0
  42. package/test/content/transform.js +9 -11
  43. package/test/helpers.js +27 -21
  44. package/test/operation/delete.js +187 -147
  45. package/test/operation/empty.js +3 -5
  46. package/test/operation/insert.js +134 -118
  47. package/test/operations/generate.js +19 -22
  48. package/test/operations/transform.js +37 -98
  49. package/lib/content/transform.js +0 -17
  50. package/lib/stringCompare.js +0 -33
  51. package/src/content/transform.js +0 -5
  52. package/src/stringCompare.js +0 -33
package/src/selection.js CHANGED
@@ -14,12 +14,10 @@ export default class Selection {
14
14
  return this.endPosition;
15
15
  }
16
16
 
17
- setStartPosition(startPosition) {
18
- this.startPosition = startPosition;
19
- }
17
+ isEmpty() {
18
+ const empty = (this.startPosition === this.endPosition);
20
19
 
21
- setEndPosition(endPosition) {
22
- this.endPosition = endPosition;
20
+ return empty;
23
21
  }
24
22
 
25
23
  isEqualTo(selection) {
@@ -37,11 +35,50 @@ export default class Selection {
37
35
  return equalTo;
38
36
  }
39
37
 
40
- isDifferentTo(selection) {
41
- const equalTo = this.isEqualTo(selection),
42
- differentTo = !equalTo;
38
+ setStartPosition(startPosition) {
39
+ this.startPosition = startPosition;
40
+ }
41
+
42
+ setEndPosition(endPosition) {
43
+ this.endPosition = endPosition;
44
+ }
45
+
46
+ startPositionShifted(startOffset) {
47
+ const startPosition = this.startPosition + startOffset,
48
+ endPosition = this.endPosition,
49
+ selection = new Selection(startPosition, endPosition);
50
+
51
+ return selection;
52
+ }
53
+
54
+ endPositionShifted(endOffset) {
55
+ const startPosition = this.startPosition,
56
+ endPosition = this.endPosition + endOffset,
57
+ selection = new Selection(startPosition, endPosition);
43
58
 
44
- return differentTo;
59
+ return selection;
60
+ }
61
+
62
+ shifted(offset) {
63
+ const startPosition = this.startPosition + offset,
64
+ endPosition = this.endPosition + offset,
65
+ selection = new Selection(startPosition, endPosition);
66
+
67
+ return selection;
68
+ }
69
+
70
+ emptied() {
71
+ const startPosition = this.startPosition,
72
+ endPosition = startPosition, ///
73
+ selection = new Selection(startPosition, endPosition);
74
+
75
+ return selection;
76
+ }
77
+
78
+ clone() {
79
+ const selection = new Selection(this.startPosition, this.endPosition);
80
+
81
+ return selection;
45
82
  }
46
83
 
47
84
  static fromNothing() {
@@ -62,6 +99,13 @@ export default class Selection {
62
99
 
63
100
  }
64
101
 
102
+ static fromStartPosition(startPosition) {
103
+ const endPosition = startPosition, ///
104
+ selection = new Selection(startPosition, endPosition);
105
+
106
+ return selection;
107
+ }
108
+
65
109
  static fromStartPositionAndEndPosition(startPosition, endPosition) {
66
110
  const selection = new Selection(startPosition, endPosition);
67
111
 
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+
3
+ export default function transformContent(content, operations) {
4
+ operations.forEach((operation) => {
5
+ const transformedContent = operation.transformContent(content);
6
+
7
+ content = transformedContent; ///
8
+ })
9
+
10
+ return content;
11
+ }
@@ -2,16 +2,16 @@
2
2
 
3
3
  import { arrayUtilities } from "necessary";
4
4
 
5
- const { first, tail } = arrayUtilities;
5
+ const { first, head, tail } = arrayUtilities;
6
6
 
7
7
  export default function transformOperations(tau, rho) {
8
8
  if ((tau.length === 0) || (rho.length === 0)) {
9
9
  return tau;
10
10
  }
11
11
 
12
- const tau1 = [first(tau)],
12
+ const tau1 = head(tau),
13
13
  tau2 = tail(tau),
14
- rho1 = [first(rho)],
14
+ rho1 = head(rho),
15
15
  rho2 = tail(rho);
16
16
 
17
17
  if (tau.length > 1 && rho.length > 1) {
@@ -0,0 +1,11 @@
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 CHANGED
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
 
3
- export const emptyType = "empty";
4
- export const deleteType = "delete";
5
- export const insertType = "insert";
3
+ export const EMPTY_TYPE = "empty";
4
+ export const DELETE_TYPE = "delete";
5
+ export const INSERT_TYPE = "insert";
6
6
 
7
7
  export default {
8
- emptyType,
9
- deleteType,
10
- insertType
8
+ EMPTY_TYPE,
9
+ DELETE_TYPE,
10
+ INSERT_TYPE
11
11
  };
@@ -0,0 +1,105 @@
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 { push } = arrayUtilities;
11
+
12
+ export default class UndoBuffer {
13
+ constructor(position, operations) {
14
+ this.position = position;
15
+ this.operations = operations;
16
+ }
17
+
18
+ getPosition() {
19
+ return this.position;
20
+ }
21
+
22
+ getOperations() {
23
+ return this.operations;
24
+ }
25
+
26
+ undo() {
27
+ let operation = null;
28
+
29
+ if (this.position > 0) {
30
+ this.position--;
31
+
32
+ operation = this.operations[this.position];
33
+
34
+ const invertedOperation = operation.invert(InsertOperation, DeleteOperation);
35
+
36
+ operation = invertedOperation; ///
37
+ }
38
+
39
+ return operation;
40
+ }
41
+
42
+ redo() {
43
+ let operation = null;
44
+
45
+ const operationsLength = this.operations.length;
46
+
47
+ if (this.position < operationsLength) {
48
+ operation = this.operations[this.position];
49
+
50
+ this.position++;
51
+ }
52
+
53
+ return operation;
54
+ }
55
+
56
+ transform(operations) {
57
+ this.operations = transformOperations(this.operations, operations);
58
+
59
+ this.filterEmptyOperations();
60
+ }
61
+
62
+ addOperations(operations) {
63
+ const start = this.position; ///
64
+
65
+ this.operations.splice(start);
66
+
67
+ push(this.operations, operations);
68
+
69
+ const operationsLength = this.operations.length;
70
+
71
+ this.position = operationsLength; ///
72
+ }
73
+
74
+ filterEmptyOperations() {
75
+ let length = this.operations.length,
76
+ position = 0;
77
+
78
+ while (position < length) {
79
+ const operation = this.operations[position];
80
+
81
+ if (operation instanceof EmptyOperation) {
82
+ const start = position, ///
83
+ deleteCount = 1;
84
+
85
+ this.operations.splice(start, deleteCount);
86
+
87
+ if (this.position > position) {
88
+ this.position--;
89
+ }
90
+ } else {
91
+ position++;
92
+ }
93
+
94
+ length = this.operations.length;
95
+ }
96
+ }
97
+
98
+ static fromNothing() {
99
+ const position = 0,
100
+ operations = [],
101
+ undoBuffer = new UndoBuffer(position, operations);
102
+
103
+ return undoBuffer;
104
+ }
105
+ }
@@ -3,12 +3,10 @@
3
3
  const { assert } = require("chai"),
4
4
  { DeleteOperation, InsertOperation, transformContent, generateOperations } = require("../../lib/main"); ///
5
5
 
6
- const helpers = require("../helpers");
7
-
8
6
  describe("transformContent", () => {
9
7
  describe("the array of operations is of zero length", () => {
10
8
  it("leaves the content unchanged", () => {
11
- const content = helpers.content(),
9
+ const content = "jik8h",
12
10
  operations = [],
13
11
  transformedContent = transformContent(content, operations),
14
12
  expectedContent = content; ///
@@ -19,13 +17,13 @@ describe("transformContent", () => {
19
17
 
20
18
  describe("the array of operations is contains a single delete operation", () => {
21
19
  it("deletes the requisite characters", () => {
22
- const content = helpers.content(),
23
- deleteOperation = DeleteOperation.fromLengthAndPosition(2, 0),
20
+ const content = "jhUngfrcD",
21
+ deleteOperation = DeleteOperation.fromContentAndPosition("ngfr", 3),
24
22
  operations = [
25
23
  deleteOperation
26
24
  ],
27
25
  transformedContent = transformContent(content, operations),
28
- expectedContent = content.substring(2);
26
+ expectedContent = "jhUcD";
29
27
 
30
28
  assert.equal(transformedContent, expectedContent);
31
29
  });
@@ -33,13 +31,13 @@ describe("transformContent", () => {
33
31
 
34
32
  describe("the array of operations is contains a single insert operation", () => {
35
33
  it("inserts the requisite characters", () => {
36
- const content = helpers.content(),
37
- insertOperation = InsertOperation.fromStringAndPosition("xyz", 0),
34
+ const content = "jubfEDf",
35
+ insertOperation = InsertOperation.fromContentAndPosition("avTgd", 2),
38
36
  operations = [
39
37
  insertOperation
40
38
  ],
41
39
  transformedContent = transformContent(content, operations),
42
- expectedContent = `xyz${content}`;
40
+ expectedContent = "juavTgdbfEDf";
43
41
 
44
42
  assert.equal(transformedContent, expectedContent);
45
43
  });
@@ -47,8 +45,8 @@ describe("transformContent", () => {
47
45
 
48
46
  describe("the array of operations is generated", () => {
49
47
  it("returns the result of applying those operations", () => {
50
- const contentA = helpers.content(),
51
- contentB = helpers.content(),
48
+ const contentA = "8hUjy",
49
+ contentB = "ABV8hUjykmj",
52
50
  operations = generateOperations(contentA, contentB),
53
51
  transformedContentA = transformContent(contentA, operations),
54
52
  expectedContent = contentB; ///
package/test/helpers.js CHANGED
@@ -11,8 +11,7 @@ const DEFAULT_CONTENT_LENGTH = 4,
11
11
  const random = randomSeed.create(".");
12
12
 
13
13
  function content(length = DEFAULT_CONTENT_LENGTH) {
14
- const string = generateString(length),
15
- content = string; ///
14
+ const content = generateContent(length);
16
15
 
17
16
  return content;
18
17
  }
@@ -36,50 +35,57 @@ module.exports = {
36
35
  operations
37
36
  };
38
37
 
39
- function generateString(length) {
40
- let string = "";
38
+ function generateContent(length) {
39
+ let content = "";
41
40
 
42
41
  const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
43
42
 
44
43
  for (let index = 0; index < length; index++) {
45
- string += characters.charAt(random(characters.length));
44
+ content += characters.charAt(random(characters.length));
46
45
  }
47
46
 
48
- return string;
47
+ return content;
49
48
  }
50
49
 
51
- function generateOperation(string) {
52
- if (string === "") {
50
+ function generateOperation(content) {
51
+ if (content === "") {
53
52
  return [
54
53
  generateEmptyOperation,
55
54
  generateInsertOperation
56
- ][random(2)](string);
55
+ ][random(2)](content);
57
56
  } else {
58
57
  return [
59
58
  generateEmptyOperation,
60
59
  generateInsertOperation,
61
60
  generateDeleteOperation
62
- ][random(3)](string);
61
+ ][random(3)](content);
63
62
  }
64
63
  }
65
64
 
66
- function generateEmptyOperation(string) {
65
+ function generateEmptyOperation(content) {
67
66
  return EmptyOperation.fromNothing();
68
67
  }
69
68
 
70
- function generateInsertOperation(string) {
71
- const stringLength = string.length,
72
- position = random(stringLength + 1);
69
+ function generateInsertOperation(content) {
70
+ const contentLength = content.length,
71
+ position = random(contentLength + 1);
73
72
 
74
- string = generateString(MAXIMUM_INSERT_OPERATION_LENGTH); ///
73
+ content = generateContent(MAXIMUM_INSERT_OPERATION_LENGTH); ///
75
74
 
76
- return InsertOperation.fromStringAndPosition(string, position);
75
+ return InsertOperation.fromContentAndPosition(content, position);
77
76
  }
78
77
 
79
- function generateDeleteOperation(string) {
80
- const stringLength = string.length,
81
- position = random(stringLength),
82
- length = random(stringLength - position) + 1;
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);
83
89
 
84
- return DeleteOperation.fromLengthAndPosition(length, position);
90
+ return DeleteOperation.fromContentAndPosition(content, position);
85
91
  }