insertion-text.js 3.0 KB

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