33// This implementation is a *hair* less strict in that it allows
44// v1.2.3 things, and also tags that don't begin with a char.
55
6- var semver = "[v=]*([0-9]+)" // major
6+ var semver = "\\s* [v=]*\\s *([0-9]+)" // major
77 + "\\.([0-9]+)" // minor
88 + "\\.([0-9]+)" // patch
99 + "(-[0-9]+-?)?" // build
@@ -30,7 +30,13 @@ exports.clean = clean
3030exports . compare = compare
3131exports . satisfies = satisfies
3232exports . gt = gt
33+ exports . gte = gte
3334exports . lt = lt
35+ exports . lte = lte
36+ exports . eq = eq
37+ exports . neq = neq
38+ exports . cmp = cmp
39+
3440exports . valid = valid
3541exports . validPackage = validPackage
3642exports . validRange = validRange
@@ -41,9 +47,11 @@ function clean (ver) {
4147 if ( ! v ) return v
4248 return [ v [ 1 ] || '' , v [ 2 ] || '' , v [ 3 ] || '' ] . join ( "." ) + ( v [ 4 ] || '' ) + ( v [ 5 ] || '' )
4349}
50+
4451function valid ( version ) {
4552 return exports . parse ( version ) && version . trim ( ) . replace ( / ^ [ v = ] + / , '' )
4653}
54+
4755function validPackage ( version ) {
4856 return version . match ( expressions . parsePackage ) && version . trim ( )
4957}
@@ -97,6 +105,7 @@ function replaceXRanges (ranges) {
97105 . map ( replaceXRange )
98106 . join ( " " )
99107}
108+
100109function replaceXRange ( version ) {
101110 return version . trim ( ) . replace ( expressions . parseXRange ,
102111 function ( v , gtlt , M , m , p ) {
@@ -191,10 +200,32 @@ function satisfies (version, range) {
191200
192201// return v1 > v2 ? 1 : -1
193202function compare ( v1 , v2 ) {
194- return v1 === v2 ? 0 : gt ( v1 , v2 ) ? 1 : - 1
203+ var g = gt ( v1 , v2 )
204+ return g === null ? 0 : g ? 1 : - 1
205+ }
206+
207+ function rcompare ( v1 , v2 ) {
208+ return compare ( v2 , v1 )
195209}
196210
197211function lt ( v1 , v2 ) { return gt ( v2 , v1 ) }
212+ function gte ( v1 , v2 ) { return ! lt ( v1 , v2 ) }
213+ function lte ( v1 , v2 ) { return ! gt ( v1 , v2 ) }
214+ function eq ( v1 , v2 ) { return gt ( v1 , v2 ) === null }
215+ function neq ( v1 , v2 ) { return gt ( v1 , v2 ) !== null }
216+ function cmp ( v1 , c , v2 ) {
217+ switch ( c ) {
218+ case ">" : return gt ( v1 , v2 )
219+ case "<" : return lt ( v1 , v2 )
220+ case ">=" : return gte ( v1 , v2 )
221+ case "<=" : return lte ( v1 , v2 )
222+ case "==" : return eq ( v1 , v2 )
223+ case "!=" : return neq ( v1 , v2 )
224+ case "===" : return v1 === v2
225+ case "!==" : return v1 !== v2
226+ default : throw new Error ( "Y U NO USE VALID COMPARATOR!? " + c )
227+ }
228+ }
198229
199230// return v1 > v2
200231function num ( v ) {
@@ -214,7 +245,13 @@ function gt (v1, v2) {
214245 // no tag is > than any tag, or use lexicographical order.
215246 var tag1 = v1 [ 5 ] || ""
216247 , tag2 = v2 [ 5 ] || ""
217- return ! ! tag2 && ( ! tag1 || tag1 > tag2 )
248+
249+ // kludge: null means they were equal. falsey, and detectable.
250+ // embarrassingly overclever, though, I know.
251+ return tag1 === tag2 ? null
252+ : ! tag1 ? true
253+ : ! tag2 ? false
254+ : tag1 > tag2
218255}
219256
220257if ( module === require . main ) { // tests below
@@ -243,11 +280,63 @@ var assert = require("assert")
243280 , [ "1.2.3-4-foo" , "1.2.3" ]
244281 , [ "1.2.3-5" , "1.2.3-5-foo" ]
245282 , [ "1.2.3-5" , "1.2.3-4" ]
283+ , [ "1.2.3-5-foo" , "1.2.3-5-Foo" ]
284+ ] . forEach ( function ( v ) {
285+ var v0 = v [ 0 ]
286+ , v1 = v [ 1 ]
287+ assert . ok ( gt ( v0 , v1 ) , "gt('" + v0 + "', '" + v1 + "')" )
288+ assert . ok ( lt ( v1 , v0 ) , "lt('" + v1 + "', '" + v0 + "')" )
289+ assert . ok ( ! gt ( v1 , v0 ) , "!gt('" + v1 + "', '" + v0 + "')" )
290+ assert . ok ( ! lt ( v0 , v1 ) , "!lt('" + v0 + "', '" + v1 + "')" )
291+ assert . ok ( eq ( v0 , v0 ) , "eq('" + v0 + "', '" + v0 + "')" )
292+ assert . ok ( eq ( v1 , v1 ) , "eq('" + v1 + "', '" + v1 + "')" )
293+ assert . ok ( neq ( v0 , v1 ) , "neq('" + v0 + "', '" + v1 + "')" )
294+ assert . ok ( cmp ( v1 , "==" , v1 ) , "cmp(" + v1 + "==" + v1 + ")" )
295+ assert . ok ( cmp ( v0 , ">=" , v1 ) , "cmp(" + v0 + "<=" + v1 + ")" )
296+ assert . ok ( cmp ( v1 , "<=" , v0 ) , "cmp(" + v1 + ">=" + v0 + ")" )
297+ assert . ok ( cmp ( v0 , "!=" , v1 ) , "cmp(" + v0 + "!=" + v1 + ")" )
298+ } )
299+
300+ // equality tests
301+ ; [ [ "1.2.3" , "v1.2.3" ]
302+ , [ "1.2.3" , "=1.2.3" ]
303+ , [ "1.2.3" , "v 1.2.3" ]
304+ , [ "1.2.3" , "= 1.2.3" ]
305+ , [ "1.2.3" , " v1.2.3" ]
306+ , [ "1.2.3" , " =1.2.3" ]
307+ , [ "1.2.3" , " v 1.2.3" ]
308+ , [ "1.2.3" , " = 1.2.3" ]
309+ , [ "1.2.3-0" , "v1.2.3-0" ]
310+ , [ "1.2.3-0" , "=1.2.3-0" ]
311+ , [ "1.2.3-0" , "v 1.2.3-0" ]
312+ , [ "1.2.3-0" , "= 1.2.3-0" ]
313+ , [ "1.2.3-0" , " v1.2.3-0" ]
314+ , [ "1.2.3-0" , " =1.2.3-0" ]
315+ , [ "1.2.3-0" , " v 1.2.3-0" ]
316+ , [ "1.2.3-0" , " = 1.2.3-0" ]
317+ , [ "1.2.3-01" , "v1.2.3-1" ]
318+ , [ "1.2.3-01" , "=1.2.3-1" ]
319+ , [ "1.2.3-01" , "v 1.2.3-1" ]
320+ , [ "1.2.3-01" , "= 1.2.3-1" ]
321+ , [ "1.2.3-01" , " v1.2.3-1" ]
322+ , [ "1.2.3-01" , " =1.2.3-1" ]
323+ , [ "1.2.3-01" , " v 1.2.3-1" ]
324+ , [ "1.2.3-01" , " = 1.2.3-1" ]
325+ , [ "1.2.3beta" , "v1.2.3beta" ]
326+ , [ "1.2.3beta" , "=1.2.3beta" ]
327+ , [ "1.2.3beta" , "v 1.2.3beta" ]
328+ , [ "1.2.3beta" , "= 1.2.3beta" ]
329+ , [ "1.2.3beta" , " v1.2.3beta" ]
330+ , [ "1.2.3beta" , " =1.2.3beta" ]
331+ , [ "1.2.3beta" , " v 1.2.3beta" ]
332+ , [ "1.2.3beta" , " = 1.2.3beta" ]
246333 ] . forEach ( function ( v ) {
247- assert . ok ( gt ( v [ 0 ] , v [ 1 ] ) , "gt('" + v [ 0 ] + "', '" + v [ 1 ] + "')" )
248- assert . ok ( lt ( v [ 1 ] , v [ 0 ] ) , "lt('" + v [ 1 ] + "', '" + v [ 0 ] + "')" )
249- assert . ok ( ! gt ( v [ 1 ] , v [ 0 ] ) , "!gt('" + v [ 1 ] + "', '" + v [ 0 ] + "')" )
250- assert . ok ( ! lt ( v [ 0 ] , v [ 1 ] ) , "!lt('" + v [ 0 ] + "', '" + v [ 1 ] + "')" )
334+ var v0 = v [ 0 ]
335+ , v1 = v [ 1 ]
336+ assert . ok ( eq ( v0 , v1 ) , "eq('" + v0 + "', '" + v1 + "')" )
337+ assert . ok ( eq ( v0 , v1 ) , "eq('" + v0 + "', '" + v1 + "')" )
338+ assert . ok ( eq ( v0 , v1 ) , "eq('" + v0 + "', '" + v1 + "')" )
339+ assert . ok ( eq ( v0 , v1 ) , "eq('" + v0 + "', '" + v1 + "')" )
251340 } )
252341
253342
0 commit comments