insertion-text.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /*
  2. Copyright 2012-2015, Yahoo Inc.
  3. Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
  4. */
  5. function InsertionText(text, consumeBlanks) {
  6. this.text = text;
  7. this.origLength = text.length;
  8. this.offsets = [];
  9. this.consumeBlanks = consumeBlanks;
  10. this.startPos = this.findFirstNonBlank();
  11. this.endPos = this.findLastNonBlank();
  12. }
  13. const WHITE_RE = /[ \f\n\r\t\v\u00A0\u2028\u2029]/;
  14. InsertionText.prototype = {
  15. findFirstNonBlank() {
  16. let pos = -1;
  17. const text = this.text;
  18. const len = text.length;
  19. let i;
  20. for (i = 0; i < len; i += 1) {
  21. if (!text.charAt(i).match(WHITE_RE)) {
  22. pos = i;
  23. break;
  24. }
  25. }
  26. return pos;
  27. },
  28. findLastNonBlank() {
  29. const text = this.text;
  30. const len = text.length;
  31. let pos = text.length + 1;
  32. let i;
  33. for (i = len - 1; i >= 0; i -= 1) {
  34. if (!text.charAt(i).match(WHITE_RE)) {
  35. pos = i;
  36. break;
  37. }
  38. }
  39. return pos;
  40. },
  41. originalLength() {
  42. return this.origLength;
  43. },
  44. insertAt(col, str, insertBefore, consumeBlanks) {
  45. consumeBlanks =
  46. typeof consumeBlanks === 'undefined'
  47. ? this.consumeBlanks
  48. : consumeBlanks;
  49. col = col > this.originalLength() ? this.originalLength() : col;
  50. col = col < 0 ? 0 : col;
  51. if (consumeBlanks) {
  52. if (col <= this.startPos) {
  53. col = 0;
  54. }
  55. if (col > this.endPos) {
  56. col = this.origLength;
  57. }
  58. }
  59. const len = str.length;
  60. const offset = this.findOffset(col, len, insertBefore);
  61. const realPos = col + offset;
  62. const text = this.text;
  63. this.text = text.substring(0, realPos) + str + text.substring(realPos);
  64. return this;
  65. },
  66. findOffset(pos, len, insertBefore) {
  67. const offsets = this.offsets;
  68. let offsetObj;
  69. let cumulativeOffset = 0;
  70. let i;
  71. for (i = 0; i < offsets.length; i += 1) {
  72. offsetObj = offsets[i];
  73. if (
  74. offsetObj.pos < pos ||
  75. (offsetObj.pos === pos && !insertBefore)
  76. ) {
  77. cumulativeOffset += offsetObj.len;
  78. }
  79. if (offsetObj.pos >= pos) {
  80. break;
  81. }
  82. }
  83. if (offsetObj && offsetObj.pos === pos) {
  84. offsetObj.len += len;
  85. } else {
  86. offsets.splice(i, 0, { pos, len });
  87. }
  88. return cumulativeOffset;
  89. },
  90. wrap(startPos, startText, endPos, endText, consumeBlanks) {
  91. this.insertAt(startPos, startText, true, consumeBlanks);
  92. this.insertAt(endPos, endText, false, consumeBlanks);
  93. return this;
  94. },
  95. wrapLine(startText, endText) {
  96. this.wrap(0, startText, this.originalLength(), endText);
  97. },
  98. toString() {
  99. return this.text;
  100. }
  101. };
  102. module.exports = InsertionText;