nak
Version:
ack and ag inspired tool written in Node. Designed to be fast.
125 lines (107 loc) • 3.07 kB
JavaScript
function PathFilter(inclusions, exclusions, showHidden) {
if (!Array.isArray(inclusions)) {
this.inclusionRe = inclusions || /^/;
this.exclusionRe = exclusions || /^/;
return;
}
var pos = [], neg = [];
if (showHidden !== true)
neg.push(".*");
var hasDirectoryMatcher = false;
var hasFileMatcher = false;
inclusions.forEach(function(p) {
p = p.trim(); // TODO this isn't gitignore compatible
if (!p || p[0] === "#")
return;
if (/\/\*?$/.test(p) || !/[.*]/.test(p)) {
hasDirectoryMatcher = true;
p = p.replace(/\/\*?$/, "");
pos.push(p, p + "/*");
} else {
hasFileMatcher = true;
pos.push(p);
}
});
if (pos.length) {
if (!hasDirectoryMatcher)
pos.push("/");
}
exclusions.forEach(function(p) {
p = p.trim();
if (!p || p[0] === "#")
return;
neg.push(p);
});
var inc = this.createMatcherRe(pos);
var exc = this.createMatcherRe(neg);
if (!inc && !exc) {
this.isPathAccepted = function(filepath) { return true; };
} if (!inc && exc && !exc.hasNegative) {
var re = exc.re;
this.isPathAccepted = function(filepath) {
return !re.test(filepath);
};
} else if (!inc && exc && exc.hasNegative) {
var re1 = exc.re;
this.isPathAccepted = function(filepath) {
var m = re1.exec(filepath);
return !(m && m[0]);
};
} else if (inc && exc) {
var excRe = exc.re, incRe = inc.re;
this.isPathAccepted = function(filepath) {
var m = excRe.exec(filepath);
if (m && m[0]) return false;
m = incRe.exec(filepath);
return !!(m && m[0]);
};
}
this.inclusionRe = inc && inc.re || /^/;
this.exclusionRe = exc && exc.re || /^/;
}
PathFilter.prototype.isPathAccepted = function(filepath) {
return !this.exclusionRe.test(filepath) || this.inclusionRe.test(filepath);
};
PathFilter.prototype.createMatcherRe = function(patterns) {
var source = "";
var hasNegative = false;
source = patterns.map(function(p) {
var contents = p;
var isNegated = p[0] === "!";
if (isNegated) {
contents = contents.slice(1);
hasNegative = true;
}
var reg = contents.replace(/(\\.)|(\*{1,2})|(\+)|([\/'*+?|()\[\]{}.\^$])/g, function(_, esc, star, plus, reg) {
if (esc)
return esc[1];
if (plus)
return ".+";
if (star)
return star[1] ? ".*?" : "[^\\/]*";
if (reg)
return "\\" + reg;
});
if (reg[1] !== "/")
reg = "\\/" + reg;
if (reg[reg.length - 1] === "\\")
reg = reg.slice(0, -1);
else if (reg[reg.length - 1] !== "/")
reg += "\\/?";
if (isNegated)
reg = "(?=" + reg + "$)";
else
reg = "(?:" + reg + "$)";
return reg;
}).filter(Boolean).join("|");
if (!source)
return;
return {
re: new RegExp(source, ""),
hasNegative: hasNegative
};
};
PathFilter.escapeRegExp = function(str) {
return str.replace(/([\/'*+?|()\[\]{}.\^$])/g, '\\$1');
};
module.exports = PathFilter;