diff --git a/.travis.yml b/.travis.yml index a7dae8d..5ba883c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,8 @@ language: node_js +dist: xenial +services: + - xvfb node_js: - - "0.11" - - "0.10" + - "12.13.0" before_script: - export DISPLAY=:99.0 - - sh -e /etc/init.d/xvfb start diff --git a/dist/susanin.js b/dist/susanin.js index 8ca08e2..78b9d92 100644 --- a/dist/susanin.js +++ b/dist/susanin.js @@ -259,7 +259,8 @@ var QUERY_STRING_PARAM_NAME = 'qs_' + EXPANDO; /** * @typedef {Object|String} RouteOptions If it's a string it means pattern for path match * @property {String} [name] Name of the route - * @property {String} pattern Pattern for path match + * @property {String} [pattern] Pattern for path match + * @property {String[]} [patterns] Patterns for path match * @property {Object} [conditions] Conditions for params in pattern * @property {Object} [defaults] Defaults values for params in pattern * @property {Object} [data] Data that will be bonded with route @@ -280,13 +281,19 @@ function Route(options) { } typeof options === 'string' && (options = { pattern : options }); + isArray(options) && (options = { patterns : options }); - if ( ! options || typeof options !== 'object') { - throw new Error('You must specify options'); + if (! isArray(options.patterns)) { + options.patterns = []; } - if (typeof options.pattern !== 'string') { - throw new Error('You must specify the pattern of the route'); + if (options.pattern) { + options.patterns.push(options.pattern); + delete options.pattern; + } + + if ( ! options || typeof options !== 'object') { + throw new Error('You must specify options'); } /** @@ -296,39 +303,76 @@ function Route(options) { this._options = options; this._conditions = options.conditions && typeof options.conditions === 'object' ? options.conditions : {}; - if (options.isTrailingSlashOptional !== false) { - options.pattern += GROUP_OPENED_CHAR + PARAM_OPENED_CHAR + - TRAILING_SLASH_PARAM_NAME + - PARAM_CLOSED_CHAR + GROUP_CLOSED_CHAR; - this._conditions[TRAILING_SLASH_PARAM_NAME] = TRAILING_SLASH_PARAM_VALUE_ESCAPED; - } + this._conditions = this._setConditions(this._conditions); - options.pattern += GROUP_OPENED_CHAR + - '?' + PARAM_OPENED_CHAR + QUERY_STRING_PARAM_NAME + PARAM_CLOSED_CHAR + - GROUP_CLOSED_CHAR; - this._conditions[QUERY_STRING_PARAM_NAME] = '.*'; + this._subRoutes = []; - this._paramsMap = []; - this._mainParamsMap = {}; - this._requiredParams = []; + for (var i = 0, l = options.patterns.length; i < l; i++) { + var subRouteOptions = options.patterns[i]; + var subRoute = {}; + var testString = typeof subRouteOptions === 'object' ? subRouteOptions.pattern : subRouteOptions; - /** - * @type {Array} - * @private - */ - this._parts = this._parsePattern(options.pattern); + if (typeof testString !== 'string') { + throw new Error('You must specify the pattern of the route'); + } else { + if (options.isTrailingSlashOptional !== false) { + testString += GROUP_OPENED_CHAR + PARAM_OPENED_CHAR + + TRAILING_SLASH_PARAM_NAME + + PARAM_CLOSED_CHAR + GROUP_CLOSED_CHAR; + } + + testString += GROUP_OPENED_CHAR + + '?' + PARAM_OPENED_CHAR + QUERY_STRING_PARAM_NAME + PARAM_CLOSED_CHAR + + GROUP_CLOSED_CHAR; - this._buildParseRegExp(); - this._buildBuildFn(); + subRoute.pattern = testString; + subRoute.paramsMap = []; + subRoute.mainParamsMap = {}; + subRoute.requiredParams = []; + subRoute.optionalParams = []; + + subRoute.conditions = subRouteOptions.conditions ? + this._setConditions(subRouteOptions.conditions) : + this._conditions; + + subRoute.defaults = subRouteOptions.defaults || this._options.defaults; + + /** + * @type {Array} + * @private + */ + subRoute.parts = this._parsePattern(subRoute, testString); + + this._buildParseRegExp(subRoute); + this._buildBuildFn(subRoute); + + this._subRoutes.push(subRoute); + } + } } +Route.prototype._getDefaults = function(subRoute) { + return subRoute.defaults; +}; + +Route.prototype._setConditions = function(conditions) { + if (this._options.isTrailingSlashOptional !== false) { + conditions[TRAILING_SLASH_PARAM_NAME] = TRAILING_SLASH_PARAM_VALUE_ESCAPED; + } + + conditions[QUERY_STRING_PARAM_NAME] = '.*'; + + return conditions; +}; + /** + * @param {Object} subRoute * @param {String} pattern * @param {Boolean} [isOptional=false] * @returns {Array} * @private */ -Route.prototype._parsePattern = function(pattern, isOptional) { +Route.prototype._parsePattern = function(subRoute, pattern, isOptional) { var parts = [], part = '', character, @@ -346,7 +390,7 @@ Route.prototype._parsePattern = function(pattern, isOptional) { ++countOpened; part += character; } else { - this._parseParams(part, parts, isOptional); + this._parseParams(subRoute, part, parts, isOptional); part = ''; countOpened = 0; isFindingClosed = true; @@ -357,7 +401,7 @@ Route.prototype._parsePattern = function(pattern, isOptional) { part = { what : 'optional', dependOnParams : [], - parts : this._parsePattern(part, true) + parts : this._parsePattern(subRoute, part, true) }; parts.push(part); @@ -386,18 +430,19 @@ Route.prototype._parsePattern = function(pattern, isOptional) { } } - this._parseParams(part, parts, isOptional); + this._parseParams(subRoute, part, parts, isOptional); return parts; }; /** + * @param {Object} subRoute * @param {String} pattern * @param {Array} parts * @param {Boolean} isOptional * @private */ -Route.prototype._parseParams = function(pattern, parts, isOptional) { +Route.prototype._parseParams = function(subRoute, pattern, parts, isOptional) { var matches = pattern.match(PARSE_PARAMS_REGEXP), i, size, part, @@ -409,9 +454,14 @@ Route.prototype._parseParams = function(pattern, parts, isOptional) { if (part.charAt(0) === PARAM_OPENED_CHAR && part.charAt(part.length - 1) === PARAM_CLOSED_CHAR) { paramName = part.substr(1, part.length - 2); - this._paramsMap.push(paramName); - this._mainParamsMap[paramName] = true; - isOptional || this._requiredParams.push(paramName); + subRoute.paramsMap.push(paramName); + subRoute.mainParamsMap[paramName] = true; + + if (isOptional) { + subRoute.optionalParams.push(paramName); + } else { + subRoute.requiredParams.push(paramName); + } parts.push({ what : 'param', @@ -427,17 +477,18 @@ Route.prototype._parseParams = function(pattern, parts, isOptional) { /** * @private */ -Route.prototype._buildParseRegExp = function() { - this._parseRegExpSource = '^' + this._buildParseRegExpParts(this._parts) + '$'; - this._parseRegExp = new RegExp(this._parseRegExpSource); +Route.prototype._buildParseRegExp = function(subRoute) { + subRoute.parseRegExpSource = '^' + this._buildParseRegExpParts(subRoute, subRoute.parts) + '$'; + subRoute.parseRegExp = new RegExp(subRoute.parseRegExpSource); }; /** + * @param {Object} subRoute * @param {Array} parts * @returns {String} * @private */ -Route.prototype._buildParseRegExpParts = function(parts) { +Route.prototype._buildParseRegExpParts = function(subRoute, parts) { var ret = '', i, size, part; @@ -448,9 +499,9 @@ Route.prototype._buildParseRegExpParts = function(parts) { if (typeof part === 'string') { ret += escape(part); } else if (part.what === 'param') { - ret += '(' + (this._getParamValueRegExpSource(part.name) || PARAM_VALUE_REGEXP_SOURCE) + ')'; + ret += '(' + (this._getParamValueRegExpSource(subRoute, part.name) || PARAM_VALUE_REGEXP_SOURCE) + ')'; } else { - ret += '(?:' + this._buildParseRegExpParts(part.parts) + ')?'; + ret += '(?:' + this._buildParseRegExpParts(subRoute, part.parts) + ')?'; } } @@ -458,16 +509,19 @@ Route.prototype._buildParseRegExpParts = function(parts) { }; /** + * @param {Object} subRoute * @param {String} paramName * @returns {?String} * @private */ -Route.prototype._getParamValueRegExpSource = function(paramName) { +Route.prototype._getParamValueRegExpSource = function(subRoute, paramName) { var regExpSource, - regExpSources = this._conditionRegExpSources || (this._conditionRegExpSources = {}), - conditions = this._conditions, + regExpSources, + conditions = subRoute.conditions, condition; + regExpSources = subRoute.conditionRegExpSources || (subRoute.conditionRegExpSources = {}); + if ( ! has(regExpSources, paramName)) { if (has(conditions, paramName)) { condition = conditions[paramName]; @@ -486,16 +540,23 @@ Route.prototype._getParamValueRegExpSource = function(paramName) { }; /** + * @param {Object} subRoute * @param {String} paramName * @returns {?RegExp} * @private */ -Route.prototype._getParamValueRegExp = function(paramName) { +Route.prototype._getParamValueRegExp = function(subRoute, paramName) { var regExpSource, + regExps; + + if (subRoute.conditions) { + regExps = subRoute.conditionRegExps || (subRoute.conditionRegExps = {}); + } else { regExps = this._conditionRegExps || (this._conditionRegExps = {}); + } if ( ! has(regExps, paramName)) { - regExpSource = this._getParamValueRegExpSource(paramName); + regExpSource = this._getParamValueRegExpSource(subRoute, paramName); regExps[paramName] = regExpSource ? new RegExp('^' + regExpSource + '$') : null; } @@ -503,35 +564,42 @@ Route.prototype._getParamValueRegExp = function(paramName) { }; /** + * @param {Object} subRoute * @param {String} paramName * @param {String} paramValue * @private {Boolean} */ -Route.prototype._checkParamValue = function(paramName, paramValue) { - var regExp = this._getParamValueRegExp(paramName); +Route.prototype._checkParamValue = function(subRoute, paramName, paramValue) { + var regExp = this._getParamValueRegExp(subRoute, paramName); return regExp ? regExp.test(paramValue) : true; }; /** + * @param {Object} subRoute * @private */ -Route.prototype._buildBuildFn = function() { - this._buildFnSource = 'var h=({}).hasOwnProperty;return ' + this._buildBuildFnParts(this._parts) + ';'; +Route.prototype._buildBuildFn = function(subRoute) { + subRoute._buildFnSource = 'var h=({}).hasOwnProperty;return ' + this._buildBuildFnParts(subRoute) + ';'; /*jshint evil:true */ - this._buildFn = new Function('p', this._buildFnSource); + subRoute._buildFn = new Function('p', subRoute._buildFnSource); }; /** - * @param {Array} parts + * @param {Object} subRoute + * @param {?Object} parts * @returns {String} * @private */ -Route.prototype._buildBuildFnParts = function(parts) { +Route.prototype._buildBuildFnParts = function(subRoute, parts) { var ret = '""', i, sizeI, j, sizeJ, part, name, - defaults = this._options.defaults; + defaults = this._getDefaults(subRoute); + + if (! parts) { + parts = subRoute.parts; + } for (i = 0, sizeI = parts.length; i < sizeI; ++i) { part = parts[i]; @@ -539,7 +607,7 @@ Route.prototype._buildBuildFnParts = function(parts) { if (typeof part === 'string') { ret += '+"' + escape(part) + '"' ; } else if (part.what === 'param') { - this._mainParamsMap[part.name] = true; + subRoute.mainParamsMap[part.name] = true; ret += '+(h.call(p,"' + escape(part.name) + '")?' + 'p["' + escape(part.name) + '"]:' + (defaults && has(defaults, part.name) ? @@ -560,7 +628,7 @@ Route.prototype._buildBuildFnParts = function(parts) { ')'; } - ret += ')?(' + this._buildBuildFnParts(part.parts) + '):"")'; + ret += ')?(' + this._buildBuildFnParts(subRoute, part.parts) + '):"")'; } } @@ -591,6 +659,32 @@ Route.prototype._isDataMatched = function(data) { return true; }; +/** + * @param {Array} patternParams + * @param {Object} params + * @param {Object} [defaultParams] + * @return {Array} + * @private + */ +Route.prototype._getPatternParamsIntersection = function(patternParams, params, defaultParams) { + var intersection = [], + paramIndex, + size, + paramName; + + defaultParams || (defaultParams = {}); + + for (paramIndex = 0, size = patternParams.length; paramIndex < size; paramIndex++) { + paramName = patternParams[paramIndex]; + + if (has(params, paramName) || has(defaultParams, paramName)) { + intersection.push(paramName); + } + } + + return intersection; +}; + /** * Matches path with route * @param {String} path @@ -598,8 +692,37 @@ Route.prototype._isDataMatched = function(data) { * @returns {Object|null} */ Route.prototype.match = function(path, data) { - var ret = null, - matches, + var selectedParams = null; + + if (typeof path !== 'string' || (data && ! this._isDataMatched(data))) { + return null; + } + + var subPatterns = this._subRoutes; + + for (var i = 0, l = subPatterns.length; i < l; i++) { + var subRoute = subPatterns[i]; + + var resultParams = this._matchSubPattern(subRoute, path); + + if (resultParams) { + selectedParams = resultParams; + break; + } + } + + return selectedParams; +}; + +/** + * @param {Object} subRoute + * @param {String} path + * @return {null|Object} + * @private + */ +Route.prototype._matchSubPattern = function(subRoute, path) { + var matches, + ret = null, i, size, paramName, paramValue, @@ -607,20 +730,16 @@ Route.prototype.match = function(path, data) { queryString, options = this._options, filter = options.postMatch, - defaults = options.defaults; - - if (typeof path !== 'string' || (data && ! this._isDataMatched(data))) { - return ret; - } + defaults = subRoute.defaults || options.defaults; - matches = path.match(this._parseRegExp); + matches = path.match(subRoute.parseRegExp); if (matches) { ret = {}; for (i = 1, size = matches.length; i < size; ++i) { if (typeof matches[i] !== 'undefined' && /* for IE lt 9*/ matches[i] !== '') { - paramName = this._paramsMap[i - 1]; + paramName = subRoute.paramsMap[i - 1]; if (paramName === QUERY_STRING_PARAM_NAME) { queryString = matches[i]; } else if (paramName === TRAILING_SLASH_PARAM_NAME) { @@ -638,18 +757,19 @@ Route.prototype.match = function(path, data) { for (paramName in queryParams) { if (has(queryParams, paramName) && ! has(ret, paramName)) { paramValue = queryParams[paramName]; - if (this._mainParamsMap[paramName] && isArray(paramValue)) { + if (subRoute.mainParamsMap[paramName] && isArray(paramValue)) { paramValue = paramValue[0]; } if (isArray(paramValue)) { ret[paramName] = []; + for (i = 0, size = paramValue.length; i < size; ++i) { - if (this._checkParamValue(paramName, paramValue[i])) { + if (this._checkParamValue(subRoute, paramName, paramValue[i])) { ret[paramName].push(paramValue[i]); } } - } else if (this._checkParamValue(paramName, paramValue)) { + } else if (this._checkParamValue(subRoute, paramName, paramValue)) { ret[paramName] = paramValue; } } @@ -664,7 +784,7 @@ Route.prototype.match = function(path, data) { } if (ret && typeof filter === 'function') { - ret = filter(ret); + ret = filter(ret, subRoute); if ( ! (ret && typeof ret === 'object')) { ret = null; } @@ -680,6 +800,67 @@ Route.prototype.match = function(path, data) { * @returns {?String} */ Route.prototype.build = function(params, isStrict) { + var subRoutes = this._subRoutes; + var selectedParams; + var selectedSubRoute; + var subRoutesLength = subRoutes.length; + + params || (params = {}); + + if (subRoutesLength > 1) { + for (var i = 0; i < subRoutesLength; i++) { + var isLastSubRoute = i + 1 === subRoutesLength; + var subRoute = subRoutes[i]; + var requiredParams = subRoute.requiredParams; + var defaultParams = this._getDefaults(subRoute); + + var resultParams = this._buildSubPatternParams(subRoute, params, isStrict); + + var requiredParamsIntersection = this._getPatternParamsIntersection(requiredParams, resultParams || {}, defaultParams); + + if ( + requiredParamsIntersection.length === requiredParams.length && resultParams || + ! isStrict && isLastSubRoute + ) { + if (isStrict || resultParams || ! isStrict && isLastSubRoute) { + selectedSubRoute = subRoute; + selectedParams = resultParams; + + break; + } + } + } + + } else { + selectedSubRoute = subRoutes[0]; + selectedParams = this._buildSubPatternParams(selectedSubRoute, params, isStrict); + } + + if (selectedParams) { + return this._buildSubPattern(selectedSubRoute, selectedParams); + } + + return null; +}; + +/** + * @param {Object} subRoute + * @param {Object} params + * @return {String} + * @private + */ +Route.prototype._buildSubPattern = function(subRoute, params) { + return subRoute._buildFn(params); +}; + +/** + * @param {Object} subRoute + * @param {Object} params + * @param {?Boolean} [isStrict=false] + * @return {null|Object} + * @private + */ +Route.prototype._buildSubPatternParams = function(subRoute, params, isStrict) { var options = this._options, newParams = {}, useQueryString = options.useQueryString !== false, @@ -688,10 +869,13 @@ Route.prototype.build = function(params, isStrict) { paramName, paramValue, filter = options.preBuild, - i, size; + i, size, + subRoutesLength = this._subRoutes.length, + hasManySubRoutes = subRoutesLength > 1, + isLastSubRoute = this._subRoutes.indexOf(subRoute) === subRoutesLength - 1; if (typeof filter === 'function') { - params = filter(params); + params = filter(params, subRoute); } for (paramName in params) { @@ -699,20 +883,20 @@ Route.prototype.build = function(params, isStrict) { has(params, paramName) && params[paramName] !== null && typeof params[paramName] !== 'undefined' && - (this._mainParamsMap[paramName] || useQueryString) + (subRoute.mainParamsMap[paramName] || useQueryString) ) { paramValue = params[paramName]; - if (isStrict && ! this._checkParamValue(paramName, paramValue)) { + if ((isStrict || hasManySubRoutes && ! isLastSubRoute) && ! this._checkParamValue(subRoute, paramName, paramValue)) { return null; } - (this._mainParamsMap[paramName] ? newParams : queryParams)[paramName] = paramValue; + (subRoute.mainParamsMap[paramName] ? newParams : queryParams)[paramName] = paramValue; } } if (isStrict) { - for (i = 0, size = this._requiredParams.length; i < size; ++i) { - if ( ! has(newParams, this._requiredParams[i])) { + for (i = 0, size = subRoute.requiredParams.length; i < size; ++i) { + if ( ! has(newParams, subRoute.requiredParams[i])) { return null; } } @@ -723,7 +907,7 @@ Route.prototype.build = function(params, isStrict) { queryString && (newParams[QUERY_STRING_PARAM_NAME] = queryString); } - return this._buildFn(newParams); + return newParams; }; /** diff --git a/dist/susanin.min.js b/dist/susanin.min.js index 64058f6..e657299 100644 --- a/dist/susanin.min.js +++ b/dist/susanin.min.js @@ -1 +1 @@ -!function(t){function e(t){return{"./querystring":function(){var t={},e=Object.prototype.hasOwnProperty,r=Object.prototype.toString,n=function(t){return"[object Array]"===r.call(t)},i={decode:function(t){var e;try{e=decodeURIComponent(t.replace(/\+/g,"%20"))}catch(r){e=t}return e},parse:function(t,r,o){var a,s,p,u,f,h,c,l={};if("string"!=typeof t||""===t)return l;for(r||(r="&"),o||(o="="),a=t.split(r),u=0,f=a.length;f>u;++u)h=i.decode(a[u]),c=h.indexOf(o),c>=0?(p=h.substr(0,c),s=h.substr(c+1)):(p=h,s=""),e.call(l,p)?n(l[p])?l[p].push(s):l[p]=[l[p],s]:l[p]=s;return l},stringify:function(t,r,n){var i,o,a,s,p,u,f="";if(!t)return f;r||(r="&"),n||(n="=");for(u in t)if(e.call(t,u))for(a=[].concat(t[u]),s=0,p=a.length;p>s;++s)o=typeof a[s],i="object"===o||"undefined"===o?"":encodeURIComponent(a[s]),f+=r+encodeURIComponent(u)+n+i;return f.substr(r.length)}};return t.exports=i,t.exports},"./route":function(){function t(e){if(!(this instanceof t))return new t(e);if("string"==typeof e&&(e={pattern:e}),!e||"object"!=typeof e)throw new Error("You must specify options");if("string"!=typeof e.pattern)throw new Error("You must specify the pattern of the route");this._options=e,this._conditions=e.conditions&&"object"==typeof e.conditions?e.conditions:{},e.isTrailingSlashOptional!==!1&&(e.pattern+=c+f+g+h+l,this._conditions[g]=P),e.pattern+=c+"?"+f+b+h+l,this._conditions[b]=".*",this._paramsMap=[],this._mainParamsMap={},this._requiredParams=[],this._parts=this._parsePattern(e.pattern),this._buildParseRegExp(),this._buildBuildFn()}var r={},n=Object.prototype.hasOwnProperty,i=function(t,e){return n.call(t,e)},o=Object.prototype.toString,a=function(t){return"[object Array]"===o.call(t)},s=e("./querystring"),p=function(){var t=["/",".","*","+","?","|","(",")","[","]","{","}","\\"],e=new RegExp("(\\"+t.join("|\\")+")","g");return function(t){return t.replace(e,"\\$1")}}(),u=String(Math.random()).substr(2,5),f="<",h=">",c="(",l=")",d="[a-zA-Z_][\\w\\-]*",m="[\\w\\-\\.~]+",_=new RegExp("("+p(f)+d+p(h)+"|"+"[^"+p(f)+p(h)+"]+"+"|"+p(f)+"|"+p(h)+")","g"),g="ts_"+u,y="/",P=p("/"),b="qs_"+u;return t.prototype._parsePattern=function(t,e){for(var r,n,i,o,a=[],s="",p=0,u=0,f=!1,h=t.length;h>p;)if(r=t.charAt(p++),r===c)f?(++u,s+=r):(this._parseParams(s,a,e),s="",u=0,f=!0);else if(r===l)if(f)if(0===u){for(s={what:"optional",dependOnParams:[],parts:this._parsePattern(s,!0)},a.push(s),n=0,i=s.parts.length;i>n;++n)o=s.parts[n]&&s.parts[n].what,"param"===o?s.dependOnParams.push(s.parts[n].name):"optional"===o&&s.dependOnParams.push.apply(s.dependOnParams,s.parts[n].dependOnParams);s="",f=!1}else--u,s+=r;else s+=r;else s+=r;return this._parseParams(s,a,e),a},t.prototype._parseParams=function(t,e,r){var n,i,o,a,s=t.match(_);if(s)for(n=0,i=s.length;i>n;++n)o=s[n],o.charAt(0)===f&&o.charAt(o.length-1)===h?(a=o.substr(1,o.length-2),this._paramsMap.push(a),this._mainParamsMap[a]=!0,r||this._requiredParams.push(a),e.push({what:"param",name:a})):e.push(o)},t.prototype._buildParseRegExp=function(){this._parseRegExpSource="^"+this._buildParseRegExpParts(this._parts)+"$",this._parseRegExp=new RegExp(this._parseRegExpSource)},t.prototype._buildParseRegExpParts=function(t){var e,r,n,i="";for(e=0,r=t.length;r>e;++e)n=t[e],i+="string"==typeof n?p(n):"param"===n.what?"("+(this._getParamValueRegExpSource(n.name)||m)+")":"(?:"+this._buildParseRegExpParts(n.parts)+")?";return i},t.prototype._getParamValueRegExpSource=function(t){var e,r,n=this._conditionRegExpSources||(this._conditionRegExpSources={}),o=this._conditions;return i(n,t)||(i(o,t)?(r=o[t],e=a(r)?"(?:"+r.join("|")+")":r+""):e=null,n[t]=e),n[t]},t.prototype._getParamValueRegExp=function(t){var e,r=this._conditionRegExps||(this._conditionRegExps={});return i(r,t)||(e=this._getParamValueRegExpSource(t),r[t]=e?new RegExp("^"+e+"$"):null),r[t]},t.prototype._checkParamValue=function(t,e){var r=this._getParamValueRegExp(t);return r?r.test(e):!0},t.prototype._buildBuildFn=function(){this._buildFnSource="var h=({}).hasOwnProperty;return "+this._buildBuildFnParts(this._parts)+";",this._buildFn=new Function("p",this._buildFnSource)},t.prototype._buildBuildFnParts=function(t){var e,r,n,o,a,s,u='""',f=this._options.defaults;for(e=0,r=t.length;r>e;++e)if(a=t[e],"string"==typeof a)u+='+"'+p(a)+'"';else if("param"===a.what)this._mainParamsMap[a.name]=!0,u+='+(h.call(p,"'+p(a.name)+'")?'+'p["'+p(a.name)+'"]:'+(f&&i(f,a.name)?'"'+p(f[a.name])+'"':'""')+")";else{for(u+="+((false",n=0,o=a.dependOnParams.length;o>n;++n)s=a.dependOnParams[n],u+='||(h.call(p,"'+p(s)+'")'+(f&&i(f,s)?'&&p["'+p(s)+'"]!=="'+p(f[s])+'"':"")+")";u+=")?("+this._buildBuildFnParts(a.parts)+'):"")'}return u},t.prototype._isDataMatched=function(t){var e,r=this._options.data;if("function"==typeof t)return Boolean(t(r));if(t&&"object"==typeof t)for(e in t)if(i(t,e)&&(!r||"object"!=typeof r||r[e]!==t[e]))return!1;return!0},t.prototype.match=function(t,e){var r,n,o,p,u,f,h,c=null,l=this._options,d=l.postMatch,m=l.defaults;if("string"!=typeof t||e&&!this._isDataMatched(e))return c;if(r=t.match(this._parseRegExp)){for(c={},n=1,o=r.length;o>n;++n)if("undefined"!=typeof r[n]&&""!==r[n])if(p=this._paramsMap[n-1],p===b)h=r[n];else if(p===g){if(t.charAt(t.length-2)===y)return null}else c[p]=r[n];if(h&&l.useQueryString!==!1){f=s.parse(h);for(p in f)if(i(f,p)&&!i(c,p))if(u=f[p],this._mainParamsMap[p]&&a(u)&&(u=u[0]),a(u))for(c[p]=[],n=0,o=u.length;o>n;++n)this._checkParamValue(p,u[n])&&c[p].push(u[n]);else this._checkParamValue(p,u)&&(c[p]=u)}for(p in m)i(m,p)&&!i(c,p)&&(c[p]=m[p])}return c&&"function"==typeof d&&(c=d(c),c&&"object"==typeof c||(c=null)),c},t.prototype.build=function(t,e){var r,n,o,a,p,u=this._options,f={},h=u.useQueryString!==!1,c={},l=u.preBuild;"function"==typeof l&&(t=l(t));for(n in t)if(i(t,n)&&null!==t[n]&&"undefined"!=typeof t[n]&&(this._mainParamsMap[n]||h)){if(o=t[n],e&&!this._checkParamValue(n,o))return null;(this._mainParamsMap[n]?f:c)[n]=o}if(e)for(a=0,p=this._requiredParams.length;p>a;++a)if(!i(f,this._requiredParams[a]))return null;return h&&(r=s.stringify(c),r&&(f[b]=r)),this._buildFn(f)},t.prototype.getData=function(){return this._options.data},t.prototype.getName=function(){return this._options.name},r.exports=t,r.exports},"./router":function(){function t(){return this instanceof t?(this._routes=[],this._routesByName={},void 0):new t}var r={},n=e("./route");return t.prototype.addRoute=function(t){var e,r;return e=new n(t),this._routes.push(e),r=e.getName(),r&&(this._routesByName[r]=e),e},t.prototype.find=function(){var t,e,r,n=[],i=this._routes;for(e=0,r=i.length;r>e;++e)t=i[e].match.apply(i[e],arguments),null!==t&&n.push([i[e],t]);return n},t.prototype.findFirst=function(){var t,e,r,n=this._routes;for(e=0,r=n.length;r>e;++e)if(t=n[e].match.apply(n[e],arguments),null!==t)return[n[e],t];return null},t.prototype.getRouteByName=function(t){return this._routesByName[t]||null},t.Route=n,r.exports=t,r.exports}}[t]()}var r=e("./router"),n=!0;"object"==typeof exports&&"string"!=typeof exports.nodeName&&(module.exports=r,n=!1),t.modules&&modules.define&&modules.require&&(modules.define("susanin",function(t){t(r)}),n=!1),"function"==typeof t.define&&define.amd&&(define(function(){return r}),n=!1),n&&(t.Susanin=r)}(this); \ No newline at end of file +!function(t){function e(t){return{"./querystring":function(){var t={},e=Object.prototype.hasOwnProperty,r=Object.prototype.toString,n=function(t){return"[object Array]"===r.call(t)},o={decode:function(t){var e;try{e=decodeURIComponent(t.replace(/\+/g,"%20"))}catch(r){e=t}return e},parse:function(t,r,a){var i,s,u,p,f,l,c,h={};if("string"!=typeof t||""===t)return h;for(r||(r="&"),a||(a="="),i=t.split(r),p=0,f=i.length;f>p;++p)l=o.decode(i[p]),c=l.indexOf(a),c>=0?(u=l.substr(0,c),s=l.substr(c+1)):(u=l,s=""),e.call(h,u)?n(h[u])?h[u].push(s):h[u]=[h[u],s]:h[u]=s;return h},stringify:function(t,r,n){var o,a,i,s,u,p,f="";if(!t)return f;r||(r="&"),n||(n="=");for(p in t)if(e.call(t,p))for(i=[].concat(t[p]),s=0,u=i.length;u>s;++s)a=typeof i[s],o="object"===a||"undefined"===a?"":encodeURIComponent(i[s]),f+=r+encodeURIComponent(p)+n+o;return f.substr(r.length)}};return t.exports=o,t.exports},"./route":function(){function t(e){if(!(this instanceof t))return new t(e);if("string"==typeof e&&(e={pattern:e}),i(e)&&(e={patterns:e}),i(e.patterns)||(e.patterns=[]),e.pattern&&(e.patterns.push(e.pattern),delete e.pattern),!e||"object"!=typeof e)throw new Error("You must specify options");this._options=e,this._conditions=e.conditions&&"object"==typeof e.conditions?e.conditions:{},this._conditions=this._setConditions(this._conditions),this._subRoutes=[];for(var r=0,n=e.patterns.length;n>r;r++){var o=e.patterns[r],a={},s="object"==typeof o?o.pattern:o;if("string"!=typeof s)throw new Error("You must specify the pattern of the route");e.isTrailingSlashOptional!==!1&&(s+=c+f+_+l+h),s+=c+"?"+f+b+l+h,a.pattern=s,a.paramsMap=[],a.mainParamsMap={},a.requiredParams=[],a.optionalParams=[],a.conditions=o.conditions?this._setConditions(o.conditions):this._conditions,a.defaults=o.defaults||this._options.defaults,a.parts=this._parsePattern(a,s),this._buildParseRegExp(a),this._buildBuildFn(a),this._subRoutes.push(a)}}var r={},n=Object.prototype.hasOwnProperty,o=function(t,e){return n.call(t,e)},a=Object.prototype.toString,i=function(t){return"[object Array]"===a.call(t)},s=e("./querystring"),u=function(){var t=["/",".","*","+","?","|","(",")","[","]","{","}","\\"],e=new RegExp("(\\"+t.join("|\\")+")","g");return function(t){return t.replace(e,"\\$1")}}(),p=String(Math.random()).substr(2,5),f="<",l=">",c="(",h=")",d="[a-zA-Z_][\\w\\-]*",m="[\\w\\-\\.~]+",g=new RegExp("("+u(f)+d+u(l)+"|"+"[^"+u(f)+u(l)+"]+"+"|"+u(f)+"|"+u(l)+")","g"),_="ts_"+p,y="/",P=u("/"),b="qs_"+p;return t.prototype._getDefaults=function(t){return t.defaults},t.prototype._setConditions=function(t){return this._options.isTrailingSlashOptional!==!1&&(t[_]=P),t[b]=".*",t},t.prototype._parsePattern=function(t,e,r){for(var n,o,a,i,s=[],u="",p=0,f=0,l=!1,d=e.length;d>p;)if(n=e.charAt(p++),n===c)l?(++f,u+=n):(this._parseParams(t,u,s,r),u="",f=0,l=!0);else if(n===h)if(l)if(0===f){for(u={what:"optional",dependOnParams:[],parts:this._parsePattern(t,u,!0)},s.push(u),o=0,a=u.parts.length;a>o;++o)i=u.parts[o]&&u.parts[o].what,"param"===i?u.dependOnParams.push(u.parts[o].name):"optional"===i&&u.dependOnParams.push.apply(u.dependOnParams,u.parts[o].dependOnParams);u="",l=!1}else--f,u+=n;else u+=n;else u+=n;return this._parseParams(t,u,s,r),s},t.prototype._parseParams=function(t,e,r,n){var o,a,i,s,u=e.match(g);if(u)for(o=0,a=u.length;a>o;++o)i=u[o],i.charAt(0)===f&&i.charAt(i.length-1)===l?(s=i.substr(1,i.length-2),t.paramsMap.push(s),t.mainParamsMap[s]=!0,n?t.optionalParams.push(s):t.requiredParams.push(s),r.push({what:"param",name:s})):r.push(i)},t.prototype._buildParseRegExp=function(t){t.parseRegExpSource="^"+this._buildParseRegExpParts(t,t.parts)+"$",t.parseRegExp=new RegExp(t.parseRegExpSource)},t.prototype._buildParseRegExpParts=function(t,e){var r,n,o,a="";for(r=0,n=e.length;n>r;++r)o=e[r],a+="string"==typeof o?u(o):"param"===o.what?"("+(this._getParamValueRegExpSource(t,o.name)||m)+")":"(?:"+this._buildParseRegExpParts(t,o.parts)+")?";return a},t.prototype._getParamValueRegExpSource=function(t,e){var r,n,a,s=t.conditions;return n=t.conditionRegExpSources||(t.conditionRegExpSources={}),o(n,e)||(o(s,e)?(a=s[e],r=i(a)?"(?:"+a.join("|")+")":a+""):r=null,n[e]=r),n[e]},t.prototype._getParamValueRegExp=function(t,e){var r,n;return n=t.conditions?t.conditionRegExps||(t.conditionRegExps={}):this._conditionRegExps||(this._conditionRegExps={}),o(n,e)||(r=this._getParamValueRegExpSource(t,e),n[e]=r?new RegExp("^"+r+"$"):null),n[e]},t.prototype._checkParamValue=function(t,e,r){var n=this._getParamValueRegExp(t,e);return n?n.test(r):!0},t.prototype._buildBuildFn=function(t){t._buildFnSource="var h=({}).hasOwnProperty;return "+this._buildBuildFnParts(t)+";",t._buildFn=new Function("p",t._buildFnSource)},t.prototype._buildBuildFnParts=function(t,e){var r,n,a,i,s,p,f='""',l=this._getDefaults(t);for(e||(e=t.parts),r=0,n=e.length;n>r;++r)if(s=e[r],"string"==typeof s)f+='+"'+u(s)+'"';else if("param"===s.what)t.mainParamsMap[s.name]=!0,f+='+(h.call(p,"'+u(s.name)+'")?'+'p["'+u(s.name)+'"]:'+(l&&o(l,s.name)?'"'+u(l[s.name])+'"':'""')+")";else{for(f+="+((false",a=0,i=s.dependOnParams.length;i>a;++a)p=s.dependOnParams[a],f+='||(h.call(p,"'+u(p)+'")'+(l&&o(l,p)?'&&p["'+u(p)+'"]!=="'+u(l[p])+'"':"")+")";f+=")?("+this._buildBuildFnParts(t,s.parts)+'):"")'}return f},t.prototype._isDataMatched=function(t){var e,r=this._options.data;if("function"==typeof t)return Boolean(t(r));if(t&&"object"==typeof t)for(e in t)if(o(t,e)&&(!r||"object"!=typeof r||r[e]!==t[e]))return!1;return!0},t.prototype._getPatternParamsIntersection=function(t,e,r){var n,a,i,s=[];for(r||(r={}),n=0,a=t.length;a>n;n++)i=t[n],(o(e,i)||o(r,i))&&s.push(i);return s},t.prototype.match=function(t,e){var r=null;if("string"!=typeof t||e&&!this._isDataMatched(e))return null;for(var n=this._subRoutes,o=0,a=n.length;a>o;o++){var i=n[o],s=this._matchSubPattern(i,t);if(s){r=s;break}}return r},t.prototype._matchSubPattern=function(t,e){var r,n,a,u,p,f,l,c=null,h=this._options,d=h.postMatch,m=t.defaults||h.defaults;if(r=e.match(t.parseRegExp)){for(c={},n=1,a=r.length;a>n;++n)if("undefined"!=typeof r[n]&&""!==r[n])if(u=t.paramsMap[n-1],u===b)l=r[n];else if(u===_){if(e.charAt(e.length-2)===y)return null}else c[u]=r[n];if(l&&h.useQueryString!==!1){f=s.parse(l);for(u in f)if(o(f,u)&&!o(c,u))if(p=f[u],t.mainParamsMap[u]&&i(p)&&(p=p[0]),i(p))for(c[u]=[],n=0,a=p.length;a>n;++n)this._checkParamValue(t,u,p[n])&&c[u].push(p[n]);else this._checkParamValue(t,u,p)&&(c[u]=p)}for(u in m)o(m,u)&&!o(c,u)&&(c[u]=m[u])}return c&&"function"==typeof d&&(c=d(c,t),c&&"object"==typeof c||(c=null)),c},t.prototype.build=function(t,e){var r,n,o=this._subRoutes,a=o.length;if(t||(t={}),a>1)for(var i=0;a>i;i++){var s=i+1===a,u=o[i],p=u.requiredParams,f=this._getDefaults(u),l=this._buildSubPatternParams(u,t,e),c=this._getPatternParamsIntersection(p,l||{},f);if((c.length===p.length&&l||!e&&s)&&(e||l||!e&&s)){n=u,r=l;break}}else n=o[0],r=this._buildSubPatternParams(n,t,e);return r?this._buildSubPattern(n,r):null},t.prototype._buildSubPattern=function(t,e){return t._buildFn(e)},t.prototype._buildSubPatternParams=function(t,e,r){var n,a,i,u,p,f=this._options,l={},c=f.useQueryString!==!1,h={},d=f.preBuild,m=this._subRoutes.length,g=m>1,_=this._subRoutes.indexOf(t)===m-1;"function"==typeof d&&(e=d(e,t));for(a in e)if(o(e,a)&&null!==e[a]&&"undefined"!=typeof e[a]&&(t.mainParamsMap[a]||c)){if(i=e[a],(r||g&&!_)&&!this._checkParamValue(t,a,i))return null;(t.mainParamsMap[a]?l:h)[a]=i}if(r)for(u=0,p=t.requiredParams.length;p>u;++u)if(!o(l,t.requiredParams[u]))return null;return c&&(n=s.stringify(h),n&&(l[b]=n)),l},t.prototype.getData=function(){return this._options.data},t.prototype.getName=function(){return this._options.name},r.exports=t,r.exports},"./router":function(){function t(){return this instanceof t?(this._routes=[],this._routesByName={},void 0):new t}var r={},n=e("./route");return t.prototype.addRoute=function(t){var e,r;return e=new n(t),this._routes.push(e),r=e.getName(),r&&(this._routesByName[r]=e),e},t.prototype.find=function(){var t,e,r,n=[],o=this._routes;for(e=0,r=o.length;r>e;++e)t=o[e].match.apply(o[e],arguments),null!==t&&n.push([o[e],t]);return n},t.prototype.findFirst=function(){var t,e,r,n=this._routes;for(e=0,r=n.length;r>e;++e)if(t=n[e].match.apply(n[e],arguments),null!==t)return[n[e],t];return null},t.prototype.getRouteByName=function(t){return this._routesByName[t]||null},t.Route=n,r.exports=t,r.exports}}[t]()}var r=e("./router"),n=!0;"object"==typeof exports&&"string"!=typeof exports.nodeName&&(module.exports=r,n=!1),t.modules&&modules.define&&modules.require&&(modules.define("susanin",function(t){t(r)}),n=!1),"function"==typeof t.define&&define.amd&&(define(function(){return r}),n=!1),n&&(t.Susanin=r)}(this); \ No newline at end of file diff --git a/karma.conf.js b/karma.conf.js index 9d9b102..24812fc 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -50,8 +50,8 @@ module.exports = function(config) { // start these browsers // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher browsers : process.env.TRAVIS ? - [ 'Firefox', 'PhantomJS' ] : - [ 'Firefox', 'PhantomJS', 'Chrome' ], + [ 'Firefox' ] : + [ 'Firefox', 'Chrome' ], // Continuous Integration mode // if true, Karma captures browsers, runs the tests and exits diff --git a/lib/route.js b/lib/route.js index d195688..600d73f 100644 --- a/lib/route.js +++ b/lib/route.js @@ -117,7 +117,8 @@ var QUERY_STRING_PARAM_NAME = 'qs_' + EXPANDO; /** * @typedef {Object|String} RouteOptions If it's a string it means pattern for path match * @property {String} [name] Name of the route - * @property {String} pattern Pattern for path match + * @property {String} [pattern] Pattern for path match + * @property {String[]} [patterns] Patterns for path match * @property {Object} [conditions] Conditions for params in pattern * @property {Object} [defaults] Defaults values for params in pattern * @property {Object} [data] Data that will be bonded with route @@ -138,13 +139,19 @@ function Route(options) { } typeof options === 'string' && (options = { pattern : options }); + isArray(options) && (options = { patterns : options }); - if ( ! options || typeof options !== 'object') { - throw new Error('You must specify options'); + if (! isArray(options.patterns)) { + options.patterns = []; + } + + if (options.pattern) { + options.patterns.push(options.pattern); + delete options.pattern; } - if (typeof options.pattern !== 'string') { - throw new Error('You must specify the pattern of the route'); + if ( ! options || typeof options !== 'object') { + throw new Error('You must specify options'); } /** @@ -154,39 +161,76 @@ function Route(options) { this._options = options; this._conditions = options.conditions && typeof options.conditions === 'object' ? options.conditions : {}; - if (options.isTrailingSlashOptional !== false) { - options.pattern += GROUP_OPENED_CHAR + PARAM_OPENED_CHAR + - TRAILING_SLASH_PARAM_NAME + - PARAM_CLOSED_CHAR + GROUP_CLOSED_CHAR; - this._conditions[TRAILING_SLASH_PARAM_NAME] = TRAILING_SLASH_PARAM_VALUE_ESCAPED; - } + this._conditions = this._setConditions(this._conditions); - options.pattern += GROUP_OPENED_CHAR + - '?' + PARAM_OPENED_CHAR + QUERY_STRING_PARAM_NAME + PARAM_CLOSED_CHAR + - GROUP_CLOSED_CHAR; - this._conditions[QUERY_STRING_PARAM_NAME] = '.*'; + this._subRoutes = []; - this._paramsMap = []; - this._mainParamsMap = {}; - this._requiredParams = []; + for (var i = 0, l = options.patterns.length; i < l; i++) { + var subRouteOptions = options.patterns[i]; + var subRoute = {}; + var testString = typeof subRouteOptions === 'object' ? subRouteOptions.pattern : subRouteOptions; - /** - * @type {Array} - * @private - */ - this._parts = this._parsePattern(options.pattern); + if (typeof testString !== 'string') { + throw new Error('You must specify the pattern of the route'); + } else { + if (options.isTrailingSlashOptional !== false) { + testString += GROUP_OPENED_CHAR + PARAM_OPENED_CHAR + + TRAILING_SLASH_PARAM_NAME + + PARAM_CLOSED_CHAR + GROUP_CLOSED_CHAR; + } - this._buildParseRegExp(); - this._buildBuildFn(); + testString += GROUP_OPENED_CHAR + + '?' + PARAM_OPENED_CHAR + QUERY_STRING_PARAM_NAME + PARAM_CLOSED_CHAR + + GROUP_CLOSED_CHAR; + + subRoute.pattern = testString; + subRoute.paramsMap = []; + subRoute.mainParamsMap = {}; + subRoute.requiredParams = []; + subRoute.optionalParams = []; + + subRoute.conditions = subRouteOptions.conditions ? + this._setConditions(subRouteOptions.conditions) : + this._conditions; + + subRoute.defaults = subRouteOptions.defaults || this._options.defaults; + + /** + * @type {Array} + * @private + */ + subRoute.parts = this._parsePattern(subRoute, testString); + + this._buildParseRegExp(subRoute); + this._buildBuildFn(subRoute); + + this._subRoutes.push(subRoute); + } + } } +Route.prototype._getDefaults = function(subRoute) { + return subRoute.defaults; +}; + +Route.prototype._setConditions = function(conditions) { + if (this._options.isTrailingSlashOptional !== false) { + conditions[TRAILING_SLASH_PARAM_NAME] = TRAILING_SLASH_PARAM_VALUE_ESCAPED; + } + + conditions[QUERY_STRING_PARAM_NAME] = '.*'; + + return conditions; +}; + /** + * @param {Object} subRoute * @param {String} pattern * @param {Boolean} [isOptional=false] * @returns {Array} * @private */ -Route.prototype._parsePattern = function(pattern, isOptional) { +Route.prototype._parsePattern = function(subRoute, pattern, isOptional) { var parts = [], part = '', character, @@ -204,7 +248,7 @@ Route.prototype._parsePattern = function(pattern, isOptional) { ++countOpened; part += character; } else { - this._parseParams(part, parts, isOptional); + this._parseParams(subRoute, part, parts, isOptional); part = ''; countOpened = 0; isFindingClosed = true; @@ -215,7 +259,7 @@ Route.prototype._parsePattern = function(pattern, isOptional) { part = { what : 'optional', dependOnParams : [], - parts : this._parsePattern(part, true) + parts : this._parsePattern(subRoute, part, true) }; parts.push(part); @@ -244,18 +288,19 @@ Route.prototype._parsePattern = function(pattern, isOptional) { } } - this._parseParams(part, parts, isOptional); + this._parseParams(subRoute, part, parts, isOptional); return parts; }; /** + * @param {Object} subRoute * @param {String} pattern * @param {Array} parts * @param {Boolean} isOptional * @private */ -Route.prototype._parseParams = function(pattern, parts, isOptional) { +Route.prototype._parseParams = function(subRoute, pattern, parts, isOptional) { var matches = pattern.match(PARSE_PARAMS_REGEXP), i, size, part, @@ -267,9 +312,14 @@ Route.prototype._parseParams = function(pattern, parts, isOptional) { if (part.charAt(0) === PARAM_OPENED_CHAR && part.charAt(part.length - 1) === PARAM_CLOSED_CHAR) { paramName = part.substr(1, part.length - 2); - this._paramsMap.push(paramName); - this._mainParamsMap[paramName] = true; - isOptional || this._requiredParams.push(paramName); + subRoute.paramsMap.push(paramName); + subRoute.mainParamsMap[paramName] = true; + + if (isOptional) { + subRoute.optionalParams.push(paramName); + } else { + subRoute.requiredParams.push(paramName); + } parts.push({ what : 'param', @@ -285,17 +335,18 @@ Route.prototype._parseParams = function(pattern, parts, isOptional) { /** * @private */ -Route.prototype._buildParseRegExp = function() { - this._parseRegExpSource = '^' + this._buildParseRegExpParts(this._parts) + '$'; - this._parseRegExp = new RegExp(this._parseRegExpSource); +Route.prototype._buildParseRegExp = function(subRoute) { + subRoute.parseRegExpSource = '^' + this._buildParseRegExpParts(subRoute, subRoute.parts) + '$'; + subRoute.parseRegExp = new RegExp(subRoute.parseRegExpSource); }; /** + * @param {Object} subRoute * @param {Array} parts * @returns {String} * @private */ -Route.prototype._buildParseRegExpParts = function(parts) { +Route.prototype._buildParseRegExpParts = function(subRoute, parts) { var ret = '', i, size, part; @@ -306,9 +357,9 @@ Route.prototype._buildParseRegExpParts = function(parts) { if (typeof part === 'string') { ret += escape(part); } else if (part.what === 'param') { - ret += '(' + (this._getParamValueRegExpSource(part.name) || PARAM_VALUE_REGEXP_SOURCE) + ')'; + ret += '(' + (this._getParamValueRegExpSource(subRoute, part.name) || PARAM_VALUE_REGEXP_SOURCE) + ')'; } else { - ret += '(?:' + this._buildParseRegExpParts(part.parts) + ')?'; + ret += '(?:' + this._buildParseRegExpParts(subRoute, part.parts) + ')?'; } } @@ -316,16 +367,19 @@ Route.prototype._buildParseRegExpParts = function(parts) { }; /** + * @param {Object} subRoute * @param {String} paramName * @returns {?String} * @private */ -Route.prototype._getParamValueRegExpSource = function(paramName) { +Route.prototype._getParamValueRegExpSource = function(subRoute, paramName) { var regExpSource, - regExpSources = this._conditionRegExpSources || (this._conditionRegExpSources = {}), - conditions = this._conditions, + regExpSources, + conditions = subRoute.conditions, condition; + regExpSources = subRoute.conditionRegExpSources || (subRoute.conditionRegExpSources = {}); + if ( ! has(regExpSources, paramName)) { if (has(conditions, paramName)) { condition = conditions[paramName]; @@ -344,16 +398,23 @@ Route.prototype._getParamValueRegExpSource = function(paramName) { }; /** + * @param {Object} subRoute * @param {String} paramName * @returns {?RegExp} * @private */ -Route.prototype._getParamValueRegExp = function(paramName) { +Route.prototype._getParamValueRegExp = function(subRoute, paramName) { var regExpSource, + regExps; + + if (subRoute.conditions) { + regExps = subRoute.conditionRegExps || (subRoute.conditionRegExps = {}); + } else { regExps = this._conditionRegExps || (this._conditionRegExps = {}); + } if ( ! has(regExps, paramName)) { - regExpSource = this._getParamValueRegExpSource(paramName); + regExpSource = this._getParamValueRegExpSource(subRoute, paramName); regExps[paramName] = regExpSource ? new RegExp('^' + regExpSource + '$') : null; } @@ -361,35 +422,42 @@ Route.prototype._getParamValueRegExp = function(paramName) { }; /** + * @param {Object} subRoute * @param {String} paramName * @param {String} paramValue * @private {Boolean} */ -Route.prototype._checkParamValue = function(paramName, paramValue) { - var regExp = this._getParamValueRegExp(paramName); +Route.prototype._checkParamValue = function(subRoute, paramName, paramValue) { + var regExp = this._getParamValueRegExp(subRoute, paramName); return regExp ? regExp.test(paramValue) : true; }; /** + * @param {Object} subRoute * @private */ -Route.prototype._buildBuildFn = function() { - this._buildFnSource = 'var h=({}).hasOwnProperty;return ' + this._buildBuildFnParts(this._parts) + ';'; +Route.prototype._buildBuildFn = function(subRoute) { + subRoute._buildFnSource = 'var h=({}).hasOwnProperty;return ' + this._buildBuildFnParts(subRoute) + ';'; /*jshint evil:true */ - this._buildFn = new Function('p', this._buildFnSource); + subRoute._buildFn = new Function('p', subRoute._buildFnSource); }; /** - * @param {Array} parts + * @param {Object} subRoute + * @param {?Object} parts * @returns {String} * @private */ -Route.prototype._buildBuildFnParts = function(parts) { +Route.prototype._buildBuildFnParts = function(subRoute, parts) { var ret = '""', i, sizeI, j, sizeJ, part, name, - defaults = this._options.defaults; + defaults = this._getDefaults(subRoute); + + if (! parts) { + parts = subRoute.parts; + } for (i = 0, sizeI = parts.length; i < sizeI; ++i) { part = parts[i]; @@ -397,7 +465,7 @@ Route.prototype._buildBuildFnParts = function(parts) { if (typeof part === 'string') { ret += '+"' + escape(part) + '"' ; } else if (part.what === 'param') { - this._mainParamsMap[part.name] = true; + subRoute.mainParamsMap[part.name] = true; ret += '+(h.call(p,"' + escape(part.name) + '")?' + 'p["' + escape(part.name) + '"]:' + (defaults && has(defaults, part.name) ? @@ -418,7 +486,7 @@ Route.prototype._buildBuildFnParts = function(parts) { ')'; } - ret += ')?(' + this._buildBuildFnParts(part.parts) + '):"")'; + ret += ')?(' + this._buildBuildFnParts(subRoute, part.parts) + '):"")'; } } @@ -449,6 +517,32 @@ Route.prototype._isDataMatched = function(data) { return true; }; +/** + * @param {Array} patternParams + * @param {Object} params + * @param {Object} [defaultParams] + * @return {Array} + * @private + */ +Route.prototype._getPatternParamsIntersection = function(patternParams, params, defaultParams) { + var intersection = [], + paramIndex, + size, + paramName; + + defaultParams || (defaultParams = {}); + + for (paramIndex = 0, size = patternParams.length; paramIndex < size; paramIndex++) { + paramName = patternParams[paramIndex]; + + if (has(params, paramName) || has(defaultParams, paramName)) { + intersection.push(paramName); + } + } + + return intersection; +}; + /** * Matches path with route * @param {String} path @@ -456,8 +550,37 @@ Route.prototype._isDataMatched = function(data) { * @returns {Object|null} */ Route.prototype.match = function(path, data) { - var ret = null, - matches, + var selectedParams = null; + + if (typeof path !== 'string' || (data && ! this._isDataMatched(data))) { + return null; + } + + var subPatterns = this._subRoutes; + + for (var i = 0, l = subPatterns.length; i < l; i++) { + var subRoute = subPatterns[i]; + + var resultParams = this._matchSubPattern(subRoute, path); + + if (resultParams) { + selectedParams = resultParams; + break; + } + } + + return selectedParams; +}; + +/** + * @param {Object} subRoute + * @param {String} path + * @return {null|Object} + * @private + */ +Route.prototype._matchSubPattern = function(subRoute, path) { + var matches, + ret = null, i, size, paramName, paramValue, @@ -465,20 +588,16 @@ Route.prototype.match = function(path, data) { queryString, options = this._options, filter = options.postMatch, - defaults = options.defaults; - - if (typeof path !== 'string' || (data && ! this._isDataMatched(data))) { - return ret; - } + defaults = subRoute.defaults || options.defaults; - matches = path.match(this._parseRegExp); + matches = path.match(subRoute.parseRegExp); if (matches) { ret = {}; for (i = 1, size = matches.length; i < size; ++i) { if (typeof matches[i] !== 'undefined' && /* for IE lt 9*/ matches[i] !== '') { - paramName = this._paramsMap[i - 1]; + paramName = subRoute.paramsMap[i - 1]; if (paramName === QUERY_STRING_PARAM_NAME) { queryString = matches[i]; } else if (paramName === TRAILING_SLASH_PARAM_NAME) { @@ -496,18 +615,19 @@ Route.prototype.match = function(path, data) { for (paramName in queryParams) { if (has(queryParams, paramName) && ! has(ret, paramName)) { paramValue = queryParams[paramName]; - if (this._mainParamsMap[paramName] && isArray(paramValue)) { + if (subRoute.mainParamsMap[paramName] && isArray(paramValue)) { paramValue = paramValue[0]; } if (isArray(paramValue)) { ret[paramName] = []; + for (i = 0, size = paramValue.length; i < size; ++i) { - if (this._checkParamValue(paramName, paramValue[i])) { + if (this._checkParamValue(subRoute, paramName, paramValue[i])) { ret[paramName].push(paramValue[i]); } } - } else if (this._checkParamValue(paramName, paramValue)) { + } else if (this._checkParamValue(subRoute, paramName, paramValue)) { ret[paramName] = paramValue; } } @@ -522,7 +642,7 @@ Route.prototype.match = function(path, data) { } if (ret && typeof filter === 'function') { - ret = filter(ret); + ret = filter(ret, subRoute); if ( ! (ret && typeof ret === 'object')) { ret = null; } @@ -538,6 +658,67 @@ Route.prototype.match = function(path, data) { * @returns {?String} */ Route.prototype.build = function(params, isStrict) { + var subRoutes = this._subRoutes; + var selectedParams; + var selectedSubRoute; + var subRoutesLength = subRoutes.length; + + params || (params = {}); + + if (subRoutesLength > 1) { + for (var i = 0; i < subRoutesLength; i++) { + var isLastSubRoute = i + 1 === subRoutesLength; + var subRoute = subRoutes[i]; + var requiredParams = subRoute.requiredParams; + var defaultParams = this._getDefaults(subRoute); + + var resultParams = this._buildSubPatternParams(subRoute, params, isStrict); + + var requiredParamsIntersection = this._getPatternParamsIntersection(requiredParams, resultParams || {}, defaultParams); + + if ( + requiredParamsIntersection.length === requiredParams.length && resultParams || + ! isStrict && isLastSubRoute + ) { + if (isStrict || resultParams || ! isStrict && isLastSubRoute) { + selectedSubRoute = subRoute; + selectedParams = resultParams; + + break; + } + } + } + + } else { + selectedSubRoute = subRoutes[0]; + selectedParams = this._buildSubPatternParams(selectedSubRoute, params, isStrict); + } + + if (selectedParams) { + return this._buildSubPattern(selectedSubRoute, selectedParams); + } + + return null; +}; + +/** + * @param {Object} subRoute + * @param {Object} params + * @return {String} + * @private + */ +Route.prototype._buildSubPattern = function(subRoute, params) { + return subRoute._buildFn(params); +}; + +/** + * @param {Object} subRoute + * @param {Object} params + * @param {?Boolean} [isStrict=false] + * @return {null|Object} + * @private + */ +Route.prototype._buildSubPatternParams = function(subRoute, params, isStrict) { var options = this._options, newParams = {}, useQueryString = options.useQueryString !== false, @@ -546,10 +727,13 @@ Route.prototype.build = function(params, isStrict) { paramName, paramValue, filter = options.preBuild, - i, size; + i, size, + subRoutesLength = this._subRoutes.length, + hasManySubRoutes = subRoutesLength > 1, + isLastSubRoute = this._subRoutes.indexOf(subRoute) === subRoutesLength - 1; if (typeof filter === 'function') { - params = filter(params); + params = filter(params, subRoute); } for (paramName in params) { @@ -557,20 +741,20 @@ Route.prototype.build = function(params, isStrict) { has(params, paramName) && params[paramName] !== null && typeof params[paramName] !== 'undefined' && - (this._mainParamsMap[paramName] || useQueryString) + (subRoute.mainParamsMap[paramName] || useQueryString) ) { paramValue = params[paramName]; - if (isStrict && ! this._checkParamValue(paramName, paramValue)) { + if ((isStrict || hasManySubRoutes && ! isLastSubRoute) && ! this._checkParamValue(subRoute, paramName, paramValue)) { return null; } - (this._mainParamsMap[paramName] ? newParams : queryParams)[paramName] = paramValue; + (subRoute.mainParamsMap[paramName] ? newParams : queryParams)[paramName] = paramValue; } } if (isStrict) { - for (i = 0, size = this._requiredParams.length; i < size; ++i) { - if ( ! has(newParams, this._requiredParams[i])) { + for (i = 0, size = subRoute.requiredParams.length; i < size; ++i) { + if ( ! has(newParams, subRoute.requiredParams[i])) { return null; } } @@ -581,7 +765,7 @@ Route.prototype.build = function(params, isStrict) { queryString && (newParams[QUERY_STRING_PARAM_NAME] = queryString); } - return this._buildFn(newParams); + return newParams; }; /** diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..9bf0cac --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2473 @@ +{ + "name": "susanin", + "version": "1.0.3", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "dev": true + }, + "assertion-error": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", + "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=", + "dev": true + }, + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "dev": true + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "dev": true, + "requires": { + "callsite": "1.0.0" + } + }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "dev": true + }, + "blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", + "dev": true + }, + "bluebird": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz", + "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==", + "dev": true + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + } + } + }, + "borschik": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/borschik/-/borschik-0.3.5.tgz", + "integrity": "sha1-03c99ugBN4cq0w/sCBR/KAMgndY=", + "dev": true, + "requires": { + "coa": "~0.4.0", + "coffee-script": "*", + "csso": "~1.3.7", + "cssp": "~1.0.6", + "inherit": "~1.0.4", + "ometajs": "~3.2.4", + "q": "~0.9.5", + "q-io": "~1.9.1", + "uglify-js": "~2.3.6" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chai": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-1.7.2.tgz", + "integrity": "sha1-ugfr1OGsE4opbN9pB3znS39KExc=", + "dev": true, + "requires": { + "assertion-error": "1.0.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "chokidar": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + } + }, + "cli": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/cli/-/cli-0.4.5.tgz", + "integrity": "sha1-ePlIXNFhtWbppsctcXDEJw6B22E=", + "dev": true, + "requires": { + "glob": ">= 3.1.4" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "coa": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/coa/-/coa-0.4.1.tgz", + "integrity": "sha1-uvb0nHrZ8gxZevObP8HlCQ/og4s=", + "dev": true, + "requires": { + "q": "~0.9.6" + } + }, + "coffee-script": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", + "integrity": "sha1-wF2uDLeVkdBbMHCoQzqYyaiczFM=", + "dev": true + }, + "collections": { + "version": "0.1.24", + "resolved": "https://registry.npmjs.org/collections/-/collections-0.1.24.tgz", + "integrity": "sha1-cPgQw1eE8/Pt+qnPJi5kpQ2ckIs=", + "dev": true, + "requires": { + "weak-map": "1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colors": { + "version": "0.6.0-1", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.0-1.tgz", + "integrity": "sha1-bbtozri8YPKzE9zFzhWZ8G0Z5no=", + "dev": true + }, + "commander": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-1.2.0.tgz", + "integrity": "sha1-/VcTv6FTx9bMWZN4patMRcU1Ap4=", + "dev": true, + "requires": { + "keypress": "0.1.x" + } + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + } + }, + "console-browserify": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-0.1.6.tgz", + "integrity": "sha1-0SijwLuINQ61YmxufHGm8P1ImDw=", + "dev": true + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=", + "dev": true + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "csso": { + "version": "1.3.12", + "resolved": "https://registry.npmjs.org/csso/-/csso-1.3.12.tgz", + "integrity": "sha1-/GKGlKLTiTiqrEmWdTIY/TEc254=", + "dev": true + }, + "cssp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cssp/-/cssp-1.0.6.tgz", + "integrity": "sha1-WsZPuiKpChI0fkbgNZghgsG/GwE=", + "dev": true, + "requires": { + "ometajs": "~ 3.1.x" + }, + "dependencies": { + "coa": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/coa/-/coa-0.3.9.tgz", + "integrity": "sha1-fj0g0wr3C4CGLpXU1JtxUYO+lgQ=", + "dev": true, + "requires": { + "q": "~0.8.10" + } + }, + "ometajs": { + "version": "3.1.19", + "resolved": "https://registry.npmjs.org/ometajs/-/ometajs-3.1.19.tgz", + "integrity": "sha1-LlXQmMYc7M0p/aFe89NoktrrbJk=", + "dev": true, + "requires": { + "coa": "0.3.x", + "q": "0.8.x", + "uglify-js": "1.3.x" + } + }, + "q": { + "version": "0.8.12", + "resolved": "https://registry.npmjs.org/q/-/q-0.8.12.tgz", + "integrity": "sha1-kWKpHhGBnEvNp9oVz1/vqtB3iCM=", + "dev": true + }, + "uglify-js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-1.3.5.tgz", + "integrity": "sha1-S1v/+Rhu/7qoiOTJ6UvZ/EyUkp0=", + "dev": true + } + } + }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "date-format": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", + "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "engine.io": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~3.3.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "engine.io-client": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "engine.io-parser": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "es-abstract": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.2.tgz", + "integrity": "sha512-jYo/J8XU2emLXl3OLwfwtuFfuF2w6DYPs+xy9ZfVyPkDcrauu6LYrw/q2TyCtrbc/KUdCiC5e9UajRhgNkVopA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "0.0.23", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-0.0.23.tgz", + "integrity": "sha1-ms+XgWQ2jkInZXHxiDnII7OoRN8=", + "dev": true, + "requires": { + "esprima": "~1.0.2", + "estraverse": "~0.0.4", + "source-map": ">= 0.1.2" + } + }, + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", + "dev": true + }, + "estraverse": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-0.0.4.tgz", + "integrity": "sha1-AaCTLf7ldGhKWYr1pnw7+bZCjbI=", + "dev": true + }, + "eventemitter3": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", + "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==", + "dev": true + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "fileset": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-0.1.8.tgz", + "integrity": "sha1-UGuRqTluqn4y+0KoQHfHoMc2t0E=", + "dev": true, + "requires": { + "glob": "3.x", + "minimatch": "0.x" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + } + }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true + }, + "follow-redirects": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.9.0.tgz", + "integrity": "sha512-CRcPzsSIbXyVDl0QI01muNDu69S8trU4jArW9LpOt2WtC6LyUJetcIrmfHsRBx7/Jb6GHJUiuqyYxPooFfNt6A==", + "dev": true, + "requires": { + "debug": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "requires": { + "inherits": "2", + "minimatch": "0.3" + }, + "dependencies": { + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + } + } + }, + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "handlebars": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-1.0.12.tgz", + "integrity": "sha1-GMbTRAw16RsZs/9YK5FRq0mF1Pw=", + "dev": true, + "requires": { + "optimist": "~0.3", + "uglify-js": "~2.3" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "dev": true, + "requires": { + "isarray": "2.0.1" + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "http-proxy": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz", + "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherit": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/inherit/-/inherit-1.0.4.tgz", + "integrity": "sha1-/zB9BZXdWovITX+W4FlzTDwdInY=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-wsl": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz", + "integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog==", + "dev": true + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + }, + "isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "istanbul": { + "version": "0.1.46", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.1.46.tgz", + "integrity": "sha1-zv6xx4fRJabbI70PY7Drk5CwtA0=", + "dev": true, + "requires": { + "abbrev": "1.0.x", + "async": "0.2.x", + "escodegen": "0.0.23", + "esprima": "1.0.x", + "fileset": "0.1.x", + "handlebars": "1.0.x", + "mkdirp": "0.3.x", + "nopt": "2.1.x", + "resolve": "0.5.x", + "which": "1.0.x", + "wordwrap": "0.0.x" + } + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + } + } + }, + "jscs": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/jscs/-/jscs-1.0.5.tgz", + "integrity": "sha1-LOqTp50GyV4MovKjtVqLXmtkUdo=", + "dev": true, + "requires": { + "colors": "0.6.0-1", + "commander": "1.2.0", + "esprima": "1.0.3", + "minimatch": "0.2.12", + "vow": "0.3.9", + "vow-fs": "0.2.3" + }, + "dependencies": { + "esprima": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.3.tgz", + "integrity": "sha1-e9tUT5VSbUJICGVNO4++koZQwP4=", + "dev": true + }, + "minimatch": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.12.tgz", + "integrity": "sha1-6oKgEqxmLH3fqhRPHBR+aUb12vs=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + } + } + }, + "jshint": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.1.10.tgz", + "integrity": "sha1-DAFexbxa1lwRxLUVLyIfJLevVSI=", + "dev": true, + "requires": { + "cli": "0.4.x", + "console-browserify": "0.1.x", + "minimatch": "0.x.x", + "shelljs": "0.1.x", + "underscore": "1.4.x" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "karma": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/karma/-/karma-4.4.1.tgz", + "integrity": "sha512-L5SIaXEYqzrh6b1wqYC42tNsFMx2PWuxky84pK9coK09MvmL7mxii3G3bZBh/0rvD27lqDd0le9jyhzvwif73A==", + "dev": true, + "requires": { + "bluebird": "^3.3.0", + "body-parser": "^1.16.1", + "braces": "^3.0.2", + "chokidar": "^3.0.0", + "colors": "^1.1.0", + "connect": "^3.6.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.0", + "flatted": "^2.0.0", + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "http-proxy": "^1.13.0", + "isbinaryfile": "^3.0.0", + "lodash": "^4.17.14", + "log4js": "^4.0.0", + "mime": "^2.3.1", + "minimatch": "^3.0.2", + "optimist": "^0.6.1", + "qjobs": "^1.1.4", + "range-parser": "^1.2.0", + "rimraf": "^2.6.0", + "safe-buffer": "^5.0.1", + "socket.io": "2.1.1", + "source-map": "^0.6.1", + "tmp": "0.0.33", + "useragent": "2.3.0" + }, + "dependencies": { + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "mime": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "karma-chrome-launcher": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz", + "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==", + "dev": true, + "requires": { + "which": "^1.2.1" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "karma-firefox-launcher": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.2.0.tgz", + "integrity": "sha512-j9Zp8M8+VLq1nI/5xZGfzeaEPtGQ/vk3G+Y8vpmFWLvKLNZ2TDjD6cu2dUu7lDbu1HXNgatsAX4jgCZTkR9qhQ==", + "dev": true, + "requires": { + "is-wsl": "^2.1.0" + } + }, + "karma-mocha": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", + "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", + "dev": true, + "requires": { + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "keypress": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz", + "integrity": "sha1-SjGI1CkbZrT2XtuZ+AaqmuKTWSo=", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "log4js": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.5.1.tgz", + "integrity": "sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==", + "dev": true, + "requires": { + "date-format": "^2.0.0", + "debug": "^4.1.1", + "flatted": "^2.0.0", + "rfdc": "^1.1.4", + "streamroller": "^1.0.6" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "dev": true + }, + "mime-db": { + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", + "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.25", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz", + "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==", + "dev": true, + "requires": { + "mime-db": "1.42.0" + } + }, + "mimeparse": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/mimeparse/-/mimeparse-0.1.4.tgz", + "integrity": "sha1-2vsCdSNw/SJgk64xUsJxrwGsJUo=", + "dev": true + }, + "minimatch": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.4.0.tgz", + "integrity": "sha1-vSx9Bg0sjI/Xzefx8u0tWycP2xs=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + }, + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + }, + "mocha": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.2.tgz", + "integrity": "sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A==", + "dev": true, + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "ms": "2.1.1", + "node-environment-flags": "1.0.5", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.0", + "yargs-parser": "13.1.1", + "yargs-unparser": "1.6.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "node-environment-flags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", + "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "node-uuid": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.0.tgz", + "integrity": "sha1-B/myM3Vy/2J1x3Xh1IUT86RdemU=", + "dev": true + }, + "nopt": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.1.2.tgz", + "integrity": "sha1-bMzZd7gBMqB3MdbozljCyDA8+a8=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", + "dev": true + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, + "ometajs": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ometajs/-/ometajs-3.2.4.tgz", + "integrity": "sha1-gHzfTA6N8XJ/Ikym2x+qxD6L2rE=", + "dev": true, + "requires": { + "coa": "0.3.x", + "q": "0.8.x", + "uglify-js": "1.3.x" + }, + "dependencies": { + "coa": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/coa/-/coa-0.3.9.tgz", + "integrity": "sha1-fj0g0wr3C4CGLpXU1JtxUYO+lgQ=", + "dev": true, + "requires": { + "q": "~0.8.10" + } + }, + "q": { + "version": "0.8.12", + "resolved": "https://registry.npmjs.org/q/-/q-0.8.12.tgz", + "integrity": "sha1-kWKpHhGBnEvNp9oVz1/vqtB3iCM=", + "dev": true + }, + "uglify-js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-1.3.5.tgz", + "integrity": "sha1-S1v/+Rhu/7qoiOTJ6UvZ/EyUkp0=", + "dev": true + } + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "dev": true, + "requires": { + "wordwrap": "~0.0.2" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha1-naGee+6NEt/wUT7Vt2lXeTvC6NQ=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "picomatch": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.1.1.tgz", + "integrity": "sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "q": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", + "integrity": "sha1-TeLmyzspCIyeTLwDv51C+5bOL3U=", + "dev": true + }, + "q-io": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/q-io/-/q-io-1.9.4.tgz", + "integrity": "sha1-rkV96cobbKOK3vOP7vogLuqfyHY=", + "dev": true, + "requires": { + "collections": "~0.1.24", + "mime": "~1.2.11", + "mimeparse": "~0.1.4", + "q": "~0.9.6", + "qs": "~0.1.0", + "url2": "~0.0.0" + } + }, + "qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true + }, + "qs": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-0.1.0.tgz", + "integrity": "sha1-mg0tcNAfY9NAHqSwUIImAbRi7ms=", + "dev": true + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "readdirp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "dev": true, + "requires": { + "picomatch": "^2.0.4" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.5.1.tgz", + "integrity": "sha1-FeSiIsQja81M+FRUQSwtD7ZSRXY=", + "dev": true + }, + "rfdc": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", + "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "shelljs": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.1.4.tgz", + "integrity": "sha1-37vnjVbDwBaNL7eeEOzR28sH7A4=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "socket.io": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "dev": true, + "requires": { + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "socket.io-adapter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", + "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==", + "dev": true + }, + "socket.io-client": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.2.0", + "to-array": "0.1.4" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "socket.io-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "streamroller": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.6.tgz", + "integrity": "sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==", + "dev": true, + "requires": { + "async": "^2.6.2", + "date-format": "^2.0.0", + "debug": "^3.2.6", + "fs-extra": "^7.0.1", + "lodash": "^4.17.14" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha1-TlUs0F3wlGfcvE73Od6J8s83wTE=", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "uglify-js": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.3.6.tgz", + "integrity": "sha1-+gmEdwtCi3qbKoBY9GNV0U/vIRo=", + "dev": true, + "requires": { + "async": "~0.2.6", + "optimist": "~0.3.5", + "source-map": "~0.1.7" + } + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true + }, + "underscore": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", + "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "url2": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/url2/-/url2-0.0.0.tgz", + "integrity": "sha1-Tqq9HVw6yQ1iq0SFyZhCKGWgSxo=", + "dev": true + }, + "useragent": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", + "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", + "dev": true, + "requires": { + "lru-cache": "4.1.x", + "tmp": "0.0.x" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + } + } + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true + }, + "vow": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/vow/-/vow-0.3.9.tgz", + "integrity": "sha1-ybZ6x+1JEaSa1a8j6/f0OS6DXXQ=", + "dev": true + }, + "vow-fs": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vow-fs/-/vow-fs-0.2.3.tgz", + "integrity": "sha1-rIyULDAXX5EhDwIC08J3MKCtn74=", + "dev": true, + "requires": { + "node-uuid": "1.4.0", + "vow-queue": "0.0.2" + } + }, + "vow-queue": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/vow-queue/-/vow-queue-0.0.2.tgz", + "integrity": "sha1-3rps/CqC1gYdEOs6EvrWOo5rtk0=", + "dev": true + }, + "weak-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.0.tgz", + "integrity": "sha1-tm5Wqd8L0lp2u/G1FNsSkIBhSjc=", + "dev": true + }, + "which": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz", + "integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=", + "dev": true + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + } + } +} diff --git a/package.json b/package.json index 173990f..6461fb1 100644 --- a/package.json +++ b/package.json @@ -1,37 +1,40 @@ { - "name" : "susanin", - "version" : "1.0.3", - "author" : { - "name" : "Ruslan Kerimov", - "email" : "rus.kerimov@gmail.com" + "name": "susanin", + "version": "1.0.3", + "author": { + "name": "Ruslan Kerimov", + "email": "rus.kerimov@gmail.com" }, - "description" : "Router system which can be used in any JavaScript environments", - "keywords" : [ "router", "routes", "routing" ], - "repository" : { - "type" : "git", - "url" : "git://github.com/nodules/susanin.git" + "description": "Router system which can be used in any JavaScript environments", + "keywords": [ + "router", + "routes", + "routing" + ], + "repository": { + "type": "git", + "url": "git://github.com/nodules/susanin.git" }, - "scripts" : { - "test" : "make test" + "scripts": { + "test": "make test" }, - "dependencies" : {}, - "devDependencies" : { - "jshint" : "2.1.10", - "jscs" : "1.0.5", - "istanbul" : "0.1.x", - "mocha" : "1.11.x", - "chai" : "1.7.x", - "borschik" : "0.3.x", - "karma" : "~0.12.24", - "karma-chrome-launcher" : "~0.1.5", - "karma-firefox-launcher" : "~0.1.3", - "karma-phantomjs-launcher" : "~0.1.4", - "karma-mocha" : "~0.1.9" + "dependencies": {}, + "devDependencies": { + "borschik": "0.3.x", + "chai": "1.7.x", + "istanbul": "0.1.x", + "jscs": "1.0.5", + "jshint": "2.1.10", + "karma": "~4.4.1", + "karma-chrome-launcher": "^3.1.0", + "karma-firefox-launcher": "^1.2.0", + "karma-mocha": "^1.3.0", + "mocha": "^6.2.2" }, - "optionalDependencies" : {}, - "main" : "lib/router.js", - "bugs" : { - "url" : "https://github.com/nodules/susanin/issues" + "optionalDependencies": {}, + "main": "lib/router.js", + "bugs": { + "url": "https://github.com/nodules/susanin/issues" }, - "license" : "MIT" + "license": "MIT" } diff --git a/test/route.build.js b/test/route.build.js index 9f25209..2fd9e94 100644 --- a/test/route.build.js +++ b/test/route.build.js @@ -183,3 +183,97 @@ describe('route.build()', function() { }); }); + +describe('route.build(): Support of multiple patterns', function() { + var Route = Router.Route; + + it('non strict', function() { + var route = Route({ + patterns : [ + { + pattern : '/search/mark-(/)/year-' + }, + '/search/mark-/price-', + '/search/mark-(/)', + '/search' + ] + }); + + var route2 = Route({ + patterns : [ + '/search/mark-/model-', + '/search/mark-/year-', + ] + }); + + assert.strictEqual(route.build(), '/search'); + assert.strictEqual(route2.build(), '/search/mark-/year-'); + assert.strictEqual(route2.build({ mark : 'vaz', model : '2106' }), '/search/mark-vaz/model-2106'); + assert.strictEqual(route2.build({ mark : 'vaz', year : '2000' }), '/search/mark-vaz/year-2000'); + assert.strictEqual(route.build({ foo : 'bar', model : '2106' }), '/search?foo=bar&model=2106'); + assert.strictEqual(route.build({ foo : 'bar', model : '2106', mark : 'vaz' }), '/search/mark-vaz/2106?foo=bar'); + assert.strictEqual(route.build({ foo : 'bar', model : '2106', mark : 'vaz', year : '1812' }), '/search/mark-vaz/2106/year-1812?foo=bar'); + assert.strictEqual(route.build({ foo : 'bar', model : '2106', mark : 'vaz', year : '1812', price : 100500 }), '/search/mark-vaz/2106/year-1812?foo=bar&price=100500'); + assert.strictEqual(route.build({ foo : 'bar', model : '2106', mark : 'vaz', price : 100500 }), '/search/mark-vaz/price-100500?foo=bar&model=2106'); + }); + + it('strict', function() { + var route = Route({ + patterns : [ + '/search/mark-(/)/year-', + '/search/mark-/price-', + '/search/mark-(/)', + ] + }); + + assert.strictEqual(route.build({}, true), null); + assert.strictEqual(route.build({ foo : 'bar', model : '2106' }, true), null); + assert.strictEqual(route.build({ foo : 'bar', model : '2106', mark : 'vaz' }, true), '/search/mark-vaz/2106?foo=bar'); + assert.strictEqual(route.build({ foo : 'bar', model : '2106', mark : 'vaz', year : '1812' }, true), '/search/mark-vaz/2106/year-1812?foo=bar'); + assert.strictEqual(route.build({ foo : 'bar', model : '2106', mark : 'vaz', year : '1812', price : 100500 }, true), '/search/mark-vaz/2106/year-1812?foo=bar&price=100500'); + assert.strictEqual(route.build({ foo : 'bar', model : '2106', mark : 'vaz', price : 100500 }, true), '/search/mark-vaz/price-100500?foo=bar&model=2106'); + }); + + it('defaults in sub pattern', function() { + var route = Route({ + defaults : { + mark : 'default-mark' + }, + patterns : [ + { + pattern : '/search/mark-/year-', + defaults : { + mark : 'default-sub-mark' + } + }, + '/search/mark-/price-', + ] + }); + + assert.strictEqual(route.build({ year : 2000 }), '/search/mark-default-sub-mark/year-2000'); + assert.strictEqual(route.build({ price : 100500 }), '/search/mark-default-mark/price-100500'); + }); + + it('conditions in sub pattern', function() { + var route = Route({ + conditions : { + year : '\\d\\d', + 'sub-year' : '\\d' + }, + patterns : [ + { + pattern : '/search/year-sub-', + conditions : { + 'sub-year' : '\\d\\d\\d\\d' + } + }, + '/search/year-', + ] + }); + + assert.strictEqual(route.build({ 'sub-year' : 2000 }), '/search/year-sub-2000'); + assert.strictEqual(route.build({ 'sub-year' : 20 }), '/search/year-?sub-year=20'); + assert.strictEqual(route.build({ 'sub-year' : 40 }, true), null); + assert.strictEqual(route.build({ year : 10 }, true), '/search/year-10'); + }); +}); diff --git a/test/route.match.js b/test/route.match.js index 38497f3..0db524d 100644 --- a/test/route.match.js +++ b/test/route.match.js @@ -245,4 +245,32 @@ describe('route.match()', function() { done(); }); + it('Support of multiple patterns', function(done) { + var route = Route({ + patterns : [ + '/search', + '/search/mark-', + '/search/mark-/year-', + '/search/mark-/price-', + '/search/mark-(/)', + '/search/mark-/', + '/search/mark-(/)/year-' + ] + }); + + assert.deepEqual(route.match('/search'), {}); + assert.deepEqual(route.match('/search?foo=bar'), { foo : 'bar' }); + assert.deepEqual(route.match('/search?model=corona'), { model : 'corona' }); + assert.deepEqual(route.match('/search?year=1993'), { year : '1993' }); + assert.deepEqual(route.match('/search?model=toyota&year=1993'), { model : 'toyota', year : '1993' }); + assert.deepEqual(route.match('/search/mark-toyota'), { mark : 'toyota' }); + assert.deepEqual(route.match('/search/mark-toyota?foo=bar'), { mark : 'toyota', foo : 'bar' }); + assert.deepEqual(route.match('/search/mark-toyota/year-1993'), { mark : 'toyota', year : '1993' }); + assert.deepEqual(route.match('/search/mark-toyota/corona'), { mark : 'toyota', model : 'corona' }); + assert.deepEqual(route.match('/search/mark-toyota/corona/year-1993'), { mark : 'toyota', model : 'corona', year : '1993' }); + assert.deepEqual(route.match('/search/mark-toyota/price-20000'), { mark : 'toyota', price : '20000' }); + + done(); + }); + });