public
Last active

Parse Semver

  • Download Gist
README.md
Markdown

Please use semver-utils instead!

npm install semver-utils

See the README for semver-utils at https://github.com/coolaj86/semver-utils

npm install semver-utils

Obsolete Functions

parse-semver.js parses a single semver such as 2.1.0-6+b. This has been tested quite a bit.

parse-semver-range.js parses ranges such as >= 1.3.1 <= 1.4.6. This needs more testing.

parse-semver-range.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
/*
* WARNING: OBSOLETE
*
* Please use the code at https://github.com/coolaj86/semver-utils, not this gist
* npm install semver-utils
*/
(function () {
"use strict";
console.warn('OBSOLETE: `npm install semver-utils` and see README at https://github.com/coolaj86/semver-utils');
 
var re = /\s*((\|\||\-)|(([<>~]?=?)\s*(v)?([0-9]+)(\.(x|[0-9]+))?(\.(x|[0-9]+))?(([\-+])([a-zA-Z0-9\.]+))?))\s*/g
;
 
function parseRangeFull(str) {
console.warn('OBSOLETE: `npm install semver-utils` and see README at https://github.com/coolaj86/semver-utils');
var m
, arr = []
, obj
;
 
function prune(key) {
if ('undefined' === typeof obj[key]) {
delete obj[key];
}
}
 
while (true) {
m = re.exec(str);
if (!m) {
break;
}
obj = {
semver: m[3]
, operator: m[4] || m[2]
, major: m[6]
, minor: m[8]
, patch: m[10]
};
if ('+' === m[12]) {
obj.build = m[13];
}
if ('-' === m[12]) {
obj.release = m[13];
}
Object.keys(obj).forEach(prune);
arr.push(obj);
//console.log(m);
}
 
return arr;
}
 
function test() {
var str = '~1.0.0 || >= 1.1.7 < 2.0.0+build.1848 || v1.1.3 || 2.0.1-alpha.1227 || 1.0.0 - 1.0.x'
;
console.log(parseRangeFull(str));
console.log(parseRangeFull('v1.0.0'));
console.log(parseRangeFull('< v2.0.0'));
console.log(parseRangeFull('~v2.0.0'));
}
 
test();
}());
parse-semver.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
/*
* WARNING: OBSOLETE
*
* Please use the code at https://github.com/coolaj86/semver-utils, not this gist
* npm install semver-utils
*/
(function () {
"use strict";
 
console.warn('OBSOLETE: `npm install semver-utils` and see README at https://github.com/coolaj86/semver-utils');
 
var good
, bad
, reSemver = /^((\d+)\.(\d+)\.(\d+))(?:-([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?(?:\+([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?$/
;
 
good = [
"1.0.8"
, "1.23.7"
, "2.0.0-alpha.123.abc"
, "2.0.0-alpha.123.abc+build.acebfde1284"
, "1.0.0-alpha"
, "1.0.0-alpha.1"
, "1.0.0-0.3.7"
, "1.0.0-x.7.z.92"
, "1.0.0-alpha"
, "1.0.0-alpha.1"
, "1.0.0-beta.2"
, "1.0.0-beta.11"
, "1.0.0-rc.1"
, "1.0.0-rc.1+build.1"
, "1.0.0-rc.1+build.1-b"
, "1.0.0"
, "1.0.0+0.3.7"
, "1.3.7+build"
, "1.3.7+build.2.b8f12d7"
, "1.3.7+build.11.e0f985a"
, "1.3.7+build.11.e0f9-85a"
, "1.0.0+build-acbe"
, "2.0.0+build.acebfde1284-alpha.123.abc"
];
 
bad = [
"v1.0.0"
, "a.b.c"
, "1"
, "1.0.0b"
, "1.0"
, "1.0.0+b[\\]^_`uild" // [,\,],^,_,` are between A-z, but not A-Za-z
, "1.0.0+build-acbe." // trailing period
, "1.0.0+build.!@#$%"
];
 
function parseSemver(version) {
console.warn('OBSOLETE: `npm install semver-utils` and see README at https://github.com/coolaj86/semver-utils');
// semver, major, minor, patch
// https://github.com/mojombo/semver/issues/32
// https://github.com/isaacs/node-semver/issues/10
// optional v
var m = reSemver.exec(version) || []
, ver = {
semver: m[0]
, version: m[1]
, major: m[2]
, minor: m[3]
, patch: m[4]
, release: m[5]
, build: m[6]
}
;
 
if (0 === m.length) {
ver = null;
}
 
return ver;
}
 
good.every(function (version) {
var result = parseSemver(version)
;
 
if (!result) {
throw new Error("didn't parse something that should be parseable: " + version);
}
 
return true;
});
 
bad.every(function (version) {
var result = parseSemver(version)
;
 
if (result) {
throw new Error("parsed something that should not be parseable: " + version);
}
 
return true;
});
 
console.log(parseSemver("a.b.c")); // null
console.log(parseSemver("1.0.3"));
/*
{
semver: 1.0.3
, major: 1
, minor: 0
, patch: 3
}
*/
 
console.log(parseSemver("1.0.3-rc.1+build.aef312"));
/*
{
semver: v1.0.3-rc.1+build.aef312
, major: 1
, minor: 0
, patch: 3
, build: build.aef312
, release: rc.1
}
*/
 
console.log(parseSemver("1.0.0-rc.1-1"));
console.log(parseSemver("1.0.0-rc.1+build.1-b"));
console.log(parseSemver("1.0.0-rc.1-1+build.1-b"));
console.log(parseSemver("2.0.0+build.acebfde1284-alpha.123.abc"));
}());

The use of "A-z" in the regex allows for the six interstitial characters between 'Z' and 'a' to be included in identifiers. (i.e. left-square-bracket, backslash, right-square-bracket, caret, underscore, and backtick). These are not legal identifier characters. Adding these two negative test cases between lines 43 and 44 demonstrates the problem:

, "1.0.0+build_with_underscore" // underscore is illegal
, "1.0.0+build[5]" // square brackets are illegal

Replacing the four instances of "A-z" with "A-Za-z" fixes this issue.

thanks for the heads up

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.