You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
3.0 KiB
114 lines
3.0 KiB
'use strict'; |
|
/* |
|
Copyright 2012-2015, Yahoo Inc. |
|
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. |
|
*/ |
|
function InsertionText(text, consumeBlanks) { |
|
this.text = text; |
|
this.origLength = text.length; |
|
this.offsets = []; |
|
this.consumeBlanks = consumeBlanks; |
|
this.startPos = this.findFirstNonBlank(); |
|
this.endPos = this.findLastNonBlank(); |
|
} |
|
|
|
const WHITE_RE = /[ \f\n\r\t\v\u00A0\u2028\u2029]/; |
|
|
|
InsertionText.prototype = { |
|
findFirstNonBlank() { |
|
let pos = -1; |
|
const text = this.text; |
|
const len = text.length; |
|
let i; |
|
for (i = 0; i < len; i += 1) { |
|
if (!text.charAt(i).match(WHITE_RE)) { |
|
pos = i; |
|
break; |
|
} |
|
} |
|
return pos; |
|
}, |
|
findLastNonBlank() { |
|
const text = this.text; |
|
const len = text.length; |
|
let pos = text.length + 1; |
|
let i; |
|
for (i = len - 1; i >= 0; i -= 1) { |
|
if (!text.charAt(i).match(WHITE_RE)) { |
|
pos = i; |
|
break; |
|
} |
|
} |
|
return pos; |
|
}, |
|
originalLength() { |
|
return this.origLength; |
|
}, |
|
|
|
insertAt(col, str, insertBefore, consumeBlanks) { |
|
consumeBlanks = |
|
typeof consumeBlanks === 'undefined' |
|
? this.consumeBlanks |
|
: consumeBlanks; |
|
col = col > this.originalLength() ? this.originalLength() : col; |
|
col = col < 0 ? 0 : col; |
|
|
|
if (consumeBlanks) { |
|
if (col <= this.startPos) { |
|
col = 0; |
|
} |
|
if (col > this.endPos) { |
|
col = this.origLength; |
|
} |
|
} |
|
|
|
const len = str.length; |
|
const offset = this.findOffset(col, len, insertBefore); |
|
const realPos = col + offset; |
|
const text = this.text; |
|
this.text = text.substring(0, realPos) + str + text.substring(realPos); |
|
return this; |
|
}, |
|
|
|
findOffset(pos, len, insertBefore) { |
|
const offsets = this.offsets; |
|
let offsetObj; |
|
let cumulativeOffset = 0; |
|
let i; |
|
|
|
for (i = 0; i < offsets.length; i += 1) { |
|
offsetObj = offsets[i]; |
|
if ( |
|
offsetObj.pos < pos || |
|
(offsetObj.pos === pos && !insertBefore) |
|
) { |
|
cumulativeOffset += offsetObj.len; |
|
} |
|
if (offsetObj.pos >= pos) { |
|
break; |
|
} |
|
} |
|
if (offsetObj && offsetObj.pos === pos) { |
|
offsetObj.len += len; |
|
} else { |
|
offsets.splice(i, 0, { pos, len }); |
|
} |
|
return cumulativeOffset; |
|
}, |
|
|
|
wrap(startPos, startText, endPos, endText, consumeBlanks) { |
|
this.insertAt(startPos, startText, true, consumeBlanks); |
|
this.insertAt(endPos, endText, false, consumeBlanks); |
|
return this; |
|
}, |
|
|
|
wrapLine(startText, endText) { |
|
this.wrap(0, startText, this.originalLength(), endText); |
|
}, |
|
|
|
toString() { |
|
return this.text; |
|
} |
|
}; |
|
|
|
module.exports = InsertionText;
|
|
|