semver
Advanced tools
Comparing version 2.0.0-alpha to 2.0.0-beta
{ | ||
"name": "semver", | ||
"version": "2.0.0-alpha", | ||
"version": "2.0.0-beta", | ||
"description": "The semantic version parser used by npm.", | ||
"main": "semver.js", | ||
"browser": "semver.browser.js", | ||
"min": "semver.min.js", | ||
"scripts": { | ||
"test": "tap test.js" | ||
"test": "tap test/*.js", | ||
"prepublish": "bash build.sh" | ||
}, | ||
"devDependencies": { | ||
"tap": "0.x >=0.0.4" | ||
"tap": "0.x >=0.0.4", | ||
"uglify-js": "~2.3.6" | ||
}, | ||
@@ -12,0 +16,0 @@ "license": "BSD", |
@@ -57,3 +57,3 @@ semver(1) -- The semantic versioner for npm | ||
ARE allowed, so `1.2.3-beta` would satisfy. | ||
* `1.2.3 - 2.3.4` := `>=1.2.3-0 <=2.3.4-0` | ||
* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4` | ||
* `~1.2.3` := `>=1.2.3-0 <1.3.0-0` "Reasonably close to 1.2.3". When | ||
@@ -74,2 +74,9 @@ using tilde operators, prerelease versions are supported as well, | ||
All methods and classes take a final `loose` boolean argument that, if | ||
true, will be more forgiving about not-quite-valid semver strings. | ||
The resulting output will always be 100% strict, of course. | ||
Strict-mode Comparators and Ranges will be strict about the SemVer | ||
strings that they parse. | ||
* valid(v): Return the parsed version, or null if it's not valid. | ||
@@ -76,0 +83,0 @@ * inc(v, release): Return the version incremented by the release type |
499
semver.js
@@ -1,3 +0,1 @@ | ||
;(function(exports) { | ||
// export the class if we are in a Node-like system. | ||
@@ -7,14 +5,15 @@ if (typeof module === 'object' && module.exports === exports) | ||
var debug; | ||
if (typeof process === 'object' && | ||
process.env && | ||
process.env.NODE_DEBUG && | ||
/\bsemver\b/i.test(process.env.NODE_DEBUG)) | ||
debug = function() { | ||
var args = Array.prototype.slice.call(arguments, 0); | ||
args.unshift('SEMVER'); | ||
console.log.apply(console, args); | ||
}; | ||
else | ||
debug = function() {}; | ||
// The debug function is excluded entirely from the minified version. | ||
/* nomin */var debug; | ||
/* nomin */if (typeof process === 'object' && | ||
/* nomin */ process.env && | ||
/* nomin */ process.env.NODE_DEBUG && | ||
/* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG)) | ||
/* nomin */ debug = function() { | ||
/* nomin */ var args = Array.prototype.slice.call(arguments, 0); | ||
/* nomin */ args.unshift('SEMVER'); | ||
/* nomin */ console.log.apply(console, args); | ||
/* nomin */ }; | ||
/* nomin */else | ||
/* nomin */ debug = function() {}; | ||
@@ -26,4 +25,5 @@ // Note: this is the semver.org version of the spec that it implements | ||
// The actual regexps go on exports.re | ||
var re = exports.re = {}; | ||
var src = exports.src = {}; | ||
var re = exports.re = []; | ||
var src = exports.src = []; | ||
var R = 0; | ||
@@ -36,3 +36,6 @@ // The following Regular Expressions can be used for tokenizing, | ||
src.numericIdentifier = '0|[1-9]\\d*'; | ||
var NUMERICIDENTIFIER = R++; | ||
src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'; | ||
var NUMERICIDENTIFIERLOOSE = R++ | ||
src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'; | ||
@@ -44,3 +47,4 @@ | ||
src.nonNumericIdentifier = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'; | ||
var NONNUMERICIDENTIFIER = R++; | ||
src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'; | ||
@@ -51,4 +55,11 @@ | ||
src.mainVersion = '(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)'; | ||
var MAINVERSION = R++; | ||
src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + | ||
'(' + src[NUMERICIDENTIFIER] + ')\\.' + | ||
'(' + src[NUMERICIDENTIFIER] + ')'; | ||
var MAINVERSIONLOOSE = R++; | ||
src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + | ||
'(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + | ||
'(' + src[NUMERICIDENTIFIERLOOSE] + ')'; | ||
@@ -58,13 +69,22 @@ // ## Pre-release Version Identifier | ||
src.prereleaseIdentifier = '(?:0|[1-9]\\d*|\\d*[a-zA-Z-][a-zA-Z0-9-]*)'; | ||
var PRERELEASEIDENTIFIER = R++; | ||
src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + | ||
'|' + src[NONNUMERICIDENTIFIER] + ')'; | ||
var PRERELEASEIDENTIFIERLOOSE = R++; | ||
src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + | ||
'|' + src[NONNUMERICIDENTIFIER] + ')'; | ||
// ## Pre-release Version | ||
// Hyphen, followed by one or more dot-separated pre-release version identifiers. | ||
// Hyphen, followed by one or more dot-separated pre-release version | ||
// identifiers. | ||
src.prerelease = '(?:-(' + src.prereleaseIdentifier + | ||
'(?:\\.' + src.prereleaseIdentifier + ')*))'; | ||
var PRERELEASE = R++; | ||
src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + | ||
'(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))'; | ||
src.prereleaseLoose = '(?:-?(' + src.prereleaseIdentifier + | ||
'(?:\\.' + src.prereleaseIdentifier + ')*))'; | ||
var PRERELEASELOOSE = R++; | ||
src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + | ||
'(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))'; | ||
@@ -74,5 +94,5 @@ // ## Build Metadata Identifier | ||
src.buildIdentifier = '[0-9A-Za-z-]+'; | ||
var BUILDIDENTIFIER = R++; | ||
src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'; | ||
// ## Build Metadata | ||
@@ -82,4 +102,5 @@ // Plus sign, followed by one or more period-separated build metadata | ||
src.build = '(?:\\+(' + src.buildIdentifier + | ||
'(?:\\.' + src.buildIdentifier + ')*))'; | ||
var BUILD = R++; | ||
src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + | ||
'(?:\\.' + src[BUILDIDENTIFIER] + ')*))'; | ||
@@ -96,17 +117,21 @@ | ||
src.full = '^' + src.mainVersion + | ||
src.prerelease + '?' + | ||
src.build + '?' + | ||
'$'; | ||
var FULL = R++; | ||
var FULLPLAIN = src[MAINVERSION] + | ||
src[PRERELEASE] + '?' + | ||
src[BUILD] + '?'; | ||
src[FULL] = '^' + FULLPLAIN + '$'; | ||
// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. | ||
// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty | ||
// common in the npm registry. | ||
var loose = '[v=\\s]*' + src.mainVersion + | ||
'(?:' + src.prereleaseLoose + ')?' + | ||
'(?:' + src.build + ')?'; | ||
var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + | ||
'(?:' + src[PRERELEASELOOSE] + ')?' + | ||
'(?:' + src[BUILD] + ')?'; | ||
src.loose = '^' + loose + '$'; | ||
var LOOSE = R++; | ||
src[LOOSE] = '^' + LOOSEPLAIN + '$'; | ||
src.gtlt = '((?:<|>)?=?)'; | ||
var GTLT = R++; | ||
src[GTLT] = '((?:<|>)?=?)'; | ||
@@ -116,23 +141,48 @@ // Something like "2.*" or "1.2.x". | ||
// Only the first item is strictly required. | ||
src.xRangeIdentifier = src.numericIdentifier + '|x|X|\\*'; | ||
src.xRangePlain = '[v=\\s]*(' + src.xRangeIdentifier + ')' + | ||
'(?:\\.(' + src.xRangeIdentifier + ')' + | ||
'(?:\\.(' + src.xRangeIdentifier + ')' + | ||
'(?:(' + src.prereleaseLoose + ')' + | ||
')?)?)?'; | ||
var XRANGEIDENTIFIERLOOSE = R++; | ||
src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'; | ||
var XRANGEIDENTIFIER = R++; | ||
src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*'; | ||
var XRANGEPLAIN = R++; | ||
src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + | ||
'(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + | ||
'(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + | ||
'(?:(' + src[PRERELEASE] + ')' + | ||
')?)?)?'; | ||
var XRANGEPLAINLOOSE = R++; | ||
src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + | ||
'(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + | ||
'(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + | ||
'(?:(' + src[PRERELEASELOOSE] + ')' + | ||
')?)?)?'; | ||
// >=2.x, for example, means >=2.0.0-0 | ||
// <1.x would be the same as "<1.0.0-0", though. | ||
src.xRange = '^' + src.gtlt + '\\s*' + src.xRangePlain + '$'; | ||
var XRANGE = R++; | ||
src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$'; | ||
var XRANGELOOSE = R++; | ||
src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$'; | ||
// Tilde ranges. | ||
// Meaning is "reasonably at or greater than" | ||
src.loneTilde = '(?:~>?)'; | ||
src.tildeTrim = src.loneTilde + '\s+'; | ||
var LONETILDE = R++; | ||
src[LONETILDE] = '(?:~>?)'; | ||
var TILDETRIM = R++; | ||
src[TILDETRIM] = src[LONETILDE] + '\s+'; | ||
var tildeTrimReplace = '$1'; | ||
src.tilde = '^' + src.loneTilde + src.xRangePlain + '$'; | ||
var TILDE = R++; | ||
src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$'; | ||
var TILDELOOSE = R++; | ||
src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$'; | ||
// A simple gt/lt/eq thing, or just "" to indicate "any version" | ||
src.comparator = '^' + src.gtlt + '\\s*(' + loose + ')$|^$'; | ||
var COMPARATORLOOSE = R++; | ||
src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$'; | ||
var COMPARATOR = R++; | ||
src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$'; | ||
@@ -142,7 +192,8 @@ | ||
// it modifies, so that `> 1.2.3` ==> `>1.2.3` | ||
src.comparatorTrim = src.gtlt + | ||
'\\s*(' + loose + '|' + src.xRangePlain + ')'; | ||
var COMPARATORTRIM = R++; | ||
src[COMPARATORTRIM] = src[GTLT] + | ||
'\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')'; | ||
// this one has to use the /g flag | ||
re.comparatorTrim = new RegExp(src.comparatorTrim, 'g'); | ||
re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g'); | ||
@@ -153,12 +204,24 @@ var comparatorTrimReplace = '$1$2 '; | ||
// Something like `1.2.3 - 1.2.4` | ||
src.hyphenRange = '^\\s*(' + loose + ')' + | ||
'\\s+-\\s+' + | ||
'(' + loose + ')' + | ||
'\\s*$'; | ||
var hyphenReplace = '>=$1 <=$7'; | ||
// Note that these all use the loose form, because they'll be | ||
// checked against either the strict or loose comparator form | ||
// later. | ||
var HYPHENRANGE = R++; | ||
src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + | ||
'\\s+-\\s+' + | ||
'(' + src[XRANGEPLAIN] + ')' + | ||
'\\s*$'; | ||
var HYPHENRANGELOOSE = R++; | ||
src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + | ||
'\\s+-\\s+' + | ||
'(' + src[XRANGEPLAINLOOSE] + ')' + | ||
'\\s*$'; | ||
// Star ranges basically just allow anything at all. | ||
src.star = '(<|>)?=?\\s*\\*'; | ||
var STAR = R++; | ||
src[STAR] = '(<|>)?=?\\s*\\*'; | ||
for (var i in src) { | ||
// Compile to actual regexp objects. | ||
// All are flag-free, unless they were created above with a flag. | ||
for (var i = 0; i < R; i++) { | ||
debug(i, src[i]); | ||
@@ -170,11 +233,11 @@ if (!re[i]) | ||
exports.valid = exports.parse = parse; | ||
function parse(version) { | ||
if (!version.match(re.loose)) | ||
return null; | ||
return new SemVer(version); | ||
function parse(version, loose) { | ||
var r = loose ? re[LOOSE] : re[FULL] | ||
return (r.test(version)) ? new SemVer(version, loose) : null; | ||
} | ||
exports.clean = clean; | ||
function clean(version) { | ||
return new SemVer(version).version; | ||
function clean(version, loose) { | ||
var s = parse(version, loose); | ||
return s ? s.version : null; | ||
} | ||
@@ -184,11 +247,16 @@ | ||
function SemVer(version) { | ||
if (version instanceof SemVer) | ||
return version; | ||
function SemVer(version, loose) { | ||
if (version instanceof SemVer) { | ||
if (version.loose === loose) | ||
return version; | ||
else | ||
version = version.version; | ||
} | ||
if (!(this instanceof SemVer)) | ||
return new SemVer(version); | ||
return new SemVer(version, loose); | ||
debug('SemVer', version); | ||
var m = version.match(re.loose); | ||
debug('SemVer', version, loose); | ||
this.loose = loose; | ||
var m = version.match(loose ? re[LOOSE] : re[FULL]); | ||
@@ -199,6 +267,16 @@ if (!m) | ||
this.raw = version; | ||
this.major = m[1]; | ||
this.minor = m[2]; | ||
this.patch = m[3]; | ||
this.prerelease = m[4] ? m[4].split('.') : []; | ||
// these are actually numbers | ||
this.major = +m[1]; | ||
this.minor = +m[2]; | ||
this.patch = +m[3]; | ||
// numberify any prerelease numeric ids | ||
if (!m[4]) | ||
this.prerelease = []; | ||
else | ||
this.prerelease = m[4].split('.').map(function(id) { | ||
return (/^[0-9]+$/.test(id)) ? +id : id; | ||
}); | ||
this.build = m[5] ? m[5].split('.') : []; | ||
@@ -213,3 +291,3 @@ this.format(); | ||
return this.version; | ||
} | ||
}; | ||
@@ -225,4 +303,5 @@ SemVer.prototype.inspect = function() { | ||
SemVer.prototype.compare = function(other) { | ||
debug('SemVer.compare', this.version, this.loose, other); | ||
if (!(other instanceof SemVer)) | ||
other = new SemVer(other); | ||
other = new SemVer(other, this.loose); | ||
@@ -234,3 +313,3 @@ return this.compareMain(other) || this.comparePre(other); | ||
if (!(other instanceof SemVer)) | ||
other = new SemVer(other); | ||
other = new SemVer(other, this.loose); | ||
@@ -244,3 +323,3 @@ return compareIdentifiers(this.major, other.major) || | ||
if (!(other instanceof SemVer)) | ||
other = new SemVer(other); | ||
other = new SemVer(other, this.loose); | ||
@@ -287,3 +366,3 @@ // NOT having a prerelease is > having one | ||
default: | ||
throw new Error('invalid increment argument: '+release); | ||
throw new Error('invalid increment argument: ' + release); | ||
} | ||
@@ -295,5 +374,5 @@ this.format(); | ||
exports.inc = inc; | ||
function inc(version, release) { | ||
function inc(version, release, loose) { | ||
try { | ||
return new SemVer(version).inc(release).version; | ||
return new SemVer(version, loose).inc(release).version; | ||
} catch (er) { | ||
@@ -316,7 +395,7 @@ return null; | ||
return (anum && !bnum) ? -1 | ||
: (bnum && !anum) ? 1 | ||
: a < b ? -1 | ||
: a > b ? 1 | ||
: 0; | ||
return (anum && !bnum) ? -1 : | ||
(bnum && !anum) ? 1 : | ||
a < b ? -1 : | ||
a > b ? 1 : | ||
0; | ||
} | ||
@@ -330,63 +409,67 @@ | ||
exports.compare = compare; | ||
function compare(a, b) { | ||
return new SemVer(a).compare(b); | ||
function compare(a, b, loose) { | ||
return new SemVer(a, loose).compare(b); | ||
} | ||
exports.rcompare = rcompare; | ||
function rcompare(a, b) { | ||
return compare(b, a); | ||
function rcompare(a, b, loose) { | ||
return compare(b, a, loose); | ||
} | ||
exports.sort = sort; | ||
function sort(list) { | ||
return list.sort(exports.compare); | ||
function sort(list, loose) { | ||
return list.sort(function(a, b) { | ||
return exports.compare(a, b, loose); | ||
}); | ||
} | ||
exports.rsort = rsort; | ||
function rsort(list) { | ||
return list.sort(exports.rcompare); | ||
function rsort(list, loose) { | ||
return list.sort(function(a, b) { | ||
return exports.rcompare(a, b, loose); | ||
}); | ||
} | ||
exports.gt = gt; | ||
function gt(a, b) { | ||
return compare(a, b) > 0; | ||
function gt(a, b, loose) { | ||
return compare(a, b, loose) > 0; | ||
} | ||
exports.lt = lt; | ||
function lt(a, b) { | ||
return compare(a, b) < 0; | ||
function lt(a, b, loose) { | ||
return compare(a, b, loose) < 0; | ||
} | ||
exports.eq = eq; | ||
function eq(a, b) { | ||
return compare(a, b) === 0; | ||
function eq(a, b, loose) { | ||
return compare(a, b, loose) === 0; | ||
} | ||
exports.neq = neq; | ||
function neq(a, b) { | ||
return compare(a, b) !== 0; | ||
function neq(a, b, loose) { | ||
return compare(a, b, loose) !== 0; | ||
} | ||
exports.gte = gte; | ||
function gte(a, b) { | ||
return compare(a, b) >= 0; | ||
function gte(a, b, loose) { | ||
return compare(a, b, loose) >= 0; | ||
} | ||
exports.lte = lte; | ||
function lte(a, b) { | ||
return compare(a, b) <= 0; | ||
function lte(a, b, loose) { | ||
return compare(a, b, loose) <= 0; | ||
} | ||
exports.cmp = cmp; | ||
function cmp(a, op, b) { | ||
function cmp(a, op, b, loose) { | ||
var ret; | ||
switch(op) { | ||
switch (op) { | ||
case '===': ret = a === b; break; | ||
case '!==': ret = a !== b; break; | ||
case '': case '=': case '==': ret = eq(a, b); break; | ||
case '!=': ret = neq(a, b); break; | ||
case '>': ret = gt(a, b); break; | ||
case '>=': ret = gte(a, b); break; | ||
case '<': ret = lt(a, b); break; | ||
case '<=': ret = lte(a, b); break; | ||
case '': case '=': case '==': ret = eq(a, b, loose); break; | ||
case '!=': ret = neq(a, b, loose); break; | ||
case '>': ret = gt(a, b, loose); break; | ||
case '>=': ret = gte(a, b, loose); break; | ||
case '<': ret = lt(a, b, loose); break; | ||
case '<=': ret = lte(a, b, loose); break; | ||
default: throw new TypeError('Invalid operator: ' + op); | ||
@@ -398,5 +481,17 @@ } | ||
exports.Comparator = Comparator; | ||
function Comparator(compString) { | ||
debug('comparator', compString); | ||
this.parse(compString); | ||
function Comparator(comp, loose) { | ||
if (comp instanceof Comparator) { | ||
if (comp.loose === loose) | ||
return comp; | ||
else | ||
comp = comp.value; | ||
} | ||
if (!(this instanceof Comparator)) | ||
return new Comparator(comp, loose); | ||
debug('comparator', comp, loose); | ||
this.loose = loose; | ||
this.parse(comp); | ||
if (this.semver === ANY) | ||
@@ -409,14 +504,15 @@ this.value = ''; | ||
var ANY = {}; | ||
Comparator.prototype.parse = function(compString) { | ||
var m = compString.match(re.comparator); | ||
Comparator.prototype.parse = function(comp) { | ||
var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; | ||
var m = comp.match(r); | ||
if (!m) | ||
throw new TypeError('Invalid comparator: ' + compString); | ||
throw new TypeError('Invalid comparator: ' + comp); | ||
// debug('parsed comparator', m); | ||
this.operator = m[1]; | ||
// if it literally is just '>' or '' then allow anything. | ||
if (!m[2]) | ||
this.semver = ANY; | ||
else { | ||
this.semver = new SemVer(m[2]); | ||
this.semver = new SemVer(m[2], this.loose); | ||
@@ -446,4 +542,5 @@ // <1.2.3-rc DOES allow 1.2.3-beta (has prerelease) | ||
Comparator.prototype.test = function(version) { | ||
debug('Comparator.test', version, this.loose); | ||
return (this.semver === ANY) ? true : | ||
cmp(version, this.operator, this.semver); | ||
cmp(version, this.operator, this.semver, this.loose); | ||
}; | ||
@@ -453,9 +550,11 @@ | ||
exports.Range = Range; | ||
function Range (range) { | ||
if (range instanceof Range) | ||
function Range(range, loose) { | ||
if ((range instanceof Range) && range.loose === loose) | ||
return range; | ||
if (!(this instanceof Range)) | ||
return new Range(range); | ||
return new Range(range, loose); | ||
this.loose = loose; | ||
// First, split based on boolean or || | ||
@@ -493,13 +592,15 @@ this.raw = range; | ||
Range.prototype.parseRange = function(range) { | ||
var loose = this.loose; | ||
range = range.trim(); | ||
debug('range', range); | ||
debug('range', range, loose); | ||
// `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` | ||
range = range.replace(re.hyphenRange, hyphenReplace); | ||
var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE]; | ||
range = range.replace(hr, hyphenReplace); | ||
debug('hyphen replace', range); | ||
// `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` | ||
range = range.replace(re.comparatorTrim, comparatorTrimReplace); | ||
range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace); | ||
debug('comparator trim', range); | ||
// `~ 1.2.3` => `~1.2.3` | ||
range = range.replace(re.tildeTrim, tildeTrimReplace); | ||
range = range.replace(re[TILDETRIM], tildeTrimReplace); | ||
@@ -509,9 +610,17 @@ // normalize spaces | ||
// At this point, the range is completely trimmed and | ||
// ready to be split into comparators. | ||
var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; | ||
var set = range.split(' ').map(function(comp) { | ||
return parseComparator(comp); | ||
}).join(' ').split(/\s+/).filter(function(comp) { | ||
// Throw out any that are not valid comparators | ||
return !!comp.match(re.comparator); | ||
}).map(function(comp) { | ||
return new Comparator(comp); | ||
return parseComparator(comp, loose); | ||
}).join(' ').split(/\s+/); | ||
if (this.loose) { | ||
// in loose mode, throw out any that are not valid comparators | ||
set = set.filter(function(comp) { | ||
return !!comp.match(compRe); | ||
}); | ||
} | ||
set = set.map(function(comp) { | ||
return new Comparator(comp, loose); | ||
}); | ||
@@ -524,4 +633,4 @@ | ||
exports.toComparators = toComparators; | ||
function toComparators(range) { | ||
return new Range(range).set.map(function(comp) { | ||
function toComparators(range, loose) { | ||
return new Range(range, loose).set.map(function(comp) { | ||
return comp.map(function(c) { | ||
@@ -533,13 +642,12 @@ return c.value; | ||
function parseComparator(comp) { | ||
// comprised of xranges, tildes, stars, and gtlt's at this point. | ||
// already replaced the hyphen ranges | ||
// turn into a set of JUST comparators. | ||
// comprised of xranges, tildes, stars, and gtlt's at this point. | ||
// already replaced the hyphen ranges | ||
// turn into a set of JUST comparators. | ||
function parseComparator(comp, loose) { | ||
debug('comp', comp); | ||
comp = replaceTildes(comp); | ||
comp = replaceTildes(comp, loose); | ||
debug('tildes', comp); | ||
comp = replaceXRanges(comp); | ||
comp = replaceXRanges(comp, loose); | ||
debug('xrange', comp); | ||
comp = replaceStars(comp); | ||
comp = replaceStars(comp, loose); | ||
debug('stars', comp); | ||
@@ -553,3 +661,2 @@ return comp; | ||
// ~, ~> --> * (any, kinda silly) | ||
@@ -561,8 +668,11 @@ // ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 | ||
// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 | ||
function replaceTildes(comp) { | ||
return comp.trim().split(/\s+/).map(replaceTilde).join(' '); | ||
function replaceTildes(comp, loose) { | ||
return comp.trim().split(/\s+/).map(function(comp) { | ||
return replaceTilde(comp, loose); | ||
}).join(' '); | ||
} | ||
function replaceTilde(comp) { | ||
return comp.replace(re.tilde, function (_, M, m, p, pr) { | ||
function replaceTilde(comp, loose) { | ||
var r = loose ? re[TILDELOOSE] : re[TILDE]; | ||
return comp.replace(r, function(_, M, m, p, pr) { | ||
debug('tilde', comp, _, M, m, p, pr); | ||
@@ -576,3 +686,3 @@ | ||
// ~1.2 == >=1.2.0- <1.3.0- | ||
ret = '>=' + M + '.' + m + '.0-0 <' + M + '.' + (+m + 1) + '.0-0' | ||
ret = '>=' + M + '.' + m + '.0-0 <' + M + '.' + (+m + 1) + '.0-0'; | ||
else if (pr) { | ||
@@ -587,3 +697,3 @@ debug('replaceTilde pr', pr); | ||
ret = '>=' + M + '.' + m + '.' + p + '-0' + | ||
' <' + M + '.' + (+m + 1) + '.0-0' | ||
' <' + M + '.' + (+m + 1) + '.0-0'; | ||
@@ -595,9 +705,13 @@ debug('tilde return', ret); | ||
function replaceXRanges(comp) { | ||
return comp.split(/\s+/).map(replaceXRange).join(' '); | ||
function replaceXRanges(comp, loose) { | ||
debug('replaceXRanges', comp, loose); | ||
return comp.split(/\s+/).map(function(comp) { | ||
return replaceXRange(comp, loose); | ||
}).join(' '); | ||
} | ||
function replaceXRange(comp) { | ||
function replaceXRange(comp, loose) { | ||
comp = comp.trim(); | ||
return comp.replace(re.xRange, function (ret, gtlt, M, m, p, pr) { | ||
var r = loose ? re[XRANGELOOSE] : re[XRANGE]; | ||
return comp.replace(r, function(ret, gtlt, M, m, p, pr) { | ||
debug('xRange', comp, ret, gtlt, M, m, p, pr); | ||
@@ -621,2 +735,20 @@ var xM = isX(M); | ||
if (gtlt === '>') { | ||
// >1 => >=2.0.0-0 | ||
// >1.2 => >=1.3.0-0 | ||
// >1.2.3 => >= 1.2.4-0 | ||
gtlt = '>='; | ||
if (xM) { | ||
// no change | ||
} else if (xm) { | ||
M = +M + 1; | ||
m = 0; | ||
p = 0; | ||
} else if (xp) { | ||
m = +m + 1; | ||
p = 0; | ||
} | ||
} | ||
ret = gtlt + M + '.' + m + '.' + p + '-0'; | ||
@@ -643,6 +775,41 @@ } else if (xM) { | ||
// and '' means "any version", just remove the *s entirely. | ||
function replaceStars(comp) { | ||
return comp.trim().replace(re.star, '') | ||
function replaceStars(comp, loose) { | ||
debug('replaceStars', comp, loose); | ||
// Looseness is ignored here. star is always as loose as it gets! | ||
return comp.trim().replace(re[STAR], ''); | ||
} | ||
// This function is passed to string.replace(re[HYPHENRANGE]) | ||
// M, m, patch, prerelease, build | ||
// 1.2 - 3.4.5 => >=1.2.0-0 <=3.4.5 | ||
// 1.2.3 - 3.4 => >=1.2.0-0 <3.5.0-0 Any 3.4.x will do | ||
// 1.2 - 3.4 => >=1.2.0-0 <3.5.0-0 | ||
function hyphenReplace($0, | ||
from, fM, fm, fp, fpr, fb, | ||
to, tM, tm, tp, tpr, tb) { | ||
if (isX(fM)) | ||
from = ''; | ||
else if (isX(fm)) | ||
from = '>=' + fM + '.0.0-0'; | ||
else if (isX(fp)) | ||
from = '>=' + fM + '.' + fm + '.0-0'; | ||
else | ||
from = '>=' + from; | ||
if (isX(tM)) | ||
to = ''; | ||
else if (isX(tm)) | ||
to = '<' + (+tM + 1) + '.0.0-0'; | ||
else if (isX(tp)) | ||
to = '<' + tM + '.' + (+tm + 1) + '.0-0'; | ||
else if (tpr) | ||
to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr; | ||
else | ||
to = '<=' + to; | ||
return (from + ' ' + to).trim(); | ||
} | ||
// if ANY of the sets match ALL of its comparators, then pass | ||
@@ -666,10 +833,10 @@ Range.prototype.test = function(version) { | ||
exports.satisfies = satisfies; | ||
function satisfies (version, range) { | ||
return new Range(range).test(version); | ||
function satisfies(version, range, loose) { | ||
return new Range(range, loose).test(version); | ||
} | ||
exports.maxSatisfying = maxSatisfying; | ||
function maxSatisfying (versions, range) { | ||
function maxSatisfying(versions, range, loose) { | ||
return versions.filter(function(version) { | ||
return satisfies(version, range); | ||
return satisfies(version, range, loose); | ||
}).sort(compare)[0] || null; | ||
@@ -687,2 +854,4 @@ } | ||
})(typeof exports === 'object' ? exports : semver = {}); | ||
// Use the define() function if we're in AMD land | ||
if (typeof define === "function" && define.amd) | ||
define(exports); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
533009
16
40802
111
2
3
2