timepiece/node_modules/replacestream/index.js

142 lines
3.5 KiB
JavaScript
Raw Normal View History

2024-05-14 14:54:12 +00:00
'use strict';
var escapeRegExp = require('escape-string-regexp');
var objectAssign = require('object-assign');
var Transform = require('readable-stream/transform');
module.exports = function ReplaceStream(search, replace, options) {
var tail = '';
var totalMatches = 0;
var isRegex = search instanceof RegExp;
options = objectAssign({
limit: Infinity,
encoding: 'utf8',
maxMatchLen: 100
}, options);
var replaceFn = replace;
replaceFn = createReplaceFn(replace, isRegex);
var match;
if (isRegex) {
match = matchFromRegex(search, options)
} else {
match = matchFromString(search, options);
options.maxMatchLen = search.length;
}
function transform(buf, enc, cb) {
var matches;
var lastPos = 0;
var runningMatch = '';
var matchCount = 0;
var rewritten = '';
var haystack = tail + buf.toString(options.encoding);
tail = '';
while (totalMatches < options.limit &&
(matches = match.exec(haystack)) !== null) {
matchCount++;
var before = haystack.slice(lastPos, matches.index);
var regexMatch = matches;
lastPos = matches.index + regexMatch[0].length;
if (lastPos > haystack.length && regexMatch[0].length < options.maxMatchLen) {
tail = regexMatch[0]
} else {
var dataToAppend = getDataToAppend(before,regexMatch);
rewritten += dataToAppend;
}
}
if (tail.length < 1)
tail = haystack.slice(lastPos).length > options.maxMatchLen ? haystack.slice(lastPos).slice(0 - options.maxMatchLen) : haystack.slice(lastPos)
var dataToQueue = getDataToQueue(matchCount,haystack,rewritten,lastPos);
cb(null, dataToQueue);
}
function getDataToAppend(before, match) {
var dataToAppend = before;
totalMatches++;
dataToAppend += isRegex ? replaceFn.apply(this, match.concat([match.index, match.input])) : replaceFn(match[0]);
return dataToAppend;
}
function getDataToQueue(matchCount, haystack, rewritten, lastPos) {
if (matchCount > 0) {
if (haystack.length > tail.length) {
return rewritten + haystack.slice(lastPos, haystack.length - tail.length);
}
return rewritten;
}
return haystack.slice(0, haystack.length - tail.length);
}
function flush(cb) {
if (tail) {
this.push(tail);
}
cb();
}
return new Transform({
transform: transform,
flush: flush
});
};
function createReplaceFn(replace, isRegEx) {
var regexReplaceFunction = function () {
var newReplace = replace;
// ability to us $1 with captures
// Start at 1 and end at length - 2 to avoid the match parameter and offset
// And string parameters
var paramLength = arguments.length - 2;
for (var i = 1; i < paramLength; i++) {
newReplace = newReplace.replace(new RegExp('\\$' + i, 'g'), arguments[i] || '')
}
return newReplace;
};
if (isRegEx && !(replace instanceof Function)) {
return regexReplaceFunction;
}
if (!(replace instanceof Function)) {
return function stringReplaceFunction() {
return replace;
};
}
return replace;
}
function matchFromRegex(regex, options) {
if (options.regExpOptions) {
regex = new RegExp(regex.source, options.regExpOptions)
}
// If there is no global flag then there can only be one match
if (!regex.global) {
options.limit = 1;
}
return regex;
}
function matchFromString(s, options) {
if (options.regExpOptions) {
return new RegExp(escapeRegExp(s), options.regExpOptions);
}
return new RegExp(escapeRegExp(s), options.ignoreCase === false ? 'gm' : 'gmi');
}