commit 38f8d713a13d80f0209c06f691e9bbe91fd443d7 Author: AJ ONeal Date: Wed Apr 24 17:38:53 2013 -0600 initial commit in own repo diff --git a/README.md b/README.md new file mode 100644 index 0000000..cd125b2 --- /dev/null +++ b/README.md @@ -0,0 +1,74 @@ +## semver-utils + +Some utils that aren't provided by the mainstream `semver` module. + +## API + +### parse(semverString) + +Turns a string such as `1.0.6-1+build-623` into the object + + { + semver: '1.0.6-1+build-623' + , version: '1.0.6' + , major: '1' + , minor: '0' + , patch: '6' + , release: '1' + , build: 'build-623' + } + +### stringify(semverObject) + +Creates a string such as `1.0.6-1+build-623` from the object + + { + major: '1' + , minor: '0' + , patch: '6' + , release: '1' + , build: 'build-623' + } + +### parseRange(rangeString) + +A solution to + +Parses a range string into an array of semver objects + +`>= 1.1.7 < 2.0.0 || 1.1.3'` becomes + + [ + { + "semver": ">= v1.1.7" + , "operator": ">=" + , "major": 1 + , "minor": 1 + , "patch": 7 + } + , { + "semver": "< v2.0.0" + , "operator": "<" + , "major": 2 + , "minor": 0 + , "patch": 0 + } + , { + "operator": "||" + } + , { + "semver": "v1.1.3" + , "operator": "=" + , "major": 1 + , "minor": 1 + , "patch": 3 + } + + ] + +## Obsolete Work + + * https://github.com/mojombo/semver/issues/32 + * https://gist.github.com/coolaj86/3012865 + * https://github.com/isaacs/node-semver/issues/10 + * https://github.com/mojombo/semver.org/issues/59 diff --git a/package.json b/package.json new file mode 100644 index 0000000..04df17d --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "semver-utils", + "version": "1.0.0", + "description": "Tools for manipulating semver strings and objects", + "main": "semver-utils.js", + "scripts": { + "test": "node semver-utils-test.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/coolaj86/semver-utils.git" + }, + "keywords": [ + "semver", + "parse", + "parseRange", + "range" + ], + "author": "AJ ONeal", + "license": "APACHEv2", + "readmeFilename": "README.md" +} diff --git a/semver-utils-tools.js b/semver-utils-tools.js new file mode 100644 index 0000000..f1faa5a --- /dev/null +++ b/semver-utils-tools.js @@ -0,0 +1,109 @@ +(function () { + var semverutils = require('semver-utils') + ; + + function testParseRange() { + 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(semverutils.parseRange(str)); + console.log(semverutils.parseRange('v1.0.0')); + console.log(semverutils.parseRange('< v2.0.0')); + console.log(semverutils.parseRange('~v2.0.0')); + } + + function testParse() { + var good + , bad + ; + + 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.!@#$%" + ]; + + good.every(function (version) { + var result = semverutils.parse(version) + ; + + if (!result) { + throw new Error("didn't parse something that should be parseable: " + version); + } + + return true; + }); + + bad.every(function (version) { + var result = semverutils.parse(version) + ; + + if (result) { + throw new Error("parsed something that should not be parseable: " + version); + } + + return true; + }); + + console.log(semverutils.parse("a.b.c")); // null + console.log(semverutils.parse("1.0.3")); + /* + { + semver: 1.0.3 + , major: 1 + , minor: 0 + , patch: 3 + } + */ + + console.log(semverutils.parse("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(semverutils.parse("1.0.0-rc.1-1")); + console.log(semverutils.parse("1.0.0-rc.1+build.1-b")); + console.log(semverutils.parse("1.0.0-rc.1-1+build.1-b")); + console.log(semverutils.parse("2.0.0+build.acebfde1284-alpha.123.abc")); + } + + testParse(); + testParseRange(); +}()); diff --git a/semver-utils.js b/semver-utils.js new file mode 100644 index 0000000..8cfd15c --- /dev/null +++ b/semver-utils.js @@ -0,0 +1,72 @@ +(function () { + "use strict"; + + var reSemver = /^((\d+)\.(\d+)\.(\d+))(?:-([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?(?:\+([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?$/ + , reSemverRange = /\s*((\|\||\-)|(([<>~]?=?)\s*(v)?([0-9]+)(\.(x|[0-9]+))?(\.(x|[0-9]+))?(([\-+])([a-zA-Z0-9\.]+))?))\s*/g + ; + + function parseSemver(version) { + // 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; + } + + function parseSemverRange(str) { + var m + , arr = [] + , obj + ; + + function prune(key) { + if ('undefined' === typeof obj[key]) { + delete obj[key]; + } + } + + while (true) { + m = reSemverRange.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; + } + + module.exports.parse = parseSemver; + module.exports.parseRange = parseSemverRange; +}());