47 lines
1.1 KiB
JavaScript
47 lines
1.1 KiB
JavaScript
|
'use strict';
|
||
|
module.exports = (input, needle, replacement, opts) => {
|
||
|
opts = Object.assign({}, opts);
|
||
|
|
||
|
if (typeof input !== 'string') {
|
||
|
throw new TypeError(`Expected input to be a string, got ${typeof input}`);
|
||
|
}
|
||
|
|
||
|
if (!(typeof needle === 'string' && needle.length > 0) ||
|
||
|
!(typeof replacement === 'string' || typeof replacement === 'function')) {
|
||
|
return input;
|
||
|
}
|
||
|
|
||
|
let ret = '';
|
||
|
let matchCount = 0;
|
||
|
let prevIndex = opts.fromIndex > 0 ? opts.fromIndex : 0;
|
||
|
|
||
|
if (prevIndex > input.length) {
|
||
|
return input;
|
||
|
}
|
||
|
|
||
|
while (true) { // eslint-disable-line no-constant-condition
|
||
|
const index = input.indexOf(needle, prevIndex);
|
||
|
|
||
|
if (index === -1) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
matchCount++;
|
||
|
|
||
|
const replaceStr = typeof replacement === 'string' ? replacement : replacement(needle, matchCount, input);
|
||
|
|
||
|
// Get the initial part of the string on the first iteration
|
||
|
const beginSlice = matchCount === 1 ? 0 : prevIndex;
|
||
|
|
||
|
ret += input.slice(beginSlice, index) + replaceStr;
|
||
|
|
||
|
prevIndex = index + needle.length;
|
||
|
}
|
||
|
|
||
|
if (matchCount === 0) {
|
||
|
return input;
|
||
|
}
|
||
|
|
||
|
return ret + input.slice(prevIndex);
|
||
|
};
|