mirror of
https://git.resf.org/sig_core/wiki.git
synced 2024-12-23 11:48:32 +00:00
6708 lines
662 KiB
JavaScript
6708 lines
662 KiB
JavaScript
|
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}(g.lunr || (g.lunr = {})).wordcut = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
|||
|
var _ = require("underscore");
|
|||
|
|
|||
|
var Acceptors = {
|
|||
|
creators: null,
|
|||
|
current: null,
|
|||
|
tag: null,
|
|||
|
|
|||
|
init: function() {
|
|||
|
this.creators = [];
|
|||
|
this.current = [];
|
|||
|
this.tag = {};
|
|||
|
},
|
|||
|
|
|||
|
reset: function() {
|
|||
|
this.current = [];
|
|||
|
this.tag = {}
|
|||
|
},
|
|||
|
|
|||
|
transit: function(ch) {
|
|||
|
var self = this;
|
|||
|
|
|||
|
self.creators.forEach(function(creator) {
|
|||
|
var acceptor = creator.createAcceptor(self.tag);
|
|||
|
if (acceptor)
|
|||
|
self.current.push(acceptor);
|
|||
|
});
|
|||
|
|
|||
|
var _current = [];
|
|||
|
self.tag = {};
|
|||
|
|
|||
|
for (var i = 0; i < self.current.length; i++) {
|
|||
|
var _acceptor = self.current[i]
|
|||
|
, acceptor = _acceptor.transit(ch);
|
|||
|
|
|||
|
if (!acceptor.isError) {
|
|||
|
_current.push(acceptor);
|
|||
|
self.tag[acceptor.tag] = acceptor;
|
|||
|
}
|
|||
|
}
|
|||
|
self.current = _current;
|
|||
|
|
|||
|
},
|
|||
|
|
|||
|
getFinalAcceptors: function() {
|
|||
|
return this.current.filter(function(acceptor) {
|
|||
|
return acceptor.isFinal;
|
|||
|
});
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
module.exports = function() {
|
|||
|
var acceptors = _.clone(Acceptors);
|
|||
|
acceptors.init();
|
|||
|
return acceptors;
|
|||
|
};
|
|||
|
|
|||
|
},{"underscore":25}],2:[function(require,module,exports){
|
|||
|
(function (__dirname){
|
|||
|
|
|||
|
var LEFT = 0;
|
|||
|
var RIGHT = 1;
|
|||
|
var path = require("path");
|
|||
|
var glob = require("glob");
|
|||
|
|
|||
|
var WordcutDict = {
|
|||
|
|
|||
|
|
|||
|
init: function (dictPathFile, withDefault, words) {
|
|||
|
withDefault = withDefault || false
|
|||
|
defaultDict = path.normalize(__dirname + "/..") + "/data/tdict-*.txt";
|
|||
|
this.dict=[]
|
|||
|
var dictPathIsDefined = dictPathFile !== undefined
|
|||
|
var dictPath = (withDefault || !dictPathIsDefined) ? [defaultDict]: [];
|
|||
|
var dictPathFile = dictPathFile || defaultDict
|
|||
|
|
|||
|
if(dictPathIsDefined){
|
|||
|
if (Array.isArray(dictPathFile)) {
|
|||
|
dictPath.concat.apply(dictPath, dictPathFile);
|
|||
|
} else {
|
|||
|
dictPath.push(dictPathFile)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
this.addFiles(dictPath, false)
|
|||
|
|
|||
|
if(words!==undefined){
|
|||
|
this.addWords(words, false)
|
|||
|
}
|
|||
|
this.finalizeDict();
|
|||
|
},
|
|||
|
|
|||
|
addWords: function(words, finalize){
|
|||
|
finalize = finalize===undefined || finalize;
|
|||
|
this.dict.push.apply(this.dict, words)
|
|||
|
if(finalize){
|
|||
|
this.finalizeDict();
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
finalizeDict: function(){
|
|||
|
this.dict = this.sortuniq(this.dict);
|
|||
|
},
|
|||
|
|
|||
|
addFiles: function(files, finalize){
|
|||
|
finalize = finalize===undefined || finalize;
|
|||
|
|
|||
|
for (var i = 0; i < 1; i++) {
|
|||
|
words = "ก.ก.\nก.ก.น.\nก.ข.ค.\nก.ค.\nก.จ.\nก.ช.น.\nก.ฌ.\nก.ต.\nก.ต.ง.\nก.ต.ช.\nก.ตร.\nก.ท.\nก.น.ช.\nก.บช.\nก.บถ.\nก.ป.ส.\nก.พ.\nก.ม.\nก.ย.\nก.ร.\nก.ล.ต.\nก.ว.\nก.ศ.ว.\nก.ส.ท.\nก.ส.ธ.\nก.ส.อ.\nก.อ.\nกก.ตชด.\nกก.ตร.น.\nกก.ภ.จว.\nกก.รสช.\nกกบ.ขส.ทบ.\nกกล.รพน.\nกง.กห.\nกง.ทบ.\nกง.ทร.\nกซข.ป.\nกซม.ป.\nกทม.กรุงเทพมหานคร\nกบ.ทบ.\nกป.สป.\nกพ.ทบ.\nกพ.ทร.\nกพ.ทหาร\nกร.ทบ.\nกรป.กลาง\nกรอ.พอ.\nกศ.ด.\nกศ.บ.\nกศ.บป.\nกศ.ม.\nกษ.ด.\nกษ.บ.\nกษ.ม.\nกส.ด.\nกส.ทบ.\nกส.บ.\nกส.ม.\nกอ.ปค.\nกอ.รพน.\nกอ.รมน.\nกอ.รสต.\nข.ต.ว.\nขว.ทบ.\nขว.ทร.\nขว.ทหาร\nขส.ทบ.\nขส.ทร.\nขส.ทอ.\nค.ด.\nค.บ.\nค.พ.ศ.\nค.ม.\nค.ร.น.\nค.ร.ฟ.\nค.ร.ม.\nค.ศ.\nค.อ.ด.\nค.อ.บ.\nค.อ.ม.\nคศ.ด.\nคศ.บ.\nคศ.ม.\nง.ด.\nจ.จ.\nจ.จ.จ.\nจ.ช.\nจ.ต.\nจ.ท.\nจ.ป.ร.\nจ.ม.\nจ.ศ.\nจ.ส.ต.\nจ.ส.ท.\nจ.ส.อ.\nจ.อ.\nจ.อ.ร.\nจ.๑๘\nจก.ธน.\nจก.สน.\nช.ค.\nช.ค.บ.\nช.พ.ค.\nช.ส.\nช.ส.ค.\nฌ.ป.ค.\nฌ.ศ.ร.\nฌ.ส.อ.\nฐท.สห.\nด.ช.\nด.ญ.\nด.ต.\nด.ศ.ค.\nด.ศ.ร.\nดย.ทร.\nต.ก.\nต.ค.\nต.จ.\nต.จ.ว.\nต.ช.\nต.ต.\nต.บ.\nต.ม.\nต.ร.\nต.ศ.ร.\nต.ห.\nต.อ.\nต.อ.จ.\nตร.กม.\nตร.ซม.\nตร.ต.\nตร.ทล.\nตร.น.\nตร.ปม.\nตร.ภ.\nตร.ม.\nตร.รฟ.\nตร.ว.\nตร.ส.\nตร.สข.\nท.จ.\nท.จ.ว.\nท.ช.\nท.ญ.\nท.ด.\nท.ท.ท.\nท.ทบ.\nท.บ.\nท.พ.\nท.ม.\nท.ศ.\nทก.ด.\nทก.บ.\nทก.ม.\nทส.ปช.\nทส.รมว.กห.\nทุ.ส.นิ.ม.\nธ.ก.ส.\nธ.ค.\nธ.ญ\nธ.บ.\nน.ช.\nน.ญ.\nน.ด.\nน.ต.\nน.ท.\nน.น.\nน.บ.\nน.บ.ท.\nน.ป.ท.\nน.พ.\nน.ม.\nน.ร.\nน.ว.\nน.ศ.\nน.ส.\nน.ส.พ.\nน.ส.๓\nน.สพ.\nน.อ.\nนปพ.ภ.\nนศ.ด.\nนศ.บ.\nนศ.ม.\nบ.ก.\nบ.ข.ส.\nบ.ช.\nบ.ด.ท.\nบ.ตร.\nบ.ภ.\nบ.ม.\nบก.จร.\nบก.ตชด.\nบก.ตม.\nบก.ทล.\nบก.น.\nบก.ป.\nบก.ปค.\nบก.ปม.\nบก.ภ.เขต\nบก.รน.\nบก.รฟ.\nบก.ร้อย.ตชด.\nบก.ส.\nบกข.ป.\nบจพ.ป.\nบช.ก.\nบช.ด.\nบช.ตชด.\nบช.น.\nบช.บ.\nบช.ปส.\nบช.ภ.\nบช.ม.\nบชท.ป.\nบชน.ป.\nบชส.ป.\nบธ.ด.\nบธ.บ.\nบธ.ม.\nบนท.ป.\nบนอ.ป.\nบปช.ป.\nป.กท.\nป.กศ.\nป.กศ.สูง\nป.จ.\nป.จ.ว.\nป.ช.\nป.ธ.\nป.ป.\nป.ป.ก.\nป.ป.ช.\nป.ป.ป.\nป.ป.ร.\nป.ป.ส.\nป.พ.\nป.พ.พ.\nป.พย.\nป.ม.\nป.ม.ก.\nป.ม.ช.\nป.ม.ธ.\nป.ม.ศ.\nป.ม.อ.\nป.ร.ร.๔\nป.ร.ร.๕\nป.ร.ร.๖\nป.ล.\nป.ว.พ.\nป.วิ.อ.\nป.ส.ส.\nป.อ.\nป.อ.ร.ส.\nป.๑\nปม.วส.\nปอ.พ.\nผกก.ภ.\nผช.ผอ.\nผต.มท.\nผบ.ตร.\nผบ.ทบ.\nผบ.ทร.\nผบ.ทสส.\nผบ.ทอ.\nผบก.น.\nผบก.ป.\nผบก.ปค.\nผบก.ปม.\nผบก.ภ.\nผบช.ก.\nผบช.ตชด.\nผบช.น.\nผบช.ภ.\nผว.กทม.\nผอ.ปจ.\nพ.ก.ง.\nพ.กศ.\nพ.ข.ต.\nพ.ค.\nพ.ค.ช.\nพ.ค.ว.\nพ.ค.ศ.\nพ.จ.ต.\nพ.จ.ท.\nพ.จ.อ.\nพ.ช.\nพ.ช.ค.\nพ.ด.\nพ.ต.\nพ.ต.ต.\nพ.ต.ท.\nพ.ต.อ.\
|
|||
|
.split(/[\r\n]+/)
|
|||
|
.filter(function (w) {
|
|||
|
return w.length > 1;
|
|||
|
})
|
|||
|
this.addWords(words, false)
|
|||
|
}
|
|||
|
if(finalize){
|
|||
|
this.finalizeDict();
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
dictSeek: function (l, r, ch, strOffset, pos) {
|
|||
|
var ans = null;
|
|||
|
while (l <= r) {
|
|||
|
var m = Math.floor((l + r) / 2),
|
|||
|
dict_item = this.dict[m],
|
|||
|
len = dict_item.length;
|
|||
|
if (len <= strOffset) {
|
|||
|
l = m + 1;
|
|||
|
} else {
|
|||
|
var ch_ = dict_item[strOffset];
|
|||
|
if (ch_ < ch) {
|
|||
|
l = m + 1;
|
|||
|
} else if (ch_ > ch) {
|
|||
|
r = m - 1;
|
|||
|
} else {
|
|||
|
ans = m;
|
|||
|
if (pos == LEFT) {
|
|||
|
r = m - 1;
|
|||
|
} else {
|
|||
|
l = m + 1;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return ans;
|
|||
|
},
|
|||
|
|
|||
|
isFinal: function (acceptor) {
|
|||
|
return this.dict[acceptor.l].length == acceptor.strOffset;
|
|||
|
},
|
|||
|
|
|||
|
createAcceptor: function () {
|
|||
|
return {
|
|||
|
l: 0,
|
|||
|
r: this.dict.length - 1,
|
|||
|
strOffset: 0,
|
|||
|
isFinal: false,
|
|||
|
dict: this,
|
|||
|
transit: function (ch) {
|
|||
|
return this.dict.transit(this, ch);
|
|||
|
},
|
|||
|
isError: false,
|
|||
|
tag: "DICT",
|
|||
|
w: 1,
|
|||
|
type: "DICT"
|
|||
|
};
|
|||
|
},
|
|||
|
|
|||
|
transit: function (acceptor, ch) {
|
|||
|
var l = this.dictSeek(acceptor.l,
|
|||
|
acceptor.r,
|
|||
|
ch,
|
|||
|
acceptor.strOffset,
|
|||
|
LEFT);
|
|||
|
if (l !== null) {
|
|||
|
var r = this.dictSeek(l,
|
|||
|
acceptor.r,
|
|||
|
ch,
|
|||
|
acceptor.strOffset,
|
|||
|
RIGHT);
|
|||
|
acceptor.l = l;
|
|||
|
acceptor.r = r;
|
|||
|
acceptor.strOffset++;
|
|||
|
acceptor.isFinal = this.isFinal(acceptor);
|
|||
|
} else {
|
|||
|
acceptor.isError = true;
|
|||
|
}
|
|||
|
return acceptor;
|
|||
|
},
|
|||
|
|
|||
|
sortuniq: function(a){
|
|||
|
return a.sort().filter(function(item, pos, arr){
|
|||
|
return !pos || item != arr[pos - 1];
|
|||
|
})
|
|||
|
},
|
|||
|
|
|||
|
flatten: function(a){
|
|||
|
//[[1,2],[3]] -> [1,2,3]
|
|||
|
return [].concat.apply([], a);
|
|||
|
}
|
|||
|
};
|
|||
|
module.exports = WordcutDict;
|
|||
|
|
|||
|
}).call(this,"/dist/tmp")
|
|||
|
},{"glob":16,"path":22}],3:[function(require,module,exports){
|
|||
|
var WordRule = {
|
|||
|
createAcceptor: function(tag) {
|
|||
|
if (tag["WORD_RULE"])
|
|||
|
return null;
|
|||
|
|
|||
|
return {strOffset: 0,
|
|||
|
isFinal: false,
|
|||
|
transit: function(ch) {
|
|||
|
var lch = ch.toLowerCase();
|
|||
|
if (lch >= "a" && lch <= "z") {
|
|||
|
this.isFinal = true;
|
|||
|
this.strOffset++;
|
|||
|
} else {
|
|||
|
this.isError = true;
|
|||
|
}
|
|||
|
return this;
|
|||
|
},
|
|||
|
isError: false,
|
|||
|
tag: "WORD_RULE",
|
|||
|
type: "WORD_RULE",
|
|||
|
w: 1};
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
var NumberRule = {
|
|||
|
createAcceptor: function(tag) {
|
|||
|
if (tag["NUMBER_RULE"])
|
|||
|
return null;
|
|||
|
|
|||
|
return {strOffset: 0,
|
|||
|
isFinal: false,
|
|||
|
transit: function(ch) {
|
|||
|
if (ch >= "0" && ch <= "9") {
|
|||
|
this.isFinal = true;
|
|||
|
this.strOffset++;
|
|||
|
} else {
|
|||
|
this.isError = true;
|
|||
|
}
|
|||
|
return this;
|
|||
|
},
|
|||
|
isError: false,
|
|||
|
tag: "NUMBER_RULE",
|
|||
|
type: "NUMBER_RULE",
|
|||
|
w: 1};
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
var SpaceRule = {
|
|||
|
tag: "SPACE_RULE",
|
|||
|
createAcceptor: function(tag) {
|
|||
|
|
|||
|
if (tag["SPACE_RULE"])
|
|||
|
return null;
|
|||
|
|
|||
|
return {strOffset: 0,
|
|||
|
isFinal: false,
|
|||
|
transit: function(ch) {
|
|||
|
if (ch == " " || ch == "\t" || ch == "\r" || ch == "\n" ||
|
|||
|
ch == "\u00A0" || ch=="\u2003"//nbsp and emsp
|
|||
|
) {
|
|||
|
this.isFinal = true;
|
|||
|
this.strOffset++;
|
|||
|
} else {
|
|||
|
this.isError = true;
|
|||
|
}
|
|||
|
return this;
|
|||
|
},
|
|||
|
isError: false,
|
|||
|
tag: SpaceRule.tag,
|
|||
|
w: 1,
|
|||
|
type: "SPACE_RULE"};
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var SingleSymbolRule = {
|
|||
|
tag: "SINSYM",
|
|||
|
createAcceptor: function(tag) {
|
|||
|
return {strOffset: 0,
|
|||
|
isFinal: false,
|
|||
|
transit: function(ch) {
|
|||
|
if (this.strOffset == 0 && ch.match(/^[\@\(\)\/\,\-\."`]$/)) {
|
|||
|
this.isFinal = true;
|
|||
|
this.strOffset++;
|
|||
|
} else {
|
|||
|
this.isError = true;
|
|||
|
}
|
|||
|
return this;
|
|||
|
},
|
|||
|
isError: false,
|
|||
|
tag: "SINSYM",
|
|||
|
w: 1,
|
|||
|
type: "SINSYM"};
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
var LatinRules = [WordRule, SpaceRule, SingleSymbolRule, NumberRule];
|
|||
|
|
|||
|
module.exports = LatinRules;
|
|||
|
|
|||
|
},{}],4:[function(require,module,exports){
|
|||
|
var _ = require("underscore")
|
|||
|
, WordcutCore = require("./wordcut_core");
|
|||
|
var PathInfoBuilder = {
|
|||
|
|
|||
|
/*
|
|||
|
buildByPartAcceptors: function(path, acceptors, i) {
|
|||
|
var
|
|||
|
var genInfos = partAcceptors.reduce(function(genInfos, acceptor) {
|
|||
|
|
|||
|
}, []);
|
|||
|
|
|||
|
return genInfos;
|
|||
|
}
|
|||
|
*/
|
|||
|
|
|||
|
buildByAcceptors: function(path, finalAcceptors, i) {
|
|||
|
var self = this;
|
|||
|
var infos = finalAcceptors.map(function(acceptor) {
|
|||
|
var p = i - acceptor.strOffset + 1
|
|||
|
, _info = path[p];
|
|||
|
|
|||
|
var info = {p: p,
|
|||
|
mw: _info.mw + (acceptor.mw === undefined ? 0 : acceptor.mw),
|
|||
|
w: acceptor.w + _info.w,
|
|||
|
unk: (acceptor.unk ? acceptor.unk : 0) + _info.unk,
|
|||
|
type: acceptor.type};
|
|||
|
|
|||
|
if (acceptor.type == "PART") {
|
|||
|
for(var j = p + 1; j <= i; j++) {
|
|||
|
path[j].merge = p;
|
|||
|
}
|
|||
|
info.merge = p;
|
|||
|
}
|
|||
|
|
|||
|
return info;
|
|||
|
});
|
|||
|
return infos.filter(function(info) { return info; });
|
|||
|
},
|
|||
|
|
|||
|
fallback: function(path, leftBoundary, text, i) {
|
|||
|
var _info = path[leftBoundary];
|
|||
|
if (text[i].match(/[\u0E48-\u0E4E]/)) {
|
|||
|
if (leftBoundary != 0)
|
|||
|
leftBoundary = path[leftBoundary].p;
|
|||
|
return {p: leftBoundary,
|
|||
|
mw: 0,
|
|||
|
w: 1 + _info.w,
|
|||
|
unk: 1 + _info.unk,
|
|||
|
type: "UNK"};
|
|||
|
/* } else if(leftBoundary > 0 && path[leftBoundary].type !== "UNK") {
|
|||
|
leftBoundary = path[leftBoundary].p;
|
|||
|
return {p: leftBoundary,
|
|||
|
w: 1 + _info.w,
|
|||
|
unk: 1 + _info.unk,
|
|||
|
type: "UNK"}; */
|
|||
|
} else {
|
|||
|
return {p: leftBoundary,
|
|||
|
mw: _info.mw,
|
|||
|
w: 1 + _info.w,
|
|||
|
unk: 1 + _info.unk,
|
|||
|
type: "UNK"};
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
build: function(path, finalAcceptors, i, leftBoundary, text) {
|
|||
|
var basicPathInfos = this.buildByAcceptors(path, finalAcceptors, i);
|
|||
|
if (basicPathInfos.length > 0) {
|
|||
|
return basicPathInfos;
|
|||
|
} else {
|
|||
|
return [this.fallback(path, leftBoundary, text, i)];
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
module.exports = function() {
|
|||
|
return _.clone(PathInfoBuilder);
|
|||
|
}
|
|||
|
|
|||
|
},{"./wordcut_core":8,"underscore":25}],5:[function(require,module,exports){
|
|||
|
var _ = require("underscore");
|
|||
|
|
|||
|
|
|||
|
var PathSelector = {
|
|||
|
selectPath: function(paths) {
|
|||
|
var path = paths.reduce(function(selectedPath, path) {
|
|||
|
if (selectedPath == null) {
|
|||
|
return path;
|
|||
|
} else {
|
|||
|
if (path.unk < selectedPath.unk)
|
|||
|
return path;
|
|||
|
if (path.unk == selectedPath.unk) {
|
|||
|
if (path.mw < selectedPath.mw)
|
|||
|
return path
|
|||
|
if (path.mw == selectedPath.mw) {
|
|||
|
if (path.w < selectedPath.w)
|
|||
|
return path;
|
|||
|
}
|
|||
|
}
|
|||
|
return selectedPath;
|
|||
|
}
|
|||
|
}, null);
|
|||
|
return path;
|
|||
|
},
|
|||
|
|
|||
|
createPath: function() {
|
|||
|
return [{p:null, w:0, unk:0, type: "INIT", mw:0}];
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
module.exports = function() {
|
|||
|
return _.clone(PathSelector);
|
|||
|
};
|
|||
|
|
|||
|
},{"underscore":25}],6:[function(require,module,exports){
|
|||
|
function isMatch(pat, offset, ch) {
|
|||
|
if (pat.length <= offset)
|
|||
|
return false;
|
|||
|
var _ch = pat[offset];
|
|||
|
return _ch == ch ||
|
|||
|
(_ch.match(/[กข]/) && ch.match(/[ก-ฮ]/)) ||
|
|||
|
(_ch.match(/[มบ]/) && ch.match(/[ก-ฮ]/)) ||
|
|||
|
(_ch.match(/\u0E49/) && ch.match(/[\u0E48-\u0E4B]/));
|
|||
|
}
|
|||
|
|
|||
|
var Rule0 = {
|
|||
|
pat: "เหก็ม",
|
|||
|
createAcceptor: function(tag) {
|
|||
|
return {strOffset: 0,
|
|||
|
isFinal: false,
|
|||
|
transit: function(ch) {
|
|||
|
if (isMatch(Rule0.pat, this.strOffset,ch)) {
|
|||
|
this.isFinal = (this.strOffset + 1 == Rule0.pat.length);
|
|||
|
this.strOffset++;
|
|||
|
} else {
|
|||
|
this.isError = true;
|
|||
|
}
|
|||
|
return this;
|
|||
|
},
|
|||
|
isError: false,
|
|||
|
tag: "THAI_RULE",
|
|||
|
type: "THAI_RULE",
|
|||
|
w: 1};
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
var PartRule = {
|
|||
|
createAcceptor: function(tag) {
|
|||
|
return {strOffset: 0,
|
|||
|
patterns: [
|
|||
|
"แก", "เก", "ก้", "กก์", "กา", "กี", "กิ", "กืก"
|
|||
|
],
|
|||
|
isFinal: false,
|
|||
|
transit: function(ch) {
|
|||
|
var offset = this.strOffset;
|
|||
|
this.patterns = this.patterns.filter(function(pat) {
|
|||
|
return isMatch(pat, offset, ch);
|
|||
|
});
|
|||
|
|
|||
|
if (this.patterns.length > 0) {
|
|||
|
var len = 1 + offset;
|
|||
|
this.isFinal = this.patterns.some(function(pat) {
|
|||
|
return pat.length == len;
|
|||
|
});
|
|||
|
this.strOffset++;
|
|||
|
} else {
|
|||
|
this.isError = true;
|
|||
|
}
|
|||
|
return this;
|
|||
|
},
|
|||
|
isError: false,
|
|||
|
tag: "PART",
|
|||
|
type: "PART",
|
|||
|
unk: 1,
|
|||
|
w: 1};
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
var ThaiRules = [Rule0, PartRule];
|
|||
|
|
|||
|
module.exports = ThaiRules;
|
|||
|
|
|||
|
},{}],7:[function(require,module,exports){
|
|||
|
var sys = require("sys")
|
|||
|
, WordcutDict = require("./dict")
|
|||
|
, WordcutCore = require("./wordcut_core")
|
|||
|
, PathInfoBuilder = require("./path_info_builder")
|
|||
|
, PathSelector = require("./path_selector")
|
|||
|
, Acceptors = require("./acceptors")
|
|||
|
, latinRules = require("./latin_rules")
|
|||
|
, thaiRules = require("./thai_rules")
|
|||
|
, _ = require("underscore");
|
|||
|
|
|||
|
|
|||
|
var Wordcut = Object.create(WordcutCore);
|
|||
|
Wordcut.defaultPathInfoBuilder = PathInfoBuilder;
|
|||
|
Wordcut.defaultPathSelector = PathSelector;
|
|||
|
Wordcut.defaultAcceptors = Acceptors;
|
|||
|
Wordcut.defaultLatinRules = latinRules;
|
|||
|
Wordcut.defaultThaiRules = thaiRules;
|
|||
|
Wordcut.defaultDict = WordcutDict;
|
|||
|
|
|||
|
|
|||
|
Wordcut.initNoDict = function(dict_path) {
|
|||
|
var self = this;
|
|||
|
self.pathInfoBuilder = new self.defaultPathInfoBuilder;
|
|||
|
self.pathSelector = new self.defaultPathSelector;
|
|||
|
self.acceptors = new self.defaultAcceptors;
|
|||
|
self.defaultLatinRules.forEach(function(rule) {
|
|||
|
self.acceptors.creators.push(rule);
|
|||
|
});
|
|||
|
self.defaultThaiRules.forEach(function(rule) {
|
|||
|
self.acceptors.creators.push(rule);
|
|||
|
});
|
|||
|
};
|
|||
|
|
|||
|
Wordcut.init = function(dict_path, withDefault, additionalWords) {
|
|||
|
withDefault = withDefault || false;
|
|||
|
this.initNoDict();
|
|||
|
var dict = _.clone(this.defaultDict);
|
|||
|
dict.init(dict_path, withDefault, additionalWords);
|
|||
|
this.acceptors.creators.push(dict);
|
|||
|
};
|
|||
|
|
|||
|
module.exports = Wordcut;
|
|||
|
|
|||
|
},{"./acceptors":1,"./dict":2,"./latin_rules":3,"./path_info_builder":4,"./path_selector":5,"./thai_rules":6,"./wordcut_core":8,"sys":28,"underscore":25}],8:[function(require,module,exports){
|
|||
|
var WordcutCore = {
|
|||
|
|
|||
|
buildPath: function(text) {
|
|||
|
var self = this
|
|||
|
, path = self.pathSelector.createPath()
|
|||
|
, leftBoundary = 0;
|
|||
|
self.acceptors.reset();
|
|||
|
for (var i = 0; i < text.length; i++) {
|
|||
|
var ch = text[i];
|
|||
|
self.acceptors.transit(ch);
|
|||
|
|
|||
|
var possiblePathInfos = self
|
|||
|
.pathInfoBuilder
|
|||
|
.build(path,
|
|||
|
self.acceptors.getFinalAcceptors(),
|
|||
|
i,
|
|||
|
leftBoundary,
|
|||
|
text);
|
|||
|
var selectedPath = self.pathSelector.selectPath(possiblePathInfos)
|
|||
|
|
|||
|
path.push(selectedPath);
|
|||
|
if (selectedPath.type !== "UNK") {
|
|||
|
leftBoundary = i;
|
|||
|
}
|
|||
|
}
|
|||
|
return path;
|
|||
|
},
|
|||
|
|
|||
|
pathToRanges: function(path) {
|
|||
|
var e = path.length - 1
|
|||
|
, ranges = [];
|
|||
|
|
|||
|
while (e > 0) {
|
|||
|
var info = path[e]
|
|||
|
, s = info.p;
|
|||
|
|
|||
|
if (info.merge !== undefined && ranges.length > 0) {
|
|||
|
var r = ranges[ranges.length - 1];
|
|||
|
r.s = info.merge;
|
|||
|
s = r.s;
|
|||
|
} else {
|
|||
|
ranges.push({s:s, e:e});
|
|||
|
}
|
|||
|
e = s;
|
|||
|
}
|
|||
|
return ranges.reverse();
|
|||
|
},
|
|||
|
|
|||
|
rangesToText: function(text, ranges, delimiter) {
|
|||
|
return ranges.map(function(r) {
|
|||
|
return text.substring(r.s, r.e);
|
|||
|
}).join(delimiter);
|
|||
|
},
|
|||
|
|
|||
|
cut: function(text, delimiter) {
|
|||
|
var path = this.buildPath(text)
|
|||
|
, ranges = this.pathToRanges(path);
|
|||
|
return this
|
|||
|
.rangesToText(text, ranges,
|
|||
|
(delimiter === undefined ? "|" : delimiter));
|
|||
|
},
|
|||
|
|
|||
|
cutIntoRanges: function(text, noText) {
|
|||
|
var path = this.buildPath(text)
|
|||
|
, ranges = this.pathToRanges(path);
|
|||
|
|
|||
|
if (!noText) {
|
|||
|
ranges.forEach(function(r) {
|
|||
|
r.text = text.substring(r.s, r.e);
|
|||
|
});
|
|||
|
}
|
|||
|
return ranges;
|
|||
|
},
|
|||
|
|
|||
|
cutIntoArray: function(text) {
|
|||
|
var path = this.buildPath(text)
|
|||
|
, ranges = this.pathToRanges(path);
|
|||
|
|
|||
|
return ranges.map(function(r) {
|
|||
|
return text.substring(r.s, r.e)
|
|||
|
});
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
module.exports = WordcutCore;
|
|||
|
|
|||
|
},{}],9:[function(require,module,exports){
|
|||
|
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
|
|||
|
//
|
|||
|
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
|
|||
|
//
|
|||
|
// Originally from narwhal.js (http://narwhaljs.org)
|
|||
|
// Copyright (c) 2009 Thomas Robinson <280north.com>
|
|||
|
//
|
|||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|||
|
// of this software and associated documentation files (the 'Software'), to
|
|||
|
// deal in the Software without restriction, including without limitation the
|
|||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|||
|
// furnished to do so, subject to the following conditions:
|
|||
|
//
|
|||
|
// The above copyright notice and this permission notice shall be included in
|
|||
|
// all copies or substantial portions of the Software.
|
|||
|
//
|
|||
|
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|||
|
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|||
|
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|||
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
|
|||
|
// when used in node, this will actually load the util module we depend on
|
|||
|
// versus loading the builtin util module as happens otherwise
|
|||
|
// this is a bug in node module loading as far as I am concerned
|
|||
|
var util = require('util/');
|
|||
|
|
|||
|
var pSlice = Array.prototype.slice;
|
|||
|
var hasOwn = Object.prototype.hasOwnProperty;
|
|||
|
|
|||
|
// 1. The assert module provides functions that throw
|
|||
|
// AssertionError's when particular conditions are not met. The
|
|||
|
// assert module must conform to the following interface.
|
|||
|
|
|||
|
var assert = module.exports = ok;
|
|||
|
|
|||
|
// 2. The AssertionError is defined in assert.
|
|||
|
// new assert.AssertionError({ message: message,
|
|||
|
// actual: actual,
|
|||
|
// expected: expected })
|
|||
|
|
|||
|
assert.AssertionError = function AssertionError(options) {
|
|||
|
this.name = 'AssertionError';
|
|||
|
this.actual = options.actual;
|
|||
|
this.expected = options.expected;
|
|||
|
this.operator = options.operator;
|
|||
|
if (options.message) {
|
|||
|
this.message = options.message;
|
|||
|
this.generatedMessage = false;
|
|||
|
} else {
|
|||
|
this.message = getMessage(this);
|
|||
|
this.generatedMessage = true;
|
|||
|
}
|
|||
|
var stackStartFunction = options.stackStartFunction || fail;
|
|||
|
|
|||
|
if (Error.captureStackTrace) {
|
|||
|
Error.captureStackTrace(this, stackStartFunction);
|
|||
|
}
|
|||
|
else {
|
|||
|
// non v8 browsers so we can have a stacktrace
|
|||
|
var err = new Error();
|
|||
|
if (err.stack) {
|
|||
|
var out = err.stack;
|
|||
|
|
|||
|
// try to strip useless frames
|
|||
|
var fn_name = stackStartFunction.name;
|
|||
|
var idx = out.indexOf('\n' + fn_name);
|
|||
|
if (idx >= 0) {
|
|||
|
// once we have located the function frame
|
|||
|
// we need to strip out everything before it (and its line)
|
|||
|
var next_line = out.indexOf('\n', idx + 1);
|
|||
|
out = out.substring(next_line + 1);
|
|||
|
}
|
|||
|
|
|||
|
this.stack = out;
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
// assert.AssertionError instanceof Error
|
|||
|
util.inherits(assert.AssertionError, Error);
|
|||
|
|
|||
|
function replacer(key, value) {
|
|||
|
if (util.isUndefined(value)) {
|
|||
|
return '' + value;
|
|||
|
}
|
|||
|
if (util.isNumber(value) && !isFinite(value)) {
|
|||
|
return value.toString();
|
|||
|
}
|
|||
|
if (util.isFunction(value) || util.isRegExp(value)) {
|
|||
|
return value.toString();
|
|||
|
}
|
|||
|
return value;
|
|||
|
}
|
|||
|
|
|||
|
function truncate(s, n) {
|
|||
|
if (util.isString(s)) {
|
|||
|
return s.length < n ? s : s.slice(0, n);
|
|||
|
} else {
|
|||
|
return s;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function getMessage(self) {
|
|||
|
return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +
|
|||
|
self.operator + ' ' +
|
|||
|
truncate(JSON.stringify(self.expected, replacer), 128);
|
|||
|
}
|
|||
|
|
|||
|
// At present only the three keys mentioned above are used and
|
|||
|
// understood by the spec. Implementations or sub modules can pass
|
|||
|
// other keys to the AssertionError's constructor - they will be
|
|||
|
// ignored.
|
|||
|
|
|||
|
// 3. All of the following functions must throw an AssertionError
|
|||
|
// when a corresponding condition is not met, with a message that
|
|||
|
// may be undefined if not provided. All assertion methods provide
|
|||
|
// both the actual and expected values to the assertion error for
|
|||
|
// display purposes.
|
|||
|
|
|||
|
function fail(actual, expected, message, operator, stackStartFunction) {
|
|||
|
throw new assert.AssertionError({
|
|||
|
message: message,
|
|||
|
actual: actual,
|
|||
|
expected: expected,
|
|||
|
operator: operator,
|
|||
|
stackStartFunction: stackStartFunction
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
// EXTENSION! allows for well behaved errors defined elsewhere.
|
|||
|
assert.fail = fail;
|
|||
|
|
|||
|
// 4. Pure assertion tests whether a value is truthy, as determined
|
|||
|
// by !!guard.
|
|||
|
// assert.ok(guard, message_opt);
|
|||
|
// This statement is equivalent to assert.equal(true, !!guard,
|
|||
|
// message_opt);. To test strictly for the value true, use
|
|||
|
// assert.strictEqual(true, guard, message_opt);.
|
|||
|
|
|||
|
function ok(value, message) {
|
|||
|
if (!value) fail(value, true, message, '==', assert.ok);
|
|||
|
}
|
|||
|
assert.ok = ok;
|
|||
|
|
|||
|
// 5. The equality assertion tests shallow, coercive equality with
|
|||
|
// ==.
|
|||
|
// assert.equal(actual, expected, message_opt);
|
|||
|
|
|||
|
assert.equal = function equal(actual, expected, message) {
|
|||
|
if (actual != expected) fail(actual, expected, message, '==', assert.equal);
|
|||
|
};
|
|||
|
|
|||
|
// 6. The non-equality assertion tests for whether two objects are not equal
|
|||
|
// with != assert.notEqual(actual, expected, message_opt);
|
|||
|
|
|||
|
assert.notEqual = function notEqual(actual, expected, message) {
|
|||
|
if (actual == expected) {
|
|||
|
fail(actual, expected, message, '!=', assert.notEqual);
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
// 7. The equivalence assertion tests a deep equality relation.
|
|||
|
// assert.deepEqual(actual, expected, message_opt);
|
|||
|
|
|||
|
assert.deepEqual = function deepEqual(actual, expected, message) {
|
|||
|
if (!_deepEqual(actual, expected)) {
|
|||
|
fail(actual, expected, message, 'deepEqual', assert.deepEqual);
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
function _deepEqual(actual, expected) {
|
|||
|
// 7.1. All identical values are equivalent, as determined by ===.
|
|||
|
if (actual === expected) {
|
|||
|
return true;
|
|||
|
|
|||
|
} else if (util.isBuffer(actual) && util.isBuffer(expected)) {
|
|||
|
if (actual.length != expected.length) return false;
|
|||
|
|
|||
|
for (var i = 0; i < actual.length; i++) {
|
|||
|
if (actual[i] !== expected[i]) return false;
|
|||
|
}
|
|||
|
|
|||
|
return true;
|
|||
|
|
|||
|
// 7.2. If the expected value is a Date object, the actual value is
|
|||
|
// equivalent if it is also a Date object that refers to the same time.
|
|||
|
} else if (util.isDate(actual) && util.isDate(expected)) {
|
|||
|
return actual.getTime() === expected.getTime();
|
|||
|
|
|||
|
// 7.3 If the expected value is a RegExp object, the actual value is
|
|||
|
// equivalent if it is also a RegExp object with the same source and
|
|||
|
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
|
|||
|
} else if (util.isRegExp(actual) && util.isRegExp(expected)) {
|
|||
|
return actual.source === expected.source &&
|
|||
|
actual.global === expected.global &&
|
|||
|
actual.multiline === expected.multiline &&
|
|||
|
actual.lastIndex === expected.lastIndex &&
|
|||
|
actual.ignoreCase === expected.ignoreCase;
|
|||
|
|
|||
|
// 7.4. Other pairs that do not both pass typeof value == 'object',
|
|||
|
// equivalence is determined by ==.
|
|||
|
} else if (!util.isObject(actual) && !util.isObject(expected)) {
|
|||
|
return actual == expected;
|
|||
|
|
|||
|
// 7.5 For all other Object pairs, including Array objects, equivalence is
|
|||
|
// determined by having the same number of owned properties (as verified
|
|||
|
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
|||
|
// (although not necessarily the same order), equivalent values for every
|
|||
|
// corresponding key, and an identical 'prototype' property. Note: this
|
|||
|
// accounts for both named and indexed properties on Arrays.
|
|||
|
} else {
|
|||
|
return objEquiv(actual, expected);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isArguments(object) {
|
|||
|
return Object.prototype.toString.call(object) == '[object Arguments]';
|
|||
|
}
|
|||
|
|
|||
|
function objEquiv(a, b) {
|
|||
|
if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))
|
|||
|
return false;
|
|||
|
// an identical 'prototype' property.
|
|||
|
if (a.prototype !== b.prototype) return false;
|
|||
|
// if one is a primitive, the other must be same
|
|||
|
if (util.isPrimitive(a) || util.isPrimitive(b)) {
|
|||
|
return a === b;
|
|||
|
}
|
|||
|
var aIsArgs = isArguments(a),
|
|||
|
bIsArgs = isArguments(b);
|
|||
|
if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs))
|
|||
|
return false;
|
|||
|
if (aIsArgs) {
|
|||
|
a = pSlice.call(a);
|
|||
|
b = pSlice.call(b);
|
|||
|
return _deepEqual(a, b);
|
|||
|
}
|
|||
|
var ka = objectKeys(a),
|
|||
|
kb = objectKeys(b),
|
|||
|
key, i;
|
|||
|
// having the same number of owned properties (keys incorporates
|
|||
|
// hasOwnProperty)
|
|||
|
if (ka.length != kb.length)
|
|||
|
return false;
|
|||
|
//the same set of keys (although not necessarily the same order),
|
|||
|
ka.sort();
|
|||
|
kb.sort();
|
|||
|
//~~~cheap key test
|
|||
|
for (i = ka.length - 1; i >= 0; i--) {
|
|||
|
if (ka[i] != kb[i])
|
|||
|
return false;
|
|||
|
}
|
|||
|
//equivalent values for every corresponding key, and
|
|||
|
//~~~possibly expensive deep test
|
|||
|
for (i = ka.length - 1; i >= 0; i--) {
|
|||
|
key = ka[i];
|
|||
|
if (!_deepEqual(a[key], b[key])) return false;
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
// 8. The non-equivalence assertion tests for any deep inequality.
|
|||
|
// assert.notDeepEqual(actual, expected, message_opt);
|
|||
|
|
|||
|
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
|
|||
|
if (_deepEqual(actual, expected)) {
|
|||
|
fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
// 9. The strict equality assertion tests strict equality, as determined by ===.
|
|||
|
// assert.strictEqual(actual, expected, message_opt);
|
|||
|
|
|||
|
assert.strictEqual = function strictEqual(actual, expected, message) {
|
|||
|
if (actual !== expected) {
|
|||
|
fail(actual, expected, message, '===', assert.strictEqual);
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
// 10. The strict non-equality assertion tests for strict inequality, as
|
|||
|
// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
|
|||
|
|
|||
|
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
|
|||
|
if (actual === expected) {
|
|||
|
fail(actual, expected, message, '!==', assert.notStrictEqual);
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
function expectedException(actual, expected) {
|
|||
|
if (!actual || !expected) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
if (Object.prototype.toString.call(expected) == '[object RegExp]') {
|
|||
|
return expected.test(actual);
|
|||
|
} else if (actual instanceof expected) {
|
|||
|
return true;
|
|||
|
} else if (expected.call({}, actual) === true) {
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
function _throws(shouldThrow, block, expected, message) {
|
|||
|
var actual;
|
|||
|
|
|||
|
if (util.isString(expected)) {
|
|||
|
message = expected;
|
|||
|
expected = null;
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
block();
|
|||
|
} catch (e) {
|
|||
|
actual = e;
|
|||
|
}
|
|||
|
|
|||
|
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
|
|||
|
(message ? ' ' + message : '.');
|
|||
|
|
|||
|
if (shouldThrow && !actual) {
|
|||
|
fail(actual, expected, 'Missing expected exception' + message);
|
|||
|
}
|
|||
|
|
|||
|
if (!shouldThrow && expectedException(actual, expected)) {
|
|||
|
fail(actual, expected, 'Got unwanted exception' + message);
|
|||
|
}
|
|||
|
|
|||
|
if ((shouldThrow && actual && expected &&
|
|||
|
!expectedException(actual, expected)) || (!shouldThrow && actual)) {
|
|||
|
throw actual;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 11. Expected to throw an error:
|
|||
|
// assert.throws(block, Error_opt, message_opt);
|
|||
|
|
|||
|
assert.throws = function(block, /*optional*/error, /*optional*/message) {
|
|||
|
_throws.apply(this, [true].concat(pSlice.call(arguments)));
|
|||
|
};
|
|||
|
|
|||
|
// EXTENSION! This is annoying to write outside this module.
|
|||
|
assert.doesNotThrow = function(block, /*optional*/message) {
|
|||
|
_throws.apply(this, [false].concat(pSlice.call(arguments)));
|
|||
|
};
|
|||
|
|
|||
|
assert.ifError = function(err) { if (err) {throw err;}};
|
|||
|
|
|||
|
var objectKeys = Object.keys || function (obj) {
|
|||
|
var keys = [];
|
|||
|
for (var key in obj) {
|
|||
|
if (hasOwn.call(obj, key)) keys.push(key);
|
|||
|
}
|
|||
|
return keys;
|
|||
|
};
|
|||
|
|
|||
|
},{"util/":28}],10:[function(require,module,exports){
|
|||
|
'use strict';
|
|||
|
module.exports = balanced;
|
|||
|
function balanced(a, b, str) {
|
|||
|
if (a instanceof RegExp) a = maybeMatch(a, str);
|
|||
|
if (b instanceof RegExp) b = maybeMatch(b, str);
|
|||
|
|
|||
|
var r = range(a, b, str);
|
|||
|
|
|||
|
return r && {
|
|||
|
start: r[0],
|
|||
|
end: r[1],
|
|||
|
pre: str.slice(0, r[0]),
|
|||
|
body: str.slice(r[0] + a.length, r[1]),
|
|||
|
post: str.slice(r[1] + b.length)
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
function maybeMatch(reg, str) {
|
|||
|
var m = str.match(reg);
|
|||
|
return m ? m[0] : null;
|
|||
|
}
|
|||
|
|
|||
|
balanced.range = range;
|
|||
|
function range(a, b, str) {
|
|||
|
var begs, beg, left, right, result;
|
|||
|
var ai = str.indexOf(a);
|
|||
|
var bi = str.indexOf(b, ai + 1);
|
|||
|
var i = ai;
|
|||
|
|
|||
|
if (ai >= 0 && bi > 0) {
|
|||
|
begs = [];
|
|||
|
left = str.length;
|
|||
|
|
|||
|
while (i >= 0 && !result) {
|
|||
|
if (i == ai) {
|
|||
|
begs.push(i);
|
|||
|
ai = str.indexOf(a, i + 1);
|
|||
|
} else if (begs.length == 1) {
|
|||
|
result = [ begs.pop(), bi ];
|
|||
|
} else {
|
|||
|
beg = begs.pop();
|
|||
|
if (beg < left) {
|
|||
|
left = beg;
|
|||
|
right = bi;
|
|||
|
}
|
|||
|
|
|||
|
bi = str.indexOf(b, i + 1);
|
|||
|
}
|
|||
|
|
|||
|
i = ai < bi && ai >= 0 ? ai : bi;
|
|||
|
}
|
|||
|
|
|||
|
if (begs.length) {
|
|||
|
result = [ left, right ];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
},{}],11:[function(require,module,exports){
|
|||
|
var concatMap = require('concat-map');
|
|||
|
var balanced = require('balanced-match');
|
|||
|
|
|||
|
module.exports = expandTop;
|
|||
|
|
|||
|
var escSlash = '\0SLASH'+Math.random()+'\0';
|
|||
|
var escOpen = '\0OPEN'+Math.random()+'\0';
|
|||
|
var escClose = '\0CLOSE'+Math.random()+'\0';
|
|||
|
var escComma = '\0COMMA'+Math.random()+'\0';
|
|||
|
var escPeriod = '\0PERIOD'+Math.random()+'\0';
|
|||
|
|
|||
|
function numeric(str) {
|
|||
|
return parseInt(str, 10) == str
|
|||
|
? parseInt(str, 10)
|
|||
|
: str.charCodeAt(0);
|
|||
|
}
|
|||
|
|
|||
|
function escapeBraces(str) {
|
|||
|
return str.split('\\\\').join(escSlash)
|
|||
|
.split('\\{').join(escOpen)
|
|||
|
.split('\\}').join(escClose)
|
|||
|
.split('\\,').join(escComma)
|
|||
|
.split('\\.').join(escPeriod);
|
|||
|
}
|
|||
|
|
|||
|
function unescapeBraces(str) {
|
|||
|
return str.split(escSlash).join('\\')
|
|||
|
.split(escOpen).join('{')
|
|||
|
.split(escClose).join('}')
|
|||
|
.split(escComma).join(',')
|
|||
|
.split(escPeriod).join('.');
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// Basically just str.split(","), but handling cases
|
|||
|
// where we have nested braced sections, which should be
|
|||
|
// treated as individual members, like {a,{b,c},d}
|
|||
|
function parseCommaParts(str) {
|
|||
|
if (!str)
|
|||
|
return [''];
|
|||
|
|
|||
|
var parts = [];
|
|||
|
var m = balanced('{', '}', str);
|
|||
|
|
|||
|
if (!m)
|
|||
|
return str.split(',');
|
|||
|
|
|||
|
var pre = m.pre;
|
|||
|
var body = m.body;
|
|||
|
var post = m.post;
|
|||
|
var p = pre.split(',');
|
|||
|
|
|||
|
p[p.length-1] += '{' + body + '}';
|
|||
|
var postParts = parseCommaParts(post);
|
|||
|
if (post.length) {
|
|||
|
p[p.length-1] += postParts.shift();
|
|||
|
p.push.apply(p, postParts);
|
|||
|
}
|
|||
|
|
|||
|
parts.push.apply(parts, p);
|
|||
|
|
|||
|
return parts;
|
|||
|
}
|
|||
|
|
|||
|
function expandTop(str) {
|
|||
|
if (!str)
|
|||
|
return [];
|
|||
|
|
|||
|
// I don't know why Bash 4.3 does this, but it does.
|
|||
|
// Anything starting with {} will have the first two bytes preserved
|
|||
|
// but *only* at the top level, so {},a}b will not expand to anything,
|
|||
|
// but a{},b}c will be expanded to [a}c,abc].
|
|||
|
// One could argue that this is a bug in Bash, but since the goal of
|
|||
|
// this module is to match Bash's rules, we escape a leading {}
|
|||
|
if (str.substr(0, 2) === '{}') {
|
|||
|
str = '\\{\\}' + str.substr(2);
|
|||
|
}
|
|||
|
|
|||
|
return expand(escapeBraces(str), true).map(unescapeBraces);
|
|||
|
}
|
|||
|
|
|||
|
function identity(e) {
|
|||
|
return e;
|
|||
|
}
|
|||
|
|
|||
|
function embrace(str) {
|
|||
|
return '{' + str + '}';
|
|||
|
}
|
|||
|
function isPadded(el) {
|
|||
|
return /^-?0\d/.test(el);
|
|||
|
}
|
|||
|
|
|||
|
function lte(i, y) {
|
|||
|
return i <= y;
|
|||
|
}
|
|||
|
function gte(i, y) {
|
|||
|
return i >= y;
|
|||
|
}
|
|||
|
|
|||
|
function expand(str, isTop) {
|
|||
|
var expansions = [];
|
|||
|
|
|||
|
var m = balanced('{', '}', str);
|
|||
|
if (!m || /\$$/.test(m.pre)) return [str];
|
|||
|
|
|||
|
var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
|
|||
|
var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
|
|||
|
var isSequence = isNumericSequence || isAlphaSequence;
|
|||
|
var isOptions = m.body.indexOf(',') >= 0;
|
|||
|
if (!isSequence && !isOptions) {
|
|||
|
// {a},b}
|
|||
|
if (m.post.match(/,.*\}/)) {
|
|||
|
str = m.pre + '{' + m.body + escClose + m.post;
|
|||
|
return expand(str);
|
|||
|
}
|
|||
|
return [str];
|
|||
|
}
|
|||
|
|
|||
|
var n;
|
|||
|
if (isSequence) {
|
|||
|
n = m.body.split(/\.\./);
|
|||
|
} else {
|
|||
|
n = parseCommaParts(m.body);
|
|||
|
if (n.length === 1) {
|
|||
|
// x{{a,b}}y ==> x{a}y x{b}y
|
|||
|
n = expand(n[0], false).map(embrace);
|
|||
|
if (n.length === 1) {
|
|||
|
var post = m.post.length
|
|||
|
? expand(m.post, false)
|
|||
|
: [''];
|
|||
|
return post.map(function(p) {
|
|||
|
return m.pre + n[0] + p;
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// at this point, n is the parts, and we know it's not a comma set
|
|||
|
// with a single entry.
|
|||
|
|
|||
|
// no need to expand pre, since it is guaranteed to be free of brace-sets
|
|||
|
var pre = m.pre;
|
|||
|
var post = m.post.length
|
|||
|
? expand(m.post, false)
|
|||
|
: [''];
|
|||
|
|
|||
|
var N;
|
|||
|
|
|||
|
if (isSequence) {
|
|||
|
var x = numeric(n[0]);
|
|||
|
var y = numeric(n[1]);
|
|||
|
var width = Math.max(n[0].length, n[1].length)
|
|||
|
var incr = n.length == 3
|
|||
|
? Math.abs(numeric(n[2]))
|
|||
|
: 1;
|
|||
|
var test = lte;
|
|||
|
var reverse = y < x;
|
|||
|
if (reverse) {
|
|||
|
incr *= -1;
|
|||
|
test = gte;
|
|||
|
}
|
|||
|
var pad = n.some(isPadded);
|
|||
|
|
|||
|
N = [];
|
|||
|
|
|||
|
for (var i = x; test(i, y); i += incr) {
|
|||
|
var c;
|
|||
|
if (isAlphaSequence) {
|
|||
|
c = String.fromCharCode(i);
|
|||
|
if (c === '\\')
|
|||
|
c = '';
|
|||
|
} else {
|
|||
|
c = String(i);
|
|||
|
if (pad) {
|
|||
|
var need = width - c.length;
|
|||
|
if (need > 0) {
|
|||
|
var z = new Array(need + 1).join('0');
|
|||
|
if (i < 0)
|
|||
|
c = '-' + z + c.slice(1);
|
|||
|
else
|
|||
|
c = z + c;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
N.push(c);
|
|||
|
}
|
|||
|
} else {
|
|||
|
N = concatMap(n, function(el) { return expand(el, false) });
|
|||
|
}
|
|||
|
|
|||
|
for (var j = 0; j < N.length; j++) {
|
|||
|
for (var k = 0; k < post.length; k++) {
|
|||
|
var expansion = pre + N[j] + post[k];
|
|||
|
if (!isTop || isSequence || expansion)
|
|||
|
expansions.push(expansion);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return expansions;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
},{"balanced-match":10,"concat-map":13}],12:[function(require,module,exports){
|
|||
|
|
|||
|
},{}],13:[function(require,module,exports){
|
|||
|
module.exports = function (xs, fn) {
|
|||
|
var res = [];
|
|||
|
for (var i = 0; i < xs.length; i++) {
|
|||
|
var x = fn(xs[i], i);
|
|||
|
if (isArray(x)) res.push.apply(res, x);
|
|||
|
else res.push(x);
|
|||
|
}
|
|||
|
return res;
|
|||
|
};
|
|||
|
|
|||
|
var isArray = Array.isArray || function (xs) {
|
|||
|
return Object.prototype.toString.call(xs) === '[object Array]';
|
|||
|
};
|
|||
|
|
|||
|
},{}],14:[function(require,module,exports){
|
|||
|
// Copyright Joyent, Inc. and other Node contributors.
|
|||
|
//
|
|||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|||
|
// copy of this software and associated documentation files (the
|
|||
|
// "Software"), to deal in the Software without restriction, including
|
|||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|||
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|||
|
// persons to whom the Software is furnished to do so, subject to the
|
|||
|
// following conditions:
|
|||
|
//
|
|||
|
// The above copyright notice and this permission notice shall be included
|
|||
|
// in all copies or substantial portions of the Software.
|
|||
|
//
|
|||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|||
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|||
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|||
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|||
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|||
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
|
|||
|
function EventEmitter() {
|
|||
|
this._events = this._events || {};
|
|||
|
this._maxListeners = this._maxListeners || undefined;
|
|||
|
}
|
|||
|
module.exports = EventEmitter;
|
|||
|
|
|||
|
// Backwards-compat with node 0.10.x
|
|||
|
EventEmitter.EventEmitter = EventEmitter;
|
|||
|
|
|||
|
EventEmitter.prototype._events = undefined;
|
|||
|
EventEmitter.prototype._maxListeners = undefined;
|
|||
|
|
|||
|
// By default EventEmitters will print a warning if more than 10 listeners are
|
|||
|
// added to it. This is a useful default which helps finding memory leaks.
|
|||
|
EventEmitter.defaultMaxListeners = 10;
|
|||
|
|
|||
|
// Obviously not all Emitters should be limited to 10. This function allows
|
|||
|
// that to be increased. Set to zero for unlimited.
|
|||
|
EventEmitter.prototype.setMaxListeners = function(n) {
|
|||
|
if (!isNumber(n) || n < 0 || isNaN(n))
|
|||
|
throw TypeError('n must be a positive number');
|
|||
|
this._maxListeners = n;
|
|||
|
return this;
|
|||
|
};
|
|||
|
|
|||
|
EventEmitter.prototype.emit = function(type) {
|
|||
|
var er, handler, len, args, i, listeners;
|
|||
|
|
|||
|
if (!this._events)
|
|||
|
this._events = {};
|
|||
|
|
|||
|
// If there is no 'error' event listener then throw.
|
|||
|
if (type === 'error') {
|
|||
|
if (!this._events.error ||
|
|||
|
(isObject(this._events.error) && !this._events.error.length)) {
|
|||
|
er = arguments[1];
|
|||
|
if (er instanceof Error) {
|
|||
|
throw er; // Unhandled 'error' event
|
|||
|
}
|
|||
|
throw TypeError('Uncaught, unspecified "error" event.');
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
handler = this._events[type];
|
|||
|
|
|||
|
if (isUndefined(handler))
|
|||
|
return false;
|
|||
|
|
|||
|
if (isFunction(handler)) {
|
|||
|
switch (arguments.length) {
|
|||
|
// fast cases
|
|||
|
case 1:
|
|||
|
handler.call(this);
|
|||
|
break;
|
|||
|
case 2:
|
|||
|
handler.call(this, arguments[1]);
|
|||
|
break;
|
|||
|
case 3:
|
|||
|
handler.call(this, arguments[1], arguments[2]);
|
|||
|
break;
|
|||
|
// slower
|
|||
|
default:
|
|||
|
len = arguments.length;
|
|||
|
args = new Array(len - 1);
|
|||
|
for (i = 1; i < len; i++)
|
|||
|
args[i - 1] = arguments[i];
|
|||
|
handler.apply(this, args);
|
|||
|
}
|
|||
|
} else if (isObject(handler)) {
|
|||
|
len = arguments.length;
|
|||
|
args = new Array(len - 1);
|
|||
|
for (i = 1; i < len; i++)
|
|||
|
args[i - 1] = arguments[i];
|
|||
|
|
|||
|
listeners = handler.slice();
|
|||
|
len = listeners.length;
|
|||
|
for (i = 0; i < len; i++)
|
|||
|
listeners[i].apply(this, args);
|
|||
|
}
|
|||
|
|
|||
|
return true;
|
|||
|
};
|
|||
|
|
|||
|
EventEmitter.prototype.addListener = function(type, listener) {
|
|||
|
var m;
|
|||
|
|
|||
|
if (!isFunction(listener))
|
|||
|
throw TypeError('listener must be a function');
|
|||
|
|
|||
|
if (!this._events)
|
|||
|
this._events = {};
|
|||
|
|
|||
|
// To avoid recursion in the case that type === "newListener"! Before
|
|||
|
// adding it to the listeners, first emit "newListener".
|
|||
|
if (this._events.newListener)
|
|||
|
this.emit('newListener', type,
|
|||
|
isFunction(listener.listener) ?
|
|||
|
listener.listener : listener);
|
|||
|
|
|||
|
if (!this._events[type])
|
|||
|
// Optimize the case of one listener. Don't need the extra array object.
|
|||
|
this._events[type] = listener;
|
|||
|
else if (isObject(this._events[type]))
|
|||
|
// If we've already got an array, just append.
|
|||
|
this._events[type].push(listener);
|
|||
|
else
|
|||
|
// Adding the second element, need to change to array.
|
|||
|
this._events[type] = [this._events[type], listener];
|
|||
|
|
|||
|
// Check for listener leak
|
|||
|
if (isObject(this._events[type]) && !this._events[type].warned) {
|
|||
|
var m;
|
|||
|
if (!isUndefined(this._maxListeners)) {
|
|||
|
m = this._maxListeners;
|
|||
|
} else {
|
|||
|
m = EventEmitter.defaultMaxListeners;
|
|||
|
}
|
|||
|
|
|||
|
if (m && m > 0 && this._events[type].length > m) {
|
|||
|
this._events[type].warned = true;
|
|||
|
console.error('(node) warning: possible EventEmitter memory ' +
|
|||
|
'leak detected. %d listeners added. ' +
|
|||
|
'Use emitter.setMaxListeners() to increase limit.',
|
|||
|
this._events[type].length);
|
|||
|
if (typeof console.trace === 'function') {
|
|||
|
// not supported in IE 10
|
|||
|
console.trace();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return this;
|
|||
|
};
|
|||
|
|
|||
|
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
|
|||
|
|
|||
|
EventEmitter.prototype.once = function(type, listener) {
|
|||
|
if (!isFunction(listener))
|
|||
|
throw TypeError('listener must be a function');
|
|||
|
|
|||
|
var fired = false;
|
|||
|
|
|||
|
function g() {
|
|||
|
this.removeListener(type, g);
|
|||
|
|
|||
|
if (!fired) {
|
|||
|
fired = true;
|
|||
|
listener.apply(this, arguments);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
g.listener = listener;
|
|||
|
this.on(type, g);
|
|||
|
|
|||
|
return this;
|
|||
|
};
|
|||
|
|
|||
|
// emits a 'removeListener' event iff the listener was removed
|
|||
|
EventEmitter.prototype.removeListener = function(type, listener) {
|
|||
|
var list, position, length, i;
|
|||
|
|
|||
|
if (!isFunction(listener))
|
|||
|
throw TypeError('listener must be a function');
|
|||
|
|
|||
|
if (!this._events || !this._events[type])
|
|||
|
return this;
|
|||
|
|
|||
|
list = this._events[type];
|
|||
|
length = list.length;
|
|||
|
position = -1;
|
|||
|
|
|||
|
if (list === listener ||
|
|||
|
(isFunction(list.listener) && list.listener === listener)) {
|
|||
|
delete this._events[type];
|
|||
|
if (this._events.removeListener)
|
|||
|
this.emit('removeListener', type, listener);
|
|||
|
|
|||
|
} else if (isObject(list)) {
|
|||
|
for (i = length; i-- > 0;) {
|
|||
|
if (list[i] === listener ||
|
|||
|
(list[i].listener && list[i].listener === listener)) {
|
|||
|
position = i;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (position < 0)
|
|||
|
return this;
|
|||
|
|
|||
|
if (list.length === 1) {
|
|||
|
list.length = 0;
|
|||
|
delete this._events[type];
|
|||
|
} else {
|
|||
|
list.splice(position, 1);
|
|||
|
}
|
|||
|
|
|||
|
if (this._events.removeListener)
|
|||
|
this.emit('removeListener', type, listener);
|
|||
|
}
|
|||
|
|
|||
|
return this;
|
|||
|
};
|
|||
|
|
|||
|
EventEmitter.prototype.removeAllListeners = function(type) {
|
|||
|
var key, listeners;
|
|||
|
|
|||
|
if (!this._events)
|
|||
|
return this;
|
|||
|
|
|||
|
// not listening for removeListener, no need to emit
|
|||
|
if (!this._events.removeListener) {
|
|||
|
if (arguments.length === 0)
|
|||
|
this._events = {};
|
|||
|
else if (this._events[type])
|
|||
|
delete this._events[type];
|
|||
|
return this;
|
|||
|
}
|
|||
|
|
|||
|
// emit removeListener for all listeners on all events
|
|||
|
if (arguments.length === 0) {
|
|||
|
for (key in this._events) {
|
|||
|
if (key === 'removeListener') continue;
|
|||
|
this.removeAllListeners(key);
|
|||
|
}
|
|||
|
this.removeAllListeners('removeListener');
|
|||
|
this._events = {};
|
|||
|
return this;
|
|||
|
}
|
|||
|
|
|||
|
listeners = this._events[type];
|
|||
|
|
|||
|
if (isFunction(listeners)) {
|
|||
|
this.removeListener(type, listeners);
|
|||
|
} else {
|
|||
|
// LIFO order
|
|||
|
while (listeners.length)
|
|||
|
this.removeListener(type, listeners[listeners.length - 1]);
|
|||
|
}
|
|||
|
delete this._events[type];
|
|||
|
|
|||
|
return this;
|
|||
|
};
|
|||
|
|
|||
|
EventEmitter.prototype.listeners = function(type) {
|
|||
|
var ret;
|
|||
|
if (!this._events || !this._events[type])
|
|||
|
ret = [];
|
|||
|
else if (isFunction(this._events[type]))
|
|||
|
ret = [this._events[type]];
|
|||
|
else
|
|||
|
ret = this._events[type].slice();
|
|||
|
return ret;
|
|||
|
};
|
|||
|
|
|||
|
EventEmitter.listenerCount = function(emitter, type) {
|
|||
|
var ret;
|
|||
|
if (!emitter._events || !emitter._events[type])
|
|||
|
ret = 0;
|
|||
|
else if (isFunction(emitter._events[type]))
|
|||
|
ret = 1;
|
|||
|
else
|
|||
|
ret = emitter._events[type].length;
|
|||
|
return ret;
|
|||
|
};
|
|||
|
|
|||
|
function isFunction(arg) {
|
|||
|
return typeof arg === 'function';
|
|||
|
}
|
|||
|
|
|||
|
function isNumber(arg) {
|
|||
|
return typeof arg === 'number';
|
|||
|
}
|
|||
|
|
|||
|
function isObject(arg) {
|
|||
|
return typeof arg === 'object' && arg !== null;
|
|||
|
}
|
|||
|
|
|||
|
function isUndefined(arg) {
|
|||
|
return arg === void 0;
|
|||
|
}
|
|||
|
|
|||
|
},{}],15:[function(require,module,exports){
|
|||
|
(function (process){
|
|||
|
exports.alphasort = alphasort
|
|||
|
exports.alphasorti = alphasorti
|
|||
|
exports.setopts = setopts
|
|||
|
exports.ownProp = ownProp
|
|||
|
exports.makeAbs = makeAbs
|
|||
|
exports.finish = finish
|
|||
|
exports.mark = mark
|
|||
|
exports.isIgnored = isIgnored
|
|||
|
exports.childrenIgnored = childrenIgnored
|
|||
|
|
|||
|
function ownProp (obj, field) {
|
|||
|
return Object.prototype.hasOwnProperty.call(obj, field)
|
|||
|
}
|
|||
|
|
|||
|
var path = require("path")
|
|||
|
var minimatch = require("minimatch")
|
|||
|
var isAbsolute = require("path-is-absolute")
|
|||
|
var Minimatch = minimatch.Minimatch
|
|||
|
|
|||
|
function alphasorti (a, b) {
|
|||
|
return a.toLowerCase().localeCompare(b.toLowerCase())
|
|||
|
}
|
|||
|
|
|||
|
function alphasort (a, b) {
|
|||
|
return a.localeCompare(b)
|
|||
|
}
|
|||
|
|
|||
|
function setupIgnores (self, options) {
|
|||
|
self.ignore = options.ignore || []
|
|||
|
|
|||
|
if (!Array.isArray(self.ignore))
|
|||
|
self.ignore = [self.ignore]
|
|||
|
|
|||
|
if (self.ignore.length) {
|
|||
|
self.ignore = self.ignore.map(ignoreMap)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function ignoreMap (pattern) {
|
|||
|
var gmatcher = null
|
|||
|
if (pattern.slice(-3) === '/**') {
|
|||
|
var gpattern = pattern.replace(/(\/\*\*)+$/, '')
|
|||
|
gmatcher = new Minimatch(gpattern)
|
|||
|
}
|
|||
|
|
|||
|
return {
|
|||
|
matcher: new Minimatch(pattern),
|
|||
|
gmatcher: gmatcher
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function setopts (self, pattern, options) {
|
|||
|
if (!options)
|
|||
|
options = {}
|
|||
|
|
|||
|
// base-matching: just use globstar for that.
|
|||
|
if (options.matchBase && -1 === pattern.indexOf("/")) {
|
|||
|
if (options.noglobstar) {
|
|||
|
throw new Error("base matching requires globstar")
|
|||
|
}
|
|||
|
pattern = "**/" + pattern
|
|||
|
}
|
|||
|
|
|||
|
self.silent = !!options.silent
|
|||
|
self.pattern = pattern
|
|||
|
self.strict = options.strict !== false
|
|||
|
self.realpath = !!options.realpath
|
|||
|
self.realpathCache = options.realpathCache || Object.create(null)
|
|||
|
self.follow = !!options.follow
|
|||
|
self.dot = !!options.dot
|
|||
|
self.mark = !!options.mark
|
|||
|
self.nodir = !!options.nodir
|
|||
|
if (self.nodir)
|
|||
|
self.mark = true
|
|||
|
self.sync = !!options.sync
|
|||
|
self.nounique = !!options.nounique
|
|||
|
self.nonull = !!options.nonull
|
|||
|
self.nosort = !!options.nosort
|
|||
|
self.nocase = !!options.nocase
|
|||
|
self.stat = !!options.stat
|
|||
|
self.noprocess = !!options.noprocess
|
|||
|
|
|||
|
self.maxLength = options.maxLength || Infinity
|
|||
|
self.cache = options.cache || Object.create(null)
|
|||
|
self.statCache = options.statCache || Object.create(null)
|
|||
|
self.symlinks = options.symlinks || Object.create(null)
|
|||
|
|
|||
|
setupIgnores(self, options)
|
|||
|
|
|||
|
self.changedCwd = false
|
|||
|
var cwd = process.cwd()
|
|||
|
if (!ownProp(options, "cwd"))
|
|||
|
self.cwd = cwd
|
|||
|
else {
|
|||
|
self.cwd = options.cwd
|
|||
|
self.changedCwd = path.resolve(options.cwd) !== cwd
|
|||
|
}
|
|||
|
|
|||
|
self.root = options.root || path.resolve(self.cwd, "/")
|
|||
|
self.root = path.resolve(self.root)
|
|||
|
if (process.platform === "win32")
|
|||
|
self.root = self.root.replace(/\\/g, "/")
|
|||
|
|
|||
|
self.nomount = !!options.nomount
|
|||
|
|
|||
|
// disable comments and negation unless the user explicitly
|
|||
|
// passes in false as the option.
|
|||
|
options.nonegate = options.nonegate === false ? false : true
|
|||
|
options.nocomment = options.nocomment === false ? false : true
|
|||
|
deprecationWarning(options)
|
|||
|
|
|||
|
self.minimatch = new Minimatch(pattern, options)
|
|||
|
self.options = self.minimatch.options
|
|||
|
}
|
|||
|
|
|||
|
// TODO(isaacs): remove entirely in v6
|
|||
|
// exported to reset in tests
|
|||
|
exports.deprecationWarned
|
|||
|
function deprecationWarning(options) {
|
|||
|
if (!options.nonegate || !options.nocomment) {
|
|||
|
if (process.noDeprecation !== true && !exports.deprecationWarned) {
|
|||
|
var msg = 'glob WARNING: comments and negation will be disabled in v6'
|
|||
|
if (process.throwDeprecation)
|
|||
|
throw new Error(msg)
|
|||
|
else if (process.traceDeprecation)
|
|||
|
console.trace(msg)
|
|||
|
else
|
|||
|
console.error(msg)
|
|||
|
|
|||
|
exports.deprecationWarned = true
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function finish (self) {
|
|||
|
var nou = self.nounique
|
|||
|
var all = nou ? [] : Object.create(null)
|
|||
|
|
|||
|
for (var i = 0, l = self.matches.length; i < l; i ++) {
|
|||
|
var matches = self.matches[i]
|
|||
|
if (!matches || Object.keys(matches).length === 0) {
|
|||
|
if (self.nonull) {
|
|||
|
// do like the shell, and spit out the literal glob
|
|||
|
var literal = self.minimatch.globSet[i]
|
|||
|
if (nou)
|
|||
|
all.push(literal)
|
|||
|
else
|
|||
|
all[literal] = true
|
|||
|
}
|
|||
|
} else {
|
|||
|
// had matches
|
|||
|
var m = Object.keys(matches)
|
|||
|
if (nou)
|
|||
|
all.push.apply(all, m)
|
|||
|
else
|
|||
|
m.forEach(function (m) {
|
|||
|
all[m] = true
|
|||
|
})
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!nou)
|
|||
|
all = Object.keys(all)
|
|||
|
|
|||
|
if (!self.nosort)
|
|||
|
all = all.sort(self.nocase ? alphasorti : alphasort)
|
|||
|
|
|||
|
// at *some* point we statted all of these
|
|||
|
if (self.mark) {
|
|||
|
for (var i = 0; i < all.length; i++) {
|
|||
|
all[i] = self._mark(all[i])
|
|||
|
}
|
|||
|
if (self.nodir) {
|
|||
|
all = all.filter(function (e) {
|
|||
|
return !(/\/$/.test(e))
|
|||
|
})
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (self.ignore.length)
|
|||
|
all = all.filter(function(m) {
|
|||
|
return !isIgnored(self, m)
|
|||
|
})
|
|||
|
|
|||
|
self.found = all
|
|||
|
}
|
|||
|
|
|||
|
function mark (self, p) {
|
|||
|
var abs = makeAbs(self, p)
|
|||
|
var c = self.cache[abs]
|
|||
|
var m = p
|
|||
|
if (c) {
|
|||
|
var isDir = c === 'DIR' || Array.isArray(c)
|
|||
|
var slash = p.slice(-1) === '/'
|
|||
|
|
|||
|
if (isDir && !slash)
|
|||
|
m += '/'
|
|||
|
else if (!isDir && slash)
|
|||
|
m = m.slice(0, -1)
|
|||
|
|
|||
|
if (m !== p) {
|
|||
|
var mabs = makeAbs(self, m)
|
|||
|
self.statCache[mabs] = self.statCache[abs]
|
|||
|
self.cache[mabs] = self.cache[abs]
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return m
|
|||
|
}
|
|||
|
|
|||
|
// lotta situps...
|
|||
|
function makeAbs (self, f) {
|
|||
|
var abs = f
|
|||
|
if (f.charAt(0) === '/') {
|
|||
|
abs = path.join(self.root, f)
|
|||
|
} else if (isAbsolute(f) || f === '') {
|
|||
|
abs = f
|
|||
|
} else if (self.changedCwd) {
|
|||
|
abs = path.resolve(self.cwd, f)
|
|||
|
} else {
|
|||
|
abs = path.resolve(f)
|
|||
|
}
|
|||
|
return abs
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// Return true, if pattern ends with globstar '**', for the accompanying parent directory.
|
|||
|
// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents
|
|||
|
function isIgnored (self, path) {
|
|||
|
if (!self.ignore.length)
|
|||
|
return false
|
|||
|
|
|||
|
return self.ignore.some(function(item) {
|
|||
|
return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path))
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function childrenIgnored (self, path) {
|
|||
|
if (!self.ignore.length)
|
|||
|
return false
|
|||
|
|
|||
|
return self.ignore.some(function(item) {
|
|||
|
return !!(item.gmatcher && item.gmatcher.match(path))
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
}).call(this,require('_process'))
|
|||
|
},{"_process":24,"minimatch":20,"path":22,"path-is-absolute":23}],16:[function(require,module,exports){
|
|||
|
(function (process){
|
|||
|
// Approach:
|
|||
|
//
|
|||
|
// 1. Get the minimatch set
|
|||
|
// 2. For each pattern in the set, PROCESS(pattern, false)
|
|||
|
// 3. Store matches per-set, then uniq them
|
|||
|
//
|
|||
|
// PROCESS(pattern, inGlobStar)
|
|||
|
// Get the first [n] items from pattern that are all strings
|
|||
|
// Join these together. This is PREFIX.
|
|||
|
// If there is no more remaining, then stat(PREFIX) and
|
|||
|
// add to matches if it succeeds. END.
|
|||
|
//
|
|||
|
// If inGlobStar and PREFIX is symlink and points to dir
|
|||
|
// set ENTRIES = []
|
|||
|
// else readdir(PREFIX) as ENTRIES
|
|||
|
// If fail, END
|
|||
|
//
|
|||
|
// with ENTRIES
|
|||
|
// If pattern[n] is GLOBSTAR
|
|||
|
// // handle the case where the globstar match is empty
|
|||
|
// // by pruning it out, and testing the resulting pattern
|
|||
|
// PROCESS(pattern[0..n] + pattern[n+1 .. $], false)
|
|||
|
// // handle other cases.
|
|||
|
// for ENTRY in ENTRIES (not dotfiles)
|
|||
|
// // attach globstar + tail onto the entry
|
|||
|
// // Mark that this entry is a globstar match
|
|||
|
// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true)
|
|||
|
//
|
|||
|
// else // not globstar
|
|||
|
// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot)
|
|||
|
// Test ENTRY against pattern[n]
|
|||
|
// If fails, continue
|
|||
|
// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $])
|
|||
|
//
|
|||
|
// Caveat:
|
|||
|
// Cache all stats and readdirs results to minimize syscall. Since all
|
|||
|
// we ever care about is existence and directory-ness, we can just keep
|
|||
|
// `true` for files, and [children,...] for directories, or `false` for
|
|||
|
// things that don't exist.
|
|||
|
|
|||
|
module.exports = glob
|
|||
|
|
|||
|
var fs = require('fs')
|
|||
|
var minimatch = require('minimatch')
|
|||
|
var Minimatch = minimatch.Minimatch
|
|||
|
var inherits = require('inherits')
|
|||
|
var EE = require('events').EventEmitter
|
|||
|
var path = require('path')
|
|||
|
var assert = require('assert')
|
|||
|
var isAbsolute = require('path-is-absolute')
|
|||
|
var globSync = require('./sync.js')
|
|||
|
var common = require('./common.js')
|
|||
|
var alphasort = common.alphasort
|
|||
|
var alphasorti = common.alphasorti
|
|||
|
var setopts = common.setopts
|
|||
|
var ownProp = common.ownProp
|
|||
|
var inflight = require('inflight')
|
|||
|
var util = require('util')
|
|||
|
var childrenIgnored = common.childrenIgnored
|
|||
|
var isIgnored = common.isIgnored
|
|||
|
|
|||
|
var once = require('once')
|
|||
|
|
|||
|
function glob (pattern, options, cb) {
|
|||
|
if (typeof options === 'function') cb = options, options = {}
|
|||
|
if (!options) options = {}
|
|||
|
|
|||
|
if (options.sync) {
|
|||
|
if (cb)
|
|||
|
throw new TypeError('callback provided to sync glob')
|
|||
|
return globSync(pattern, options)
|
|||
|
}
|
|||
|
|
|||
|
return new Glob(pattern, options, cb)
|
|||
|
}
|
|||
|
|
|||
|
glob.sync = globSync
|
|||
|
var GlobSync = glob.GlobSync = globSync.GlobSync
|
|||
|
|
|||
|
// old api surface
|
|||
|
glob.glob = glob
|
|||
|
|
|||
|
glob.hasMagic = function (pattern, options_) {
|
|||
|
var options = util._extend({}, options_)
|
|||
|
options.noprocess = true
|
|||
|
|
|||
|
var g = new Glob(pattern, options)
|
|||
|
var set = g.minimatch.set
|
|||
|
if (set.length > 1)
|
|||
|
return true
|
|||
|
|
|||
|
for (var j = 0; j < set[0].length; j++) {
|
|||
|
if (typeof set[0][j] !== 'string')
|
|||
|
return true
|
|||
|
}
|
|||
|
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
glob.Glob = Glob
|
|||
|
inherits(Glob, EE)
|
|||
|
function Glob (pattern, options, cb) {
|
|||
|
if (typeof options === 'function') {
|
|||
|
cb = options
|
|||
|
options = null
|
|||
|
}
|
|||
|
|
|||
|
if (options && options.sync) {
|
|||
|
if (cb)
|
|||
|
throw new TypeError('callback provided to sync glob')
|
|||
|
return new GlobSync(pattern, options)
|
|||
|
}
|
|||
|
|
|||
|
if (!(this instanceof Glob))
|
|||
|
return new Glob(pattern, options, cb)
|
|||
|
|
|||
|
setopts(this, pattern, options)
|
|||
|
this._didRealPath = false
|
|||
|
|
|||
|
// process each pattern in the minimatch set
|
|||
|
var n = this.minimatch.set.length
|
|||
|
|
|||
|
// The matches are stored as {<filename>: true,...} so that
|
|||
|
// duplicates are automagically pruned.
|
|||
|
// Later, we do an Object.keys() on these.
|
|||
|
// Keep them as a list so we can fill in when nonull is set.
|
|||
|
this.matches = new Array(n)
|
|||
|
|
|||
|
if (typeof cb === 'function') {
|
|||
|
cb = once(cb)
|
|||
|
this.on('error', cb)
|
|||
|
this.on('end', function (matches) {
|
|||
|
cb(null, matches)
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
var self = this
|
|||
|
var n = this.minimatch.set.length
|
|||
|
this._processing = 0
|
|||
|
this.matches = new Array(n)
|
|||
|
|
|||
|
this._emitQueue = []
|
|||
|
this._processQueue = []
|
|||
|
this.paused = false
|
|||
|
|
|||
|
if (this.noprocess)
|
|||
|
return this
|
|||
|
|
|||
|
if (n === 0)
|
|||
|
return done()
|
|||
|
|
|||
|
for (var i = 0; i < n; i ++) {
|
|||
|
this._process(this.minimatch.set[i], i, false, done)
|
|||
|
}
|
|||
|
|
|||
|
function done () {
|
|||
|
--self._processing
|
|||
|
if (self._processing <= 0)
|
|||
|
self._finish()
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype._finish = function () {
|
|||
|
assert(this instanceof Glob)
|
|||
|
if (this.aborted)
|
|||
|
return
|
|||
|
|
|||
|
if (this.realpath && !this._didRealpath)
|
|||
|
return this._realpath()
|
|||
|
|
|||
|
common.finish(this)
|
|||
|
this.emit('end', this.found)
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype._realpath = function () {
|
|||
|
if (this._didRealpath)
|
|||
|
return
|
|||
|
|
|||
|
this._didRealpath = true
|
|||
|
|
|||
|
var n = this.matches.length
|
|||
|
if (n === 0)
|
|||
|
return this._finish()
|
|||
|
|
|||
|
var self = this
|
|||
|
for (var i = 0; i < this.matches.length; i++)
|
|||
|
this._realpathSet(i, next)
|
|||
|
|
|||
|
function next () {
|
|||
|
if (--n === 0)
|
|||
|
self._finish()
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype._realpathSet = function (index, cb) {
|
|||
|
var matchset = this.matches[index]
|
|||
|
if (!matchset)
|
|||
|
return cb()
|
|||
|
|
|||
|
var found = Object.keys(matchset)
|
|||
|
var self = this
|
|||
|
var n = found.length
|
|||
|
|
|||
|
if (n === 0)
|
|||
|
return cb()
|
|||
|
|
|||
|
var set = this.matches[index] = Object.create(null)
|
|||
|
found.forEach(function (p, i) {
|
|||
|
// If there's a problem with the stat, then it means that
|
|||
|
// one or more of the links in the realpath couldn't be
|
|||
|
// resolved. just return the abs value in that case.
|
|||
|
p = self._makeAbs(p)
|
|||
|
fs.realpath(p, self.realpathCache, function (er, real) {
|
|||
|
if (!er)
|
|||
|
set[real] = true
|
|||
|
else if (er.syscall === 'stat')
|
|||
|
set[p] = true
|
|||
|
else
|
|||
|
self.emit('error', er) // srsly wtf right here
|
|||
|
|
|||
|
if (--n === 0) {
|
|||
|
self.matches[index] = set
|
|||
|
cb()
|
|||
|
}
|
|||
|
})
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype._mark = function (p) {
|
|||
|
return common.mark(this, p)
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype._makeAbs = function (f) {
|
|||
|
return common.makeAbs(this, f)
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype.abort = function () {
|
|||
|
this.aborted = true
|
|||
|
this.emit('abort')
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype.pause = function () {
|
|||
|
if (!this.paused) {
|
|||
|
this.paused = true
|
|||
|
this.emit('pause')
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype.resume = function () {
|
|||
|
if (this.paused) {
|
|||
|
this.emit('resume')
|
|||
|
this.paused = false
|
|||
|
if (this._emitQueue.length) {
|
|||
|
var eq = this._emitQueue.slice(0)
|
|||
|
this._emitQueue.length = 0
|
|||
|
for (var i = 0; i < eq.length; i ++) {
|
|||
|
var e = eq[i]
|
|||
|
this._emitMatch(e[0], e[1])
|
|||
|
}
|
|||
|
}
|
|||
|
if (this._processQueue.length) {
|
|||
|
var pq = this._processQueue.slice(0)
|
|||
|
this._processQueue.length = 0
|
|||
|
for (var i = 0; i < pq.length; i ++) {
|
|||
|
var p = pq[i]
|
|||
|
this._processing--
|
|||
|
this._process(p[0], p[1], p[2], p[3])
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype._process = function (pattern, index, inGlobStar, cb) {
|
|||
|
assert(this instanceof Glob)
|
|||
|
assert(typeof cb === 'function')
|
|||
|
|
|||
|
if (this.aborted)
|
|||
|
return
|
|||
|
|
|||
|
this._processing++
|
|||
|
if (this.paused) {
|
|||
|
this._processQueue.push([pattern, index, inGlobStar, cb])
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
//console.error('PROCESS %d', this._processing, pattern)
|
|||
|
|
|||
|
// Get the first [n] parts of pattern that are all strings.
|
|||
|
var n = 0
|
|||
|
while (typeof pattern[n] === 'string') {
|
|||
|
n ++
|
|||
|
}
|
|||
|
// now n is the index of the first one that is *not* a string.
|
|||
|
|
|||
|
// see if there's anything else
|
|||
|
var prefix
|
|||
|
switch (n) {
|
|||
|
// if not, then this is rather simple
|
|||
|
case pattern.length:
|
|||
|
this._processSimple(pattern.join('/'), index, cb)
|
|||
|
return
|
|||
|
|
|||
|
case 0:
|
|||
|
// pattern *starts* with some non-trivial item.
|
|||
|
// going to readdir(cwd), but not include the prefix in matches.
|
|||
|
prefix = null
|
|||
|
break
|
|||
|
|
|||
|
default:
|
|||
|
// pattern has some string bits in the front.
|
|||
|
// whatever it starts with, whether that's 'absolute' like /foo/bar,
|
|||
|
// or 'relative' like '../baz'
|
|||
|
prefix = pattern.slice(0, n).join('/')
|
|||
|
break
|
|||
|
}
|
|||
|
|
|||
|
var remain = pattern.slice(n)
|
|||
|
|
|||
|
// get the list of entries.
|
|||
|
var read
|
|||
|
if (prefix === null)
|
|||
|
read = '.'
|
|||
|
else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) {
|
|||
|
if (!prefix || !isAbsolute(prefix))
|
|||
|
prefix = '/' + prefix
|
|||
|
read = prefix
|
|||
|
} else
|
|||
|
read = prefix
|
|||
|
|
|||
|
var abs = this._makeAbs(read)
|
|||
|
|
|||
|
//if ignored, skip _processing
|
|||
|
if (childrenIgnored(this, read))
|
|||
|
return cb()
|
|||
|
|
|||
|
var isGlobStar = remain[0] === minimatch.GLOBSTAR
|
|||
|
if (isGlobStar)
|
|||
|
this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb)
|
|||
|
else
|
|||
|
this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb)
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) {
|
|||
|
var self = this
|
|||
|
this._readdir(abs, inGlobStar, function (er, entries) {
|
|||
|
return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
|
|||
|
|
|||
|
// if the abs isn't a dir, then nothing can match!
|
|||
|
if (!entries)
|
|||
|
return cb()
|
|||
|
|
|||
|
// It will only match dot entries if it starts with a dot, or if
|
|||
|
// dot is set. Stuff like @(.foo|.bar) isn't allowed.
|
|||
|
var pn = remain[0]
|
|||
|
var negate = !!this.minimatch.negate
|
|||
|
var rawGlob = pn._glob
|
|||
|
var dotOk = this.dot || rawGlob.charAt(0) === '.'
|
|||
|
|
|||
|
var matchedEntries = []
|
|||
|
for (var i = 0; i < entries.length; i++) {
|
|||
|
var e = entries[i]
|
|||
|
if (e.charAt(0) !== '.' || dotOk) {
|
|||
|
var m
|
|||
|
if (negate && !prefix) {
|
|||
|
m = !e.match(pn)
|
|||
|
} else {
|
|||
|
m = e.match(pn)
|
|||
|
}
|
|||
|
if (m)
|
|||
|
matchedEntries.push(e)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries)
|
|||
|
|
|||
|
var len = matchedEntries.length
|
|||
|
// If there are no matched entries, then nothing matches.
|
|||
|
if (len === 0)
|
|||
|
return cb()
|
|||
|
|
|||
|
// if this is the last remaining pattern bit, then no need for
|
|||
|
// an additional stat *unless* the user has specified mark or
|
|||
|
// stat explicitly. We know they exist, since readdir returned
|
|||
|
// them.
|
|||
|
|
|||
|
if (remain.length === 1 && !this.mark && !this.stat) {
|
|||
|
if (!this.matches[index])
|
|||
|
this.matches[index] = Object.create(null)
|
|||
|
|
|||
|
for (var i = 0; i < len; i ++) {
|
|||
|
var e = matchedEntries[i]
|
|||
|
if (prefix) {
|
|||
|
if (prefix !== '/')
|
|||
|
e = prefix + '/' + e
|
|||
|
else
|
|||
|
e = prefix + e
|
|||
|
}
|
|||
|
|
|||
|
if (e.charAt(0) === '/' && !this.nomount) {
|
|||
|
e = path.join(this.root, e)
|
|||
|
}
|
|||
|
this._emitMatch(index, e)
|
|||
|
}
|
|||
|
// This was the last one, and no stats were needed
|
|||
|
return cb()
|
|||
|
}
|
|||
|
|
|||
|
// now test all matched entries as stand-ins for that part
|
|||
|
// of the pattern.
|
|||
|
remain.shift()
|
|||
|
for (var i = 0; i < len; i ++) {
|
|||
|
var e = matchedEntries[i]
|
|||
|
var newPattern
|
|||
|
if (prefix) {
|
|||
|
if (prefix !== '/')
|
|||
|
e = prefix + '/' + e
|
|||
|
else
|
|||
|
e = prefix + e
|
|||
|
}
|
|||
|
this._process([e].concat(remain), index, inGlobStar, cb)
|
|||
|
}
|
|||
|
cb()
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype._emitMatch = function (index, e) {
|
|||
|
if (this.aborted)
|
|||
|
return
|
|||
|
|
|||
|
if (this.matches[index][e])
|
|||
|
return
|
|||
|
|
|||
|
if (isIgnored(this, e))
|
|||
|
return
|
|||
|
|
|||
|
if (this.paused) {
|
|||
|
this._emitQueue.push([index, e])
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
var abs = this._makeAbs(e)
|
|||
|
|
|||
|
if (this.nodir) {
|
|||
|
var c = this.cache[abs]
|
|||
|
if (c === 'DIR' || Array.isArray(c))
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
if (this.mark)
|
|||
|
e = this._mark(e)
|
|||
|
|
|||
|
this.matches[index][e] = true
|
|||
|
|
|||
|
var st = this.statCache[abs]
|
|||
|
if (st)
|
|||
|
this.emit('stat', e, st)
|
|||
|
|
|||
|
this.emit('match', e)
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype._readdirInGlobStar = function (abs, cb) {
|
|||
|
if (this.aborted)
|
|||
|
return
|
|||
|
|
|||
|
// follow all symlinked directories forever
|
|||
|
// just proceed as if this is a non-globstar situation
|
|||
|
if (this.follow)
|
|||
|
return this._readdir(abs, false, cb)
|
|||
|
|
|||
|
var lstatkey = 'lstat\0' + abs
|
|||
|
var self = this
|
|||
|
var lstatcb = inflight(lstatkey, lstatcb_)
|
|||
|
|
|||
|
if (lstatcb)
|
|||
|
fs.lstat(abs, lstatcb)
|
|||
|
|
|||
|
function lstatcb_ (er, lstat) {
|
|||
|
if (er)
|
|||
|
return cb()
|
|||
|
|
|||
|
var isSym = lstat.isSymbolicLink()
|
|||
|
self.symlinks[abs] = isSym
|
|||
|
|
|||
|
// If it's not a symlink or a dir, then it's definitely a regular file.
|
|||
|
// don't bother doing a readdir in that case.
|
|||
|
if (!isSym && !lstat.isDirectory()) {
|
|||
|
self.cache[abs] = 'FILE'
|
|||
|
cb()
|
|||
|
} else
|
|||
|
self._readdir(abs, false, cb)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype._readdir = function (abs, inGlobStar, cb) {
|
|||
|
if (this.aborted)
|
|||
|
return
|
|||
|
|
|||
|
cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb)
|
|||
|
if (!cb)
|
|||
|
return
|
|||
|
|
|||
|
//console.error('RD %j %j', +inGlobStar, abs)
|
|||
|
if (inGlobStar && !ownProp(this.symlinks, abs))
|
|||
|
return this._readdirInGlobStar(abs, cb)
|
|||
|
|
|||
|
if (ownProp(this.cache, abs)) {
|
|||
|
var c = this.cache[abs]
|
|||
|
if (!c || c === 'FILE')
|
|||
|
return cb()
|
|||
|
|
|||
|
if (Array.isArray(c))
|
|||
|
return cb(null, c)
|
|||
|
}
|
|||
|
|
|||
|
var self = this
|
|||
|
fs.readdir(abs, readdirCb(this, abs, cb))
|
|||
|
}
|
|||
|
|
|||
|
function readdirCb (self, abs, cb) {
|
|||
|
return function (er, entries) {
|
|||
|
if (er)
|
|||
|
self._readdirError(abs, er, cb)
|
|||
|
else
|
|||
|
self._readdirEntries(abs, entries, cb)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype._readdirEntries = function (abs, entries, cb) {
|
|||
|
if (this.aborted)
|
|||
|
return
|
|||
|
|
|||
|
// if we haven't asked to stat everything, then just
|
|||
|
// assume that everything in there exists, so we can avoid
|
|||
|
// having to stat it a second time.
|
|||
|
if (!this.mark && !this.stat) {
|
|||
|
for (var i = 0; i < entries.length; i ++) {
|
|||
|
var e = entries[i]
|
|||
|
if (abs === '/')
|
|||
|
e = abs + e
|
|||
|
else
|
|||
|
e = abs + '/' + e
|
|||
|
this.cache[e] = true
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
this.cache[abs] = entries
|
|||
|
return cb(null, entries)
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype._readdirError = function (f, er, cb) {
|
|||
|
if (this.aborted)
|
|||
|
return
|
|||
|
|
|||
|
// handle errors, and cache the information
|
|||
|
switch (er.code) {
|
|||
|
case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205
|
|||
|
case 'ENOTDIR': // totally normal. means it *does* exist.
|
|||
|
this.cache[this._makeAbs(f)] = 'FILE'
|
|||
|
break
|
|||
|
|
|||
|
case 'ENOENT': // not terribly unusual
|
|||
|
case 'ELOOP':
|
|||
|
case 'ENAMETOOLONG':
|
|||
|
case 'UNKNOWN':
|
|||
|
this.cache[this._makeAbs(f)] = false
|
|||
|
break
|
|||
|
|
|||
|
default: // some unusual error. Treat as failure.
|
|||
|
this.cache[this._makeAbs(f)] = false
|
|||
|
if (this.strict) {
|
|||
|
this.emit('error', er)
|
|||
|
// If the error is handled, then we abort
|
|||
|
// if not, we threw out of here
|
|||
|
this.abort()
|
|||
|
}
|
|||
|
if (!this.silent)
|
|||
|
console.error('glob error', er)
|
|||
|
break
|
|||
|
}
|
|||
|
|
|||
|
return cb()
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) {
|
|||
|
var self = this
|
|||
|
this._readdir(abs, inGlobStar, function (er, entries) {
|
|||
|
self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
|
|||
|
//console.error('pgs2', prefix, remain[0], entries)
|
|||
|
|
|||
|
// no entries means not a dir, so it can never have matches
|
|||
|
// foo.txt/** doesn't match foo.txt
|
|||
|
if (!entries)
|
|||
|
return cb()
|
|||
|
|
|||
|
// test without the globstar, and with every child both below
|
|||
|
// and replacing the globstar.
|
|||
|
var remainWithoutGlobStar = remain.slice(1)
|
|||
|
var gspref = prefix ? [ prefix ] : []
|
|||
|
var noGlobStar = gspref.concat(remainWithoutGlobStar)
|
|||
|
|
|||
|
// the noGlobStar pattern exits the inGlobStar state
|
|||
|
this._process(noGlobStar, index, false, cb)
|
|||
|
|
|||
|
var isSym = this.symlinks[abs]
|
|||
|
var len = entries.length
|
|||
|
|
|||
|
// If it's a symlink, and we're in a globstar, then stop
|
|||
|
if (isSym && inGlobStar)
|
|||
|
return cb()
|
|||
|
|
|||
|
for (var i = 0; i < len; i++) {
|
|||
|
var e = entries[i]
|
|||
|
if (e.charAt(0) === '.' && !this.dot)
|
|||
|
continue
|
|||
|
|
|||
|
// these two cases enter the inGlobStar state
|
|||
|
var instead = gspref.concat(entries[i], remainWithoutGlobStar)
|
|||
|
this._process(instead, index, true, cb)
|
|||
|
|
|||
|
var below = gspref.concat(entries[i], remain)
|
|||
|
this._process(below, index, true, cb)
|
|||
|
}
|
|||
|
|
|||
|
cb()
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype._processSimple = function (prefix, index, cb) {
|
|||
|
// XXX review this. Shouldn't it be doing the mounting etc
|
|||
|
// before doing stat? kinda weird?
|
|||
|
var self = this
|
|||
|
this._stat(prefix, function (er, exists) {
|
|||
|
self._processSimple2(prefix, index, er, exists, cb)
|
|||
|
})
|
|||
|
}
|
|||
|
Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) {
|
|||
|
|
|||
|
//console.error('ps2', prefix, exists)
|
|||
|
|
|||
|
if (!this.matches[index])
|
|||
|
this.matches[index] = Object.create(null)
|
|||
|
|
|||
|
// If it doesn't exist, then just mark the lack of results
|
|||
|
if (!exists)
|
|||
|
return cb()
|
|||
|
|
|||
|
if (prefix && isAbsolute(prefix) && !this.nomount) {
|
|||
|
var trail = /[\/\\]$/.test(prefix)
|
|||
|
if (prefix.charAt(0) === '/') {
|
|||
|
prefix = path.join(this.root, prefix)
|
|||
|
} else {
|
|||
|
prefix = path.resolve(this.root, prefix)
|
|||
|
if (trail)
|
|||
|
prefix += '/'
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (process.platform === 'win32')
|
|||
|
prefix = prefix.replace(/\\/g, '/')
|
|||
|
|
|||
|
// Mark this as a match
|
|||
|
this._emitMatch(index, prefix)
|
|||
|
cb()
|
|||
|
}
|
|||
|
|
|||
|
// Returns either 'DIR', 'FILE', or false
|
|||
|
Glob.prototype._stat = function (f, cb) {
|
|||
|
var abs = this._makeAbs(f)
|
|||
|
var needDir = f.slice(-1) === '/'
|
|||
|
|
|||
|
if (f.length > this.maxLength)
|
|||
|
return cb()
|
|||
|
|
|||
|
if (!this.stat && ownProp(this.cache, abs)) {
|
|||
|
var c = this.cache[abs]
|
|||
|
|
|||
|
if (Array.isArray(c))
|
|||
|
c = 'DIR'
|
|||
|
|
|||
|
// It exists, but maybe not how we need it
|
|||
|
if (!needDir || c === 'DIR')
|
|||
|
return cb(null, c)
|
|||
|
|
|||
|
if (needDir && c === 'FILE')
|
|||
|
return cb()
|
|||
|
|
|||
|
// otherwise we have to stat, because maybe c=true
|
|||
|
// if we know it exists, but not what it is.
|
|||
|
}
|
|||
|
|
|||
|
var exists
|
|||
|
var stat = this.statCache[abs]
|
|||
|
if (stat !== undefined) {
|
|||
|
if (stat === false)
|
|||
|
return cb(null, stat)
|
|||
|
else {
|
|||
|
var type = stat.isDirectory() ? 'DIR' : 'FILE'
|
|||
|
if (needDir && type === 'FILE')
|
|||
|
return cb()
|
|||
|
else
|
|||
|
return cb(null, type, stat)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var self = this
|
|||
|
var statcb = inflight('stat\0' + abs, lstatcb_)
|
|||
|
if (statcb)
|
|||
|
fs.lstat(abs, statcb)
|
|||
|
|
|||
|
function lstatcb_ (er, lstat) {
|
|||
|
if (lstat && lstat.isSymbolicLink()) {
|
|||
|
// If it's a symlink, then treat it as the target, unless
|
|||
|
// the target does not exist, then treat it as a file.
|
|||
|
return fs.stat(abs, function (er, stat) {
|
|||
|
if (er)
|
|||
|
self._stat2(f, abs, null, lstat, cb)
|
|||
|
else
|
|||
|
self._stat2(f, abs, er, stat, cb)
|
|||
|
})
|
|||
|
} else {
|
|||
|
self._stat2(f, abs, er, lstat, cb)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Glob.prototype._stat2 = function (f, abs, er, stat, cb) {
|
|||
|
if (er) {
|
|||
|
this.statCache[abs] = false
|
|||
|
return cb()
|
|||
|
}
|
|||
|
|
|||
|
var needDir = f.slice(-1) === '/'
|
|||
|
this.statCache[abs] = stat
|
|||
|
|
|||
|
if (abs.slice(-1) === '/' && !stat.isDirectory())
|
|||
|
return cb(null, false, stat)
|
|||
|
|
|||
|
var c = stat.isDirectory() ? 'DIR' : 'FILE'
|
|||
|
this.cache[abs] = this.cache[abs] || c
|
|||
|
|
|||
|
if (needDir && c !== 'DIR')
|
|||
|
return cb()
|
|||
|
|
|||
|
return cb(null, c, stat)
|
|||
|
}
|
|||
|
|
|||
|
}).call(this,require('_process'))
|
|||
|
},{"./common.js":15,"./sync.js":17,"_process":24,"assert":9,"events":14,"fs":12,"inflight":18,"inherits":19,"minimatch":20,"once":21,"path":22,"path-is-absolute":23,"util":28}],17:[function(require,module,exports){
|
|||
|
(function (process){
|
|||
|
module.exports = globSync
|
|||
|
globSync.GlobSync = GlobSync
|
|||
|
|
|||
|
var fs = require('fs')
|
|||
|
var minimatch = require('minimatch')
|
|||
|
var Minimatch = minimatch.Minimatch
|
|||
|
var Glob = require('./glob.js').Glob
|
|||
|
var util = require('util')
|
|||
|
var path = require('path')
|
|||
|
var assert = require('assert')
|
|||
|
var isAbsolute = require('path-is-absolute')
|
|||
|
var common = require('./common.js')
|
|||
|
var alphasort = common.alphasort
|
|||
|
var alphasorti = common.alphasorti
|
|||
|
var setopts = common.setopts
|
|||
|
var ownProp = common.ownProp
|
|||
|
var childrenIgnored = common.childrenIgnored
|
|||
|
|
|||
|
function globSync (pattern, options) {
|
|||
|
if (typeof options === 'function' || arguments.length === 3)
|
|||
|
throw new TypeError('callback provided to sync glob\n'+
|
|||
|
'See: https://github.com/isaacs/node-glob/issues/167')
|
|||
|
|
|||
|
return new GlobSync(pattern, options).found
|
|||
|
}
|
|||
|
|
|||
|
function GlobSync (pattern, options) {
|
|||
|
if (!pattern)
|
|||
|
throw new Error('must provide pattern')
|
|||
|
|
|||
|
if (typeof options === 'function' || arguments.length === 3)
|
|||
|
throw new TypeError('callback provided to sync glob\n'+
|
|||
|
'See: https://github.com/isaacs/node-glob/issues/167')
|
|||
|
|
|||
|
if (!(this instanceof GlobSync))
|
|||
|
return new GlobSync(pattern, options)
|
|||
|
|
|||
|
setopts(this, pattern, options)
|
|||
|
|
|||
|
if (this.noprocess)
|
|||
|
return this
|
|||
|
|
|||
|
var n = this.minimatch.set.length
|
|||
|
this.matches = new Array(n)
|
|||
|
for (var i = 0; i < n; i ++) {
|
|||
|
this._process(this.minimatch.set[i], i, false)
|
|||
|
}
|
|||
|
this._finish()
|
|||
|
}
|
|||
|
|
|||
|
GlobSync.prototype._finish = function () {
|
|||
|
assert(this instanceof GlobSync)
|
|||
|
if (this.realpath) {
|
|||
|
var self = this
|
|||
|
this.matches.forEach(function (matchset, index) {
|
|||
|
var set = self.matches[index] = Object.create(null)
|
|||
|
for (var p in matchset) {
|
|||
|
try {
|
|||
|
p = self._makeAbs(p)
|
|||
|
var real = fs.realpathSync(p, self.realpathCache)
|
|||
|
set[real] = true
|
|||
|
} catch (er) {
|
|||
|
if (er.syscall === 'stat')
|
|||
|
set[self._makeAbs(p)] = true
|
|||
|
else
|
|||
|
throw er
|
|||
|
}
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
common.finish(this)
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
GlobSync.prototype._process = function (pattern, index, inGlobStar) {
|
|||
|
assert(this instanceof GlobSync)
|
|||
|
|
|||
|
// Get the first [n] parts of pattern that are all strings.
|
|||
|
var n = 0
|
|||
|
while (typeof pattern[n] === 'string') {
|
|||
|
n ++
|
|||
|
}
|
|||
|
// now n is the index of the first one that is *not* a string.
|
|||
|
|
|||
|
// See if there's anything else
|
|||
|
var prefix
|
|||
|
switch (n) {
|
|||
|
// if not, then this is rather simple
|
|||
|
case pattern.length:
|
|||
|
this._processSimple(pattern.join('/'), index)
|
|||
|
return
|
|||
|
|
|||
|
case 0:
|
|||
|
// pattern *starts* with some non-trivial item.
|
|||
|
// going to readdir(cwd), but not include the prefix in matches.
|
|||
|
prefix = null
|
|||
|
break
|
|||
|
|
|||
|
default:
|
|||
|
// pattern has some string bits in the front.
|
|||
|
// whatever it starts with, whether that's 'absolute' like /foo/bar,
|
|||
|
// or 'relative' like '../baz'
|
|||
|
prefix = pattern.slice(0, n).join('/')
|
|||
|
break
|
|||
|
}
|
|||
|
|
|||
|
var remain = pattern.slice(n)
|
|||
|
|
|||
|
// get the list of entries.
|
|||
|
var read
|
|||
|
if (prefix === null)
|
|||
|
read = '.'
|
|||
|
else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) {
|
|||
|
if (!prefix || !isAbsolute(prefix))
|
|||
|
prefix = '/' + prefix
|
|||
|
read = prefix
|
|||
|
} else
|
|||
|
read = prefix
|
|||
|
|
|||
|
var abs = this._makeAbs(read)
|
|||
|
|
|||
|
//if ignored, skip processing
|
|||
|
if (childrenIgnored(this, read))
|
|||
|
return
|
|||
|
|
|||
|
var isGlobStar = remain[0] === minimatch.GLOBSTAR
|
|||
|
if (isGlobStar)
|
|||
|
this._processGlobStar(prefix, read, abs, remain, index, inGlobStar)
|
|||
|
else
|
|||
|
this._processReaddir(prefix, read, abs, remain, index, inGlobStar)
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) {
|
|||
|
var entries = this._readdir(abs, inGlobStar)
|
|||
|
|
|||
|
// if the abs isn't a dir, then nothing can match!
|
|||
|
if (!entries)
|
|||
|
return
|
|||
|
|
|||
|
// It will only match dot entries if it starts with a dot, or if
|
|||
|
// dot is set. Stuff like @(.foo|.bar) isn't allowed.
|
|||
|
var pn = remain[0]
|
|||
|
var negate = !!this.minimatch.negate
|
|||
|
var rawGlob = pn._glob
|
|||
|
var dotOk = this.dot || rawGlob.charAt(0) === '.'
|
|||
|
|
|||
|
var matchedEntries = []
|
|||
|
for (var i = 0; i < entries.length; i++) {
|
|||
|
var e = entries[i]
|
|||
|
if (e.charAt(0) !== '.' || dotOk) {
|
|||
|
var m
|
|||
|
if (negate && !prefix) {
|
|||
|
m = !e.match(pn)
|
|||
|
} else {
|
|||
|
m = e.match(pn)
|
|||
|
}
|
|||
|
if (m)
|
|||
|
matchedEntries.push(e)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var len = matchedEntries.length
|
|||
|
// If there are no matched entries, then nothing matches.
|
|||
|
if (len === 0)
|
|||
|
return
|
|||
|
|
|||
|
// if this is the last remaining pattern bit, then no need for
|
|||
|
// an additional stat *unless* the user has specified mark or
|
|||
|
// stat explicitly. We know they exist, since readdir returned
|
|||
|
// them.
|
|||
|
|
|||
|
if (remain.length === 1 && !this.mark && !this.stat) {
|
|||
|
if (!this.matches[index])
|
|||
|
this.matches[index] = Object.create(null)
|
|||
|
|
|||
|
for (var i = 0; i < len; i ++) {
|
|||
|
var e = matchedEntries[i]
|
|||
|
if (prefix) {
|
|||
|
if (prefix.slice(-1) !== '/')
|
|||
|
e = prefix + '/' + e
|
|||
|
else
|
|||
|
e = prefix + e
|
|||
|
}
|
|||
|
|
|||
|
if (e.charAt(0) === '/' && !this.nomount) {
|
|||
|
e = path.join(this.root, e)
|
|||
|
}
|
|||
|
this.matches[index][e] = true
|
|||
|
}
|
|||
|
// This was the last one, and no stats were needed
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// now test all matched entries as stand-ins for that part
|
|||
|
// of the pattern.
|
|||
|
remain.shift()
|
|||
|
for (var i = 0; i < len; i ++) {
|
|||
|
var e = matchedEntries[i]
|
|||
|
var newPattern
|
|||
|
if (prefix)
|
|||
|
newPattern = [prefix, e]
|
|||
|
else
|
|||
|
newPattern = [e]
|
|||
|
this._process(newPattern.concat(remain), index, inGlobStar)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
GlobSync.prototype._emitMatch = function (index, e) {
|
|||
|
var abs = this._makeAbs(e)
|
|||
|
if (this.mark)
|
|||
|
e = this._mark(e)
|
|||
|
|
|||
|
if (this.matches[index][e])
|
|||
|
return
|
|||
|
|
|||
|
if (this.nodir) {
|
|||
|
var c = this.cache[this._makeAbs(e)]
|
|||
|
if (c === 'DIR' || Array.isArray(c))
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
this.matches[index][e] = true
|
|||
|
if (this.stat)
|
|||
|
this._stat(e)
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
GlobSync.prototype._readdirInGlobStar = function (abs) {
|
|||
|
// follow all symlinked directories forever
|
|||
|
// just proceed as if this is a non-globstar situation
|
|||
|
if (this.follow)
|
|||
|
return this._readdir(abs, false)
|
|||
|
|
|||
|
var entries
|
|||
|
var lstat
|
|||
|
var stat
|
|||
|
try {
|
|||
|
lstat = fs.lstatSync(abs)
|
|||
|
} catch (er) {
|
|||
|
// lstat failed, doesn't exist
|
|||
|
return null
|
|||
|
}
|
|||
|
|
|||
|
var isSym = lstat.isSymbolicLink()
|
|||
|
this.symlinks[abs] = isSym
|
|||
|
|
|||
|
// If it's not a symlink or a dir, then it's definitely a regular file.
|
|||
|
// don't bother doing a readdir in that case.
|
|||
|
if (!isSym && !lstat.isDirectory())
|
|||
|
this.cache[abs] = 'FILE'
|
|||
|
else
|
|||
|
entries = this._readdir(abs, false)
|
|||
|
|
|||
|
return entries
|
|||
|
}
|
|||
|
|
|||
|
GlobSync.prototype._readdir = function (abs, inGlobStar) {
|
|||
|
var entries
|
|||
|
|
|||
|
if (inGlobStar && !ownProp(this.symlinks, abs))
|
|||
|
return this._readdirInGlobStar(abs)
|
|||
|
|
|||
|
if (ownProp(this.cache, abs)) {
|
|||
|
var c = this.cache[abs]
|
|||
|
if (!c || c === 'FILE')
|
|||
|
return null
|
|||
|
|
|||
|
if (Array.isArray(c))
|
|||
|
return c
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
return this._readdirEntries(abs, fs.readdirSync(abs))
|
|||
|
} catch (er) {
|
|||
|
this._readdirError(abs, er)
|
|||
|
return null
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
GlobSync.prototype._readdirEntries = function (abs, entries) {
|
|||
|
// if we haven't asked to stat everything, then just
|
|||
|
// assume that everything in there exists, so we can avoid
|
|||
|
// having to stat it a second time.
|
|||
|
if (!this.mark && !this.stat) {
|
|||
|
for (var i = 0; i < entries.length; i ++) {
|
|||
|
var e = entries[i]
|
|||
|
if (abs === '/')
|
|||
|
e = abs + e
|
|||
|
else
|
|||
|
e = abs + '/' + e
|
|||
|
this.cache[e] = true
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
this.cache[abs] = entries
|
|||
|
|
|||
|
// mark and cache dir-ness
|
|||
|
return entries
|
|||
|
}
|
|||
|
|
|||
|
GlobSync.prototype._readdirError = function (f, er) {
|
|||
|
// handle errors, and cache the information
|
|||
|
switch (er.code) {
|
|||
|
case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205
|
|||
|
case 'ENOTDIR': // totally normal. means it *does* exist.
|
|||
|
this.cache[this._makeAbs(f)] = 'FILE'
|
|||
|
break
|
|||
|
|
|||
|
case 'ENOENT': // not terribly unusual
|
|||
|
case 'ELOOP':
|
|||
|
case 'ENAMETOOLONG':
|
|||
|
case 'UNKNOWN':
|
|||
|
this.cache[this._makeAbs(f)] = false
|
|||
|
break
|
|||
|
|
|||
|
default: // some unusual error. Treat as failure.
|
|||
|
this.cache[this._makeAbs(f)] = false
|
|||
|
if (this.strict)
|
|||
|
throw er
|
|||
|
if (!this.silent)
|
|||
|
console.error('glob error', er)
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) {
|
|||
|
|
|||
|
var entries = this._readdir(abs, inGlobStar)
|
|||
|
|
|||
|
// no entries means not a dir, so it can never have matches
|
|||
|
// foo.txt/** doesn't match foo.txt
|
|||
|
if (!entries)
|
|||
|
return
|
|||
|
|
|||
|
// test without the globstar, and with every child both below
|
|||
|
// and replacing the globstar.
|
|||
|
var remainWithoutGlobStar = remain.slice(1)
|
|||
|
var gspref = prefix ? [ prefix ] : []
|
|||
|
var noGlobStar = gspref.concat(remainWithoutGlobStar)
|
|||
|
|
|||
|
// the noGlobStar pattern exits the inGlobStar state
|
|||
|
this._process(noGlobStar, index, false)
|
|||
|
|
|||
|
var len = entries.length
|
|||
|
var isSym = this.symlinks[abs]
|
|||
|
|
|||
|
// If it's a symlink, and we're in a globstar, then stop
|
|||
|
if (isSym && inGlobStar)
|
|||
|
return
|
|||
|
|
|||
|
for (var i = 0; i < len; i++) {
|
|||
|
var e = entries[i]
|
|||
|
if (e.charAt(0) === '.' && !this.dot)
|
|||
|
continue
|
|||
|
|
|||
|
// these two cases enter the inGlobStar state
|
|||
|
var instead = gspref.concat(entries[i], remainWithoutGlobStar)
|
|||
|
this._process(instead, index, true)
|
|||
|
|
|||
|
var below = gspref.concat(entries[i], remain)
|
|||
|
this._process(below, index, true)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
GlobSync.prototype._processSimple = function (prefix, index) {
|
|||
|
// XXX review this. Shouldn't it be doing the mounting etc
|
|||
|
// before doing stat? kinda weird?
|
|||
|
var exists = this._stat(prefix)
|
|||
|
|
|||
|
if (!this.matches[index])
|
|||
|
this.matches[index] = Object.create(null)
|
|||
|
|
|||
|
// If it doesn't exist, then just mark the lack of results
|
|||
|
if (!exists)
|
|||
|
return
|
|||
|
|
|||
|
if (prefix && isAbsolute(prefix) && !this.nomount) {
|
|||
|
var trail = /[\/\\]$/.test(prefix)
|
|||
|
if (prefix.charAt(0) === '/') {
|
|||
|
prefix = path.join(this.root, prefix)
|
|||
|
} else {
|
|||
|
prefix = path.resolve(this.root, prefix)
|
|||
|
if (trail)
|
|||
|
prefix += '/'
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (process.platform === 'win32')
|
|||
|
prefix = prefix.replace(/\\/g, '/')
|
|||
|
|
|||
|
// Mark this as a match
|
|||
|
this.matches[index][prefix] = true
|
|||
|
}
|
|||
|
|
|||
|
// Returns either 'DIR', 'FILE', or false
|
|||
|
GlobSync.prototype._stat = function (f) {
|
|||
|
var abs = this._makeAbs(f)
|
|||
|
var needDir = f.slice(-1) === '/'
|
|||
|
|
|||
|
if (f.length > this.maxLength)
|
|||
|
return false
|
|||
|
|
|||
|
if (!this.stat && ownProp(this.cache, abs)) {
|
|||
|
var c = this.cache[abs]
|
|||
|
|
|||
|
if (Array.isArray(c))
|
|||
|
c = 'DIR'
|
|||
|
|
|||
|
// It exists, but maybe not how we need it
|
|||
|
if (!needDir || c === 'DIR')
|
|||
|
return c
|
|||
|
|
|||
|
if (needDir && c === 'FILE')
|
|||
|
return false
|
|||
|
|
|||
|
// otherwise we have to stat, because maybe c=true
|
|||
|
// if we know it exists, but not what it is.
|
|||
|
}
|
|||
|
|
|||
|
var exists
|
|||
|
var stat = this.statCache[abs]
|
|||
|
if (!stat) {
|
|||
|
var lstat
|
|||
|
try {
|
|||
|
lstat = fs.lstatSync(abs)
|
|||
|
} catch (er) {
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
if (lstat.isSymbolicLink()) {
|
|||
|
try {
|
|||
|
stat = fs.statSync(abs)
|
|||
|
} catch (er) {
|
|||
|
stat = lstat
|
|||
|
}
|
|||
|
} else {
|
|||
|
stat = lstat
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
this.statCache[abs] = stat
|
|||
|
|
|||
|
var c = stat.isDirectory() ? 'DIR' : 'FILE'
|
|||
|
this.cache[abs] = this.cache[abs] || c
|
|||
|
|
|||
|
if (needDir && c !== 'DIR')
|
|||
|
return false
|
|||
|
|
|||
|
return c
|
|||
|
}
|
|||
|
|
|||
|
GlobSync.prototype._mark = function (p) {
|
|||
|
return common.mark(this, p)
|
|||
|
}
|
|||
|
|
|||
|
GlobSync.prototype._makeAbs = function (f) {
|
|||
|
return common.makeAbs(this, f)
|
|||
|
}
|
|||
|
|
|||
|
}).call(this,require('_process'))
|
|||
|
},{"./common.js":15,"./glob.js":16,"_process":24,"assert":9,"fs":12,"minimatch":20,"path":22,"path-is-absolute":23,"util":28}],18:[function(require,module,exports){
|
|||
|
(function (process){
|
|||
|
var wrappy = require('wrappy')
|
|||
|
var reqs = Object.create(null)
|
|||
|
var once = require('once')
|
|||
|
|
|||
|
module.exports = wrappy(inflight)
|
|||
|
|
|||
|
function inflight (key, cb) {
|
|||
|
if (reqs[key]) {
|
|||
|
reqs[key].push(cb)
|
|||
|
return null
|
|||
|
} else {
|
|||
|
reqs[key] = [cb]
|
|||
|
return makeres(key)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function makeres (key) {
|
|||
|
return once(function RES () {
|
|||
|
var cbs = reqs[key]
|
|||
|
var len = cbs.length
|
|||
|
var args = slice(arguments)
|
|||
|
|
|||
|
// XXX It's somewhat ambiguous whether a new callback added in this
|
|||
|
// pass should be queued for later execution if something in the
|
|||
|
// list of callbacks throws, or if it should just be discarded.
|
|||
|
// However, it's such an edge case that it hardly matters, and either
|
|||
|
// choice is likely as surprising as the other.
|
|||
|
// As it happens, we do go ahead and schedule it for later execution.
|
|||
|
try {
|
|||
|
for (var i = 0; i < len; i++) {
|
|||
|
cbs[i].apply(null, args)
|
|||
|
}
|
|||
|
} finally {
|
|||
|
if (cbs.length > len) {
|
|||
|
// added more in the interim.
|
|||
|
// de-zalgo, just in case, but don't call again.
|
|||
|
cbs.splice(0, len)
|
|||
|
process.nextTick(function () {
|
|||
|
RES.apply(null, args)
|
|||
|
})
|
|||
|
} else {
|
|||
|
delete reqs[key]
|
|||
|
}
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function slice (args) {
|
|||
|
var length = args.length
|
|||
|
var array = []
|
|||
|
|
|||
|
for (var i = 0; i < length; i++) array[i] = args[i]
|
|||
|
return array
|
|||
|
}
|
|||
|
|
|||
|
}).call(this,require('_process'))
|
|||
|
},{"_process":24,"once":21,"wrappy":29}],19:[function(require,module,exports){
|
|||
|
if (typeof Object.create === 'function') {
|
|||
|
// implementation from standard node.js 'util' module
|
|||
|
module.exports = function inherits(ctor, superCtor) {
|
|||
|
ctor.super_ = superCtor
|
|||
|
ctor.prototype = Object.create(superCtor.prototype, {
|
|||
|
constructor: {
|
|||
|
value: ctor,
|
|||
|
enumerable: false,
|
|||
|
writable: true,
|
|||
|
configurable: true
|
|||
|
}
|
|||
|
});
|
|||
|
};
|
|||
|
} else {
|
|||
|
// old school shim for old browsers
|
|||
|
module.exports = function inherits(ctor, superCtor) {
|
|||
|
ctor.super_ = superCtor
|
|||
|
var TempCtor = function () {}
|
|||
|
TempCtor.prototype = superCtor.prototype
|
|||
|
ctor.prototype = new TempCtor()
|
|||
|
ctor.prototype.constructor = ctor
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
},{}],20:[function(require,module,exports){
|
|||
|
module.exports = minimatch
|
|||
|
minimatch.Minimatch = Minimatch
|
|||
|
|
|||
|
var path = { sep: '/' }
|
|||
|
try {
|
|||
|
path = require('path')
|
|||
|
} catch (er) {}
|
|||
|
|
|||
|
var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
|
|||
|
var expand = require('brace-expansion')
|
|||
|
|
|||
|
var plTypes = {
|
|||
|
'!': { open: '(?:(?!(?:', close: '))[^/]*?)'},
|
|||
|
'?': { open: '(?:', close: ')?' },
|
|||
|
'+': { open: '(?:', close: ')+' },
|
|||
|
'*': { open: '(?:', close: ')*' },
|
|||
|
'@': { open: '(?:', close: ')' }
|
|||
|
}
|
|||
|
|
|||
|
// any single thing other than /
|
|||
|
// don't need to escape / when using new RegExp()
|
|||
|
var qmark = '[^/]'
|
|||
|
|
|||
|
// * => any number of characters
|
|||
|
var star = qmark + '*?'
|
|||
|
|
|||
|
// ** when dots are allowed. Anything goes, except .. and .
|
|||
|
// not (^ or / followed by one or two dots followed by $ or /),
|
|||
|
// followed by anything, any number of times.
|
|||
|
var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'
|
|||
|
|
|||
|
// not a ^ or / followed by a dot,
|
|||
|
// followed by anything, any number of times.
|
|||
|
var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'
|
|||
|
|
|||
|
// characters that need to be escaped in RegExp.
|
|||
|
var reSpecials = charSet('().*{}+?[]^$\\!')
|
|||
|
|
|||
|
// "abc" -> { a:true, b:true, c:true }
|
|||
|
function charSet (s) {
|
|||
|
return s.split('').reduce(function (set, c) {
|
|||
|
set[c] = true
|
|||
|
return set
|
|||
|
}, {})
|
|||
|
}
|
|||
|
|
|||
|
// normalizes slashes.
|
|||
|
var slashSplit = /\/+/
|
|||
|
|
|||
|
minimatch.filter = filter
|
|||
|
function filter (pattern, options) {
|
|||
|
options = options || {}
|
|||
|
return function (p, i, list) {
|
|||
|
return minimatch(p, pattern, options)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function ext (a, b) {
|
|||
|
a = a || {}
|
|||
|
b = b || {}
|
|||
|
var t = {}
|
|||
|
Object.keys(b).forEach(function (k) {
|
|||
|
t[k] = b[k]
|
|||
|
})
|
|||
|
Object.keys(a).forEach(function (k) {
|
|||
|
t[k] = a[k]
|
|||
|
})
|
|||
|
return t
|
|||
|
}
|
|||
|
|
|||
|
minimatch.defaults = function (def) {
|
|||
|
if (!def || !Object.keys(def).length) return minimatch
|
|||
|
|
|||
|
var orig = minimatch
|
|||
|
|
|||
|
var m = function minimatch (p, pattern, options) {
|
|||
|
return orig.minimatch(p, pattern, ext(def, options))
|
|||
|
}
|
|||
|
|
|||
|
m.Minimatch = function Minimatch (pattern, options) {
|
|||
|
return new orig.Minimatch(pattern, ext(def, options))
|
|||
|
}
|
|||
|
|
|||
|
return m
|
|||
|
}
|
|||
|
|
|||
|
Minimatch.defaults = function (def) {
|
|||
|
if (!def || !Object.keys(def).length) return Minimatch
|
|||
|
return minimatch.defaults(def).Minimatch
|
|||
|
}
|
|||
|
|
|||
|
function minimatch (p, pattern, options) {
|
|||
|
if (typeof pattern !== 'string') {
|
|||
|
throw new TypeError('glob pattern string required')
|
|||
|
}
|
|||
|
|
|||
|
if (!options) options = {}
|
|||
|
|
|||
|
// shortcut: comments match nothing.
|
|||
|
if (!options.nocomment && pattern.charAt(0) === '#') {
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
// "" only matches ""
|
|||
|
if (pattern.trim() === '') return p === ''
|
|||
|
|
|||
|
return new Minimatch(pattern, options).match(p)
|
|||
|
}
|
|||
|
|
|||
|
function Minimatch (pattern, options) {
|
|||
|
if (!(this instanceof Minimatch)) {
|
|||
|
return new Minimatch(pattern, options)
|
|||
|
}
|
|||
|
|
|||
|
if (typeof pattern !== 'string') {
|
|||
|
throw new TypeError('glob pattern string required')
|
|||
|
}
|
|||
|
|
|||
|
if (!options) options = {}
|
|||
|
pattern = pattern.trim()
|
|||
|
|
|||
|
// windows support: need to use /, not \
|
|||
|
if (path.sep !== '/') {
|
|||
|
pattern = pattern.split(path.sep).join('/')
|
|||
|
}
|
|||
|
|
|||
|
this.options = options
|
|||
|
this.set = []
|
|||
|
this.pattern = pattern
|
|||
|
this.regexp = null
|
|||
|
this.negate = false
|
|||
|
this.comment = false
|
|||
|
this.empty = false
|
|||
|
|
|||
|
// make the set of regexps etc.
|
|||
|
this.make()
|
|||
|
}
|
|||
|
|
|||
|
Minimatch.prototype.debug = function () {}
|
|||
|
|
|||
|
Minimatch.prototype.make = make
|
|||
|
function make () {
|
|||
|
// don't do it more than once.
|
|||
|
if (this._made) return
|
|||
|
|
|||
|
var pattern = this.pattern
|
|||
|
var options = this.options
|
|||
|
|
|||
|
// empty patterns and comments match nothing.
|
|||
|
if (!options.nocomment && pattern.charAt(0) === '#') {
|
|||
|
this.comment = true
|
|||
|
return
|
|||
|
}
|
|||
|
if (!pattern) {
|
|||
|
this.empty = true
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// step 1: figure out negation, etc.
|
|||
|
this.parseNegate()
|
|||
|
|
|||
|
// step 2: expand braces
|
|||
|
var set = this.globSet = this.braceExpand()
|
|||
|
|
|||
|
if (options.debug) this.debug = console.error
|
|||
|
|
|||
|
this.debug(this.pattern, set)
|
|||
|
|
|||
|
// step 3: now we have a set, so turn each one into a series of path-portion
|
|||
|
// matching patterns.
|
|||
|
// These will be regexps, except in the case of "**", which is
|
|||
|
// set to the GLOBSTAR object for globstar behavior,
|
|||
|
// and will not contain any / characters
|
|||
|
set = this.globParts = set.map(function (s) {
|
|||
|
return s.split(slashSplit)
|
|||
|
})
|
|||
|
|
|||
|
this.debug(this.pattern, set)
|
|||
|
|
|||
|
// glob --> regexps
|
|||
|
set = set.map(function (s, si, set) {
|
|||
|
return s.map(this.parse, this)
|
|||
|
}, this)
|
|||
|
|
|||
|
this.debug(this.pattern, set)
|
|||
|
|
|||
|
// filter out everything that didn't compile properly.
|
|||
|
set = set.filter(function (s) {
|
|||
|
return s.indexOf(false) === -1
|
|||
|
})
|
|||
|
|
|||
|
this.debug(this.pattern, set)
|
|||
|
|
|||
|
this.set = set
|
|||
|
}
|
|||
|
|
|||
|
Minimatch.prototype.parseNegate = parseNegate
|
|||
|
function parseNegate () {
|
|||
|
var pattern = this.pattern
|
|||
|
var negate = false
|
|||
|
var options = this.options
|
|||
|
var negateOffset = 0
|
|||
|
|
|||
|
if (options.nonegate) return
|
|||
|
|
|||
|
for (var i = 0, l = pattern.length
|
|||
|
; i < l && pattern.charAt(i) === '!'
|
|||
|
; i++) {
|
|||
|
negate = !negate
|
|||
|
negateOffset++
|
|||
|
}
|
|||
|
|
|||
|
if (negateOffset) this.pattern = pattern.substr(negateOffset)
|
|||
|
this.negate = negate
|
|||
|
}
|
|||
|
|
|||
|
// Brace expansion:
|
|||
|
// a{b,c}d -> abd acd
|
|||
|
// a{b,}c -> abc ac
|
|||
|
// a{0..3}d -> a0d a1d a2d a3d
|
|||
|
// a{b,c{d,e}f}g -> abg acdfg acefg
|
|||
|
// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
|
|||
|
//
|
|||
|
// Invalid sets are not expanded.
|
|||
|
// a{2..}b -> a{2..}b
|
|||
|
// a{b}c -> a{b}c
|
|||
|
minimatch.braceExpand = function (pattern, options) {
|
|||
|
return braceExpand(pattern, options)
|
|||
|
}
|
|||
|
|
|||
|
Minimatch.prototype.braceExpand = braceExpand
|
|||
|
|
|||
|
function braceExpand (pattern, options) {
|
|||
|
if (!options) {
|
|||
|
if (this instanceof Minimatch) {
|
|||
|
options = this.options
|
|||
|
} else {
|
|||
|
options = {}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
pattern = typeof pattern === 'undefined'
|
|||
|
? this.pattern : pattern
|
|||
|
|
|||
|
if (typeof pattern === 'undefined') {
|
|||
|
throw new TypeError('undefined pattern')
|
|||
|
}
|
|||
|
|
|||
|
if (options.nobrace ||
|
|||
|
!pattern.match(/\{.*\}/)) {
|
|||
|
// shortcut. no need to expand.
|
|||
|
return [pattern]
|
|||
|
}
|
|||
|
|
|||
|
return expand(pattern)
|
|||
|
}
|
|||
|
|
|||
|
// parse a component of the expanded set.
|
|||
|
// At this point, no pattern may contain "/" in it
|
|||
|
// so we're going to return a 2d array, where each entry is the full
|
|||
|
// pattern, split on '/', and then turned into a regular expression.
|
|||
|
// A regexp is made at the end which joins each array with an
|
|||
|
// escaped /, and another full one which joins each regexp with |.
|
|||
|
//
|
|||
|
// Following the lead of Bash 4.1, note that "**" only has special meaning
|
|||
|
// when it is the *only* thing in a path portion. Otherwise, any series
|
|||
|
// of * is equivalent to a single *. Globstar behavior is enabled by
|
|||
|
// default, and can be disabled by setting options.noglobstar.
|
|||
|
Minimatch.prototype.parse = parse
|
|||
|
var SUBPARSE = {}
|
|||
|
function parse (pattern, isSub) {
|
|||
|
if (pattern.length > 1024 * 64) {
|
|||
|
throw new TypeError('pattern is too long')
|
|||
|
}
|
|||
|
|
|||
|
var options = this.options
|
|||
|
|
|||
|
// shortcuts
|
|||
|
if (!options.noglobstar && pattern === '**') return GLOBSTAR
|
|||
|
if (pattern === '') return ''
|
|||
|
|
|||
|
var re = ''
|
|||
|
var hasMagic = !!options.nocase
|
|||
|
var escaping = false
|
|||
|
// ? => one single character
|
|||
|
var patternListStack = []
|
|||
|
var negativeLists = []
|
|||
|
var stateChar
|
|||
|
var inClass = false
|
|||
|
var reClassStart = -1
|
|||
|
var classStart = -1
|
|||
|
// . and .. never match anything that doesn't start with .,
|
|||
|
// even when options.dot is set.
|
|||
|
var patternStart = pattern.charAt(0) === '.' ? '' // anything
|
|||
|
// not (start or / followed by . or .. followed by / or end)
|
|||
|
: options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))'
|
|||
|
: '(?!\\.)'
|
|||
|
var self = this
|
|||
|
|
|||
|
function clearStateChar () {
|
|||
|
if (stateChar) {
|
|||
|
// we had some state-tracking character
|
|||
|
// that wasn't consumed by this pass.
|
|||
|
switch (stateChar) {
|
|||
|
case '*':
|
|||
|
re += star
|
|||
|
hasMagic = true
|
|||
|
break
|
|||
|
case '?':
|
|||
|
re += qmark
|
|||
|
hasMagic = true
|
|||
|
break
|
|||
|
default:
|
|||
|
re += '\\' + stateChar
|
|||
|
break
|
|||
|
}
|
|||
|
self.debug('clearStateChar %j %j', stateChar, re)
|
|||
|
stateChar = false
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for (var i = 0, len = pattern.length, c
|
|||
|
; (i < len) && (c = pattern.charAt(i))
|
|||
|
; i++) {
|
|||
|
this.debug('%s\t%s %s %j', pattern, i, re, c)
|
|||
|
|
|||
|
// skip over any that are escaped.
|
|||
|
if (escaping && reSpecials[c]) {
|
|||
|
re += '\\' + c
|
|||
|
escaping = false
|
|||
|
continue
|
|||
|
}
|
|||
|
|
|||
|
switch (c) {
|
|||
|
case '/':
|
|||
|
// completely not allowed, even escaped.
|
|||
|
// Should already be path-split by now.
|
|||
|
return false
|
|||
|
|
|||
|
case '\\':
|
|||
|
clearStateChar()
|
|||
|
escaping = true
|
|||
|
continue
|
|||
|
|
|||
|
// the various stateChar values
|
|||
|
// for the "extglob" stuff.
|
|||
|
case '?':
|
|||
|
case '*':
|
|||
|
case '+':
|
|||
|
case '@':
|
|||
|
case '!':
|
|||
|
this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
|
|||
|
|
|||
|
// all of those are literals inside a class, except that
|
|||
|
// the glob [!a] means [^a] in regexp
|
|||
|
if (inClass) {
|
|||
|
this.debug(' in class')
|
|||
|
if (c === '!' && i === classStart + 1) c = '^'
|
|||
|
re += c
|
|||
|
continue
|
|||
|
}
|
|||
|
|
|||
|
// if we already have a stateChar, then it means
|
|||
|
// that there was something like ** or +? in there.
|
|||
|
// Handle the stateChar, then proceed with this one.
|
|||
|
self.debug('call clearStateChar %j', stateChar)
|
|||
|
clearStateChar()
|
|||
|
stateChar = c
|
|||
|
// if extglob is disabled, then +(asdf|foo) isn't a thing.
|
|||
|
// just clear the statechar *now*, rather than even diving into
|
|||
|
// the patternList stuff.
|
|||
|
if (options.noext) clearStateChar()
|
|||
|
continue
|
|||
|
|
|||
|
case '(':
|
|||
|
if (inClass) {
|
|||
|
re += '('
|
|||
|
continue
|
|||
|
}
|
|||
|
|
|||
|
if (!stateChar) {
|
|||
|
re += '\\('
|
|||
|
continue
|
|||
|
}
|
|||
|
|
|||
|
patternListStack.push({
|
|||
|
type: stateChar,
|
|||
|
start: i - 1,
|
|||
|
reStart: re.length,
|
|||
|
open: plTypes[stateChar].open,
|
|||
|
close: plTypes[stateChar].close
|
|||
|
})
|
|||
|
// negation is (?:(?!js)[^/]*)
|
|||
|
re += stateChar === '!' ? '(?:(?!(?:' : '(?:'
|
|||
|
this.debug('plType %j %j', stateChar, re)
|
|||
|
stateChar = false
|
|||
|
continue
|
|||
|
|
|||
|
case ')':
|
|||
|
if (inClass || !patternListStack.length) {
|
|||
|
re += '\\)'
|
|||
|
continue
|
|||
|
}
|
|||
|
|
|||
|
clearStateChar()
|
|||
|
hasMagic = true
|
|||
|
var pl = patternListStack.pop()
|
|||
|
// negation is (?:(?!js)[^/]*)
|
|||
|
// The others are (?:<pattern>)<type>
|
|||
|
re += pl.close
|
|||
|
if (pl.type === '!') {
|
|||
|
negativeLists.push(pl)
|
|||
|
}
|
|||
|
pl.reEnd = re.length
|
|||
|
continue
|
|||
|
|
|||
|
case '|':
|
|||
|
if (inClass || !patternListStack.length || escaping) {
|
|||
|
re += '\\|'
|
|||
|
escaping = false
|
|||
|
continue
|
|||
|
}
|
|||
|
|
|||
|
clearStateChar()
|
|||
|
re += '|'
|
|||
|
continue
|
|||
|
|
|||
|
// these are mostly the same in regexp and glob
|
|||
|
case '[':
|
|||
|
// swallow any state-tracking char before the [
|
|||
|
clearStateChar()
|
|||
|
|
|||
|
if (inClass) {
|
|||
|
re += '\\' + c
|
|||
|
continue
|
|||
|
}
|
|||
|
|
|||
|
inClass = true
|
|||
|
classStart = i
|
|||
|
reClassStart = re.length
|
|||
|
re += c
|
|||
|
continue
|
|||
|
|
|||
|
case ']':
|
|||
|
// a right bracket shall lose its special
|
|||
|
// meaning and represent itself in
|
|||
|
// a bracket expression if it occurs
|
|||
|
// first in the list. -- POSIX.2 2.8.3.2
|
|||
|
if (i === classStart + 1 || !inClass) {
|
|||
|
re += '\\' + c
|
|||
|
escaping = false
|
|||
|
continue
|
|||
|
}
|
|||
|
|
|||
|
// handle the case where we left a class open.
|
|||
|
// "[z-a]" is valid, equivalent to "\[z-a\]"
|
|||
|
if (inClass) {
|
|||
|
// split where the last [ was, make sure we don't have
|
|||
|
// an invalid re. if so, re-walk the contents of the
|
|||
|
// would-be class to re-translate any characters that
|
|||
|
// were passed through as-is
|
|||
|
// TODO: It would probably be faster to determine this
|
|||
|
// without a try/catch and a new RegExp, but it's tricky
|
|||
|
// to do safely. For now, this is safe and works.
|
|||
|
var cs = pattern.substring(classStart + 1, i)
|
|||
|
try {
|
|||
|
RegExp('[' + cs + ']')
|
|||
|
} catch (er) {
|
|||
|
// not a valid class!
|
|||
|
var sp = this.parse(cs, SUBPARSE)
|
|||
|
re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
|
|||
|
hasMagic = hasMagic || sp[1]
|
|||
|
inClass = false
|
|||
|
continue
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// finish up the class.
|
|||
|
hasMagic = true
|
|||
|
inClass = false
|
|||
|
re += c
|
|||
|
continue
|
|||
|
|
|||
|
default:
|
|||
|
// swallow any state char that wasn't consumed
|
|||
|
clearStateChar()
|
|||
|
|
|||
|
if (escaping) {
|
|||
|
// no need
|
|||
|
escaping = false
|
|||
|
} else if (reSpecials[c]
|
|||
|
&& !(c === '^' && inClass)) {
|
|||
|
re += '\\'
|
|||
|
}
|
|||
|
|
|||
|
re += c
|
|||
|
|
|||
|
} // switch
|
|||
|
} // for
|
|||
|
|
|||
|
// handle the case where we left a class open.
|
|||
|
// "[abc" is valid, equivalent to "\[abc"
|
|||
|
if (inClass) {
|
|||
|
// split where the last [ was, and escape it
|
|||
|
// this is a huge pita. We now have to re-walk
|
|||
|
// the contents of the would-be class to re-translate
|
|||
|
// any characters that were passed through as-is
|
|||
|
cs = pattern.substr(classStart + 1)
|
|||
|
sp = this.parse(cs, SUBPARSE)
|
|||
|
re = re.substr(0, reClassStart) + '\\[' + sp[0]
|
|||
|
hasMagic = hasMagic || sp[1]
|
|||
|
}
|
|||
|
|
|||
|
// handle the case where we had a +( thing at the *end*
|
|||
|
// of the pattern.
|
|||
|
// each pattern list stack adds 3 chars, and we need to go through
|
|||
|
// and escape any | chars that were passed through as-is for the regexp.
|
|||
|
// Go through and escape them, taking care not to double-escape any
|
|||
|
// | chars that were already escaped.
|
|||
|
for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
|
|||
|
var tail = re.slice(pl.reStart + pl.open.length)
|
|||
|
this.debug('setting tail', re, pl)
|
|||
|
// maybe some even number of \, then maybe 1 \, followed by a |
|
|||
|
tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) {
|
|||
|
if (!$2) {
|
|||
|
// the | isn't already escaped, so escape it.
|
|||
|
$2 = '\\'
|
|||
|
}
|
|||
|
|
|||
|
// need to escape all those slashes *again*, without escaping the
|
|||
|
// one that we need for escaping the | character. As it works out,
|
|||
|
// escaping an even number of slashes can be done by simply repeating
|
|||
|
// it exactly after itself. That's why this trick works.
|
|||
|
//
|
|||
|
// I am sorry that you have to see this.
|
|||
|
return $1 + $1 + $2 + '|'
|
|||
|
})
|
|||
|
|
|||
|
this.debug('tail=%j\n %s', tail, tail, pl, re)
|
|||
|
var t = pl.type === '*' ? star
|
|||
|
: pl.type === '?' ? qmark
|
|||
|
: '\\' + pl.type
|
|||
|
|
|||
|
hasMagic = true
|
|||
|
re = re.slice(0, pl.reStart) + t + '\\(' + tail
|
|||
|
}
|
|||
|
|
|||
|
// handle trailing things that only matter at the very end.
|
|||
|
clearStateChar()
|
|||
|
if (escaping) {
|
|||
|
// trailing \\
|
|||
|
re += '\\\\'
|
|||
|
}
|
|||
|
|
|||
|
// only need to apply the nodot start if the re starts with
|
|||
|
// something that could conceivably capture a dot
|
|||
|
var addPatternStart = false
|
|||
|
switch (re.charAt(0)) {
|
|||
|
case '.':
|
|||
|
case '[':
|
|||
|
case '(': addPatternStart = true
|
|||
|
}
|
|||
|
|
|||
|
// Hack to work around lack of negative lookbehind in JS
|
|||
|
// A pattern like: *.!(x).!(y|z) needs to ensure that a name
|
|||
|
// like 'a.xyz.yz' doesn't match. So, the first negative
|
|||
|
// lookahead, has to look ALL the way ahead, to the end of
|
|||
|
// the pattern.
|
|||
|
for (var n = negativeLists.length - 1; n > -1; n--) {
|
|||
|
var nl = negativeLists[n]
|
|||
|
|
|||
|
var nlBefore = re.slice(0, nl.reStart)
|
|||
|
var nlFirst = re.slice(nl.reStart, nl.reEnd - 8)
|
|||
|
var nlLast = re.slice(nl.reEnd - 8, nl.reEnd)
|
|||
|
var nlAfter = re.slice(nl.reEnd)
|
|||
|
|
|||
|
nlLast += nlAfter
|
|||
|
|
|||
|
// Handle nested stuff like *(*.js|!(*.json)), where open parens
|
|||
|
// mean that we should *not* include the ) in the bit that is considered
|
|||
|
// "after" the negated section.
|
|||
|
var openParensBefore = nlBefore.split('(').length - 1
|
|||
|
var cleanAfter = nlAfter
|
|||
|
for (i = 0; i < openParensBefore; i++) {
|
|||
|
cleanAfter = cleanAfter.replace(/\)[+*?]?/, '')
|
|||
|
}
|
|||
|
nlAfter = cleanAfter
|
|||
|
|
|||
|
var dollar = ''
|
|||
|
if (nlAfter === '' && isSub !== SUBPARSE) {
|
|||
|
dollar = '$'
|
|||
|
}
|
|||
|
var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast
|
|||
|
re = newRe
|
|||
|
}
|
|||
|
|
|||
|
// if the re is not "" at this point, then we need to make sure
|
|||
|
// it doesn't match against an empty path part.
|
|||
|
// Otherwise a/* will match a/, which it should not.
|
|||
|
if (re !== '' && hasMagic) {
|
|||
|
re = '(?=.)' + re
|
|||
|
}
|
|||
|
|
|||
|
if (addPatternStart) {
|
|||
|
re = patternStart + re
|
|||
|
}
|
|||
|
|
|||
|
// parsing just a piece of a larger pattern.
|
|||
|
if (isSub === SUBPARSE) {
|
|||
|
return [re, hasMagic]
|
|||
|
}
|
|||
|
|
|||
|
// skip the regexp for non-magical patterns
|
|||
|
// unescape anything in it, though, so that it'll be
|
|||
|
// an exact match against a file etc.
|
|||
|
if (!hasMagic) {
|
|||
|
return globUnescape(pattern)
|
|||
|
}
|
|||
|
|
|||
|
var flags = options.nocase ? 'i' : ''
|
|||
|
try {
|
|||
|
var regExp = new RegExp('^' + re + '$', flags)
|
|||
|
} catch (er) {
|
|||
|
// If it was an invalid regular expression, then it can't match
|
|||
|
// anything. This trick looks for a character after the end of
|
|||
|
// the string, which is of course impossible, except in multi-line
|
|||
|
// mode, but it's not a /m regex.
|
|||
|
return new RegExp('$.')
|
|||
|
}
|
|||
|
|
|||
|
regExp._glob = pattern
|
|||
|
regExp._src = re
|
|||
|
|
|||
|
return regExp
|
|||
|
}
|
|||
|
|
|||
|
minimatch.makeRe = function (pattern, options) {
|
|||
|
return new Minimatch(pattern, options || {}).makeRe()
|
|||
|
}
|
|||
|
|
|||
|
Minimatch.prototype.makeRe = makeRe
|
|||
|
function makeRe () {
|
|||
|
if (this.regexp || this.regexp === false) return this.regexp
|
|||
|
|
|||
|
// at this point, this.set is a 2d array of partial
|
|||
|
// pattern strings, or "**".
|
|||
|
//
|
|||
|
// It's better to use .match(). This function shouldn't
|
|||
|
// be used, really, but it's pretty convenient sometimes,
|
|||
|
// when you just want to work with a regex.
|
|||
|
var set = this.set
|
|||
|
|
|||
|
if (!set.length) {
|
|||
|
this.regexp = false
|
|||
|
return this.regexp
|
|||
|
}
|
|||
|
var options = this.options
|
|||
|
|
|||
|
var twoStar = options.noglobstar ? star
|
|||
|
: options.dot ? twoStarDot
|
|||
|
: twoStarNoDot
|
|||
|
var flags = options.nocase ? 'i' : ''
|
|||
|
|
|||
|
var re = set.map(function (pattern) {
|
|||
|
return pattern.map(function (p) {
|
|||
|
return (p === GLOBSTAR) ? twoStar
|
|||
|
: (typeof p === 'string') ? regExpEscape(p)
|
|||
|
: p._src
|
|||
|
}).join('\\\/')
|
|||
|
}).join('|')
|
|||
|
|
|||
|
// must match entire pattern
|
|||
|
// ending in a * or ** will make it less strict.
|
|||
|
re = '^(?:' + re + ')$'
|
|||
|
|
|||
|
// can match anything, as long as it's not this.
|
|||
|
if (this.negate) re = '^(?!' + re + ').*$'
|
|||
|
|
|||
|
try {
|
|||
|
this.regexp = new RegExp(re, flags)
|
|||
|
} catch (ex) {
|
|||
|
this.regexp = false
|
|||
|
}
|
|||
|
return this.regexp
|
|||
|
}
|
|||
|
|
|||
|
minimatch.match = function (list, pattern, options) {
|
|||
|
options = options || {}
|
|||
|
var mm = new Minimatch(pattern, options)
|
|||
|
list = list.filter(function (f) {
|
|||
|
return mm.match(f)
|
|||
|
})
|
|||
|
if (mm.options.nonull && !list.length) {
|
|||
|
list.push(pattern)
|
|||
|
}
|
|||
|
return list
|
|||
|
}
|
|||
|
|
|||
|
Minimatch.prototype.match = match
|
|||
|
function match (f, partial) {
|
|||
|
this.debug('match', f, this.pattern)
|
|||
|
// short-circuit in the case of busted things.
|
|||
|
// comments, etc.
|
|||
|
if (this.comment) return false
|
|||
|
if (this.empty) return f === ''
|
|||
|
|
|||
|
if (f === '/' && partial) return true
|
|||
|
|
|||
|
var options = this.options
|
|||
|
|
|||
|
// windows: need to use /, not \
|
|||
|
if (path.sep !== '/') {
|
|||
|
f = f.split(path.sep).join('/')
|
|||
|
}
|
|||
|
|
|||
|
// treat the test path as a set of pathparts.
|
|||
|
f = f.split(slashSplit)
|
|||
|
this.debug(this.pattern, 'split', f)
|
|||
|
|
|||
|
// just ONE of the pattern sets in this.set needs to match
|
|||
|
// in order for it to be valid. If negating, then just one
|
|||
|
// match means that we have failed.
|
|||
|
// Either way, return on the first hit.
|
|||
|
|
|||
|
var set = this.set
|
|||
|
this.debug(this.pattern, 'set', set)
|
|||
|
|
|||
|
// Find the basename of the path by looking for the last non-empty segment
|
|||
|
var filename
|
|||
|
var i
|
|||
|
for (i = f.length - 1; i >= 0; i--) {
|
|||
|
filename = f[i]
|
|||
|
if (filename) break
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < set.length; i++) {
|
|||
|
var pattern = set[i]
|
|||
|
var file = f
|
|||
|
if (options.matchBase && pattern.length === 1) {
|
|||
|
file = [filename]
|
|||
|
}
|
|||
|
var hit = this.matchOne(file, pattern, partial)
|
|||
|
if (hit) {
|
|||
|
if (options.flipNegate) return true
|
|||
|
return !this.negate
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// didn't get any hits. this is success if it's a negative
|
|||
|
// pattern, failure otherwise.
|
|||
|
if (options.flipNegate) return false
|
|||
|
return this.negate
|
|||
|
}
|
|||
|
|
|||
|
// set partial to true to test if, for example,
|
|||
|
// "/a/b" matches the start of "/*/b/*/d"
|
|||
|
// Partial means, if you run out of file before you run
|
|||
|
// out of pattern, then that's fine, as long as all
|
|||
|
// the parts match.
|
|||
|
Minimatch.prototype.matchOne = function (file, pattern, partial) {
|
|||
|
var options = this.options
|
|||
|
|
|||
|
this.debug('matchOne',
|
|||
|
{ 'this': this, file: file, pattern: pattern })
|
|||
|
|
|||
|
this.debug('matchOne', file.length, pattern.length)
|
|||
|
|
|||
|
for (var fi = 0,
|
|||
|
pi = 0,
|
|||
|
fl = file.length,
|
|||
|
pl = pattern.length
|
|||
|
; (fi < fl) && (pi < pl)
|
|||
|
; fi++, pi++) {
|
|||
|
this.debug('matchOne loop')
|
|||
|
var p = pattern[pi]
|
|||
|
var f = file[fi]
|
|||
|
|
|||
|
this.debug(pattern, p, f)
|
|||
|
|
|||
|
// should be impossible.
|
|||
|
// some invalid regexp stuff in the set.
|
|||
|
if (p === false) return false
|
|||
|
|
|||
|
if (p === GLOBSTAR) {
|
|||
|
this.debug('GLOBSTAR', [pattern, p, f])
|
|||
|
|
|||
|
// "**"
|
|||
|
// a/**/b/**/c would match the following:
|
|||
|
// a/b/x/y/z/c
|
|||
|
// a/x/y/z/b/c
|
|||
|
// a/b/x/b/x/c
|
|||
|
// a/b/c
|
|||
|
// To do this, take the rest of the pattern after
|
|||
|
// the **, and see if it would match the file remainder.
|
|||
|
// If so, return success.
|
|||
|
// If not, the ** "swallows" a segment, and try again.
|
|||
|
// This is recursively awful.
|
|||
|
//
|
|||
|
// a/**/b/**/c matching a/b/x/y/z/c
|
|||
|
// - a matches a
|
|||
|
// - doublestar
|
|||
|
// - matchOne(b/x/y/z/c, b/**/c)
|
|||
|
// - b matches b
|
|||
|
// - doublestar
|
|||
|
// - matchOne(x/y/z/c, c) -> no
|
|||
|
// - matchOne(y/z/c, c) -> no
|
|||
|
// - matchOne(z/c, c) -> no
|
|||
|
// - matchOne(c, c) yes, hit
|
|||
|
var fr = fi
|
|||
|
var pr = pi + 1
|
|||
|
if (pr === pl) {
|
|||
|
this.debug('** at the end')
|
|||
|
// a ** at the end will just swallow the rest.
|
|||
|
// We have found a match.
|
|||
|
// however, it will not swallow /.x, unless
|
|||
|
// options.dot is set.
|
|||
|
// . and .. are *never* matched by **, for explosively
|
|||
|
// exponential reasons.
|
|||
|
for (; fi < fl; fi++) {
|
|||
|
if (file[fi] === '.' || file[fi] === '..' ||
|
|||
|
(!options.dot && file[fi].charAt(0) === '.')) return false
|
|||
|
}
|
|||
|
return true
|
|||
|
}
|
|||
|
|
|||
|
// ok, let's see if we can swallow whatever we can.
|
|||
|
while (fr < fl) {
|
|||
|
var swallowee = file[fr]
|
|||
|
|
|||
|
this.debug('\nglobstar while', file, fr, pattern, pr, swallowee)
|
|||
|
|
|||
|
// XXX remove this slice. Just pass the start index.
|
|||
|
if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
|
|||
|
this.debug('globstar found match!', fr, fl, swallowee)
|
|||
|
// found a match.
|
|||
|
return true
|
|||
|
} else {
|
|||
|
// can't swallow "." or ".." ever.
|
|||
|
// can only swallow ".foo" when explicitly asked.
|
|||
|
if (swallowee === '.' || swallowee === '..' ||
|
|||
|
(!options.dot && swallowee.charAt(0) === '.')) {
|
|||
|
this.debug('dot detected!', file, fr, pattern, pr)
|
|||
|
break
|
|||
|
}
|
|||
|
|
|||
|
// ** swallows a segment, and continue.
|
|||
|
this.debug('globstar swallow a segment, and continue')
|
|||
|
fr++
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// no match was found.
|
|||
|
// However, in partial mode, we can't say this is necessarily over.
|
|||
|
// If there's more *pattern* left, then
|
|||
|
if (partial) {
|
|||
|
// ran out of file
|
|||
|
this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
|
|||
|
if (fr === fl) return true
|
|||
|
}
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
// something other than **
|
|||
|
// non-magic patterns just have to match exactly
|
|||
|
// patterns with magic have been turned into regexps.
|
|||
|
var hit
|
|||
|
if (typeof p === 'string') {
|
|||
|
if (options.nocase) {
|
|||
|
hit = f.toLowerCase() === p.toLowerCase()
|
|||
|
} else {
|
|||
|
hit = f === p
|
|||
|
}
|
|||
|
this.debug('string match', p, f, hit)
|
|||
|
} else {
|
|||
|
hit = f.match(p)
|
|||
|
this.debug('pattern match', p, f, hit)
|
|||
|
}
|
|||
|
|
|||
|
if (!hit) return false
|
|||
|
}
|
|||
|
|
|||
|
// Note: ending in / means that we'll get a final ""
|
|||
|
// at the end of the pattern. This can only match a
|
|||
|
// corresponding "" at the end of the file.
|
|||
|
// If the file ends in /, then it can only match a
|
|||
|
// a pattern that ends in /, unless the pattern just
|
|||
|
// doesn't have any more for it. But, a/b/ should *not*
|
|||
|
// match "a/b/*", even though "" matches against the
|
|||
|
// [^/]*? pattern, except in partial mode, where it might
|
|||
|
// simply not be reached yet.
|
|||
|
// However, a/b/ should still satisfy a/*
|
|||
|
|
|||
|
// now either we fell off the end of the pattern, or we're done.
|
|||
|
if (fi === fl && pi === pl) {
|
|||
|
// ran out of pattern and filename at the same time.
|
|||
|
// an exact hit!
|
|||
|
return true
|
|||
|
} else if (fi === fl) {
|
|||
|
// ran out of file, but still had pattern left.
|
|||
|
// this is ok if we're doing the match as part of
|
|||
|
// a glob fs traversal.
|
|||
|
return partial
|
|||
|
} else if (pi === pl) {
|
|||
|
// ran out of pattern, still have file left.
|
|||
|
// this is only acceptable if we're on the very last
|
|||
|
// empty segment of a file with a trailing slash.
|
|||
|
// a/* should match a/b/
|
|||
|
var emptyFileEnd = (fi === fl - 1) && (file[fi] === '')
|
|||
|
return emptyFileEnd
|
|||
|
}
|
|||
|
|
|||
|
// should be unreachable.
|
|||
|
throw new Error('wtf?')
|
|||
|
}
|
|||
|
|
|||
|
// replace stuff like \* with *
|
|||
|
function globUnescape (s) {
|
|||
|
return s.replace(/\\(.)/g, '$1')
|
|||
|
}
|
|||
|
|
|||
|
function regExpEscape (s) {
|
|||
|
return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
|
|||
|
}
|
|||
|
|
|||
|
},{"brace-expansion":11,"path":22}],21:[function(require,module,exports){
|
|||
|
var wrappy = require('wrappy')
|
|||
|
module.exports = wrappy(once)
|
|||
|
module.exports.strict = wrappy(onceStrict)
|
|||
|
|
|||
|
once.proto = once(function () {
|
|||
|
Object.defineProperty(Function.prototype, 'once', {
|
|||
|
value: function () {
|
|||
|
return once(this)
|
|||
|
},
|
|||
|
configurable: true
|
|||
|
})
|
|||
|
|
|||
|
Object.defineProperty(Function.prototype, 'onceStrict', {
|
|||
|
value: function () {
|
|||
|
return onceStrict(this)
|
|||
|
},
|
|||
|
configurable: true
|
|||
|
})
|
|||
|
})
|
|||
|
|
|||
|
function once (fn) {
|
|||
|
var f = function () {
|
|||
|
if (f.called) return f.value
|
|||
|
f.called = true
|
|||
|
return f.value = fn.apply(this, arguments)
|
|||
|
}
|
|||
|
f.called = false
|
|||
|
return f
|
|||
|
}
|
|||
|
|
|||
|
function onceStrict (fn) {
|
|||
|
var f = function () {
|
|||
|
if (f.called)
|
|||
|
throw new Error(f.onceError)
|
|||
|
f.called = true
|
|||
|
return f.value = fn.apply(this, arguments)
|
|||
|
}
|
|||
|
var name = fn.name || 'Function wrapped with `once`'
|
|||
|
f.onceError = name + " shouldn't be called more than once"
|
|||
|
f.called = false
|
|||
|
return f
|
|||
|
}
|
|||
|
|
|||
|
},{"wrappy":29}],22:[function(require,module,exports){
|
|||
|
(function (process){
|
|||
|
// Copyright Joyent, Inc. and other Node contributors.
|
|||
|
//
|
|||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|||
|
// copy of this software and associated documentation files (the
|
|||
|
// "Software"), to deal in the Software without restriction, including
|
|||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|||
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|||
|
// persons to whom the Software is furnished to do so, subject to the
|
|||
|
// following conditions:
|
|||
|
//
|
|||
|
// The above copyright notice and this permission notice shall be included
|
|||
|
// in all copies or substantial portions of the Software.
|
|||
|
//
|
|||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|||
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|||
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|||
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|||
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|||
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
|
|||
|
// resolves . and .. elements in a path array with directory names there
|
|||
|
// must be no slashes, empty elements, or device names (c:\) in the array
|
|||
|
// (so also no leading and trailing slashes - it does not distinguish
|
|||
|
// relative and absolute paths)
|
|||
|
function normalizeArray(parts, allowAboveRoot) {
|
|||
|
// if the path tries to go above the root, `up` ends up > 0
|
|||
|
var up = 0;
|
|||
|
for (var i = parts.length - 1; i >= 0; i--) {
|
|||
|
var last = parts[i];
|
|||
|
if (last === '.') {
|
|||
|
parts.splice(i, 1);
|
|||
|
} else if (last === '..') {
|
|||
|
parts.splice(i, 1);
|
|||
|
up++;
|
|||
|
} else if (up) {
|
|||
|
parts.splice(i, 1);
|
|||
|
up--;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// if the path is allowed to go above the root, restore leading ..s
|
|||
|
if (allowAboveRoot) {
|
|||
|
for (; up--; up) {
|
|||
|
parts.unshift('..');
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return parts;
|
|||
|
}
|
|||
|
|
|||
|
// Split a filename into [root, dir, basename, ext], unix version
|
|||
|
// 'root' is just a slash, or nothing.
|
|||
|
var splitPathRe =
|
|||
|
/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
|
|||
|
var splitPath = function(filename) {
|
|||
|
return splitPathRe.exec(filename).slice(1);
|
|||
|
};
|
|||
|
|
|||
|
// path.resolve([from ...], to)
|
|||
|
// posix version
|
|||
|
exports.resolve = function() {
|
|||
|
var resolvedPath = '',
|
|||
|
resolvedAbsolute = false;
|
|||
|
|
|||
|
for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
|
|||
|
var path = (i >= 0) ? arguments[i] : process.cwd();
|
|||
|
|
|||
|
// Skip empty and invalid entries
|
|||
|
if (typeof path !== 'string') {
|
|||
|
throw new TypeError('Arguments to path.resolve must be strings');
|
|||
|
} else if (!path) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
resolvedPath = path + '/' + resolvedPath;
|
|||
|
resolvedAbsolute = path.charAt(0) === '/';
|
|||
|
}
|
|||
|
|
|||
|
// At this point the path should be resolved to a full absolute path, but
|
|||
|
// handle relative paths to be safe (might happen when process.cwd() fails)
|
|||
|
|
|||
|
// Normalize the path
|
|||
|
resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
|
|||
|
return !!p;
|
|||
|
}), !resolvedAbsolute).join('/');
|
|||
|
|
|||
|
return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
|
|||
|
};
|
|||
|
|
|||
|
// path.normalize(path)
|
|||
|
// posix version
|
|||
|
exports.normalize = function(path) {
|
|||
|
var isAbsolute = exports.isAbsolute(path),
|
|||
|
trailingSlash = substr(path, -1) === '/';
|
|||
|
|
|||
|
// Normalize the path
|
|||
|
path = normalizeArray(filter(path.split('/'), function(p) {
|
|||
|
return !!p;
|
|||
|
}), !isAbsolute).join('/');
|
|||
|
|
|||
|
if (!path && !isAbsolute) {
|
|||
|
path = '.';
|
|||
|
}
|
|||
|
if (path && trailingSlash) {
|
|||
|
path += '/';
|
|||
|
}
|
|||
|
|
|||
|
return (isAbsolute ? '/' : '') + path;
|
|||
|
};
|
|||
|
|
|||
|
// posix version
|
|||
|
exports.isAbsolute = function(path) {
|
|||
|
return path.charAt(0) === '/';
|
|||
|
};
|
|||
|
|
|||
|
// posix version
|
|||
|
exports.join = function() {
|
|||
|
var paths = Array.prototype.slice.call(arguments, 0);
|
|||
|
return exports.normalize(filter(paths, function(p, index) {
|
|||
|
if (typeof p !== 'string') {
|
|||
|
throw new TypeError('Arguments to path.join must be strings');
|
|||
|
}
|
|||
|
return p;
|
|||
|
}).join('/'));
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
// path.relative(from, to)
|
|||
|
// posix version
|
|||
|
exports.relative = function(from, to) {
|
|||
|
from = exports.resolve(from).substr(1);
|
|||
|
to = exports.resolve(to).substr(1);
|
|||
|
|
|||
|
function trim(arr) {
|
|||
|
var start = 0;
|
|||
|
for (; start < arr.length; start++) {
|
|||
|
if (arr[start] !== '') break;
|
|||
|
}
|
|||
|
|
|||
|
var end = arr.length - 1;
|
|||
|
for (; end >= 0; end--) {
|
|||
|
if (arr[end] !== '') break;
|
|||
|
}
|
|||
|
|
|||
|
if (start > end) return [];
|
|||
|
return arr.slice(start, end - start + 1);
|
|||
|
}
|
|||
|
|
|||
|
var fromParts = trim(from.split('/'));
|
|||
|
var toParts = trim(to.split('/'));
|
|||
|
|
|||
|
var length = Math.min(fromParts.length, toParts.length);
|
|||
|
var samePartsLength = length;
|
|||
|
for (var i = 0; i < length; i++) {
|
|||
|
if (fromParts[i] !== toParts[i]) {
|
|||
|
samePartsLength = i;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var outputParts = [];
|
|||
|
for (var i = samePartsLength; i < fromParts.length; i++) {
|
|||
|
outputParts.push('..');
|
|||
|
}
|
|||
|
|
|||
|
outputParts = outputParts.concat(toParts.slice(samePartsLength));
|
|||
|
|
|||
|
return outputParts.join('/');
|
|||
|
};
|
|||
|
|
|||
|
exports.sep = '/';
|
|||
|
exports.delimiter = ':';
|
|||
|
|
|||
|
exports.dirname = function(path) {
|
|||
|
var result = splitPath(path),
|
|||
|
root = result[0],
|
|||
|
dir = result[1];
|
|||
|
|
|||
|
if (!root && !dir) {
|
|||
|
// No dirname whatsoever
|
|||
|
return '.';
|
|||
|
}
|
|||
|
|
|||
|
if (dir) {
|
|||
|
// It has a dirname, strip trailing slash
|
|||
|
dir = dir.substr(0, dir.length - 1);
|
|||
|
}
|
|||
|
|
|||
|
return root + dir;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
exports.basename = function(path, ext) {
|
|||
|
var f = splitPath(path)[2];
|
|||
|
// TODO: make this comparison case-insensitive on windows?
|
|||
|
if (ext && f.substr(-1 * ext.length) === ext) {
|
|||
|
f = f.substr(0, f.length - ext.length);
|
|||
|
}
|
|||
|
return f;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
exports.extname = function(path) {
|
|||
|
return splitPath(path)[3];
|
|||
|
};
|
|||
|
|
|||
|
function filter (xs, f) {
|
|||
|
if (xs.filter) return xs.filter(f);
|
|||
|
var res = [];
|
|||
|
for (var i = 0; i < xs.length; i++) {
|
|||
|
if (f(xs[i], i, xs)) res.push(xs[i]);
|
|||
|
}
|
|||
|
return res;
|
|||
|
}
|
|||
|
|
|||
|
// String.prototype.substr - negative index don't work in IE8
|
|||
|
var substr = 'ab'.substr(-1) === 'b'
|
|||
|
? function (str, start, len) { return str.substr(start, len) }
|
|||
|
: function (str, start, len) {
|
|||
|
if (start < 0) start = str.length + start;
|
|||
|
return str.substr(start, len);
|
|||
|
}
|
|||
|
;
|
|||
|
|
|||
|
}).call(this,require('_process'))
|
|||
|
},{"_process":24}],23:[function(require,module,exports){
|
|||
|
(function (process){
|
|||
|
'use strict';
|
|||
|
|
|||
|
function posix(path) {
|
|||
|
return path.charAt(0) === '/';
|
|||
|
}
|
|||
|
|
|||
|
function win32(path) {
|
|||
|
// https://github.com/nodejs/node/blob/b3fcc245fb25539909ef1d5eaa01dbf92e168633/lib/path.js#L56
|
|||
|
var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/;
|
|||
|
var result = splitDeviceRe.exec(path);
|
|||
|
var device = result[1] || '';
|
|||
|
var isUnc = Boolean(device && device.charAt(1) !== ':');
|
|||
|
|
|||
|
// UNC paths are always absolute
|
|||
|
return Boolean(result[2] || isUnc);
|
|||
|
}
|
|||
|
|
|||
|
module.exports = process.platform === 'win32' ? win32 : posix;
|
|||
|
module.exports.posix = posix;
|
|||
|
module.exports.win32 = win32;
|
|||
|
|
|||
|
}).call(this,require('_process'))
|
|||
|
},{"_process":24}],24:[function(require,module,exports){
|
|||
|
// shim for using process in browser
|
|||
|
var process = module.exports = {};
|
|||
|
|
|||
|
// cached from whatever global is present so that test runners that stub it
|
|||
|
// don't break things. But we need to wrap it in a try catch in case it is
|
|||
|
// wrapped in strict mode code which doesn't define any globals. It's inside a
|
|||
|
// function because try/catches deoptimize in certain engines.
|
|||
|
|
|||
|
var cachedSetTimeout;
|
|||
|
var cachedClearTimeout;
|
|||
|
|
|||
|
function defaultSetTimout() {
|
|||
|
throw new Error('setTimeout has not been defined');
|
|||
|
}
|
|||
|
function defaultClearTimeout () {
|
|||
|
throw new Error('clearTimeout has not been defined');
|
|||
|
}
|
|||
|
(function () {
|
|||
|
try {
|
|||
|
if (typeof setTimeout === 'function') {
|
|||
|
cachedSetTimeout = setTimeout;
|
|||
|
} else {
|
|||
|
cachedSetTimeout = defaultSetTimout;
|
|||
|
}
|
|||
|
} catch (e) {
|
|||
|
cachedSetTimeout = defaultSetTimout;
|
|||
|
}
|
|||
|
try {
|
|||
|
if (typeof clearTimeout === 'function') {
|
|||
|
cachedClearTimeout = clearTimeout;
|
|||
|
} else {
|
|||
|
cachedClearTimeout = defaultClearTimeout;
|
|||
|
}
|
|||
|
} catch (e) {
|
|||
|
cachedClearTimeout = defaultClearTimeout;
|
|||
|
}
|
|||
|
} ())
|
|||
|
function runTimeout(fun) {
|
|||
|
if (cachedSetTimeout === setTimeout) {
|
|||
|
//normal enviroments in sane situations
|
|||
|
return setTimeout(fun, 0);
|
|||
|
}
|
|||
|
// if setTimeout wasn't available but was latter defined
|
|||
|
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
|
|||
|
cachedSetTimeout = setTimeout;
|
|||
|
return setTimeout(fun, 0);
|
|||
|
}
|
|||
|
try {
|
|||
|
// when when somebody has screwed with setTimeout but no I.E. maddness
|
|||
|
return cachedSetTimeout(fun, 0);
|
|||
|
} catch(e){
|
|||
|
try {
|
|||
|
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
|
|||
|
return cachedSetTimeout.call(null, fun, 0);
|
|||
|
} catch(e){
|
|||
|
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
|
|||
|
return cachedSetTimeout.call(this, fun, 0);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
function runClearTimeout(marker) {
|
|||
|
if (cachedClearTimeout === clearTimeout) {
|
|||
|
//normal enviroments in sane situations
|
|||
|
return clearTimeout(marker);
|
|||
|
}
|
|||
|
// if clearTimeout wasn't available but was latter defined
|
|||
|
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
|
|||
|
cachedClearTimeout = clearTimeout;
|
|||
|
return clearTimeout(marker);
|
|||
|
}
|
|||
|
try {
|
|||
|
// when when somebody has screwed with setTimeout but no I.E. maddness
|
|||
|
return cachedClearTimeout(marker);
|
|||
|
} catch (e){
|
|||
|
try {
|
|||
|
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
|
|||
|
return cachedClearTimeout.call(null, marker);
|
|||
|
} catch (e){
|
|||
|
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
|
|||
|
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
|
|||
|
return cachedClearTimeout.call(this, marker);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
var queue = [];
|
|||
|
var draining = false;
|
|||
|
var currentQueue;
|
|||
|
var queueIndex = -1;
|
|||
|
|
|||
|
function cleanUpNextTick() {
|
|||
|
if (!draining || !currentQueue) {
|
|||
|
return;
|
|||
|
}
|
|||
|
draining = false;
|
|||
|
if (currentQueue.length) {
|
|||
|
queue = currentQueue.concat(queue);
|
|||
|
} else {
|
|||
|
queueIndex = -1;
|
|||
|
}
|
|||
|
if (queue.length) {
|
|||
|
drainQueue();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function drainQueue() {
|
|||
|
if (draining) {
|
|||
|
return;
|
|||
|
}
|
|||
|
var timeout = runTimeout(cleanUpNextTick);
|
|||
|
draining = true;
|
|||
|
|
|||
|
var len = queue.length;
|
|||
|
while(len) {
|
|||
|
currentQueue = queue;
|
|||
|
queue = [];
|
|||
|
while (++queueIndex < len) {
|
|||
|
if (currentQueue) {
|
|||
|
currentQueue[queueIndex].run();
|
|||
|
}
|
|||
|
}
|
|||
|
queueIndex = -1;
|
|||
|
len = queue.length;
|
|||
|
}
|
|||
|
currentQueue = null;
|
|||
|
draining = false;
|
|||
|
runClearTimeout(timeout);
|
|||
|
}
|
|||
|
|
|||
|
process.nextTick = function (fun) {
|
|||
|
var args = new Array(arguments.length - 1);
|
|||
|
if (arguments.length > 1) {
|
|||
|
for (var i = 1; i < arguments.length; i++) {
|
|||
|
args[i - 1] = arguments[i];
|
|||
|
}
|
|||
|
}
|
|||
|
queue.push(new Item(fun, args));
|
|||
|
if (queue.length === 1 && !draining) {
|
|||
|
runTimeout(drainQueue);
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
// v8 likes predictible objects
|
|||
|
function Item(fun, array) {
|
|||
|
this.fun = fun;
|
|||
|
this.array = array;
|
|||
|
}
|
|||
|
Item.prototype.run = function () {
|
|||
|
this.fun.apply(null, this.array);
|
|||
|
};
|
|||
|
process.title = 'browser';
|
|||
|
process.browser = true;
|
|||
|
process.env = {};
|
|||
|
process.argv = [];
|
|||
|
process.version = ''; // empty string to avoid regexp issues
|
|||
|
process.versions = {};
|
|||
|
|
|||
|
function noop() {}
|
|||
|
|
|||
|
process.on = noop;
|
|||
|
process.addListener = noop;
|
|||
|
process.once = noop;
|
|||
|
process.off = noop;
|
|||
|
process.removeListener = noop;
|
|||
|
process.removeAllListeners = noop;
|
|||
|
process.emit = noop;
|
|||
|
process.prependListener = noop;
|
|||
|
process.prependOnceListener = noop;
|
|||
|
|
|||
|
process.listeners = function (name) { return [] }
|
|||
|
|
|||
|
process.binding = function (name) {
|
|||
|
throw new Error('process.binding is not supported');
|
|||
|
};
|
|||
|
|
|||
|
process.cwd = function () { return '/' };
|
|||
|
process.chdir = function (dir) {
|
|||
|
throw new Error('process.chdir is not supported');
|
|||
|
};
|
|||
|
process.umask = function() { return 0; };
|
|||
|
|
|||
|
},{}],25:[function(require,module,exports){
|
|||
|
// Underscore.js 1.8.3
|
|||
|
// http://underscorejs.org
|
|||
|
// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
|||
|
// Underscore may be freely distributed under the MIT license.
|
|||
|
|
|||
|
(function() {
|
|||
|
|
|||
|
// Baseline setup
|
|||
|
// --------------
|
|||
|
|
|||
|
// Establish the root object, `window` in the browser, or `exports` on the server.
|
|||
|
var root = this;
|
|||
|
|
|||
|
// Save the previous value of the `_` variable.
|
|||
|
var previousUnderscore = root._;
|
|||
|
|
|||
|
// Save bytes in the minified (but not gzipped) version:
|
|||
|
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
|
|||
|
|
|||
|
// Create quick reference variables for speed access to core prototypes.
|
|||
|
var
|
|||
|
push = ArrayProto.push,
|
|||
|
slice = ArrayProto.slice,
|
|||
|
toString = ObjProto.toString,
|
|||
|
hasOwnProperty = ObjProto.hasOwnProperty;
|
|||
|
|
|||
|
// All **ECMAScript 5** native function implementations that we hope to use
|
|||
|
// are declared here.
|
|||
|
var
|
|||
|
nativeIsArray = Array.isArray,
|
|||
|
nativeKeys = Object.keys,
|
|||
|
nativeBind = FuncProto.bind,
|
|||
|
nativeCreate = Object.create;
|
|||
|
|
|||
|
// Naked function reference for surrogate-prototype-swapping.
|
|||
|
var Ctor = function(){};
|
|||
|
|
|||
|
// Create a safe reference to the Underscore object for use below.
|
|||
|
var _ = function(obj) {
|
|||
|
if (obj instanceof _) return obj;
|
|||
|
if (!(this instanceof _)) return new _(obj);
|
|||
|
this._wrapped = obj;
|
|||
|
};
|
|||
|
|
|||
|
// Export the Underscore object for **Node.js**, with
|
|||
|
// backwards-compatibility for the old `require()` API. If we're in
|
|||
|
// the browser, add `_` as a global object.
|
|||
|
if (typeof exports !== 'undefined') {
|
|||
|
if (typeof module !== 'undefined' && module.exports) {
|
|||
|
exports = module.exports = _;
|
|||
|
}
|
|||
|
exports._ = _;
|
|||
|
} else {
|
|||
|
root._ = _;
|
|||
|
}
|
|||
|
|
|||
|
// Current version.
|
|||
|
_.VERSION = '1.8.3';
|
|||
|
|
|||
|
// Internal function that returns an efficient (for current engines) version
|
|||
|
// of the passed-in callback, to be repeatedly applied in other Underscore
|
|||
|
// functions.
|
|||
|
var optimizeCb = function(func, context, argCount) {
|
|||
|
if (context === void 0) return func;
|
|||
|
switch (argCount == null ? 3 : argCount) {
|
|||
|
case 1: return function(value) {
|
|||
|
return func.call(context, value);
|
|||
|
};
|
|||
|
case 2: return function(value, other) {
|
|||
|
return func.call(context, value, other);
|
|||
|
};
|
|||
|
case 3: return function(value, index, collection) {
|
|||
|
return func.call(context, value, index, collection);
|
|||
|
};
|
|||
|
case 4: return function(accumulator, value, index, collection) {
|
|||
|
return func.call(context, accumulator, value, index, collection);
|
|||
|
};
|
|||
|
}
|
|||
|
return function() {
|
|||
|
return func.apply(context, arguments);
|
|||
|
};
|
|||
|
};
|
|||
|
|
|||
|
// A mostly-internal function to generate callbacks that can be applied
|
|||
|
// to each element in a collection, returning the desired result — either
|
|||
|
// identity, an arbitrary callback, a property matcher, or a property accessor.
|
|||
|
var cb = function(value, context, argCount) {
|
|||
|
if (value == null) return _.identity;
|
|||
|
if (_.isFunction(value)) return optimizeCb(value, context, argCount);
|
|||
|
if (_.isObject(value)) return _.matcher(value);
|
|||
|
return _.property(value);
|
|||
|
};
|
|||
|
_.iteratee = function(value, context) {
|
|||
|
return cb(value, context, Infinity);
|
|||
|
};
|
|||
|
|
|||
|
// An internal function for creating assigner functions.
|
|||
|
var createAssigner = function(keysFunc, undefinedOnly) {
|
|||
|
return function(obj) {
|
|||
|
var length = arguments.length;
|
|||
|
if (length < 2 || obj == null) return obj;
|
|||
|
for (var index = 1; index < length; index++) {
|
|||
|
var source = arguments[index],
|
|||
|
keys = keysFunc(source),
|
|||
|
l = keys.length;
|
|||
|
for (var i = 0; i < l; i++) {
|
|||
|
var key = keys[i];
|
|||
|
if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
|
|||
|
}
|
|||
|
}
|
|||
|
return obj;
|
|||
|
};
|
|||
|
};
|
|||
|
|
|||
|
// An internal function for creating a new object that inherits from another.
|
|||
|
var baseCreate = function(prototype) {
|
|||
|
if (!_.isObject(prototype)) return {};
|
|||
|
if (nativeCreate) return nativeCreate(prototype);
|
|||
|
Ctor.prototype = prototype;
|
|||
|
var result = new Ctor;
|
|||
|
Ctor.prototype = null;
|
|||
|
return result;
|
|||
|
};
|
|||
|
|
|||
|
var property = function(key) {
|
|||
|
return function(obj) {
|
|||
|
return obj == null ? void 0 : obj[key];
|
|||
|
};
|
|||
|
};
|
|||
|
|
|||
|
// Helper for collection methods to determine whether a collection
|
|||
|
// should be iterated as an array or as an object
|
|||
|
// Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
|
|||
|
// Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
|
|||
|
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
|
|||
|
var getLength = property('length');
|
|||
|
var isArrayLike = function(collection) {
|
|||
|
var length = getLength(collection);
|
|||
|
return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
|
|||
|
};
|
|||
|
|
|||
|
// Collection Functions
|
|||
|
// --------------------
|
|||
|
|
|||
|
// The cornerstone, an `each` implementation, aka `forEach`.
|
|||
|
// Handles raw objects in addition to array-likes. Treats all
|
|||
|
// sparse array-likes as if they were dense.
|
|||
|
_.each = _.forEach = function(obj, iteratee, context) {
|
|||
|
iteratee = optimizeCb(iteratee, context);
|
|||
|
var i, length;
|
|||
|
if (isArrayLike(obj)) {
|
|||
|
for (i = 0, length = obj.length; i < length; i++) {
|
|||
|
iteratee(obj[i], i, obj);
|
|||
|
}
|
|||
|
} else {
|
|||
|
var keys = _.keys(obj);
|
|||
|
for (i = 0, length = keys.length; i < length; i++) {
|
|||
|
iteratee(obj[keys[i]], keys[i], obj);
|
|||
|
}
|
|||
|
}
|
|||
|
return obj;
|
|||
|
};
|
|||
|
|
|||
|
// Return the results of applying the iteratee to each element.
|
|||
|
_.map = _.collect = function(obj, iteratee, context) {
|
|||
|
iteratee = cb(iteratee, context);
|
|||
|
var keys = !isArrayLike(obj) && _.keys(obj),
|
|||
|
length = (keys || obj).length,
|
|||
|
results = Array(length);
|
|||
|
for (var index = 0; index < length; index++) {
|
|||
|
var currentKey = keys ? keys[index] : index;
|
|||
|
results[index] = iteratee(obj[currentKey], currentKey, obj);
|
|||
|
}
|
|||
|
return results;
|
|||
|
};
|
|||
|
|
|||
|
// Create a reducing function iterating left or right.
|
|||
|
function createReduce(dir) {
|
|||
|
// Optimized iterator function as using arguments.length
|
|||
|
// in the main function will deoptimize the, see #1991.
|
|||
|
function iterator(obj, iteratee, memo, keys, index, length) {
|
|||
|
for (; index >= 0 && index < length; index += dir) {
|
|||
|
var currentKey = keys ? keys[index] : index;
|
|||
|
memo = iteratee(memo, obj[currentKey], currentKey, obj);
|
|||
|
}
|
|||
|
return memo;
|
|||
|
}
|
|||
|
|
|||
|
return function(obj, iteratee, memo, context) {
|
|||
|
iteratee = optimizeCb(iteratee, context, 4);
|
|||
|
var keys = !isArrayLike(obj) && _.keys(obj),
|
|||
|
length = (keys || obj).length,
|
|||
|
index = dir > 0 ? 0 : length - 1;
|
|||
|
// Determine the initial value if none is provided.
|
|||
|
if (arguments.length < 3) {
|
|||
|
memo = obj[keys ? keys[index] : index];
|
|||
|
index += dir;
|
|||
|
}
|
|||
|
return iterator(obj, iteratee, memo, keys, index, length);
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
// **Reduce** builds up a single result from a list of values, aka `inject`,
|
|||
|
// or `foldl`.
|
|||
|
_.reduce = _.foldl = _.inject = createReduce(1);
|
|||
|
|
|||
|
// The right-associative version of reduce, also known as `foldr`.
|
|||
|
_.reduceRight = _.foldr = createReduce(-1);
|
|||
|
|
|||
|
// Return the first value which passes a truth test. Aliased as `detect`.
|
|||
|
_.find = _.detect = function(obj, predicate, context) {
|
|||
|
var key;
|
|||
|
if (isArrayLike(obj)) {
|
|||
|
key = _.findIndex(obj, predicate, context);
|
|||
|
} else {
|
|||
|
key = _.findKey(obj, predicate, context);
|
|||
|
}
|
|||
|
if (key !== void 0 && key !== -1) return obj[key];
|
|||
|
};
|
|||
|
|
|||
|
// Return all the elements that pass a truth test.
|
|||
|
// Aliased as `select`.
|
|||
|
_.filter = _.select = function(obj, predicate, context) {
|
|||
|
var results = [];
|
|||
|
predicate = cb(predicate, context);
|
|||
|
_.each(obj, function(value, index, list) {
|
|||
|
if (predicate(value, index, list)) results.push(value);
|
|||
|
});
|
|||
|
return results;
|
|||
|
};
|
|||
|
|
|||
|
// Return all the elements for which a truth test fails.
|
|||
|
_.reject = function(obj, predicate, context) {
|
|||
|
return _.filter(obj, _.negate(cb(predicate)), context);
|
|||
|
};
|
|||
|
|
|||
|
// Determine whether all of the elements match a truth test.
|
|||
|
// Aliased as `all`.
|
|||
|
_.every = _.all = function(obj, predicate, context) {
|
|||
|
predicate = cb(predicate, context);
|
|||
|
var keys = !isArrayLike(obj) && _.keys(obj),
|
|||
|
length = (keys || obj).length;
|
|||
|
for (var index = 0; index < length; index++) {
|
|||
|
var currentKey = keys ? keys[index] : index;
|
|||
|
if (!predicate(obj[currentKey], currentKey, obj)) return false;
|
|||
|
}
|
|||
|
return true;
|
|||
|
};
|
|||
|
|
|||
|
// Determine if at least one element in the object matches a truth test.
|
|||
|
// Aliased as `any`.
|
|||
|
_.some = _.any = function(obj, predicate, context) {
|
|||
|
predicate = cb(predicate, context);
|
|||
|
var keys = !isArrayLike(obj) && _.keys(obj),
|
|||
|
length = (keys || obj).length;
|
|||
|
for (var index = 0; index < length; index++) {
|
|||
|
var currentKey = keys ? keys[index] : index;
|
|||
|
if (predicate(obj[currentKey], currentKey, obj)) return true;
|
|||
|
}
|
|||
|
return false;
|
|||
|
};
|
|||
|
|
|||
|
// Determine if the array or object contains a given item (using `===`).
|
|||
|
// Aliased as `includes` and `include`.
|
|||
|
_.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
|
|||
|
if (!isArrayLike(obj)) obj = _.values(obj);
|
|||
|
if (typeof fromIndex != 'number' || guard) fromIndex = 0;
|
|||
|
return _.indexOf(obj, item, fromIndex) >= 0;
|
|||
|
};
|
|||
|
|
|||
|
// Invoke a method (with arguments) on every item in a collection.
|
|||
|
_.invoke = function(obj, method) {
|
|||
|
var args = slice.call(arguments, 2);
|
|||
|
var isFunc = _.isFunction(method);
|
|||
|
return _.map(obj, function(value) {
|
|||
|
var func = isFunc ? method : value[method];
|
|||
|
return func == null ? func : func.apply(value, args);
|
|||
|
});
|
|||
|
};
|
|||
|
|
|||
|
// Convenience version of a common use case of `map`: fetching a property.
|
|||
|
_.pluck = function(obj, key) {
|
|||
|
return _.map(obj, _.property(key));
|
|||
|
};
|
|||
|
|
|||
|
// Convenience version of a common use case of `filter`: selecting only objects
|
|||
|
// containing specific `key:value` pairs.
|
|||
|
_.where = function(obj, attrs) {
|
|||
|
return _.filter(obj, _.matcher(attrs));
|
|||
|
};
|
|||
|
|
|||
|
// Convenience version of a common use case of `find`: getting the first object
|
|||
|
// containing specific `key:value` pairs.
|
|||
|
_.findWhere = function(obj, attrs) {
|
|||
|
return _.find(obj, _.matcher(attrs));
|
|||
|
};
|
|||
|
|
|||
|
// Return the maximum element (or element-based computation).
|
|||
|
_.max = function(obj, iteratee, context) {
|
|||
|
var result = -Infinity, lastComputed = -Infinity,
|
|||
|
value, computed;
|
|||
|
if (iteratee == null && obj != null) {
|
|||
|
obj = isArrayLike(obj) ? obj : _.values(obj);
|
|||
|
for (var i = 0, length = obj.length; i < length; i++) {
|
|||
|
value = obj[i];
|
|||
|
if (value > result) {
|
|||
|
result = value;
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
iteratee = cb(iteratee, context);
|
|||
|
_.each(obj, function(value, index, list) {
|
|||
|
computed = iteratee(value, index, list);
|
|||
|
if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
|
|||
|
result = value;
|
|||
|
lastComputed = computed;
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
return result;
|
|||
|
};
|
|||
|
|
|||
|
// Return the minimum element (or element-based computation).
|
|||
|
_.min = function(obj, iteratee, context) {
|
|||
|
var result = Infinity, lastComputed = Infinity,
|
|||
|
value, computed;
|
|||
|
if (iteratee == null && obj != null) {
|
|||
|
obj = isArrayLike(obj) ? obj : _.values(obj);
|
|||
|
for (var i = 0, length = obj.length; i < length; i++) {
|
|||
|
value = obj[i];
|
|||
|
if (value < result) {
|
|||
|
result = value;
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
iteratee = cb(iteratee, context);
|
|||
|
_.each(obj, function(value, index, list) {
|
|||
|
computed = iteratee(value, index, list);
|
|||
|
if (computed < lastComputed || computed === Infinity && result === Infinity) {
|
|||
|
result = value;
|
|||
|
lastComputed = computed;
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
return result;
|
|||
|
};
|
|||
|
|
|||
|
// Shuffle a collection, using the modern version of the
|
|||
|
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
|
|||
|
_.shuffle = function(obj) {
|
|||
|
var set = isArrayLike(obj) ? obj : _.values(obj);
|
|||
|
var length = set.length;
|
|||
|
var shuffled = Array(length);
|
|||
|
for (var index = 0, rand; index < length; index++) {
|
|||
|
rand = _.random(0, index);
|
|||
|
if (rand !== index) shuffled[index] = shuffled[rand];
|
|||
|
shuffled[rand] = set[index];
|
|||
|
}
|
|||
|
return shuffled;
|
|||
|
};
|
|||
|
|
|||
|
// Sample **n** random values from a collection.
|
|||
|
// If **n** is not specified, returns a single random element.
|
|||
|
// The internal `guard` argument allows it to work with `map`.
|
|||
|
_.sample = function(obj, n, guard) {
|
|||
|
if (n == null || guard) {
|
|||
|
if (!isArrayLike(obj)) obj = _.values(obj);
|
|||
|
return obj[_.random(obj.length - 1)];
|
|||
|
}
|
|||
|
return _.shuffle(obj).slice(0, Math.max(0, n));
|
|||
|
};
|
|||
|
|
|||
|
// Sort the object's values by a criterion produced by an iteratee.
|
|||
|
_.sortBy = function(obj, iteratee, context) {
|
|||
|
iteratee = cb(iteratee, context);
|
|||
|
return _.pluck(_.map(obj, function(value, index, list) {
|
|||
|
return {
|
|||
|
value: value,
|
|||
|
index: index,
|
|||
|
criteria: iteratee(value, index, list)
|
|||
|
};
|
|||
|
}).sort(function(left, right) {
|
|||
|
var a = left.criteria;
|
|||
|
var b = right.criteria;
|
|||
|
if (a !== b) {
|
|||
|
if (a > b || a === void 0) return 1;
|
|||
|
if (a < b || b === void 0) return -1;
|
|||
|
}
|
|||
|
return left.index - right.index;
|
|||
|
}), 'value');
|
|||
|
};
|
|||
|
|
|||
|
// An internal function used for aggregate "group by" operations.
|
|||
|
var group = function(behavior) {
|
|||
|
return function(obj, iteratee, context) {
|
|||
|
var result = {};
|
|||
|
iteratee = cb(iteratee, context);
|
|||
|
_.each(obj, function(value, index) {
|
|||
|
var key = iteratee(value, index, obj);
|
|||
|
behavior(result, value, key);
|
|||
|
});
|
|||
|
return result;
|
|||
|
};
|
|||
|
};
|
|||
|
|
|||
|
// Groups the object's values by a criterion. Pass either a string attribute
|
|||
|
// to group by, or a function that returns the criterion.
|
|||
|
_.groupBy = group(function(result, value, key) {
|
|||
|
if (_.has(result, key)) result[key].push(value); else result[key] = [value];
|
|||
|
});
|
|||
|
|
|||
|
// Indexes the object's values by a criterion, similar to `groupBy`, but for
|
|||
|
// when you know that your index values will be unique.
|
|||
|
_.indexBy = group(function(result, value, key) {
|
|||
|
result[key] = value;
|
|||
|
});
|
|||
|
|
|||
|
// Counts instances of an object that group by a certain criterion. Pass
|
|||
|
// either a string attribute to count by, or a function that returns the
|
|||
|
// criterion.
|
|||
|
_.countBy = group(function(result, value, key) {
|
|||
|
if (_.has(result, key)) result[key]++; else result[key] = 1;
|
|||
|
});
|
|||
|
|
|||
|
// Safely create a real, live array from anything iterable.
|
|||
|
_.toArray = function(obj) {
|
|||
|
if (!obj) return [];
|
|||
|
if (_.isArray(obj)) return slice.call(obj);
|
|||
|
if (isArrayLike(obj)) return _.map(obj, _.identity);
|
|||
|
return _.values(obj);
|
|||
|
};
|
|||
|
|
|||
|
// Return the number of elements in an object.
|
|||
|
_.size = function(obj) {
|
|||
|
if (obj == null) return 0;
|
|||
|
return isArrayLike(obj) ? obj.length : _.keys(obj).length;
|
|||
|
};
|
|||
|
|
|||
|
// Split a collection into two arrays: one whose elements all satisfy the given
|
|||
|
// predicate, and one whose elements all do not satisfy the predicate.
|
|||
|
_.partition = function(obj, predicate, context) {
|
|||
|
predicate = cb(predicate, context);
|
|||
|
var pass = [], fail = [];
|
|||
|
_.each(obj, function(value, key, obj) {
|
|||
|
(predicate(value, key, obj) ? pass : fail).push(value);
|
|||
|
});
|
|||
|
return [pass, fail];
|
|||
|
};
|
|||
|
|
|||
|
// Array Functions
|
|||
|
// ---------------
|
|||
|
|
|||
|
// Get the first element of an array. Passing **n** will return the first N
|
|||
|
// values in the array. Aliased as `head` and `take`. The **guard** check
|
|||
|
// allows it to work with `_.map`.
|
|||
|
_.first = _.head = _.take = function(array, n, guard) {
|
|||
|
if (array == null) return void 0;
|
|||
|
if (n == null || guard) return array[0];
|
|||
|
return _.initial(array, array.length - n);
|
|||
|
};
|
|||
|
|
|||
|
// Returns everything but the last entry of the array. Especially useful on
|
|||
|
// the arguments object. Passing **n** will return all the values in
|
|||
|
// the array, excluding the last N.
|
|||
|
_.initial = function(array, n, guard) {
|
|||
|
return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
|
|||
|
};
|
|||
|
|
|||
|
// Get the last element of an array. Passing **n** will return the last N
|
|||
|
// values in the array.
|
|||
|
_.last = function(array, n, guard) {
|
|||
|
if (array == null) return void 0;
|
|||
|
if (n == null || guard) return array[array.length - 1];
|
|||
|
return _.rest(array, Math.max(0, array.length - n));
|
|||
|
};
|
|||
|
|
|||
|
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
|
|||
|
// Especially useful on the arguments object. Passing an **n** will return
|
|||
|
// the rest N values in the array.
|
|||
|
_.rest = _.tail = _.drop = function(array, n, guard) {
|
|||
|
return slice.call(array, n == null || guard ? 1 : n);
|
|||
|
};
|
|||
|
|
|||
|
// Trim out all falsy values from an array.
|
|||
|
_.compact = function(array) {
|
|||
|
return _.filter(array, _.identity);
|
|||
|
};
|
|||
|
|
|||
|
// Internal implementation of a recursive `flatten` function.
|
|||
|
var flatten = function(input, shallow, strict, startIndex) {
|
|||
|
var output = [], idx = 0;
|
|||
|
for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
|
|||
|
var value = input[i];
|
|||
|
if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
|
|||
|
//flatten current level of array or arguments object
|
|||
|
if (!shallow) value = flatten(value, shallow, strict);
|
|||
|
var j = 0, len = value.length;
|
|||
|
output.length += len;
|
|||
|
while (j < len) {
|
|||
|
output[idx++] = value[j++];
|
|||
|
}
|
|||
|
} else if (!strict) {
|
|||
|
output[idx++] = value;
|
|||
|
}
|
|||
|
}
|
|||
|
return output;
|
|||
|
};
|
|||
|
|
|||
|
// Flatten out an array, either recursively (by default), or just one level.
|
|||
|
_.flatten = function(array, shallow) {
|
|||
|
return flatten(array, shallow, false);
|
|||
|
};
|
|||
|
|
|||
|
// Return a version of the array that does not contain the specified value(s).
|
|||
|
_.without = function(array) {
|
|||
|
return _.difference(array, slice.call(arguments, 1));
|
|||
|
};
|
|||
|
|
|||
|
// Produce a duplicate-free version of the array. If the array has already
|
|||
|
// been sorted, you have the option of using a faster algorithm.
|
|||
|
// Aliased as `unique`.
|
|||
|
_.uniq = _.unique = function(array, isSorted, iteratee, context) {
|
|||
|
if (!_.isBoolean(isSorted)) {
|
|||
|
context = iteratee;
|
|||
|
iteratee = isSorted;
|
|||
|
isSorted = false;
|
|||
|
}
|
|||
|
if (iteratee != null) iteratee = cb(iteratee, context);
|
|||
|
var result = [];
|
|||
|
var seen = [];
|
|||
|
for (var i = 0, length = getLength(array); i < length; i++) {
|
|||
|
var value = array[i],
|
|||
|
computed = iteratee ? iteratee(value, i, array) : value;
|
|||
|
if (isSorted) {
|
|||
|
if (!i || seen !== computed) result.push(value);
|
|||
|
seen = computed;
|
|||
|
} else if (iteratee) {
|
|||
|
if (!_.contains(seen, computed)) {
|
|||
|
seen.push(computed);
|
|||
|
result.push(value);
|
|||
|
}
|
|||
|
} else if (!_.contains(result, value)) {
|
|||
|
result.push(value);
|
|||
|
}
|
|||
|
}
|
|||
|
return result;
|
|||
|
};
|
|||
|
|
|||
|
// Produce an array that contains the union: each distinct element from all of
|
|||
|
// the passed-in arrays.
|
|||
|
_.union = function() {
|
|||
|
return _.uniq(flatten(arguments, true, true));
|
|||
|
};
|
|||
|
|
|||
|
// Produce an array that contains every item shared between all the
|
|||
|
// passed-in arrays.
|
|||
|
_.intersection = function(array) {
|
|||
|
var result = [];
|
|||
|
var argsLength = arguments.length;
|
|||
|
for (var i = 0, length = getLength(array); i < length; i++) {
|
|||
|
var item = array[i];
|
|||
|
if (_.contains(result, item)) continue;
|
|||
|
for (var j = 1; j < argsLength; j++) {
|
|||
|
if (!_.contains(arguments[j], item)) break;
|
|||
|
}
|
|||
|
if (j === argsLength) result.push(item);
|
|||
|
}
|
|||
|
return result;
|
|||
|
};
|
|||
|
|
|||
|
// Take the difference between one array and a number of other arrays.
|
|||
|
// Only the elements present in just the first array will remain.
|
|||
|
_.difference = function(array) {
|
|||
|
var rest = flatten(arguments, true, true, 1);
|
|||
|
return _.filter(array, function(value){
|
|||
|
return !_.contains(rest, value);
|
|||
|
});
|
|||
|
};
|
|||
|
|
|||
|
// Zip together multiple lists into a single array -- elements that share
|
|||
|
// an index go together.
|
|||
|
_.zip = function() {
|
|||
|
return _.unzip(arguments);
|
|||
|
};
|
|||
|
|
|||
|
// Complement of _.zip. Unzip accepts an array of arrays and groups
|
|||
|
// each array's elements on shared indices
|
|||
|
_.unzip = function(array) {
|
|||
|
var length = array && _.max(array, getLength).length || 0;
|
|||
|
var result = Array(length);
|
|||
|
|
|||
|
for (var index = 0; index < length; index++) {
|
|||
|
result[index] = _.pluck(array, index);
|
|||
|
}
|
|||
|
return result;
|
|||
|
};
|
|||
|
|
|||
|
// Converts lists into objects. Pass either a single array of `[key, value]`
|
|||
|
// pairs, or two parallel arrays of the same length -- one of keys, and one of
|
|||
|
// the corresponding values.
|
|||
|
_.object = function(list, values) {
|
|||
|
var result = {};
|
|||
|
for (var i = 0, length = getLength(list); i < length; i++) {
|
|||
|
if (values) {
|
|||
|
result[list[i]] = values[i];
|
|||
|
} else {
|
|||
|
result[list[i][0]] = list[i][1];
|
|||
|
}
|
|||
|
}
|
|||
|
return result;
|
|||
|
};
|
|||
|
|
|||
|
// Generator function to create the findIndex and findLastIndex functions
|
|||
|
function createPredicateIndexFinder(dir) {
|
|||
|
return function(array, predicate, context) {
|
|||
|
predicate = cb(predicate, context);
|
|||
|
var length = getLength(array);
|
|||
|
var index = dir > 0 ? 0 : length - 1;
|
|||
|
for (; index >= 0 && index < length; index += dir) {
|
|||
|
if (predicate(array[index], index, array)) return index;
|
|||
|
}
|
|||
|
return -1;
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
// Returns the first index on an array-like that passes a predicate test
|
|||
|
_.findIndex = createPredicateIndexFinder(1);
|
|||
|
_.findLastIndex = createPredicateIndexFinder(-1);
|
|||
|
|
|||
|
// Use a comparator function to figure out the smallest index at which
|
|||
|
// an object should be inserted so as to maintain order. Uses binary search.
|
|||
|
_.sortedIndex = function(array, obj, iteratee, context) {
|
|||
|
iteratee = cb(iteratee, context, 1);
|
|||
|
var value = iteratee(obj);
|
|||
|
var low = 0, high = getLength(array);
|
|||
|
while (low < high) {
|
|||
|
var mid = Math.floor((low + high) / 2);
|
|||
|
if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
|
|||
|
}
|
|||
|
return low;
|
|||
|
};
|
|||
|
|
|||
|
// Generator function to create the indexOf and lastIndexOf functions
|
|||
|
function createIndexFinder(dir, predicateFind, sortedIndex) {
|
|||
|
return function(array, item, idx) {
|
|||
|
var i = 0, length = getLength(array);
|
|||
|
if (typeof idx == 'number') {
|
|||
|
if (dir > 0) {
|
|||
|
i = idx >= 0 ? idx : Math.max(idx + length, i);
|
|||
|
} else {
|
|||
|
length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
|
|||
|
}
|
|||
|
} else if (sortedIndex && idx && length) {
|
|||
|
idx = sortedIndex(array, item);
|
|||
|
return array[idx] === item ? idx : -1;
|
|||
|
}
|
|||
|
if (item !== item) {
|
|||
|
idx = predicateFind(slice.call(array, i, length), _.isNaN);
|
|||
|
return idx >= 0 ? idx + i : -1;
|
|||
|
}
|
|||
|
for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
|
|||
|
if (array[idx] === item) return idx;
|
|||
|
}
|
|||
|
return -1;
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
// Return the position of the first occurrence of an item in an array,
|
|||
|
// or -1 if the item is not included in the array.
|
|||
|
// If the array is large and already in sort order, pass `true`
|
|||
|
// for **isSorted** to use binary search.
|
|||
|
_.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
|
|||
|
_.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
|
|||
|
|
|||
|
// Generate an integer Array containing an arithmetic progression. A port of
|
|||
|
// the native Python `range()` function. See
|
|||
|
// [the Python documentation](http://docs.python.org/library/functions.html#range).
|
|||
|
_.range = function(start, stop, step) {
|
|||
|
if (stop == null) {
|
|||
|
stop = start || 0;
|
|||
|
start = 0;
|
|||
|
}
|
|||
|
step = step || 1;
|
|||
|
|
|||
|
var length = Math.max(Math.ceil((stop - start) / step), 0);
|
|||
|
var range = Array(length);
|
|||
|
|
|||
|
for (var idx = 0; idx < length; idx++, start += step) {
|
|||
|
range[idx] = start;
|
|||
|
}
|
|||
|
|
|||
|
return range;
|
|||
|
};
|
|||
|
|
|||
|
// Function (ahem) Functions
|
|||
|
// ------------------
|
|||
|
|
|||
|
// Determines whether to execute a function as a constructor
|
|||
|
// or a normal function with the provided arguments
|
|||
|
var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
|
|||
|
if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
|
|||
|
var self = baseCreate(sourceFunc.prototype);
|
|||
|
var result = sourceFunc.apply(self, args);
|
|||
|
if (_.isObject(result)) return result;
|
|||
|
return self;
|
|||
|
};
|
|||
|
|
|||
|
// Create a function bound to a given object (assigning `this`, and arguments,
|
|||
|
// optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
|
|||
|
// available.
|
|||
|
_.bind = function(func, context) {
|
|||
|
if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
|
|||
|
if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
|
|||
|
var args = slice.call(arguments, 2);
|
|||
|
var bound = function() {
|
|||
|
return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
|
|||
|
};
|
|||
|
return bound;
|
|||
|
};
|
|||
|
|
|||
|
// Partially apply a function by creating a version that has had some of its
|
|||
|
// arguments pre-filled, without changing its dynamic `this` context. _ acts
|
|||
|
// as a placeholder, allowing any combination of arguments to be pre-filled.
|
|||
|
_.partial = function(func) {
|
|||
|
var boundArgs = slice.call(arguments, 1);
|
|||
|
var bound = function() {
|
|||
|
var position = 0, length = boundArgs.length;
|
|||
|
var args = Array(length);
|
|||
|
for (var i = 0; i < length; i++) {
|
|||
|
args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
|
|||
|
}
|
|||
|
while (position < arguments.length) args.push(arguments[position++]);
|
|||
|
return executeBound(func, bound, this, this, args);
|
|||
|
};
|
|||
|
return bound;
|
|||
|
};
|
|||
|
|
|||
|
// Bind a number of an object's methods to that object. Remaining arguments
|
|||
|
// are the method names to be bound. Useful for ensuring that all callbacks
|
|||
|
// defined on an object belong to it.
|
|||
|
_.bindAll = function(obj) {
|
|||
|
var i, length = arguments.length, key;
|
|||
|
if (length <= 1) throw new Error('bindAll must be passed function names');
|
|||
|
for (i = 1; i < length; i++) {
|
|||
|
key = arguments[i];
|
|||
|
obj[key] = _.bind(obj[key], obj);
|
|||
|
}
|
|||
|
return obj;
|
|||
|
};
|
|||
|
|
|||
|
// Memoize an expensive function by storing its results.
|
|||
|
_.memoize = function(func, hasher) {
|
|||
|
var memoize = function(key) {
|
|||
|
var cache = memoize.cache;
|
|||
|
var address = '' + (hasher ? hasher.apply(this, arguments) : key);
|
|||
|
if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
|
|||
|
return cache[address];
|
|||
|
};
|
|||
|
memoize.cache = {};
|
|||
|
return memoize;
|
|||
|
};
|
|||
|
|
|||
|
// Delays a function for the given number of milliseconds, and then calls
|
|||
|
// it with the arguments supplied.
|
|||
|
_.delay = function(func, wait) {
|
|||
|
var args = slice.call(arguments, 2);
|
|||
|
return setTimeout(function(){
|
|||
|
return func.apply(null, args);
|
|||
|
}, wait);
|
|||
|
};
|
|||
|
|
|||
|
// Defers a function, scheduling it to run after the current call stack has
|
|||
|
// cleared.
|
|||
|
_.defer = _.partial(_.delay, _, 1);
|
|||
|
|
|||
|
// Returns a function, that, when invoked, will only be triggered at most once
|
|||
|
// during a given window of time. Normally, the throttled function will run
|
|||
|
// as much as it can, without ever going more than once per `wait` duration;
|
|||
|
// but if you'd like to disable the execution on the leading edge, pass
|
|||
|
// `{leading: false}`. To disable execution on the trailing edge, ditto.
|
|||
|
_.throttle = function(func, wait, options) {
|
|||
|
var context, args, result;
|
|||
|
var timeout = null;
|
|||
|
var previous = 0;
|
|||
|
if (!options) options = {};
|
|||
|
var later = function() {
|
|||
|
previous = options.leading === false ? 0 : _.now();
|
|||
|
timeout = null;
|
|||
|
result = func.apply(context, args);
|
|||
|
if (!timeout) context = args = null;
|
|||
|
};
|
|||
|
return function() {
|
|||
|
var now = _.now();
|
|||
|
if (!previous && options.leading === false) previous = now;
|
|||
|
var remaining = wait - (now - previous);
|
|||
|
context = this;
|
|||
|
args = arguments;
|
|||
|
if (remaining <= 0 || remaining > wait) {
|
|||
|
if (timeout) {
|
|||
|
clearTimeout(timeout);
|
|||
|
timeout = null;
|
|||
|
}
|
|||
|
previous = now;
|
|||
|
result = func.apply(context, args);
|
|||
|
if (!timeout) context = args = null;
|
|||
|
} else if (!timeout && options.trailing !== false) {
|
|||
|
timeout = setTimeout(later, remaining);
|
|||
|
}
|
|||
|
return result;
|
|||
|
};
|
|||
|
};
|
|||
|
|
|||
|
// Returns a function, that, as long as it continues to be invoked, will not
|
|||
|
// be triggered. The function will be called after it stops being called for
|
|||
|
// N milliseconds. If `immediate` is passed, trigger the function on the
|
|||
|
// leading edge, instead of the trailing.
|
|||
|
_.debounce = function(func, wait, immediate) {
|
|||
|
var timeout, args, context, timestamp, result;
|
|||
|
|
|||
|
var later = function() {
|
|||
|
var last = _.now() - timestamp;
|
|||
|
|
|||
|
if (last < wait && last >= 0) {
|
|||
|
timeout = setTimeout(later, wait - last);
|
|||
|
} else {
|
|||
|
timeout = null;
|
|||
|
if (!immediate) {
|
|||
|
result = func.apply(context, args);
|
|||
|
if (!timeout) context = args = null;
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
return function() {
|
|||
|
context = this;
|
|||
|
args = arguments;
|
|||
|
timestamp = _.now();
|
|||
|
var callNow = immediate && !timeout;
|
|||
|
if (!timeout) timeout = setTimeout(later, wait);
|
|||
|
if (callNow) {
|
|||
|
result = func.apply(context, args);
|
|||
|
context = args = null;
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
};
|
|||
|
};
|
|||
|
|
|||
|
// Returns the first function passed as an argument to the second,
|
|||
|
// allowing you to adjust arguments, run code before and after, and
|
|||
|
// conditionally execute the original function.
|
|||
|
_.wrap = function(func, wrapper) {
|
|||
|
return _.partial(wrapper, func);
|
|||
|
};
|
|||
|
|
|||
|
// Returns a negated version of the passed-in predicate.
|
|||
|
_.negate = function(predicate) {
|
|||
|
return function() {
|
|||
|
return !predicate.apply(this, arguments);
|
|||
|
};
|
|||
|
};
|
|||
|
|
|||
|
// Returns a function that is the composition of a list of functions, each
|
|||
|
// consuming the return value of the function that follows.
|
|||
|
_.compose = function() {
|
|||
|
var args = arguments;
|
|||
|
var start = args.length - 1;
|
|||
|
return function() {
|
|||
|
var i = start;
|
|||
|
var result = args[start].apply(this, arguments);
|
|||
|
while (i--) result = args[i].call(this, result);
|
|||
|
return result;
|
|||
|
};
|
|||
|
};
|
|||
|
|
|||
|
// Returns a function that will only be executed on and after the Nth call.
|
|||
|
_.after = function(times, func) {
|
|||
|
return function() {
|
|||
|
if (--times < 1) {
|
|||
|
return func.apply(this, arguments);
|
|||
|
}
|
|||
|
};
|
|||
|
};
|
|||
|
|
|||
|
// Returns a function that will only be executed up to (but not including) the Nth call.
|
|||
|
_.before = function(times, func) {
|
|||
|
var memo;
|
|||
|
return function() {
|
|||
|
if (--times > 0) {
|
|||
|
memo = func.apply(this, arguments);
|
|||
|
}
|
|||
|
if (times <= 1) func = null;
|
|||
|
return memo;
|
|||
|
};
|
|||
|
};
|
|||
|
|
|||
|
// Returns a function that will be executed at most one time, no matter how
|
|||
|
// often you call it. Useful for lazy initialization.
|
|||
|
_.once = _.partial(_.before, 2);
|
|||
|
|
|||
|
// Object Functions
|
|||
|
// ----------------
|
|||
|
|
|||
|
// Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
|
|||
|
var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
|
|||
|
var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
|
|||
|
'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
|
|||
|
|
|||
|
function collectNonEnumProps(obj, keys) {
|
|||
|
var nonEnumIdx = nonEnumerableProps.length;
|
|||
|
var constructor = obj.constructor;
|
|||
|
var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
|
|||
|
|
|||
|
// Constructor is a special case.
|
|||
|
var prop = 'constructor';
|
|||
|
if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
|
|||
|
|
|||
|
while (nonEnumIdx--) {
|
|||
|
prop = nonEnumerableProps[nonEnumIdx];
|
|||
|
if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
|
|||
|
keys.push(prop);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Retrieve the names of an object's own properties.
|
|||
|
// Delegates to **ECMAScript 5**'s native `Object.keys`
|
|||
|
_.keys = function(obj) {
|
|||
|
if (!_.isObject(obj)) return [];
|
|||
|
if (nativeKeys) return nativeKeys(obj);
|
|||
|
var keys = [];
|
|||
|
for (var key in obj) if (_.has(obj, key)) keys.push(key);
|
|||
|
// Ahem, IE < 9.
|
|||
|
if (hasEnumBug) collectNonEnumProps(obj, keys);
|
|||
|
return keys;
|
|||
|
};
|
|||
|
|
|||
|
// Retrieve all the property names of an object.
|
|||
|
_.allKeys = function(obj) {
|
|||
|
if (!_.isObject(obj)) return [];
|
|||
|
var keys = [];
|
|||
|
for (var key in obj) keys.push(key);
|
|||
|
// Ahem, IE < 9.
|
|||
|
if (hasEnumBug) collectNonEnumProps(obj, keys);
|
|||
|
return keys;
|
|||
|
};
|
|||
|
|
|||
|
// Retrieve the values of an object's properties.
|
|||
|
_.values = function(obj) {
|
|||
|
var keys = _.keys(obj);
|
|||
|
var length = keys.length;
|
|||
|
var values = Array(length);
|
|||
|
for (var i = 0; i < length; i++) {
|
|||
|
values[i] = obj[keys[i]];
|
|||
|
}
|
|||
|
return values;
|
|||
|
};
|
|||
|
|
|||
|
// Returns the results of applying the iteratee to each element of the object
|
|||
|
// In contrast to _.map it returns an object
|
|||
|
_.mapObject = function(obj, iteratee, context) {
|
|||
|
iteratee = cb(iteratee, context);
|
|||
|
var keys = _.keys(obj),
|
|||
|
length = keys.length,
|
|||
|
results = {},
|
|||
|
currentKey;
|
|||
|
for (var index = 0; index < length; index++) {
|
|||
|
currentKey = keys[index];
|
|||
|
results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
|
|||
|
}
|
|||
|
return results;
|
|||
|
};
|
|||
|
|
|||
|
// Convert an object into a list of `[key, value]` pairs.
|
|||
|
_.pairs = function(obj) {
|
|||
|
var keys = _.keys(obj);
|
|||
|
var length = keys.length;
|
|||
|
var pairs = Array(length);
|
|||
|
for (var i = 0; i < length; i++) {
|
|||
|
pairs[i] = [keys[i], obj[keys[i]]];
|
|||
|
}
|
|||
|
return pairs;
|
|||
|
};
|
|||
|
|
|||
|
// Invert the keys and values of an object. The values must be serializable.
|
|||
|
_.invert = function(obj) {
|
|||
|
var result = {};
|
|||
|
var keys = _.keys(obj);
|
|||
|
for (var i = 0, length = keys.length; i < length; i++) {
|
|||
|
result[obj[keys[i]]] = keys[i];
|
|||
|
}
|
|||
|
return result;
|
|||
|
};
|
|||
|
|
|||
|
// Return a sorted list of the function names available on the object.
|
|||
|
// Aliased as `methods`
|
|||
|
_.functions = _.methods = function(obj) {
|
|||
|
var names = [];
|
|||
|
for (var key in obj) {
|
|||
|
if (_.isFunction(obj[key])) names.push(key);
|
|||
|
}
|
|||
|
return names.sort();
|
|||
|
};
|
|||
|
|
|||
|
// Extend a given object with all the properties in passed-in object(s).
|
|||
|
_.extend = createAssigner(_.allKeys);
|
|||
|
|
|||
|
// Assigns a given object with all the own properties in the passed-in object(s)
|
|||
|
// (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
|
|||
|
_.extendOwn = _.assign = createAssigner(_.keys);
|
|||
|
|
|||
|
// Returns the first key on an object that passes a predicate test
|
|||
|
_.findKey = function(obj, predicate, context) {
|
|||
|
predicate = cb(predicate, context);
|
|||
|
var keys = _.keys(obj), key;
|
|||
|
for (var i = 0, length = keys.length; i < length; i++) {
|
|||
|
key = keys[i];
|
|||
|
if (predicate(obj[key], key, obj)) return key;
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
// Return a copy of the object only containing the whitelisted properties.
|
|||
|
_.pick = function(object, oiteratee, context) {
|
|||
|
var result = {}, obj = object, iteratee, keys;
|
|||
|
if (obj == null) return result;
|
|||
|
if (_.isFunction(oiteratee)) {
|
|||
|
keys = _.allKeys(obj);
|
|||
|
iteratee = optimizeCb(oiteratee, context);
|
|||
|
} else {
|
|||
|
keys = flatten(arguments, false, false, 1);
|
|||
|
iteratee = function(value, key, obj) { return key in obj; };
|
|||
|
obj = Object(obj);
|
|||
|
}
|
|||
|
for (var i = 0, length = keys.length; i < length; i++) {
|
|||
|
var key = keys[i];
|
|||
|
var value = obj[key];
|
|||
|
if (iteratee(value, key, obj)) result[key] = value;
|
|||
|
}
|
|||
|
return result;
|
|||
|
};
|
|||
|
|
|||
|
// Return a copy of the object without the blacklisted properties.
|
|||
|
_.omit = function(obj, iteratee, context) {
|
|||
|
if (_.isFunction(iteratee)) {
|
|||
|
iteratee = _.negate(iteratee);
|
|||
|
} else {
|
|||
|
var keys = _.map(flatten(arguments, false, false, 1), String);
|
|||
|
iteratee = function(value, key) {
|
|||
|
return !_.contains(keys, key);
|
|||
|
};
|
|||
|
}
|
|||
|
return _.pick(obj, iteratee, context);
|
|||
|
};
|
|||
|
|
|||
|
// Fill in a given object with default properties.
|
|||
|
_.defaults = createAssigner(_.allKeys, true);
|
|||
|
|
|||
|
// Creates an object that inherits from the given prototype object.
|
|||
|
// If additional properties are provided then they will be added to the
|
|||
|
// created object.
|
|||
|
_.create = function(prototype, props) {
|
|||
|
var result = baseCreate(prototype);
|
|||
|
if (props) _.extendOwn(result, props);
|
|||
|
return result;
|
|||
|
};
|
|||
|
|
|||
|
// Create a (shallow-cloned) duplicate of an object.
|
|||
|
_.clone = function(obj) {
|
|||
|
if (!_.isObject(obj)) return obj;
|
|||
|
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
|
|||
|
};
|
|||
|
|
|||
|
// Invokes interceptor with the obj, and then returns obj.
|
|||
|
// The primary purpose of this method is to "tap into" a method chain, in
|
|||
|
// order to perform operations on intermediate results within the chain.
|
|||
|
_.tap = function(obj, interceptor) {
|
|||
|
interceptor(obj);
|
|||
|
return obj;
|
|||
|
};
|
|||
|
|
|||
|
// Returns whether an object has a given set of `key:value` pairs.
|
|||
|
_.isMatch = function(object, attrs) {
|
|||
|
var keys = _.keys(attrs), length = keys.length;
|
|||
|
if (object == null) return !length;
|
|||
|
var obj = Object(object);
|
|||
|
for (var i = 0; i < length; i++) {
|
|||
|
var key = keys[i];
|
|||
|
if (attrs[key] !== obj[key] || !(key in obj)) return false;
|
|||
|
}
|
|||
|
return true;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
// Internal recursive comparison function for `isEqual`.
|
|||
|
var eq = function(a, b, aStack, bStack) {
|
|||
|
// Identical objects are equal. `0 === -0`, but they aren't identical.
|
|||
|
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
|
|||
|
if (a === b) return a !== 0 || 1 / a === 1 / b;
|
|||
|
// A strict comparison is necessary because `null == undefined`.
|
|||
|
if (a == null || b == null) return a === b;
|
|||
|
// Unwrap any wrapped objects.
|
|||
|
if (a instanceof _) a = a._wrapped;
|
|||
|
if (b instanceof _) b = b._wrapped;
|
|||
|
// Compare `[[Class]]` names.
|
|||
|
var className = toString.call(a);
|
|||
|
if (className !== toString.call(b)) return false;
|
|||
|
switch (className) {
|
|||
|
// Strings, numbers, regular expressions, dates, and booleans are compared by value.
|
|||
|
case '[object RegExp]':
|
|||
|
// RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
|
|||
|
case '[object String]':
|
|||
|
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
|
|||
|
// equivalent to `new String("5")`.
|
|||
|
return '' + a === '' + b;
|
|||
|
case '[object Number]':
|
|||
|
// `NaN`s are equivalent, but non-reflexive.
|
|||
|
// Object(NaN) is equivalent to NaN
|
|||
|
if (+a !== +a) return +b !== +b;
|
|||
|
// An `egal` comparison is performed for other numeric values.
|
|||
|
return +a === 0 ? 1 / +a === 1 / b : +a === +b;
|
|||
|
case '[object Date]':
|
|||
|
case '[object Boolean]':
|
|||
|
// Coerce dates and booleans to numeric primitive values. Dates are compared by their
|
|||
|
// millisecond representations. Note that invalid dates with millisecond representations
|
|||
|
// of `NaN` are not equivalent.
|
|||
|
return +a === +b;
|
|||
|
}
|
|||
|
|
|||
|
var areArrays = className === '[object Array]';
|
|||
|
if (!areArrays) {
|
|||
|
if (typeof a != 'object' || typeof b != 'object') return false;
|
|||
|
|
|||
|
// Objects with different constructors are not equivalent, but `Object`s or `Array`s
|
|||
|
// from different frames are.
|
|||
|
var aCtor = a.constructor, bCtor = b.constructor;
|
|||
|
if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
|
|||
|
_.isFunction(bCtor) && bCtor instanceof bCtor)
|
|||
|
&& ('constructor' in a && 'constructor' in b)) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
// Assume equality for cyclic structures. The algorithm for detecting cyclic
|
|||
|
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
|
|||
|
|
|||
|
// Initializing stack of traversed objects.
|
|||
|
// It's done here since we only need them for objects and arrays comparison.
|
|||
|
aStack = aStack || [];
|
|||
|
bStack = bStack || [];
|
|||
|
var length = aStack.length;
|
|||
|
while (length--) {
|
|||
|
// Linear search. Performance is inversely proportional to the number of
|
|||
|
// unique nested structures.
|
|||
|
if (aStack[length] === a) return bStack[length] === b;
|
|||
|
}
|
|||
|
|
|||
|
// Add the first object to the stack of traversed objects.
|
|||
|
aStack.push(a);
|
|||
|
bStack.push(b);
|
|||
|
|
|||
|
// Recursively compare objects and arrays.
|
|||
|
if (areArrays) {
|
|||
|
// Compare array lengths to determine if a deep comparison is necessary.
|
|||
|
length = a.length;
|
|||
|
if (length !== b.length) return false;
|
|||
|
// Deep compare the contents, ignoring non-numeric properties.
|
|||
|
while (length--) {
|
|||
|
if (!eq(a[length], b[length], aStack, bStack)) return false;
|
|||
|
}
|
|||
|
} else {
|
|||
|
// Deep compare objects.
|
|||
|
var keys = _.keys(a), key;
|
|||
|
length = keys.length;
|
|||
|
// Ensure that both objects contain the same number of properties before comparing deep equality.
|
|||
|
if (_.keys(b).length !== length) return false;
|
|||
|
while (length--) {
|
|||
|
// Deep compare each member
|
|||
|
key = keys[length];
|
|||
|
if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
|
|||
|
}
|
|||
|
}
|
|||
|
// Remove the first object from the stack of traversed objects.
|
|||
|
aStack.pop();
|
|||
|
bStack.pop();
|
|||
|
return true;
|
|||
|
};
|
|||
|
|
|||
|
// Perform a deep comparison to check if two objects are equal.
|
|||
|
_.isEqual = function(a, b) {
|
|||
|
return eq(a, b);
|
|||
|
};
|
|||
|
|
|||
|
// Is a given array, string, or object empty?
|
|||
|
// An "empty" object has no enumerable own-properties.
|
|||
|
_.isEmpty = function(obj) {
|
|||
|
if (obj == null) return true;
|
|||
|
if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
|
|||
|
return _.keys(obj).length === 0;
|
|||
|
};
|
|||
|
|
|||
|
// Is a given value a DOM element?
|
|||
|
_.isElement = function(obj) {
|
|||
|
return !!(obj && obj.nodeType === 1);
|
|||
|
};
|
|||
|
|
|||
|
// Is a given value an array?
|
|||
|
// Delegates to ECMA5's native Array.isArray
|
|||
|
_.isArray = nativeIsArray || function(obj) {
|
|||
|
return toString.call(obj) === '[object Array]';
|
|||
|
};
|
|||
|
|
|||
|
// Is a given variable an object?
|
|||
|
_.isObject = function(obj) {
|
|||
|
var type = typeof obj;
|
|||
|
return type === 'function' || type === 'object' && !!obj;
|
|||
|
};
|
|||
|
|
|||
|
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
|
|||
|
_.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
|
|||
|
_['is' + name] = function(obj) {
|
|||
|
return toString.call(obj) === '[object ' + name + ']';
|
|||
|
};
|
|||
|
});
|
|||
|
|
|||
|
// Define a fallback version of the method in browsers (ahem, IE < 9), where
|
|||
|
// there isn't any inspectable "Arguments" type.
|
|||
|
if (!_.isArguments(arguments)) {
|
|||
|
_.isArguments = function(obj) {
|
|||
|
return _.has(obj, 'callee');
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
// Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
|
|||
|
// IE 11 (#1621), and in Safari 8 (#1929).
|
|||
|
if (typeof /./ != 'function' && typeof Int8Array != 'object') {
|
|||
|
_.isFunction = function(obj) {
|
|||
|
return typeof obj == 'function' || false;
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
// Is a given object a finite number?
|
|||
|
_.isFinite = function(obj) {
|
|||
|
return isFinite(obj) && !isNaN(parseFloat(obj));
|
|||
|
};
|
|||
|
|
|||
|
// Is the given value `NaN`? (NaN is the only number which does not equal itself).
|
|||
|
_.isNaN = function(obj) {
|
|||
|
return _.isNumber(obj) && obj !== +obj;
|
|||
|
};
|
|||
|
|
|||
|
// Is a given value a boolean?
|
|||
|
_.isBoolean = function(obj) {
|
|||
|
return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
|
|||
|
};
|
|||
|
|
|||
|
// Is a given value equal to null?
|
|||
|
_.isNull = function(obj) {
|
|||
|
return obj === null;
|
|||
|
};
|
|||
|
|
|||
|
// Is a given variable undefined?
|
|||
|
_.isUndefined = function(obj) {
|
|||
|
return obj === void 0;
|
|||
|
};
|
|||
|
|
|||
|
// Shortcut function for checking if an object has a given property directly
|
|||
|
// on itself (in other words, not on a prototype).
|
|||
|
_.has = function(obj, key) {
|
|||
|
return obj != null && hasOwnProperty.call(obj, key);
|
|||
|
};
|
|||
|
|
|||
|
// Utility Functions
|
|||
|
// -----------------
|
|||
|
|
|||
|
// Run Underscore.js in *noConflict* mode, returning the `_` variable to its
|
|||
|
// previous owner. Returns a reference to the Underscore object.
|
|||
|
_.noConflict = function() {
|
|||
|
root._ = previousUnderscore;
|
|||
|
return this;
|
|||
|
};
|
|||
|
|
|||
|
// Keep the identity function around for default iteratees.
|
|||
|
_.identity = function(value) {
|
|||
|
return value;
|
|||
|
};
|
|||
|
|
|||
|
// Predicate-generating functions. Often useful outside of Underscore.
|
|||
|
_.constant = function(value) {
|
|||
|
return function() {
|
|||
|
return value;
|
|||
|
};
|
|||
|
};
|
|||
|
|
|||
|
_.noop = function(){};
|
|||
|
|
|||
|
_.property = property;
|
|||
|
|
|||
|
// Generates a function for a given object that returns a given property.
|
|||
|
_.propertyOf = function(obj) {
|
|||
|
return obj == null ? function(){} : function(key) {
|
|||
|
return obj[key];
|
|||
|
};
|
|||
|
};
|
|||
|
|
|||
|
// Returns a predicate for checking whether an object has a given set of
|
|||
|
// `key:value` pairs.
|
|||
|
_.matcher = _.matches = function(attrs) {
|
|||
|
attrs = _.extendOwn({}, attrs);
|
|||
|
return function(obj) {
|
|||
|
return _.isMatch(obj, attrs);
|
|||
|
};
|
|||
|
};
|
|||
|
|
|||
|
// Run a function **n** times.
|
|||
|
_.times = function(n, iteratee, context) {
|
|||
|
var accum = Array(Math.max(0, n));
|
|||
|
iteratee = optimizeCb(iteratee, context, 1);
|
|||
|
for (var i = 0; i < n; i++) accum[i] = iteratee(i);
|
|||
|
return accum;
|
|||
|
};
|
|||
|
|
|||
|
// Return a random integer between min and max (inclusive).
|
|||
|
_.random = function(min, max) {
|
|||
|
if (max == null) {
|
|||
|
max = min;
|
|||
|
min = 0;
|
|||
|
}
|
|||
|
return min + Math.floor(Math.random() * (max - min + 1));
|
|||
|
};
|
|||
|
|
|||
|
// A (possibly faster) way to get the current timestamp as an integer.
|
|||
|
_.now = Date.now || function() {
|
|||
|
return new Date().getTime();
|
|||
|
};
|
|||
|
|
|||
|
// List of HTML entities for escaping.
|
|||
|
var escapeMap = {
|
|||
|
'&': '&',
|
|||
|
'<': '<',
|
|||
|
'>': '>',
|
|||
|
'"': '"',
|
|||
|
"'": ''',
|
|||
|
'`': '`'
|
|||
|
};
|
|||
|
var unescapeMap = _.invert(escapeMap);
|
|||
|
|
|||
|
// Functions for escaping and unescaping strings to/from HTML interpolation.
|
|||
|
var createEscaper = function(map) {
|
|||
|
var escaper = function(match) {
|
|||
|
return map[match];
|
|||
|
};
|
|||
|
// Regexes for identifying a key that needs to be escaped
|
|||
|
var source = '(?:' + _.keys(map).join('|') + ')';
|
|||
|
var testRegexp = RegExp(source);
|
|||
|
var replaceRegexp = RegExp(source, 'g');
|
|||
|
return function(string) {
|
|||
|
string = string == null ? '' : '' + string;
|
|||
|
return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
|
|||
|
};
|
|||
|
};
|
|||
|
_.escape = createEscaper(escapeMap);
|
|||
|
_.unescape = createEscaper(unescapeMap);
|
|||
|
|
|||
|
// If the value of the named `property` is a function then invoke it with the
|
|||
|
// `object` as context; otherwise, return it.
|
|||
|
_.result = function(object, property, fallback) {
|
|||
|
var value = object == null ? void 0 : object[property];
|
|||
|
if (value === void 0) {
|
|||
|
value = fallback;
|
|||
|
}
|
|||
|
return _.isFunction(value) ? value.call(object) : value;
|
|||
|
};
|
|||
|
|
|||
|
// Generate a unique integer id (unique within the entire client session).
|
|||
|
// Useful for temporary DOM ids.
|
|||
|
var idCounter = 0;
|
|||
|
_.uniqueId = function(prefix) {
|
|||
|
var id = ++idCounter + '';
|
|||
|
return prefix ? prefix + id : id;
|
|||
|
};
|
|||
|
|
|||
|
// By default, Underscore uses ERB-style template delimiters, change the
|
|||
|
// following template settings to use alternative delimiters.
|
|||
|
_.templateSettings = {
|
|||
|
evaluate : /<%([\s\S]+?)%>/g,
|
|||
|
interpolate : /<%=([\s\S]+?)%>/g,
|
|||
|
escape : /<%-([\s\S]+?)%>/g
|
|||
|
};
|
|||
|
|
|||
|
// When customizing `templateSettings`, if you don't want to define an
|
|||
|
// interpolation, evaluation or escaping regex, we need one that is
|
|||
|
// guaranteed not to match.
|
|||
|
var noMatch = /(.)^/;
|
|||
|
|
|||
|
// Certain characters need to be escaped so that they can be put into a
|
|||
|
// string literal.
|
|||
|
var escapes = {
|
|||
|
"'": "'",
|
|||
|
'\\': '\\',
|
|||
|
'\r': 'r',
|
|||
|
'\n': 'n',
|
|||
|
'\u2028': 'u2028',
|
|||
|
'\u2029': 'u2029'
|
|||
|
};
|
|||
|
|
|||
|
var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
|
|||
|
|
|||
|
var escapeChar = function(match) {
|
|||
|
return '\\' + escapes[match];
|
|||
|
};
|
|||
|
|
|||
|
// JavaScript micro-templating, similar to John Resig's implementation.
|
|||
|
// Underscore templating handles arbitrary delimiters, preserves whitespace,
|
|||
|
// and correctly escapes quotes within interpolated code.
|
|||
|
// NB: `oldSettings` only exists for backwards compatibility.
|
|||
|
_.template = function(text, settings, oldSettings) {
|
|||
|
if (!settings && oldSettings) settings = oldSettings;
|
|||
|
settings = _.defaults({}, settings, _.templateSettings);
|
|||
|
|
|||
|
// Combine delimiters into one regular expression via alternation.
|
|||
|
var matcher = RegExp([
|
|||
|
(settings.escape || noMatch).source,
|
|||
|
(settings.interpolate || noMatch).source,
|
|||
|
(settings.evaluate || noMatch).source
|
|||
|
].join('|') + '|$', 'g');
|
|||
|
|
|||
|
// Compile the template source, escaping string literals appropriately.
|
|||
|
var index = 0;
|
|||
|
var source = "__p+='";
|
|||
|
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
|
|||
|
source += text.slice(index, offset).replace(escaper, escapeChar);
|
|||
|
index = offset + match.length;
|
|||
|
|
|||
|
if (escape) {
|
|||
|
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
|
|||
|
} else if (interpolate) {
|
|||
|
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
|
|||
|
} else if (evaluate) {
|
|||
|
source += "';\n" + evaluate + "\n__p+='";
|
|||
|
}
|
|||
|
|
|||
|
// Adobe VMs need the match returned to produce the correct offest.
|
|||
|
return match;
|
|||
|
});
|
|||
|
source += "';\n";
|
|||
|
|
|||
|
// If a variable is not specified, place data values in local scope.
|
|||
|
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
|
|||
|
|
|||
|
source = "var __t,__p='',__j=Array.prototype.join," +
|
|||
|
"print=function(){__p+=__j.call(arguments,'');};\n" +
|
|||
|
source + 'return __p;\n';
|
|||
|
|
|||
|
try {
|
|||
|
var render = new Function(settings.variable || 'obj', '_', source);
|
|||
|
} catch (e) {
|
|||
|
e.source = source;
|
|||
|
throw e;
|
|||
|
}
|
|||
|
|
|||
|
var template = function(data) {
|
|||
|
return render.call(this, data, _);
|
|||
|
};
|
|||
|
|
|||
|
// Provide the compiled source as a convenience for precompilation.
|
|||
|
var argument = settings.variable || 'obj';
|
|||
|
template.source = 'function(' + argument + '){\n' + source + '}';
|
|||
|
|
|||
|
return template;
|
|||
|
};
|
|||
|
|
|||
|
// Add a "chain" function. Start chaining a wrapped Underscore object.
|
|||
|
_.chain = function(obj) {
|
|||
|
var instance = _(obj);
|
|||
|
instance._chain = true;
|
|||
|
return instance;
|
|||
|
};
|
|||
|
|
|||
|
// OOP
|
|||
|
// ---------------
|
|||
|
// If Underscore is called as a function, it returns a wrapped object that
|
|||
|
// can be used OO-style. This wrapper holds altered versions of all the
|
|||
|
// underscore functions. Wrapped objects may be chained.
|
|||
|
|
|||
|
// Helper function to continue chaining intermediate results.
|
|||
|
var result = function(instance, obj) {
|
|||
|
return instance._chain ? _(obj).chain() : obj;
|
|||
|
};
|
|||
|
|
|||
|
// Add your own custom functions to the Underscore object.
|
|||
|
_.mixin = function(obj) {
|
|||
|
_.each(_.functions(obj), function(name) {
|
|||
|
var func = _[name] = obj[name];
|
|||
|
_.prototype[name] = function() {
|
|||
|
var args = [this._wrapped];
|
|||
|
push.apply(args, arguments);
|
|||
|
return result(this, func.apply(_, args));
|
|||
|
};
|
|||
|
});
|
|||
|
};
|
|||
|
|
|||
|
// Add all of the Underscore functions to the wrapper object.
|
|||
|
_.mixin(_);
|
|||
|
|
|||
|
// Add all mutator Array functions to the wrapper.
|
|||
|
_.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
|
|||
|
var method = ArrayProto[name];
|
|||
|
_.prototype[name] = function() {
|
|||
|
var obj = this._wrapped;
|
|||
|
method.apply(obj, arguments);
|
|||
|
if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
|
|||
|
return result(this, obj);
|
|||
|
};
|
|||
|
});
|
|||
|
|
|||
|
// Add all accessor Array functions to the wrapper.
|
|||
|
_.each(['concat', 'join', 'slice'], function(name) {
|
|||
|
var method = ArrayProto[name];
|
|||
|
_.prototype[name] = function() {
|
|||
|
return result(this, method.apply(this._wrapped, arguments));
|
|||
|
};
|
|||
|
});
|
|||
|
|
|||
|
// Extracts the result from a wrapped and chained object.
|
|||
|
_.prototype.value = function() {
|
|||
|
return this._wrapped;
|
|||
|
};
|
|||
|
|
|||
|
// Provide unwrapping proxy for some methods used in engine operations
|
|||
|
// such as arithmetic and JSON stringification.
|
|||
|
_.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
|
|||
|
|
|||
|
_.prototype.toString = function() {
|
|||
|
return '' + this._wrapped;
|
|||
|
};
|
|||
|
|
|||
|
// AMD registration happens at the end for compatibility with AMD loaders
|
|||
|
// that may not enforce next-turn semantics on modules. Even though general
|
|||
|
// practice for AMD registration is to be anonymous, underscore registers
|
|||
|
// as a named module because, like jQuery, it is a base library that is
|
|||
|
// popular enough to be bundled in a third party lib, but not be part of
|
|||
|
// an AMD load request. Those cases could generate an error when an
|
|||
|
// anonymous define() is called outside of a loader request.
|
|||
|
if (typeof define === 'function' && define.amd) {
|
|||
|
define('underscore', [], function() {
|
|||
|
return _;
|
|||
|
});
|
|||
|
}
|
|||
|
}.call(this));
|
|||
|
|
|||
|
},{}],26:[function(require,module,exports){
|
|||
|
arguments[4][19][0].apply(exports,arguments)
|
|||
|
},{"dup":19}],27:[function(require,module,exports){
|
|||
|
module.exports = function isBuffer(arg) {
|
|||
|
return arg && typeof arg === 'object'
|
|||
|
&& typeof arg.copy === 'function'
|
|||
|
&& typeof arg.fill === 'function'
|
|||
|
&& typeof arg.readUInt8 === 'function';
|
|||
|
}
|
|||
|
},{}],28:[function(require,module,exports){
|
|||
|
(function (process,global){
|
|||
|
// Copyright Joyent, Inc. and other Node contributors.
|
|||
|
//
|
|||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|||
|
// copy of this software and associated documentation files (the
|
|||
|
// "Software"), to deal in the Software without restriction, including
|
|||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|||
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|||
|
// persons to whom the Software is furnished to do so, subject to the
|
|||
|
// following conditions:
|
|||
|
//
|
|||
|
// The above copyright notice and this permission notice shall be included
|
|||
|
// in all copies or substantial portions of the Software.
|
|||
|
//
|
|||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|||
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|||
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|||
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|||
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|||
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
|
|||
|
var formatRegExp = /%[sdj%]/g;
|
|||
|
exports.format = function(f) {
|
|||
|
if (!isString(f)) {
|
|||
|
var objects = [];
|
|||
|
for (var i = 0; i < arguments.length; i++) {
|
|||
|
objects.push(inspect(arguments[i]));
|
|||
|
}
|
|||
|
return objects.join(' ');
|
|||
|
}
|
|||
|
|
|||
|
var i = 1;
|
|||
|
var args = arguments;
|
|||
|
var len = args.length;
|
|||
|
var str = String(f).replace(formatRegExp, function(x) {
|
|||
|
if (x === '%%') return '%';
|
|||
|
if (i >= len) return x;
|
|||
|
switch (x) {
|
|||
|
case '%s': return String(args[i++]);
|
|||
|
case '%d': return Number(args[i++]);
|
|||
|
case '%j':
|
|||
|
try {
|
|||
|
return JSON.stringify(args[i++]);
|
|||
|
} catch (_) {
|
|||
|
return '[Circular]';
|
|||
|
}
|
|||
|
default:
|
|||
|
return x;
|
|||
|
}
|
|||
|
});
|
|||
|
for (var x = args[i]; i < len; x = args[++i]) {
|
|||
|
if (isNull(x) || !isObject(x)) {
|
|||
|
str += ' ' + x;
|
|||
|
} else {
|
|||
|
str += ' ' + inspect(x);
|
|||
|
}
|
|||
|
}
|
|||
|
return str;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
// Mark that a method should not be used.
|
|||
|
// Returns a modified function which warns once by default.
|
|||
|
// If --no-deprecation is set, then it is a no-op.
|
|||
|
exports.deprecate = function(fn, msg) {
|
|||
|
// Allow for deprecating things in the process of starting up.
|
|||
|
if (isUndefined(global.process)) {
|
|||
|
return function() {
|
|||
|
return exports.deprecate(fn, msg).apply(this, arguments);
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
if (process.noDeprecation === true) {
|
|||
|
return fn;
|
|||
|
}
|
|||
|
|
|||
|
var warned = false;
|
|||
|
function deprecated() {
|
|||
|
if (!warned) {
|
|||
|
if (process.throwDeprecation) {
|
|||
|
throw new Error(msg);
|
|||
|
} else if (process.traceDeprecation) {
|
|||
|
console.trace(msg);
|
|||
|
} else {
|
|||
|
console.error(msg);
|
|||
|
}
|
|||
|
warned = true;
|
|||
|
}
|
|||
|
return fn.apply(this, arguments);
|
|||
|
}
|
|||
|
|
|||
|
return deprecated;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
var debugs = {};
|
|||
|
var debugEnviron;
|
|||
|
exports.debuglog = function(set) {
|
|||
|
if (isUndefined(debugEnviron))
|
|||
|
debugEnviron = process.env.NODE_DEBUG || '';
|
|||
|
set = set.toUpperCase();
|
|||
|
if (!debugs[set]) {
|
|||
|
if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
|
|||
|
var pid = process.pid;
|
|||
|
debugs[set] = function() {
|
|||
|
var msg = exports.format.apply(exports, arguments);
|
|||
|
console.error('%s %d: %s', set, pid, msg);
|
|||
|
};
|
|||
|
} else {
|
|||
|
debugs[set] = function() {};
|
|||
|
}
|
|||
|
}
|
|||
|
return debugs[set];
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Echos the value of a value. Trys to print the value out
|
|||
|
* in the best way possible given the different types.
|
|||
|
*
|
|||
|
* @param {Object} obj The object to print out.
|
|||
|
* @param {Object} opts Optional options object that alters the output.
|
|||
|
*/
|
|||
|
/* legacy: obj, showHidden, depth, colors*/
|
|||
|
function inspect(obj, opts) {
|
|||
|
// default options
|
|||
|
var ctx = {
|
|||
|
seen: [],
|
|||
|
stylize: stylizeNoColor
|
|||
|
};
|
|||
|
// legacy...
|
|||
|
if (arguments.length >= 3) ctx.depth = arguments[2];
|
|||
|
if (arguments.length >= 4) ctx.colors = arguments[3];
|
|||
|
if (isBoolean(opts)) {
|
|||
|
// legacy...
|
|||
|
ctx.showHidden = opts;
|
|||
|
} else if (opts) {
|
|||
|
// got an "options" object
|
|||
|
exports._extend(ctx, opts);
|
|||
|
}
|
|||
|
// set default options
|
|||
|
if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
|
|||
|
if (isUndefined(ctx.depth)) ctx.depth = 2;
|
|||
|
if (isUndefined(ctx.colors)) ctx.colors = false;
|
|||
|
if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
|
|||
|
if (ctx.colors) ctx.stylize = stylizeWithColor;
|
|||
|
return formatValue(ctx, obj, ctx.depth);
|
|||
|
}
|
|||
|
exports.inspect = inspect;
|
|||
|
|
|||
|
|
|||
|
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
|||
|
inspect.colors = {
|
|||
|
'bold' : [1, 22],
|
|||
|
'italic' : [3, 23],
|
|||
|
'underline' : [4, 24],
|
|||
|
'inverse' : [7, 27],
|
|||
|
'white' : [37, 39],
|
|||
|
'grey' : [90, 39],
|
|||
|
'black' : [30, 39],
|
|||
|
'blue' : [34, 39],
|
|||
|
'cyan' : [36, 39],
|
|||
|
'green' : [32, 39],
|
|||
|
'magenta' : [35, 39],
|
|||
|
'red' : [31, 39],
|
|||
|
'yellow' : [33, 39]
|
|||
|
};
|
|||
|
|
|||
|
// Don't use 'blue' not visible on cmd.exe
|
|||
|
inspect.styles = {
|
|||
|
'special': 'cyan',
|
|||
|
'number': 'yellow',
|
|||
|
'boolean': 'yellow',
|
|||
|
'undefined': 'grey',
|
|||
|
'null': 'bold',
|
|||
|
'string': 'green',
|
|||
|
'date': 'magenta',
|
|||
|
// "name": intentionally not styling
|
|||
|
'regexp': 'red'
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
function stylizeWithColor(str, styleType) {
|
|||
|
var style = inspect.styles[styleType];
|
|||
|
|
|||
|
if (style) {
|
|||
|
return '\u001b[' + inspect.colors[style][0] + 'm' + str +
|
|||
|
'\u001b[' + inspect.colors[style][1] + 'm';
|
|||
|
} else {
|
|||
|
return str;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function stylizeNoColor(str, styleType) {
|
|||
|
return str;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function arrayToHash(array) {
|
|||
|
var hash = {};
|
|||
|
|
|||
|
array.forEach(function(val, idx) {
|
|||
|
hash[val] = true;
|
|||
|
});
|
|||
|
|
|||
|
return hash;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function formatValue(ctx, value, recurseTimes) {
|
|||
|
// Provide a hook for user-specified inspect functions.
|
|||
|
// Check that value is an object with an inspect function on it
|
|||
|
if (ctx.customInspect &&
|
|||
|
value &&
|
|||
|
isFunction(value.inspect) &&
|
|||
|
// Filter out the util module, it's inspect function is special
|
|||
|
value.inspect !== exports.inspect &&
|
|||
|
// Also filter out any prototype objects using the circular check.
|
|||
|
!(value.constructor && value.constructor.prototype === value)) {
|
|||
|
var ret = value.inspect(recurseTimes, ctx);
|
|||
|
if (!isString(ret)) {
|
|||
|
ret = formatValue(ctx, ret, recurseTimes);
|
|||
|
}
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
// Primitive types cannot have properties
|
|||
|
var primitive = formatPrimitive(ctx, value);
|
|||
|
if (primitive) {
|
|||
|
return primitive;
|
|||
|
}
|
|||
|
|
|||
|
// Look up the keys of the object.
|
|||
|
var keys = Object.keys(value);
|
|||
|
var visibleKeys = arrayToHash(keys);
|
|||
|
|
|||
|
if (ctx.showHidden) {
|
|||
|
keys = Object.getOwnPropertyNames(value);
|
|||
|
}
|
|||
|
|
|||
|
// IE doesn't make error fields non-enumerable
|
|||
|
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
|
|||
|
if (isError(value)
|
|||
|
&& (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
|
|||
|
return formatError(value);
|
|||
|
}
|
|||
|
|
|||
|
// Some type of object without properties can be shortcutted.
|
|||
|
if (keys.length === 0) {
|
|||
|
if (isFunction(value)) {
|
|||
|
var name = value.name ? ': ' + value.name : '';
|
|||
|
return ctx.stylize('[Function' + name + ']', 'special');
|
|||
|
}
|
|||
|
if (isRegExp(value)) {
|
|||
|
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
|||
|
}
|
|||
|
if (isDate(value)) {
|
|||
|
return ctx.stylize(Date.prototype.toString.call(value), 'date');
|
|||
|
}
|
|||
|
if (isError(value)) {
|
|||
|
return formatError(value);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var base = '', array = false, braces = ['{', '}'];
|
|||
|
|
|||
|
// Make Array say that they are Array
|
|||
|
if (isArray(value)) {
|
|||
|
array = true;
|
|||
|
braces = ['[', ']'];
|
|||
|
}
|
|||
|
|
|||
|
// Make functions say that they are functions
|
|||
|
if (isFunction(value)) {
|
|||
|
var n = value.name ? ': ' + value.name : '';
|
|||
|
base = ' [Function' + n + ']';
|
|||
|
}
|
|||
|
|
|||
|
// Make RegExps say that they are RegExps
|
|||
|
if (isRegExp(value)) {
|
|||
|
base = ' ' + RegExp.prototype.toString.call(value);
|
|||
|
}
|
|||
|
|
|||
|
// Make dates with properties first say the date
|
|||
|
if (isDate(value)) {
|
|||
|
base = ' ' + Date.prototype.toUTCString.call(value);
|
|||
|
}
|
|||
|
|
|||
|
// Make error with message first say the error
|
|||
|
if (isError(value)) {
|
|||
|
base = ' ' + formatError(value);
|
|||
|
}
|
|||
|
|
|||
|
if (keys.length === 0 && (!array || value.length == 0)) {
|
|||
|
return braces[0] + base + braces[1];
|
|||
|
}
|
|||
|
|
|||
|
if (recurseTimes < 0) {
|
|||
|
if (isRegExp(value)) {
|
|||
|
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
|||
|
} else {
|
|||
|
return ctx.stylize('[Object]', 'special');
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
ctx.seen.push(value);
|
|||
|
|
|||
|
var output;
|
|||
|
if (array) {
|
|||
|
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
|
|||
|
} else {
|
|||
|
output = keys.map(function(key) {
|
|||
|
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
ctx.seen.pop();
|
|||
|
|
|||
|
return reduceToSingleString(output, base, braces);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function formatPrimitive(ctx, value) {
|
|||
|
if (isUndefined(value))
|
|||
|
return ctx.stylize('undefined', 'undefined');
|
|||
|
if (isString(value)) {
|
|||
|
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
|
|||
|
.replace(/'/g, "\\'")
|
|||
|
.replace(/\\"/g, '"') + '\'';
|
|||
|
return ctx.stylize(simple, 'string');
|
|||
|
}
|
|||
|
if (isNumber(value))
|
|||
|
return ctx.stylize('' + value, 'number');
|
|||
|
if (isBoolean(value))
|
|||
|
return ctx.stylize('' + value, 'boolean');
|
|||
|
// For some reason typeof null is "object", so special case here.
|
|||
|
if (isNull(value))
|
|||
|
return ctx.stylize('null', 'null');
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function formatError(value) {
|
|||
|
return '[' + Error.prototype.toString.call(value) + ']';
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
|
|||
|
var output = [];
|
|||
|
for (var i = 0, l = value.length; i < l; ++i) {
|
|||
|
if (hasOwnProperty(value, String(i))) {
|
|||
|
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
|||
|
String(i), true));
|
|||
|
} else {
|
|||
|
output.push('');
|
|||
|
}
|
|||
|
}
|
|||
|
keys.forEach(function(key) {
|
|||
|
if (!key.match(/^\d+$/)) {
|
|||
|
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
|||
|
key, true));
|
|||
|
}
|
|||
|
});
|
|||
|
return output;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
|
|||
|
var name, str, desc;
|
|||
|
desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
|
|||
|
if (desc.get) {
|
|||
|
if (desc.set) {
|
|||
|
str = ctx.stylize('[Getter/Setter]', 'special');
|
|||
|
} else {
|
|||
|
str = ctx.stylize('[Getter]', 'special');
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (desc.set) {
|
|||
|
str = ctx.stylize('[Setter]', 'special');
|
|||
|
}
|
|||
|
}
|
|||
|
if (!hasOwnProperty(visibleKeys, key)) {
|
|||
|
name = '[' + key + ']';
|
|||
|
}
|
|||
|
if (!str) {
|
|||
|
if (ctx.seen.indexOf(desc.value) < 0) {
|
|||
|
if (isNull(recurseTimes)) {
|
|||
|
str = formatValue(ctx, desc.value, null);
|
|||
|
} else {
|
|||
|
str = formatValue(ctx, desc.value, recurseTimes - 1);
|
|||
|
}
|
|||
|
if (str.indexOf('\n') > -1) {
|
|||
|
if (array) {
|
|||
|
str = str.split('\n').map(function(line) {
|
|||
|
return ' ' + line;
|
|||
|
}).join('\n').substr(2);
|
|||
|
} else {
|
|||
|
str = '\n' + str.split('\n').map(function(line) {
|
|||
|
return ' ' + line;
|
|||
|
}).join('\n');
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
str = ctx.stylize('[Circular]', 'special');
|
|||
|
}
|
|||
|
}
|
|||
|
if (isUndefined(name)) {
|
|||
|
if (array && key.match(/^\d+$/)) {
|
|||
|
return str;
|
|||
|
}
|
|||
|
name = JSON.stringify('' + key);
|
|||
|
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
|
|||
|
name = name.substr(1, name.length - 2);
|
|||
|
name = ctx.stylize(name, 'name');
|
|||
|
} else {
|
|||
|
name = name.replace(/'/g, "\\'")
|
|||
|
.replace(/\\"/g, '"')
|
|||
|
.replace(/(^"|"$)/g, "'");
|
|||
|
name = ctx.stylize(name, 'string');
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return name + ': ' + str;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function reduceToSingleString(output, base, braces) {
|
|||
|
var numLinesEst = 0;
|
|||
|
var length = output.reduce(function(prev, cur) {
|
|||
|
numLinesEst++;
|
|||
|
if (cur.indexOf('\n') >= 0) numLinesEst++;
|
|||
|
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
|
|||
|
}, 0);
|
|||
|
|
|||
|
if (length > 60) {
|
|||
|
return braces[0] +
|
|||
|
(base === '' ? '' : base + '\n ') +
|
|||
|
' ' +
|
|||
|
output.join(',\n ') +
|
|||
|
' ' +
|
|||
|
braces[1];
|
|||
|
}
|
|||
|
|
|||
|
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// NOTE: These type checking functions intentionally don't use `instanceof`
|
|||
|
// because it is fragile and can be easily faked with `Object.create()`.
|
|||
|
function isArray(ar) {
|
|||
|
return Array.isArray(ar);
|
|||
|
}
|
|||
|
exports.isArray = isArray;
|
|||
|
|
|||
|
function isBoolean(arg) {
|
|||
|
return typeof arg === 'boolean';
|
|||
|
}
|
|||
|
exports.isBoolean = isBoolean;
|
|||
|
|
|||
|
function isNull(arg) {
|
|||
|
return arg === null;
|
|||
|
}
|
|||
|
exports.isNull = isNull;
|
|||
|
|
|||
|
function isNullOrUndefined(arg) {
|
|||
|
return arg == null;
|
|||
|
}
|
|||
|
exports.isNullOrUndefined = isNullOrUndefined;
|
|||
|
|
|||
|
function isNumber(arg) {
|
|||
|
return typeof arg === 'number';
|
|||
|
}
|
|||
|
exports.isNumber = isNumber;
|
|||
|
|
|||
|
function isString(arg) {
|
|||
|
return typeof arg === 'string';
|
|||
|
}
|
|||
|
exports.isString = isString;
|
|||
|
|
|||
|
function isSymbol(arg) {
|
|||
|
return typeof arg === 'symbol';
|
|||
|
}
|
|||
|
exports.isSymbol = isSymbol;
|
|||
|
|
|||
|
function isUndefined(arg) {
|
|||
|
return arg === void 0;
|
|||
|
}
|
|||
|
exports.isUndefined = isUndefined;
|
|||
|
|
|||
|
function isRegExp(re) {
|
|||
|
return isObject(re) && objectToString(re) === '[object RegExp]';
|
|||
|
}
|
|||
|
exports.isRegExp = isRegExp;
|
|||
|
|
|||
|
function isObject(arg) {
|
|||
|
return typeof arg === 'object' && arg !== null;
|
|||
|
}
|
|||
|
exports.isObject = isObject;
|
|||
|
|
|||
|
function isDate(d) {
|
|||
|
return isObject(d) && objectToString(d) === '[object Date]';
|
|||
|
}
|
|||
|
exports.isDate = isDate;
|
|||
|
|
|||
|
function isError(e) {
|
|||
|
return isObject(e) &&
|
|||
|
(objectToString(e) === '[object Error]' || e instanceof Error);
|
|||
|
}
|
|||
|
exports.isError = isError;
|
|||
|
|
|||
|
function isFunction(arg) {
|
|||
|
return typeof arg === 'function';
|
|||
|
}
|
|||
|
exports.isFunction = isFunction;
|
|||
|
|
|||
|
function isPrimitive(arg) {
|
|||
|
return arg === null ||
|
|||
|
typeof arg === 'boolean' ||
|
|||
|
typeof arg === 'number' ||
|
|||
|
typeof arg === 'string' ||
|
|||
|
typeof arg === 'symbol' || // ES6 symbol
|
|||
|
typeof arg === 'undefined';
|
|||
|
}
|
|||
|
exports.isPrimitive = isPrimitive;
|
|||
|
|
|||
|
exports.isBuffer = require('./support/isBuffer');
|
|||
|
|
|||
|
function objectToString(o) {
|
|||
|
return Object.prototype.toString.call(o);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function pad(n) {
|
|||
|
return n < 10 ? '0' + n.toString(10) : n.toString(10);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
|
|||
|
'Oct', 'Nov', 'Dec'];
|
|||
|
|
|||
|
// 26 Feb 16:19:34
|
|||
|
function timestamp() {
|
|||
|
var d = new Date();
|
|||
|
var time = [pad(d.getHours()),
|
|||
|
pad(d.getMinutes()),
|
|||
|
pad(d.getSeconds())].join(':');
|
|||
|
return [d.getDate(), months[d.getMonth()], time].join(' ');
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// log is just a thin wrapper to console.log that prepends a timestamp
|
|||
|
exports.log = function() {
|
|||
|
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Inherit the prototype methods from one constructor into another.
|
|||
|
*
|
|||
|
* The Function.prototype.inherits from lang.js rewritten as a standalone
|
|||
|
* function (not on Function.prototype). NOTE: If this file is to be loaded
|
|||
|
* during bootstrapping this function needs to be rewritten using some native
|
|||
|
* functions as prototype setup using normal JavaScript does not work as
|
|||
|
* expected during bootstrapping (see mirror.js in r114903).
|
|||
|
*
|
|||
|
* @param {function} ctor Constructor function which needs to inherit the
|
|||
|
* prototype.
|
|||
|
* @param {function} superCtor Constructor function to inherit prototype from.
|
|||
|
*/
|
|||
|
exports.inherits = require('inherits');
|
|||
|
|
|||
|
exports._extend = function(origin, add) {
|
|||
|
// Don't do anything if add isn't an object
|
|||
|
if (!add || !isObject(add)) return origin;
|
|||
|
|
|||
|
var keys = Object.keys(add);
|
|||
|
var i = keys.length;
|
|||
|
while (i--) {
|
|||
|
origin[keys[i]] = add[keys[i]];
|
|||
|
}
|
|||
|
return origin;
|
|||
|
};
|
|||
|
|
|||
|
function hasOwnProperty(obj, prop) {
|
|||
|
return Object.prototype.hasOwnProperty.call(obj, prop);
|
|||
|
}
|
|||
|
|
|||
|
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
|||
|
},{"./support/isBuffer":27,"_process":24,"inherits":26}],29:[function(require,module,exports){
|
|||
|
// Returns a wrapper function that returns a wrapped callback
|
|||
|
// The wrapper function should do some stuff, and return a
|
|||
|
// presumably different callback function.
|
|||
|
// This makes sure that own properties are retained, so that
|
|||
|
// decorations and such are not lost along the way.
|
|||
|
module.exports = wrappy
|
|||
|
function wrappy (fn, cb) {
|
|||
|
if (fn && cb) return wrappy(fn)(cb)
|
|||
|
|
|||
|
if (typeof fn !== 'function')
|
|||
|
throw new TypeError('need wrapper function')
|
|||
|
|
|||
|
Object.keys(fn).forEach(function (k) {
|
|||
|
wrapper[k] = fn[k]
|
|||
|
})
|
|||
|
|
|||
|
return wrapper
|
|||
|
|
|||
|
function wrapper() {
|
|||
|
var args = new Array(arguments.length)
|
|||
|
for (var i = 0; i < args.length; i++) {
|
|||
|
args[i] = arguments[i]
|
|||
|
}
|
|||
|
var ret = fn.apply(this, args)
|
|||
|
var cb = args[args.length-1]
|
|||
|
if (typeof ret === 'function' && ret !== cb) {
|
|||
|
Object.keys(cb).forEach(function (k) {
|
|||
|
ret[k] = cb[k]
|
|||
|
})
|
|||
|
}
|
|||
|
return ret
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
},{}]},{},[7])(7)
|
|||
|
});
|