Files
whistle/lib/util/replace-pattern-transform.js
2018-10-19 19:34:28 +08:00

66 lines
1.8 KiB
JavaScript

var Transform = require('pipestream').Transform;
var util = require('util');
var LENGTH = 5120;
var slice = [].slice;
var SUB_MATCH_RE = /(^|..?)?(\$[&\d])/g;
function ReplacePatternTransform(pattern, value) {
Transform.call(this);
this._pattern = pattern;
this._value = value == null ? '' : value + '';
this._rest = '';
}
util.inherits(ReplacePatternTransform, Transform);
var proto = ReplacePatternTransform.prototype;
proto._transform = function(chunk, encoding, callback) {
if (chunk != null) {
chunk = this._rest + chunk;
var index = 0;
var value = this._value;
var result = chunk.replace(this._pattern, function() {
var matcher = replacePattern(value, arguments);
var lastIndex = arguments.length - 1;
index = arguments[lastIndex - 1] + arguments[lastIndex].length;
return matcher;
});
index = Math.max(index, chunk.length + 1 - LENGTH);
this._rest = chunk.substring(index);
chunk = result.substring(0, result.length - this._rest.length);
} else if (this._rest) {
chunk = this._rest.replace(this._pattern, function() {
return replacePattern(this._value, arguments);
});
}
callback(null, chunk);
};
function getSubMatchers(args) {
args = slice.call(args);
return args.slice(0, -2);
}
function replacePattern(replacement, args) {
var arr = args.length ? getSubMatchers(args) : args;
return replacement ? replacement.replace(SUB_MATCH_RE, function(_, $1, $2) {
if ($1 === '\\\\') {
$1 = '\\';
} else {
$1 = $1 || '';
var lastChar = $1[1] || $1[0];
if (lastChar === '\\') {
return $1.slice(0, -1) + $2;
}
}
$2 = $2.substring(1);
if ($2 === '&') {
$2 = 0;
}
return $1 + (arr[$2] || '');
}) : '';
}
ReplacePatternTransform.replacePattern = replacePattern;
module.exports = ReplacePatternTransform;