edit_operation.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // @ts-check
  2. /**
  3. * @typedef {import('../file_data')} FileData
  4. * @typedef {import('../types').RawEditOperation} RawEditOperation
  5. */
  6. class EditOperation {
  7. constructor() {
  8. if (this.constructor === EditOperation) {
  9. throw new Error('Cannot instantiate abstract class')
  10. }
  11. }
  12. /**
  13. * Converts operation into a JSON value.
  14. * @returns {RawEditOperation}
  15. */
  16. toJSON() {
  17. throw new Error('Abstract method not implemented')
  18. }
  19. /**
  20. * @abstract
  21. * @param {FileData} fileData
  22. */
  23. apply(fileData) {
  24. throw new Error('Abstract method not implemented')
  25. }
  26. /**
  27. * Determine the effect of this operation on the length of the text.
  28. *
  29. * NB: This is an Overleaf addition to the original OT system.
  30. *
  31. * @param {number} length of the original string; non-negative
  32. * @return {number} length of the new string; non-negative
  33. */
  34. applyToLength(length) {
  35. return length
  36. }
  37. /**
  38. * Computes the inverse of an operation. The inverse of an operation is the
  39. * operation that reverts the effects of the operation, e.g. when you have an
  40. * operation 'insert("hello "); skip(6);' then the inverse is 'remove("hello ");
  41. * skip(6);'. The inverse should be used for implementing undo.
  42. * @param {FileData} previousState
  43. * @returns {EditOperation}
  44. */
  45. invert(previousState) {
  46. throw new Error('Abstract method not implemented')
  47. }
  48. /**
  49. *
  50. * @param {EditOperation} other
  51. * @returns {boolean}
  52. */
  53. canBeComposedWith(other) {
  54. return false
  55. }
  56. /**
  57. * When you use ctrl-z to undo your latest changes, you expect the program not
  58. * to undo every single keystroke but to undo your last sentence you wrote at
  59. * a stretch or the deletion you did by holding the backspace key down. This
  60. * This can be implemented by composing operations on the undo stack. This
  61. * method can help decide whether two operations should be composed. It
  62. * returns true if the operations are consecutive insert operations or both
  63. * operations delete text at the same position. You may want to include other
  64. * factors like the time since the last change in your decision.
  65. * @param {EditOperation} other
  66. */
  67. canBeComposedWithForUndo(other) {
  68. return false
  69. }
  70. /**
  71. * Compose merges two consecutive operations into one operation, that
  72. * preserves the changes of both. Or, in other words, for each input string S
  73. * and a pair of consecutive operations A and B,
  74. * apply(apply(S, A), B) = apply(S, compose(A, B)) must hold.
  75. * @param {EditOperation} other
  76. * @returns {EditOperation}
  77. */
  78. compose(other) {
  79. throw new Error('Abstract method not implemented')
  80. }
  81. }
  82. module.exports = EditOperation