Last active
October 28, 2015 14:23
-
-
Save IUnknown68/34f9370345bc16b22675 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/**************************************************************************//** | |
* @file | |
* @brief SemVer.js: Semantic version implementation. | |
* @author Arne Seib <[email protected]> | |
* @copyright 2015 Arne Seib (http://www.seiberspace.de). | |
*****************************************************************************/ | |
SemVer = (function() { | |
//------------------------------------------------------------------------------ | |
// private function: validate `from[name]` with validator `type`. | |
// If `from[name]` is undefined, leave `to` unchanged. | |
// If `from[name]` is invalid, throw. | |
// Otherwise set `to[name]`. | |
function _validate(from, to, name, type) { | |
var val = from[name]; | |
if ('undefined' === typeof val) { | |
return; | |
} | |
if (!SemVer.validators[type].test(val)) { | |
throw new Error('SemVer: Expected ' + type + ' for ' + val); | |
} | |
to[name] = ('number' === type) ? parseInt(val,10) : val; | |
} | |
//------------------------------------------------------------------------------ | |
// class SemVer | |
// Contructor can take: | |
// - a string: gets parsed | |
// - an object: copies attributes one by one and validates them | |
// - nothing: create empty SemVer | |
// If `val` is invalid, an exception is thrown. | |
function SemVer(val) { | |
SemVer.reset(this); | |
switch(typeof val) { | |
case 'undefined': | |
return; | |
break; | |
case 'string': | |
SemVer.parse(val, this); | |
break; | |
case 'object': | |
SemVer.safeCopy(val, this); | |
break; | |
default: | |
throw new TypeError('SemVer::SemVer(): Argument of invalid type: ' + val); | |
break; | |
} | |
} | |
//------------------------------------------------------------------------------ | |
SemVer.prototype = { | |
// reset all values to defaults (0.0.0) | |
reset: function() {SemVer.reset(this);}, | |
// return true if this version number is equal to other | |
isEqual: function(other) {return 0 === SemVer.compare(this, other);}, | |
// return true if this version number is higher than other | |
isHigher: function(other) {return SemVer.compare(this, other) > 0;}, | |
// return true if this version number is lower than other | |
isLower: function(other) {return SemVer.compare(this, other) < 0;}, | |
// return formatted version number | |
toString: function() {return SemVer.print(this);} | |
}; | |
//------------------------------------------------------------------------------ | |
// validator regexps | |
// regex is based on https://github.com/sindresorhus/semver-regex | |
SemVer.validators = { | |
// major, minor and patch | |
number: /^(?:0|[1-9][0-9]*)$/i, | |
// pre and meta | |
string: /^[\da-z\-]+(?:\.[\da-z\-]+)*$/i, | |
version: /^((?:0|[1-9][0-9]*))\.((?:0|[1-9][0-9]*))\.((?:0|[1-9][0-9]*))(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+([\da-z\-]+(?:\.[\da-z\-]+)*))?$/i | |
}; | |
//------------------------------------------------------------------------------ | |
// static function reset: Clear to 0.0.0 | |
SemVer.reset = function(item) { | |
item.major = item.minor = item.patch = 0; | |
item.pre = item.meta = ''; | |
return item; | |
}; | |
//------------------------------------------------------------------------------ | |
// static function: check if `val` is a valid version string | |
SemVer.isVersion = function(val) { | |
return !!SemVer.validators.version.exec(val); | |
}; | |
//------------------------------------------------------------------------------ | |
// static function: check if `val` is a valid version string | |
SemVer.print = function(item) { | |
var s = '' + item.major + '.' + item.minor + '.' + item.patch; | |
if (item.pre) { | |
s += '-' + item.pre; | |
} | |
if (item.meta) { | |
s += '+' + item.meta; | |
} | |
return s; | |
}; | |
//------------------------------------------------------------------------------ | |
// static function: copy values from `from` to `to`. Throw on any invalid value. | |
// returns `to`. | |
SemVer.safeCopy = function(from, to) { | |
to = to || {}; | |
to.major = _validate(from, to, 'major', 'number'); | |
to.minor = _validate(from, to, 'minor', 'number'); | |
to.patch = _validate(from, to, 'patch', 'number'); | |
to.pre = _validate(from, to, 'pre', 'string'); | |
to.meta = _validate(from, to, 'meta', 'string'); | |
return to; | |
}; | |
//------------------------------------------------------------------------------ | |
// static function: parse a string `from` into `to` and return `to`. | |
SemVer.parse = function(from, to) { | |
to = to || {}; | |
var m = SemVer.validators.version.exec(from); | |
if (!m) { | |
throw new TypeError('SemVer::SemVer(): Argument is not a valid version string: ' + from); | |
} | |
to.major = parseInt(m[1],10); | |
to.minor = parseInt(m[2],10); | |
to.patch = parseInt(m[3],10); | |
to.pre = m[4] || ''; | |
to.meta = m[5] || ''; | |
return to; | |
}; | |
//------------------------------------------------------------------------------ | |
// static function: compare two SemVer objects. Can also be used to sort arrays. | |
SemVer.compare = function(a, b) { | |
if (a.major !== b.major) { | |
return a.major - b.major; | |
} | |
if (a.minor !== b.minor) { | |
return a.minor - b.minor; | |
} | |
if (a.patch !== b.patch) { | |
return a.patch - b.patch; | |
} | |
if (a.pre !== b.pre) { | |
if (a.pre === '') { | |
return 1; | |
} | |
if (b.pre === '') { | |
return -1; | |
} | |
return a.pre.localeCompare(b.pre); | |
} | |
return 0; | |
}; | |
return SemVer; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment