Compare commits

..

No commits in common. "master" and "v1.0.2" have entirely different histories.

8 changed files with 161 additions and 439 deletions

1
.gitignore vendored
View File

@ -1 +0,0 @@
node_modules

41
LICENSE
View File

@ -1,41 +0,0 @@
Copyright 2013 AJ ONeal
This is open source software; you can redistribute it and/or modify it under the
terms of either:
a) the "MIT License"
b) the "Apache-2.0 License"
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Apache-2.0 License Summary
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,37 +1,15 @@
## semver-utils.js
| Sponsored by [ppl](https://ppl.family)
## semver-utils
Some utils that aren't provided by the mainstream `semver` module.
### Usage
```bash
npm install --save semver-utils
```
```javascript
'use strict';
var semverUtils = require('semver-utils');
var version = require('./package.json').version;
var semver = semverUtils.parse(version);
console.log(semver);
```
## API
* `semverUtils.parse(semverString)`
* `semverUtils.stringify(semverObject)`
* `semverUtils.parseRange(rangeString)`
* `semverUtils.stringifyRange(rangeArray)`
### semverUtils.parse(semverString)
### parse(semverString)
Turns a string such as `1.0.6-1+build-623` into the object
{ semver: '1.0.6-1+build-623'
{
semver: '1.0.6-1+build-623'
, version: '1.0.6'
, major: '1'
, minor: '0'
@ -42,24 +20,25 @@ Turns a string such as `1.0.6-1+build-623` into the object
returns `null` on **error**
### semverUtils.stringify(semverObject)
### stringify(semverObject)
Creates a string such as `1.0.6-1+build-623` from the object
{ major: '1'
{
major: '1'
, minor: '0'
, patch: '6'
, release: '1'
, build: 'build-623'
}
### semverUtils.parseRange(rangeString)
### parseRange(rangeString)
A solution to <https://github.com/isaacs/node-semver/issues/10>
Parses a range string into an array of semver objects
`>= 1.1.7 < 2.0.0 || 1.1.3` becomes
`>= 1.1.7 < 2.0.0 || 1.1.3'` becomes
[
{
@ -89,35 +68,6 @@ Parses a range string into an array of semver objects
]
### semverUtils.stringifyRange(rangeArray)
Creates a range string such as `>= 1.1.7 < 2.0.0 || 1.1.3`
from an array of semver objects (and operators) such as
[
{ "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

View File

@ -1,15 +1,14 @@
{
"name": "semver-utils",
"version": "1.1.3",
"version": "1.0.2",
"description": "Tools for manipulating semver strings and objects",
"homepage": "https://git.coolaj86.com/coolaj86/semver-utils.js",
"main": "semver-utils.js",
"scripts": {
"test": "mocha"
"test": "node semver-utils-test.js"
},
"repository": {
"type": "git",
"url": "git://git.coolaj86.com/coolaj86/semver-utils.js.git"
"url": "git://github.com/coolaj86/semver-utils.git"
},
"keywords": [
"semver",
@ -19,9 +18,5 @@
],
"author": "AJ ONeal",
"license": "APACHEv2",
"readmeFilename": "README.md",
"devDependencies": {
"chai": "^3.0.0",
"mocha": "^2.2.5"
}
"readmeFilename": "README.md"
}

109
semver-utils-tools.js Normal file
View File

@ -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();
}());

View File

@ -1,31 +1,36 @@
(function () {
"use strict";
// TODO break these down into escaped strings with meaningful comments and create using new RegExp()
// |optional 'v'
// | | 3 segment version
// | | |optional release prefixed by '-'
// | | | |optional build prefixed by '+'
var reSemver = /^v?((\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
, reSemverRange = /\s*((\|\||\-)|(((?:(?:~?[<>]?)|\^?)=?)\s*(v)?([0-9]+)(\.(x|\*|[0-9]+))?(\.(x|\*|[0-9]+))?(([\-+])([a-zA-Z0-9\.-]+))?))\s*/g
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
;
// Returns a new object with all of the undefined properties removed from the given object
function pruned(obj) {
var o = {};
for(var key in obj) {
if ('undefined' !== typeof obj[key]) {
o[key] = obj[key];
}
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 o;
return ver;
}
function stringifySemver(obj) {
var str = ''
;
var str = '';
str += obj.major || '0';
str += '.';
str += obj.minor || '0';
@ -40,89 +45,23 @@
return str;
}
function stringifySemverRange(arr) {
var str = ''
;
function stringify(ver) {
if (ver.operator) {
str += ver.operator + ' ';
}
if (ver.major) {
str += ver.toString() + ' ';
}
}
arr.forEach(stringify);
return str.trim();
}
function SemVer(obj) {
if (!obj) {
return;
}
var me = this
;
Object.keys(obj).forEach(function (key) {
me[key] = obj[key];
});
}
SemVer.prototype.toString = function () {
return stringifySemver(this);
};
/*
function SemVerRange(obj) {
if (!obj) {
return;
}
var me = this
;
Object.keys(obj).forEach(function (key) {
me[key] = obj[key];
});
}
SemVerRange.prototype = [];
SemVerRange.prototype.toString = stringifySemverRange;
*/
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 = new SemVer(pruned({
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
;
while (m = reSemverRange.exec(str)) {
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]
@ -136,16 +75,15 @@
if ('-' === m[12]) {
obj.release = m[13];
}
arr.push(new SemVer(pruned(obj)));
Object.keys(obj).forEach(prune);
arr.push(obj);
//console.log(m);
}
//return new SemVerRange(arr);
return arr;
}
module.exports.parse = parseSemver;
module.exports.stringify = stringifySemver;
module.exports.parseRange = parseSemverRange;
module.exports.stringifyRange = stringifySemverRange;
}());

View File

@ -1,26 +0,0 @@
var assert = require('chai').assert;
// we need to define our own deepEqual function that ignores properties that are not hasOwnProperty. Not supported in chai.assert.deepEqual as of v3.0.0.
function deepOwnEqual(a, b) {
// if arrays of objects, recurse down to the objects
if(Array.isArray(a) && Array.isArray(b)) {
assert.deepEqual(a.length, b.length, 'Arrays have different lengths')
for(var i=0; i<a.length; i++) {
deepOwnEqual(a[i], b[i])
}
}
// compare all the object properties
else {
var aKeys = Object.keys(a);
var bKeys = Object.keys(b);
assert.deepEqual(aKeys, bKeys, 'Objects have different keys');
aKeys.forEach(function(key) {
assert.deepEqual(a[key], b[key], 'Expected values of "' + key + '" property to be equal in each object')
});
}
}
module.exports = deepOwnEqual

View File

@ -1,202 +0,0 @@
var assert = require('chai').assert;
var semverutils = require('../semver-utils');
var deepOwnEqual = require('./deepOwnEqual');
describe('parse', function() {
it('should parse a simple 3-part version', function() {
deepOwnEqual(semverutils.parse('1.0.0'), {
semver: '1.0.0',
version: '1.0.0',
major: '1',
minor: '0',
patch: '0'
});
});
it('should parse pre-release versions', function() {
deepOwnEqual(semverutils.parse('1.0.0-alpha1'), {
semver: '1.0.0-alpha1',
version: '1.0.0',
major: '1',
minor: '0',
patch: '0',
release: 'alpha1'
});
});
it('should parse build numbers', function() {
deepOwnEqual(semverutils.parse('1.0.0+build-123'), {
semver: '1.0.0+build-123',
version: '1.0.0',
major: '1',
minor: '0',
patch: '0',
build: 'build-123'
});
});
it('should not parse invalid versions', function() {
assert.equal(semverutils.parse('a.b.c'), null);
assert.equal(semverutils.parse('1'), null);
assert.equal(semverutils.parse('1.0'), null);
assert.equal(semverutils.parse('1.0.0b'), null);
assert.equal(semverutils.parse('1.0.0+build-abc.'), null, 'trailing period');
});
});
describe('parseRange', function() {
it('should parse an exact version as a range', function() {
deepOwnEqual(semverutils.parseRange('1.0.0'), [{
semver: '1.0.0',
major: '1',
minor: '0',
patch: '0'
}]);
});
it('should ignore the v- prefix', function() {
deepOwnEqual(semverutils.parseRange('v1.0.0'), [{
semver: 'v1.0.0',
major: '1',
minor: '0',
patch: '0'
}]);
});
it('should parse a comparison operator', function() {
deepOwnEqual(semverutils.parseRange('< v2.0.0'), [{
semver: '< v2.0.0',
operator: '<',
major: '2',
minor: '0',
patch: '0'
}]);
});
it('should parse tilde', function() {
deepOwnEqual(semverutils.parseRange('~1.0.0'), [{
semver: '~1.0.0',
operator: '~',
major: '1',
minor: '0',
patch: '0'
}]);
});
it('should parse caret', function() {
deepOwnEqual(semverutils.parseRange('^1.0.0'), [{
semver: '^1.0.0',
operator: '^',
major: '1',
minor: '0',
patch: '0'
}]);
});
it('should parse tilde and v- prefix', function() {
deepOwnEqual(semverutils.parseRange('~v1.0.0'), [{
semver: '~v1.0.0',
operator: '~',
major: '1',
minor: '0',
patch: '0'
}]);
});
it('should parse ||', function() {
deepOwnEqual(semverutils.parseRange('~1.0.0 || ~2.0.0'), [{
semver: '~1.0.0',
operator: '~',
major: '1',
minor: '0',
patch: '0'
}, {
operator: '||'
}, {
semver: '~2.0.0',
operator: '~',
major: '2',
minor: '0',
patch: '0'
}]);
});
it('should parse build numbers', function() {
deepOwnEqual(semverutils.parseRange('2.0.0+build.1848'), [{
semver: '2.0.0+build.1848',
major: '2',
minor: '0',
patch: '0',
build: 'build.1848'
}]);
});
it('should parse pre-release versions', function() {
deepOwnEqual(semverutils.parseRange('1.0.0-rc1'), [{
semver: '1.0.0-rc1',
major: '1',
minor: '0',
patch: '0',
release: 'rc1'
}]);
});
it('should parse pre-release versions with hyphens', function() {
deepOwnEqual(semverutils.parseRange('1.0.0-rc-2'), [{
semver: '1.0.0-rc-2',
major: '1',
minor: '0',
patch: '0',
release: 'rc-2'
}]);
});
it('should parse hyphen ranges', function() {
deepOwnEqual(semverutils.parseRange('1.0.0 - 1.0.x'), [{
semver: '1.0.0',
major: '1',
minor: '0',
patch: '0'
}, {
operator: '-'
}, {
semver: '1.0.x',
major: '1',
minor: '0',
patch: 'x'
}]);
});
it('should parse constrained * ranges', function() {
deepOwnEqual(semverutils.parseRange('1.*'), [{
semver: '1.*',
major: '1',
minor: '*',
}]);
});
it('should parse constrained .x', function() {
deepOwnEqual(semverutils.parseRange('1.x'), [{
semver: '1.x',
major: '1',
minor: 'x',
}]);
});
it('should parse ~> ranges', function() {
deepOwnEqual(semverutils.parseRange('~> 2.0.0'), [{
semver: '~> 2.0.0',
operator: '~>',
major: '2',
minor: '0',
patch: '0'
}]);
});
});