deleted inigui, created features

This commit is contained in:
Bachir Soussi Chiadmi
2015-02-21 17:37:57 +01:00
parent 1f1ff5a8ef
commit 118ebf517d
2749 changed files with 523597 additions and 2764 deletions
@@ -0,0 +1,22 @@
Copyright (c) 2014 Sindre Sorhus, contributors
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.
+446
View File
@@ -0,0 +1,446 @@
# grunt-contrib-compass v0.9.0 [![Build Status: Linux](https://travis-ci.org/gruntjs/grunt-contrib-compass.png?branch=master)](https://travis-ci.org/gruntjs/grunt-contrib-compass)
> Compile Sass to CSS using Compass
## Getting Started
This plugin requires Grunt `^0.4.0`
If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:
```shell
npm install grunt-contrib-compass --save-dev
```
Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:
```js
grunt.loadNpmTasks('grunt-contrib-compass');
```
## Compass task
_Run this task with the `grunt compass` command._
[Compass](http://compass-style.org/) is an open-source authoring framework for the [Sass](http://sass-lang.com/) css preprocessor. It helps you build stylesheets faster with a huge library of Sass mixins and functions, advanced tools for spriting, and workflow improvements including file based Sass configuration and a simple pattern for building and using Compass extensions.
This task requires you to have [Ruby](http://www.ruby-lang.org/en/downloads/), [Sass](http://sass-lang.com/tutorial.html), and [Compass](http://compass-style.org/install/) >=0.12.2 installed. If you're on OS X or Linux you probably already have Ruby installed; test with `ruby -v` in your terminal. When you've confirmed you have Ruby installed, run `gem update --system && gem install compass` to install Compass and Sass.
Compass operates on a folder level. Because of this you don't specify any src/dest, but instead define the `sassDir` and `cssDir` options.
### Options
Compass doesn't expose all of its [options][config] through the CLI, which this task makes use of. If you need an option not mentioned below you can either specify a path to a config.rb file in the `config` option or embed it directly into the `raw` option. Options defined in your Gruntfile will override those specified in your config.rb or `raw` property. `config` and `raw` are mutually exclusive.
#### config
Type: `String`
Default: same path as your Gruntfile
Specify the location of the Compass [configuration file][config] explicitly.
#### raw
Type: `String`
String form of the Compass [configuration file][config].
#### basePath
Type: `String`
The path Compass will run from. Defaults to the same path as your Gruntfile.
#### banner
Type: `String`
Prepend the specified string to the output file. Useful for licensing
information. **Note:** This only works in combination with the `specify` option
and can conflict with sourcemap generation.
#### app
Type: `String`
Default: `stand_alone`
Tell compass what kind of application it is integrating with. Can be `stand_alone` or `rails`.
#### sassDir
Type: `String`
The source directory where you keep your Sass stylesheets.
#### cssDir
Type: `String`
The target directory where you keep your CSS stylesheets.
#### specify
Type: `String|Array`
Lets you specify which files you want to compile. Useful if you don't want to compile the whole folder. Globbing supported. Ignores filenames starting with underscore.
#### imagesDir
Type: `String`
The directory where you keep your images.
#### javascriptsDir
Type: `String`
The directory where you keep your JavaScript files.
#### fontsDir
Type: `String`
The directory where you keep your fonts.
#### environment
Type: `String`
Default: `development`
Use sensible defaults for your current environment. Can be: `development` or `production`
#### outputStyle
Type: `String`
CSS output mode. Can be: `nested`, `expanded`, `compact`, `compressed`.
#### relativeAssets
Type: `Boolean`
Make Compass asset helpers generate relative urls to assets.
#### noLineComments
Type: `Boolean`
Disable line comments.
#### httpPath
Type: `String`
Default: `/`
The path to the project when running within the web server.
#### cssPath
Type: `String`
The directory where the css stylesheets are kept. It is relative to the `projectPath`. Defaults to "stylesheets".
#### httpStylesheetsPath
Type: `String`
Default: `httpPath + "/" + cssDir`
The full http path to stylesheets on the web server.
#### sassPath
Type: `String`
Default: `sass`
The directory where the sass stylesheets are kept. It is relative to the `projectPath`.
#### imagesPath
Type: `String`
Default: `images`
The directory where the images are kept. It is relative to the projectPath.
#### httpImagesPath
Type: `String`
Default: `httpPath + "/" + imagesDir`
The full http path to images on the web server.
#### generatedImagesDir
Type: `String`
Default: value of `imagesDir`
The directory where generated images are kept. It is relative to the `projectPath`.
#### generatedImagesPath
Type: `String`
Default: value of `projectPath/generatedImagesDir`
The full path to where generated images are kept.
#### httpGeneratedImagesPath
Type: `String`
Default: `httpPath + "/" + generatedImagesDir`
The full http path to generated images on the web server.
#### spriteLoadPath
Type: `String|Array`
Default: value of `imagesPath`
Add additional locations to look for sprites. The imagesPath is always the last entry in this list.
#### javascriptsPath
Type: `String`
Default: `projectPath/javascriptsDir`
The full path to where javascripts are kept.
#### httpJavascriptsPath
Type: `String`
Default: `httpPath + "/" + javascriptsDir`
The full http path to javascripts on the web server.
#### fontsPath
Type: `String`
Default: `projectPath/fontsDir`
The full path to where font files are kept.
#### httpFontsPath
Type: `String`
The full http path to font files on the web server.
#### httpFontsDir
Type: `String`
The relative http path to font files on the web server.
#### extensionsPath
Type: `String`
Default: `project_root/extensions`
The full http path to the ad-hoc extensions folder on the web server. This is used to access compass plugins that have been installed directly to the project (e.g. through [Bower](https://github.com/bower/bower)) instead of globally as gems. *Only Compass >=0.12.2*
#### extensionsDir
Type: `String`
The relative http path to the ad-hoc extensions folder on the web server. *Only Compass >=0.12.2*
#### assetCacheBuster
Type: `Boolean`
Default: `true`
If set to `false`, this disables the default asset cache buster.
#### cacheDir
Type: `String`
Default: `.sass-cache`
The relative path to the folder where the sass cache files are generated.
#### require
Type: `String|Array`
Require the given Ruby library before running commands. This is used to access Compass plugins without having a project configuration file.
#### load
Type: `String|Array`
Load the framework or extensions found in the specified directory.
#### loadAll
Type: `String|Array`
Load all the frameworks or extensions found in the specified directory.
#### importPath
Type: `String|Array`
Makes files under the specified folder findable by Sass's @import directive.
#### debugInfo
Type: `Boolean`
Causes the line number and file where a selector is defined to be emitted into the compiled CSS in a format that can be understood by the browser. Automatically disabled when using `outputStyle: 'compressed'`.
#### quiet
Type: `Boolean`
Quiet mode.
#### trace
Type: `Boolean`
Show a full stacktrace on error.
#### force
Type: `Boolean`
Allows Compass to overwrite existing files.
#### dryRun
Type: `Boolean`
Dry Run. Tells you what it plans to do.
#### boring
Type: `Boolean`
Turn off colorized output.
#### bundleExec
Type: `Boolean`
Run `compass compile` with [bundle exec](http://gembundler.com/v1.3/man/bundle-exec.1.html): `bundle exec compass compile`.
#### clean
Type: `Boolean`
Remove generated files and the sass cache. Runs `compass clean` instead of `compass compile`.
#### watch
Type: `Boolean`
Runs `compass watch` instead of `compass compile`. This will use Compass' native watch command to listen for changes to Sass files and recompile your CSS on changes. While much faster than running `compass compile` each time you want to compile your Sass, Compass becomes a blocking task. This means that if you would like to use it in conjunction with another blocking task, such as `watch`, you will need to use it in conjunction with a paralleling task such as [grunt-concurrent](https://github.com/sindresorhus/grunt-concurrent).
[config]: http://compass-style.org/help/tutorials/configuration-reference/
### Usage Examples
#### Example config
```javascript
grunt.initConfig({
compass: { // Task
dist: { // Target
options: { // Target options
sassDir: 'sass',
cssDir: 'css',
environment: 'production'
}
},
dev: { // Another target
options: {
sassDir: 'sass',
cssDir: 'css'
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-compass');
grunt.registerTask('default', ['jshint', 'compass']);
```
#### Example usage
##### Use external config file
```javascript
grunt.initConfig({
compass: {
dist: {
options: {
config: 'config/config.rb'
}
}
}
});
```
##### Override setting in external config file
```javascript
grunt.initConfig({
compass: {
dist: {
options: {
config: 'config/config.rb', // css_dir = 'dev/css'
cssDir: 'dist/css'
}
}
}
});
```
##### Use `raw` option
```javascript
grunt.initConfig({
compass: {
dist: {
options: {
sassDir: 'sass',
cssDir: 'css',
raw: 'preferred_syntax = :sass\n' // Use `raw` since it's not directly available
}
}
}
});
```
## Release History
* 2014-09-24   v0.9.0   Add Compass version check to ensure only a supported version is used.
* 2014-05-16   v0.8.0   Add `spriteLoadPath` option.
* 2014-02-09   v0.7.2   Improve compatibility with Compass 0.13.
* 2014-01-26   v0.7.1   Fix `assetCacheBuster` option.
* 2013-12-07   v0.7.0   Add `cacheDir` option.
* 2013-10-04   v0.6.0   Add `watch` option. Fix Compass errors not propagating.
* 2013-08-08   v0.5.0   Add `assetCacheBuster` option.
* 2013-07-28   v0.4.1   Fix `banner` option with `.css.scss` files.
* 2013-07-19   v0.4.0   Add `banner` option. Show compilation time.
* 2013-06-24   v0.3.0   Add `extensionDir` and `extensionPath` options. *Requires Compass >=0.12.2*.
* 2013-04-11   v0.2.0   Add `clean` option. Expose `raw` options as Grunt options. Fix detection of `Nothing to compile` situation.
* 2013-02-27   v0.1.3   Fixes bundleExec.
* 2013-02-17   v0.1.2   Ensure Gruntfile.js is included on npm.
* 2013-02-15   v0.1.1   First official release for Grunt 0.4.0.
* 2013-02-05   v0.1.1rc8   Added new options: basePath specify, debugInfo.
* 2013-01-25   v0.1.1rc7   Updating grunt/gruntplugin dependencies to rc7. Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions.
* 2013-01-10   v0.1.1rc5   Updating to work with grunt v0.4.0rc5.
* 2012-10-22   v0.1.0   Initial release
---
Task submitted by [Sindre Sorhus](http://github.com/sindresorhus)
*This file was generated on Tue Jun 24 2014 22:15:11.*
@@ -0,0 +1 @@
../bin-version-check/cli.js
@@ -0,0 +1,3 @@
language: node_js
node_js:
- "0.10"
@@ -0,0 +1,19 @@
Copyright (c) 2010-2014 Caolan McMahon
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.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,11 @@
{
"name": "async",
"repo": "caolan/async",
"description": "Higher-order functions and common patterns for asynchronous code",
"version": "0.1.23",
"keywords": [],
"dependencies": {},
"development": {},
"main": "lib/async.js",
"scripts": [ "lib/async.js" ]
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,59 @@
{
"name": "async",
"description": "Higher-order functions and common patterns for asynchronous code",
"main": "./lib/async",
"author": {
"name": "Caolan McMahon"
},
"version": "0.8.0",
"repository": {
"type": "git",
"url": "https://github.com/caolan/async.git"
},
"bugs": {
"url": "https://github.com/caolan/async/issues"
},
"licenses": [
{
"type": "MIT",
"url": "https://github.com/caolan/async/raw/master/LICENSE"
}
],
"devDependencies": {
"nodeunit": ">0.0.0",
"uglify-js": "1.2.x",
"nodelint": ">0.0.0"
},
"jam": {
"main": "lib/async.js",
"include": [
"lib/async.js",
"README.md",
"LICENSE"
]
},
"scripts": {
"test": "nodeunit test/test-async.js"
},
"homepage": "https://github.com/caolan/async",
"_id": "async@0.8.0",
"dist": {
"shasum": "ee65ec77298c2ff1456bc4418a052d0f06435112",
"tarball": "http://registry.npmjs.org/async/-/async-0.8.0.tgz"
},
"_from": "async@>=0.8.0 <0.9.0",
"_npmVersion": "1.4.3",
"_npmUser": {
"name": "caolan",
"email": "caolan.mcmahon@gmail.com"
},
"maintainers": [
{
"name": "caolan",
"email": "caolan@caolanmcmahon.com"
}
],
"directories": {},
"_shasum": "ee65ec77298c2ff1456bc4418a052d0f06435112",
"_resolved": "https://registry.npmjs.org/async/-/async-0.8.0.tgz"
}
@@ -0,0 +1,39 @@
#!/usr/bin/env node
'use strict';
var argv = require('minimist')(process.argv.slice(2));
var pkg = require('./package.json');
var binVersionCheck = require('./');
function help() {
console.log([
pkg.description,
'',
'Usage',
' $ bin-version-check <binary> <semver-range>',
'',
'Example',
' $ curl --version',
' curl 7.30.0 (x86_64-apple-darwin13.0)',
' $ bin-version-check curl \'>=8\'',
' curl 7.30.0 does not satisfy the version requirement of >=8',
'',
'Exits with code 0 if the semver range is satisfied and 1 if not'
].join('\n'));
}
if (argv._.length === 0 || argv.help) {
help();
return;
}
if (argv.version) {
console.log(pkg.version);
return;
}
binVersionCheck(argv._[0], argv._[1], function (err) {
if (err) {
console.error(err.message);
process.exit(1);
}
});
@@ -0,0 +1,27 @@
'use strict';
var semver = require('semver');
var binVersion = require('bin-version');
module.exports = function (bin, versionRange, cb) {
if (typeof bin !== 'string' || typeof versionRange !== 'string') {
throw new Error('`binary` and `versionRange` required');
}
if (!semver.validRange(versionRange)) {
return cb(new Error('Invalid version range'));
}
binVersion(bin, function (err, binVersion) {
if (err) {
return cb(err);
}
if (!semver.satisfies(binVersion, versionRange)) {
err = new Error(bin + ' ' + binVersion + ' does not satisfy the version requirement of ' + versionRange);
err.name = 'InvalidBinVersion';
return cb(err);
}
cb();
});
};
@@ -0,0 +1 @@
../semver/bin/semver
@@ -0,0 +1,17 @@
'use strict';
var execFile = require('child_process').execFile;
var findVersions = require('find-versions');
module.exports = function (bin, cb) {
execFile(bin, ['--version'], function (err, stdout, stderr) {
if (err) {
if (err.code === 'ENOENT') {
err.message = 'Couldn\'t find the `' + bin + '` binary. Make sure it\'s installed and in your $PATH';
}
return cb(err);
}
cb(null, findVersions(stdout.trim() || stderr.trim(), {loose: true})[0]);
});
};
@@ -0,0 +1,53 @@
#!/usr/bin/env node
'use strict';
var stdin = require('get-stdin');
var argv = require('minimist')(process.argv.slice(2));
var pkg = require('./package.json');
var findVersions = require('./');
var input = argv._[0];
function help() {
console.log([
pkg.description,
'',
'Usage',
' $ find-versions <string> [--first] [--loose]',
' $ echo <string> | find-versions',
'',
'Example',
' $ find-versions \'unicorns v1.2.3\'',
' 1.2.3',
' $ curl --version | find-versions --first',
' 7.30.0',
'',
'Options',
' --first Return the first match',
' --loose Match non-semver versions like 1.88'
].join('\n'));
}
function init(data) {
var ret = findVersions(data, {loose: argv.loose});
console.log(argv.first ? ret[0] : ret.join('\n'));
}
if (argv.help) {
help();
return;
}
if (argv.version) {
console.log(pkg.version);
return;
}
if (process.stdin.isTTY) {
if (!input) {
help();
return;
}
init(input);
} else {
stdin(init);
}
@@ -0,0 +1,33 @@
'use strict';
var semverRegex = require('semver-regex');
var arrayUniq = require('array-uniq');
function findLoose(str) {
var match;
var matches = [];
var reVersion = /[^\d\.]v?(\d+\.\d+)[^\.\+\-]?/g; // match 1.1, but not semver 1.1.0
while (match = reVersion.exec(' ' + str + ' ')) { // pad it to make crappy regex work
if (match[1]) {
matches.push(match[1]);
}
}
return matches;
}
module.exports = function (str, opts) {
if (typeof str !== 'string') {
throw new TypeError('Expected a string');
}
opts = opts || {};
var loose = opts.loose === undefined ? false : opts.loose;
var semverMatches = str.match(semverRegex()) || [];
var looseMatches = loose ? findLoose(str) : [];
return arrayUniq(semverMatches.concat(looseMatches).map(function (el) {
return el.replace(/^v/, '').replace(/^\d+\.\d+$/, '$&.0');
}));
};
@@ -0,0 +1,49 @@
'use strict';
// we have 3 implementations for unique, written in increasing order of efficiency
// 1 - no Set type is defined
function uniqNoSet(arr) {
var ret = [];
for (var i = 0; i < arr.length; i++) {
if (ret.indexOf(arr[i]) === -1) {
ret.push(arr[i]);
}
}
return ret;
}
// 2 - a simple Set type is defined
function uniqSet(arr) {
var seen = new Set();
return arr.filter(function (el) {
if (!seen.has(el)) {
seen.add(el);
return true;
}
});
}
// 3 - a standard Set type is defined and it has a forEach method
function uniqSetWithForEach(arr) {
var ret = [];
(new Set(arr)).forEach(function (el) {
ret.push(el);
});
return ret;
}
// export the relevant implementation
if ('Set' in global) {
if (typeof Set.prototype.forEach === 'function') {
module.exports = uniqSetWithForEach;
} else {
module.exports = uniqSet;
}
} else {
module.exports = uniqNoSet;
}
@@ -0,0 +1,62 @@
{
"name": "array-uniq",
"version": "0.1.1",
"description": "Create an array without duplicates",
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/sindresorhus/array-uniq"
},
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "http://sindresorhus.com"
},
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"test": "mocha"
},
"files": [
"index.js"
],
"keywords": [
"array",
"arr",
"set",
"uniq",
"unique",
"es6",
"duplicate",
"remove"
],
"devDependencies": {
"es6-set": "^0.1.0",
"mocha": "*"
},
"bugs": {
"url": "https://github.com/sindresorhus/array-uniq/issues"
},
"homepage": "https://github.com/sindresorhus/array-uniq",
"_id": "array-uniq@0.1.1",
"_shasum": "5861f3ed4e4bb6175597a4e078e8aa78ebe958c7",
"_from": "array-uniq@>=0.1.0 <0.2.0",
"_npmVersion": "1.4.9",
"_npmUser": {
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
},
"maintainers": [
{
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
}
],
"dist": {
"shasum": "5861f3ed4e4bb6175597a4e078e8aa78ebe958c7",
"tarball": "http://registry.npmjs.org/array-uniq/-/array-uniq-0.1.1.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-0.1.1.tgz"
}
@@ -0,0 +1,30 @@
# array-uniq [![Build Status](https://travis-ci.org/sindresorhus/array-uniq.svg?branch=master)](https://travis-ci.org/sindresorhus/array-uniq)
> Create an array without duplicates
It's already pretty fast, but will be much faster when [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) becomes available in V8 (especially with large arrays).
## Install
```sh
$ npm install --save array-uniq
```
## Usage
```js
var arrayUniq = require('array-uniq');
arrayUniq([1, 1, 2, 3, 3]);
//=> [1, 2, 3]
arrayUniq(['foo', 'foo', 'bar', 'foo']);
//=> ['foo', 'bar']
```
## License
MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,15 @@
'use strict';
module.exports = function (cb) {
var ret = '';
process.stdin.resume();
process.stdin.setEncoding('utf8');
process.stdin.on('data', function (data) {
ret += data;
});
process.stdin.on('end', function () {
cb(ret);
});
};
@@ -0,0 +1,58 @@
{
"name": "get-stdin",
"version": "0.1.0",
"description": "Easier stdin",
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/sindresorhus/get-stdin"
},
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "http://sindresorhus.com"
},
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"test": "echo unicorns | mocha"
},
"files": [
"index.js"
],
"keywords": [
"stdin",
"stdio",
"concat",
"buffer",
"stream"
],
"devDependencies": {
"mocha": "*"
},
"bugs": {
"url": "https://github.com/sindresorhus/get-stdin/issues"
},
"homepage": "https://github.com/sindresorhus/get-stdin",
"_id": "get-stdin@0.1.0",
"dist": {
"shasum": "5998af24aafc802d15c82c685657eeb8b10d4a91",
"tarball": "http://registry.npmjs.org/get-stdin/-/get-stdin-0.1.0.tgz"
},
"_from": "get-stdin@>=0.1.0 <0.2.0",
"_npmVersion": "1.3.26",
"_npmUser": {
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
},
"maintainers": [
{
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
}
],
"directories": {},
"_shasum": "5998af24aafc802d15c82c685657eeb8b10d4a91",
"_resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-0.1.0.tgz"
}
@@ -0,0 +1,32 @@
# get-stdin [![Build Status](https://travis-ci.org/sindresorhus/get-stdin.png?branch=master)](https://travis-ci.org/sindresorhus/get-stdin)
> Easier stdin
## Install
```
npm install --save get-stdin
```
## Example
```js
// example.js
var stdin = require('get-stdin');
stdin(function (data) {
console.log(data);
//=> unicorns
});
```
```
$ echo unicorns | node example.js
```
## License
MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,4 @@
'use strict';
module.exports = function () {
return /\bv?(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)(?:-[\da-z\-]+(?:\.[\da-z\-]+)*)?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?\b/ig;
};
@@ -0,0 +1,62 @@
{
"name": "semver-regex",
"version": "0.1.1",
"description": "Regular expression for matching semver versions",
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/sindresorhus/semver-regex"
},
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "http://sindresorhus.com"
},
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"test": "mocha"
},
"files": [
"index.js"
],
"keywords": [
"semver",
"version",
"versions",
"regex",
"regexp",
"re",
"match",
"matching",
"semantic"
],
"devDependencies": {
"mocha": "*"
},
"bugs": {
"url": "https://github.com/sindresorhus/semver-regex/issues"
},
"homepage": "https://github.com/sindresorhus/semver-regex",
"_id": "semver-regex@0.1.1",
"_shasum": "a9d6717eba5871107ff8f4d81f5278d4ad4a29f9",
"_from": "semver-regex@>=0.1.0 <0.2.0",
"_npmVersion": "1.4.9",
"_npmUser": {
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
},
"maintainers": [
{
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
}
],
"dist": {
"shasum": "a9d6717eba5871107ff8f4d81f5278d4ad4a29f9",
"tarball": "http://registry.npmjs.org/semver-regex/-/semver-regex-0.1.1.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-0.1.1.tgz"
}
@@ -0,0 +1,36 @@
# semver-regex [![Build Status](https://travis-ci.org/sindresorhus/semver-regex.svg?branch=master)](https://travis-ci.org/sindresorhus/semver-regex)
> Regular expression for matching [semver](https://github.com/isaacs/node-semver) versions
## Install
```sh
$ npm install --save semver-regex
```
## Usage
```js
var semverRegex = require('semver-regex');
semverRegex().test('v1.0.0');
//=> true
semverRegex().test('1.2.3-alpha.10.beta.0+build.unicorn.rainbow');
//=> true
semverRegex().exec('unicorn 1.0.0 rainbow')[0];
//=> 1.0.0
'unicorn 1.0.0 and rainbow 2.1.3'.match(semverRegex());
//=> ['1.0.0', '2.1.3']
```
*It's a function so you can create multiple instances. Regexes with the global flag will have the `.lastIndex` property changed for each call to methods on the instance. Therefore reusing the instance with multiple calls will not work as expected for `.test()`.*
## License
MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,77 @@
{
"name": "find-versions",
"version": "0.1.1",
"description": "Find semver versions in a string: `unicorn 1.0.0` → `1.0.0`",
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/sindresorhus/find-versions"
},
"bin": {
"find-versions": "cli.js"
},
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "http://sindresorhus.com"
},
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"test": "mocha"
},
"files": [
"index.js",
"cli.js"
],
"keywords": [
"cli",
"bin",
"semver",
"version",
"versions",
"regex",
"regexp",
"re",
"match",
"matching",
"semantic",
"find",
"extract",
"get"
],
"dependencies": {
"array-uniq": "^0.1.0",
"get-stdin": "^0.1.0",
"minimist": "^0.1.0",
"semver-regex": "^0.1.0"
},
"devDependencies": {
"mocha": "*"
},
"bugs": {
"url": "https://github.com/sindresorhus/find-versions/issues"
},
"homepage": "https://github.com/sindresorhus/find-versions",
"_id": "find-versions@0.1.1",
"_shasum": "3a5bc2cf346ab1b6bd57cd60c480d0022df5ec17",
"_from": "find-versions@>=0.1.0 <0.2.0",
"_npmVersion": "1.4.9",
"_npmUser": {
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
},
"maintainers": [
{
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
}
],
"dist": {
"shasum": "3a5bc2cf346ab1b6bd57cd60c480d0022df5ec17",
"tarball": "http://registry.npmjs.org/find-versions/-/find-versions-0.1.1.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/find-versions/-/find-versions-0.1.1.tgz"
}
@@ -0,0 +1,71 @@
# find-versions [![Build Status](https://travis-ci.org/sindresorhus/find-versions.svg?branch=master)](https://travis-ci.org/sindresorhus/find-versions)
> Find semver versions in a string: `unicorn 1.0.0` → `1.0.0`
## Install
```sh
$ npm install --save find-versions
```
## Usage
```js
var findVersions = require('find-versions');
findVersions('unicorn 1.0.0 rainbow v2.3.4+build.1');
//=> ['1.0.0', '2.3.4+build.1']
findVersions('cp (GNU coreutils) 8.22', {loose: true});
//=> ['8.22.0']
```
## API
### findVersions(input, options)
#### input
*Required*
Type: `string`
#### options.loose
Type: `boolean`
Default: `false`
Also match non-semver versions like `1.88`.
They're coerced into semver compliant versions.
## CLI
```sh
$ npm install --global find-versions
```
```sh
$ find-versions --help
Usage
$ find-versions <string> [--first] [--loose]
$ echo <string> | find-versions
Example
$ find-versions 'unicorns v1.2.3'
1.2.3
$ curl --version | find-versions --first
7.30.0
Options
--first Return the first match
--loose Match non-semver versions like 1.88
```
## License
MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,63 @@
{
"name": "bin-version",
"version": "0.1.0",
"description": "Get the version of a binary in semver format",
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/sindresorhus/bin-version"
},
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "http://sindresorhus.com"
},
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"test": "mocha"
},
"files": [
"index.js"
],
"keywords": [
"bin",
"binary",
"executable",
"version",
"semver",
"semantic",
"cli"
],
"dependencies": {
"find-versions": "^0.1.0"
},
"devDependencies": {
"mocha": "*"
},
"bugs": {
"url": "https://github.com/sindresorhus/bin-version/issues"
},
"homepage": "https://github.com/sindresorhus/bin-version",
"_id": "bin-version@0.1.0",
"_shasum": "247aa9d410a34d07fa5e3021ac517d6439efc9c5",
"_from": "bin-version@>=0.1.0 <0.2.0",
"_npmVersion": "1.4.9",
"_npmUser": {
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
},
"maintainers": [
{
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
}
],
"dist": {
"shasum": "247aa9d410a34d07fa5e3021ac517d6439efc9c5",
"tarball": "http://registry.npmjs.org/bin-version/-/bin-version-0.1.0.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/bin-version/-/bin-version-0.1.0.tgz"
}
@@ -0,0 +1,41 @@
# bin-version [![Build Status](https://travis-ci.org/sindresorhus/bin-version.svg?branch=master)](https://travis-ci.org/sindresorhus/bin-version)
> Get the version of a binary in [semver](https://github.com/isaacs/node-semver) format
## Install
```sh
$ npm install --save bin-version
```
## Usage
```sh
$ curl --version
curl 7.30.0 (x86_64-apple-darwin13.0)
```
```js
var binVersion = require('bin-version');
binVersion('curl', function (err, version) {
if (err) {
throw err;
}
console.log(version);
//=> 7.30.0
});
```
## CLI
See the [find-versions](https://github.com/sindresorhus/find-versions#cli) CLI.
## License
MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,4 @@
language: node_js
node_js:
- "0.8"
- "0.10"
@@ -0,0 +1,18 @@
This software is released under the 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.
@@ -0,0 +1,2 @@
var argv = require('../')(process.argv.slice(2));
console.dir(argv);
@@ -0,0 +1,195 @@
module.exports = function (args, opts) {
if (!opts) opts = {};
var flags = { bools : {}, strings : {} };
[].concat(opts['boolean']).filter(Boolean).forEach(function (key) {
flags.bools[key] = true;
});
var aliases = {};
Object.keys(opts.alias || {}).forEach(function (key) {
aliases[key] = [].concat(opts.alias[key]);
aliases[key].forEach(function (x) {
aliases[x] = [key].concat(aliases[key].filter(function (y) {
return x !== y;
}));
});
});
[].concat(opts.string).filter(Boolean).forEach(function (key) {
flags.strings[key] = true;
if (aliases[key]) {
flags.strings[aliases[key]] = true;
}
});
var defaults = opts['default'] || {};
var argv = { _ : [] };
Object.keys(flags.bools).forEach(function (key) {
setArg(key, defaults[key] === undefined ? false : defaults[key]);
});
var notFlags = [];
if (args.indexOf('--') !== -1) {
notFlags = args.slice(args.indexOf('--')+1);
args = args.slice(0, args.indexOf('--'));
}
function setArg (key, val) {
var value = !flags.strings[key] && isNumber(val)
? Number(val) : val
;
setKey(argv, key.split('.'), value);
(aliases[key] || []).forEach(function (x) {
setKey(argv, x.split('.'), value);
});
}
for (var i = 0; i < args.length; i++) {
var arg = args[i];
if (/^--.+=/.test(arg)) {
// Using [\s\S] instead of . because js doesn't support the
// 'dotall' regex modifier. See:
// http://stackoverflow.com/a/1068308/13216
var m = arg.match(/^--([^=]+)=([\s\S]*)$/);
setArg(m[1], m[2]);
}
else if (/^--no-.+/.test(arg)) {
var key = arg.match(/^--no-(.+)/)[1];
setArg(key, false);
}
else if (/^--.+/.test(arg)) {
var key = arg.match(/^--(.+)/)[1];
var next = args[i + 1];
if (next !== undefined && !/^-/.test(next)
&& !flags.bools[key]
&& (aliases[key] ? !flags.bools[aliases[key]] : true)) {
setArg(key, next);
i++;
}
else if (/^(true|false)$/.test(next)) {
setArg(key, next === 'true');
i++;
}
else {
setArg(key, flags.strings[key] ? '' : true);
}
}
else if (/^-[^-]+/.test(arg)) {
var letters = arg.slice(1,-1).split('');
var broken = false;
for (var j = 0; j < letters.length; j++) {
var next = arg.slice(j+2);
if (next === '-') {
setArg(letters[j], next)
continue;
}
if (/[A-Za-z]/.test(letters[j])
&& /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
setArg(letters[j], next);
broken = true;
break;
}
if (letters[j+1] && letters[j+1].match(/\W/)) {
setArg(letters[j], arg.slice(j+2));
broken = true;
break;
}
else {
setArg(letters[j], flags.strings[letters[j]] ? '' : true);
}
}
var key = arg.slice(-1)[0];
if (!broken && key !== '-') {
if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1])
&& !flags.bools[key]
&& (aliases[key] ? !flags.bools[aliases[key]] : true)) {
setArg(key, args[i+1]);
i++;
}
else if (args[i+1] && /true|false/.test(args[i+1])) {
setArg(key, args[i+1] === 'true');
i++;
}
else {
setArg(key, flags.strings[key] ? '' : true);
}
}
}
else {
argv._.push(
flags.strings['_'] || !isNumber(arg) ? arg : Number(arg)
);
}
}
Object.keys(defaults).forEach(function (key) {
if (!hasKey(argv, key.split('.'))) {
setKey(argv, key.split('.'), defaults[key]);
(aliases[key] || []).forEach(function (x) {
setKey(argv, x.split('.'), defaults[key]);
});
}
});
if (opts['--']) {
argv['--'] = new Array();
notFlags.forEach(function(key) {
argv['--'].push(key);
});
}
else {
notFlags.forEach(function(key) {
argv._.push(key);
});
}
return argv;
};
function hasKey (obj, keys) {
var o = obj;
keys.slice(0,-1).forEach(function (key) {
o = (o[key] || {});
});
var key = keys[keys.length - 1];
return key in o;
}
function setKey (obj, keys, value) {
var o = obj;
keys.slice(0,-1).forEach(function (key) {
if (o[key] === undefined) o[key] = {};
o = o[key];
});
var key = keys[keys.length - 1];
if (o[key] === undefined || typeof o[key] === 'boolean') {
o[key] = value;
}
else if (Array.isArray(o[key])) {
o[key].push(value);
}
else {
o[key] = [ o[key], value ];
}
}
function isNumber (x) {
if (typeof x === 'number') return true;
if (/^0x[0-9a-f]+$/i.test(x)) return true;
return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
}
@@ -0,0 +1,66 @@
{
"name": "minimist",
"version": "0.1.0",
"description": "parse argument options",
"main": "index.js",
"devDependencies": {
"tape": "~1.0.4",
"tap": "~0.4.0"
},
"scripts": {
"test": "tap test/*.js"
},
"testling": {
"files": "test/*.js",
"browsers": [
"ie/6..latest",
"ff/5",
"firefox/latest",
"chrome/10",
"chrome/latest",
"safari/5.1",
"safari/latest",
"opera/12"
]
},
"repository": {
"type": "git",
"url": "git://github.com/substack/minimist.git"
},
"homepage": "https://github.com/substack/minimist",
"keywords": [
"argv",
"getopt",
"parser",
"optimist"
],
"author": {
"name": "James Halliday",
"email": "mail@substack.net",
"url": "http://substack.net"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/substack/minimist/issues"
},
"_id": "minimist@0.1.0",
"dist": {
"shasum": "99df657a52574c21c9057497df742790b2b4c0de",
"tarball": "http://registry.npmjs.org/minimist/-/minimist-0.1.0.tgz"
},
"_from": "minimist@>=0.1.0 <0.2.0",
"_npmVersion": "1.4.3",
"_npmUser": {
"name": "substack",
"email": "mail@substack.net"
},
"maintainers": [
{
"name": "substack",
"email": "mail@substack.net"
}
],
"directories": {},
"_shasum": "99df657a52574c21c9057497df742790b2b4c0de",
"_resolved": "https://registry.npmjs.org/minimist/-/minimist-0.1.0.tgz"
}
@@ -0,0 +1,84 @@
# minimist
parse argument options
This module is the guts of optimist's argument parser without all the
fanciful decoration.
[![browser support](https://ci.testling.com/substack/minimist.png)](http://ci.testling.com/substack/minimist)
[![build status](https://secure.travis-ci.org/substack/minimist.png)](http://travis-ci.org/substack/minimist)
# example
``` js
var argv = require('minimist')(process.argv.slice(2));
console.dir(argv);
```
```
$ node example/parse.js -a beep -b boop
{ _: [], a: 'beep', b: 'boop' }
```
```
$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
{ _: [ 'foo', 'bar', 'baz' ],
x: 3,
y: 4,
n: 5,
a: true,
b: true,
c: true,
beep: 'boop' }
```
# methods
``` js
var parseArgs = require('minimist')
```
## var argv = parseArgs(args, opts={})
Return an argument object `argv` populated with the array arguments from `args`.
`argv._` contains all the arguments that didn't have an option associated with
them.
Numeric-looking arguments will be returned as numbers unless `opts.string` or
`opts.boolean` is set for that argument name.
Any arguments after `'--'` will not be parsed and will end up in `argv._`.
options can be:
* `opts.string` - a string or array of strings argument names to always treat as
strings
* `opts.boolean` - a string or array of strings to always treat as booleans
* `opts.alias` - an object mapping string names to strings or arrays of string
argument names to use as aliases
* `opts.default` - an object mapping string argument names to default values
* `opts['--']` - when true, populate `argv._` with everything before the `--`
and `argv['--']` with everything after the `--`. Here's an example:
```
> require('./')('one two three -- four five --six'.split(' '), { '--': true })
{ _: [ 'one', 'two', 'three' ],
'--': [ 'four', 'five', '--six' ] }
```
Note that with `opts['--']` set, parsing for arguments still stops after the
`--`.
# install
With [npm](https://npmjs.org) do:
```
npm install minimist
```
# license
MIT
@@ -0,0 +1,119 @@
var parse = require('../');
var test = require('tape');
test('flag boolean default false', function (t) {
var argv = parse(['moo'], {
boolean: ['t', 'verbose'],
default: { verbose: false, t: false }
});
t.deepEqual(argv, {
verbose: false,
t: false,
_: ['moo']
});
t.deepEqual(typeof argv.verbose, 'boolean');
t.deepEqual(typeof argv.t, 'boolean');
t.end();
});
test('boolean groups', function (t) {
var argv = parse([ '-x', '-z', 'one', 'two', 'three' ], {
boolean: ['x','y','z']
});
t.deepEqual(argv, {
x : true,
y : false,
z : true,
_ : [ 'one', 'two', 'three' ]
});
t.deepEqual(typeof argv.x, 'boolean');
t.deepEqual(typeof argv.y, 'boolean');
t.deepEqual(typeof argv.z, 'boolean');
t.end();
});
test('boolean and alias with chainable api', function (t) {
var aliased = [ '-h', 'derp' ];
var regular = [ '--herp', 'derp' ];
var opts = {
herp: { alias: 'h', boolean: true }
};
var aliasedArgv = parse(aliased, {
boolean: 'herp',
alias: { h: 'herp' }
});
var propertyArgv = parse(regular, {
boolean: 'herp',
alias: { h: 'herp' }
});
var expected = {
herp: true,
h: true,
'_': [ 'derp' ]
};
t.same(aliasedArgv, expected);
t.same(propertyArgv, expected);
t.end();
});
test('boolean and alias with options hash', function (t) {
var aliased = [ '-h', 'derp' ];
var regular = [ '--herp', 'derp' ];
var opts = {
alias: { 'h': 'herp' },
boolean: 'herp'
};
var aliasedArgv = parse(aliased, opts);
var propertyArgv = parse(regular, opts);
var expected = {
herp: true,
h: true,
'_': [ 'derp' ]
};
t.same(aliasedArgv, expected);
t.same(propertyArgv, expected);
t.end();
});
test('boolean and alias using explicit true', function (t) {
var aliased = [ '-h', 'true' ];
var regular = [ '--herp', 'true' ];
var opts = {
alias: { h: 'herp' },
boolean: 'h'
};
var aliasedArgv = parse(aliased, opts);
var propertyArgv = parse(regular, opts);
var expected = {
herp: true,
h: true,
'_': [ ]
};
t.same(aliasedArgv, expected);
t.same(propertyArgv, expected);
t.end();
});
// regression, see https://github.com/substack/node-optimist/issues/71
test('boolean and --x=true', function(t) {
var parsed = parse(['--boool', '--other=true'], {
boolean: 'boool'
});
t.same(parsed.boool, true);
t.same(parsed.other, 'true');
parsed = parse(['--boool', '--other=false'], {
boolean: 'boool'
});
t.same(parsed.boool, true);
t.same(parsed.other, 'false');
t.end();
});
@@ -0,0 +1,31 @@
var parse = require('../');
var test = require('tape');
test('-', function (t) {
t.plan(5);
t.deepEqual(parse([ '-n', '-' ]), { n: '-', _: [] });
t.deepEqual(parse([ '-' ]), { _: [ '-' ] });
t.deepEqual(parse([ '-f-' ]), { f: '-', _: [] });
t.deepEqual(
parse([ '-b', '-' ], { boolean: 'b' }),
{ b: true, _: [ '-' ] }
);
t.deepEqual(
parse([ '-s', '-' ], { string: 's' }),
{ s: '-', _: [] }
);
});
test('-a -- b', function (t) {
t.plan(3);
t.deepEqual(parse([ '-a', '--', 'b' ]), { a: true, _: [ 'b' ] });
t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] });
t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] });
});
test('move arguments after the -- into their own `--` array', function(t) {
t.plan(1);
t.deepEqual(
parse([ '--name', 'John', 'before', '--', 'after' ], { '--': true }),
{ name: 'John', _: [ 'before' ], '--': [ 'after' ] });
});
@@ -0,0 +1,20 @@
var test = require('tape');
var parse = require('../');
test('boolean default true', function (t) {
var argv = parse([], {
boolean: 'sometrue',
default: { sometrue: true }
});
t.equal(argv.sometrue, true);
t.end();
});
test('boolean default false', function (t) {
var argv = parse([], {
boolean: 'somefalse',
default: { somefalse: false }
});
t.equal(argv.somefalse, false);
t.end();
});
@@ -0,0 +1,22 @@
var parse = require('../');
var test = require('tape');
test('dotted alias', function (t) {
var argv = parse(['--a.b', '22'], {default: {'a.b': 11}, alias: {'a.b': 'aa.bb'}});
t.equal(argv.a.b, 22);
t.equal(argv.aa.bb, 22);
t.end();
});
test('dotted default', function (t) {
var argv = parse('', {default: {'a.b': 11}, alias: {'a.b': 'aa.bb'}});
t.equal(argv.a.b, 11);
t.equal(argv.aa.bb, 11);
t.end();
});
test('dotted default with no alias', function (t) {
var argv = parse('', {default: {'a.b': 11}});
t.equal(argv.a.b, 11);
t.end();
});
@@ -0,0 +1,31 @@
var test = require('tape');
var parse = require('../');
test('long opts', function (t) {
t.deepEqual(
parse([ '--bool' ]),
{ bool : true, _ : [] },
'long boolean'
);
t.deepEqual(
parse([ '--pow', 'xixxle' ]),
{ pow : 'xixxle', _ : [] },
'long capture sp'
);
t.deepEqual(
parse([ '--pow=xixxle' ]),
{ pow : 'xixxle', _ : [] },
'long capture eq'
);
t.deepEqual(
parse([ '--host', 'localhost', '--port', '555' ]),
{ host : 'localhost', port : 555, _ : [] },
'long captures sp'
);
t.deepEqual(
parse([ '--host=localhost', '--port=555' ]),
{ host : 'localhost', port : 555, _ : [] },
'long captures eq'
);
t.end();
});
@@ -0,0 +1,36 @@
var parse = require('../');
var test = require('tape');
test('nums', function (t) {
var argv = parse([
'-x', '1234',
'-y', '5.67',
'-z', '1e7',
'-w', '10f',
'--hex', '0xdeadbeef',
'789'
]);
t.deepEqual(argv, {
x : 1234,
y : 5.67,
z : 1e7,
w : '10f',
hex : 0xdeadbeef,
_ : [ 789 ]
});
t.deepEqual(typeof argv.x, 'number');
t.deepEqual(typeof argv.y, 'number');
t.deepEqual(typeof argv.z, 'number');
t.deepEqual(typeof argv.w, 'string');
t.deepEqual(typeof argv.hex, 'number');
t.deepEqual(typeof argv._[0], 'number');
t.end();
});
test('already a number', function (t) {
var argv = parse([ '-x', 1234, 789 ]);
t.deepEqual(argv, { x : 1234, _ : [ 789 ] });
t.deepEqual(typeof argv.x, 'number');
t.deepEqual(typeof argv._[0], 'number');
t.end();
});
@@ -0,0 +1,197 @@
var parse = require('../');
var test = require('tape');
test('parse args', function (t) {
t.deepEqual(
parse([ '--no-moo' ]),
{ moo : false, _ : [] },
'no'
);
t.deepEqual(
parse([ '-v', 'a', '-v', 'b', '-v', 'c' ]),
{ v : ['a','b','c'], _ : [] },
'multi'
);
t.end();
});
test('comprehensive', function (t) {
t.deepEqual(
parse([
'--name=meowmers', 'bare', '-cats', 'woo',
'-h', 'awesome', '--multi=quux',
'--key', 'value',
'-b', '--bool', '--no-meep', '--multi=baz',
'--', '--not-a-flag', 'eek'
]),
{
c : true,
a : true,
t : true,
s : 'woo',
h : 'awesome',
b : true,
bool : true,
key : 'value',
multi : [ 'quux', 'baz' ],
meep : false,
name : 'meowmers',
_ : [ 'bare', '--not-a-flag', 'eek' ]
}
);
t.end();
});
test('flag boolean', function (t) {
var argv = parse([ '-t', 'moo' ], { boolean: 't' });
t.deepEqual(argv, { t : true, _ : [ 'moo' ] });
t.deepEqual(typeof argv.t, 'boolean');
t.end();
});
test('flag boolean value', function (t) {
var argv = parse(['--verbose', 'false', 'moo', '-t', 'true'], {
boolean: [ 't', 'verbose' ],
default: { verbose: true }
});
t.deepEqual(argv, {
verbose: false,
t: true,
_: ['moo']
});
t.deepEqual(typeof argv.verbose, 'boolean');
t.deepEqual(typeof argv.t, 'boolean');
t.end();
});
test('newlines in params' , function (t) {
var args = parse([ '-s', "X\nX" ])
t.deepEqual(args, { _ : [], s : "X\nX" });
// reproduce in bash:
// VALUE="new
// line"
// node program.js --s="$VALUE"
args = parse([ "--s=X\nX" ])
t.deepEqual(args, { _ : [], s : "X\nX" });
t.end();
});
test('strings' , function (t) {
var s = parse([ '-s', '0001234' ], { string: 's' }).s;
t.equal(s, '0001234');
t.equal(typeof s, 'string');
var x = parse([ '-x', '56' ], { string: 'x' }).x;
t.equal(x, '56');
t.equal(typeof x, 'string');
t.end();
});
test('stringArgs', function (t) {
var s = parse([ ' ', ' ' ], { string: '_' })._;
t.same(s.length, 2);
t.same(typeof s[0], 'string');
t.same(s[0], ' ');
t.same(typeof s[1], 'string');
t.same(s[1], ' ');
t.end();
});
test('empty strings', function(t) {
var s = parse([ '-s' ], { string: 's' }).s;
t.equal(s, '');
t.equal(typeof s, 'string');
var str = parse([ '--str' ], { string: 'str' }).str;
t.equal(str, '');
t.equal(typeof str, 'string');
var letters = parse([ '-art' ], {
string: [ 'a', 't' ]
});
t.equal(letters.a, '');
t.equal(letters.r, true);
t.equal(letters.t, '');
t.end();
});
test('string and alias', function(t) {
var x = parse([ '--str', '000123' ], {
string: 's',
alias: { s: 'str' }
});
t.equal(x.str, '000123');
t.equal(typeof x.str, 'string');
t.equal(x.s, '000123');
t.equal(typeof x.s, 'string');
var y = parse([ '-s', '000123' ], {
string: 'str',
alias: { str: 's' }
});
t.equal(y.str, '000123');
t.equal(typeof y.str, 'string');
t.equal(y.s, '000123');
t.equal(typeof y.s, 'string');
t.end();
});
test('slashBreak', function (t) {
t.same(
parse([ '-I/foo/bar/baz' ]),
{ I : '/foo/bar/baz', _ : [] }
);
t.same(
parse([ '-xyz/foo/bar/baz' ]),
{ x : true, y : true, z : '/foo/bar/baz', _ : [] }
);
t.end();
});
test('alias', function (t) {
var argv = parse([ '-f', '11', '--zoom', '55' ], {
alias: { z: 'zoom' }
});
t.equal(argv.zoom, 55);
t.equal(argv.z, argv.zoom);
t.equal(argv.f, 11);
t.end();
});
test('multiAlias', function (t) {
var argv = parse([ '-f', '11', '--zoom', '55' ], {
alias: { z: [ 'zm', 'zoom' ] }
});
t.equal(argv.zoom, 55);
t.equal(argv.z, argv.zoom);
t.equal(argv.z, argv.zm);
t.equal(argv.f, 11);
t.end();
});
test('nested dotted objects', function (t) {
var argv = parse([
'--foo.bar', '3', '--foo.baz', '4',
'--foo.quux.quibble', '5', '--foo.quux.o_O',
'--beep.boop'
]);
t.same(argv.foo, {
bar : 3,
baz : 4,
quux : {
quibble : 5,
o_O : true
}
});
t.same(argv.beep, { boop : true });
t.end();
});
@@ -0,0 +1,9 @@
var parse = require('../');
var test = require('tape');
test('parse with modifier functions' , function (t) {
t.plan(1);
var argv = parse([ '-b', '123' ], { boolean: 'b' });
t.deepEqual(argv, { b: true, _: ['123'] });
});
@@ -0,0 +1,67 @@
var parse = require('../');
var test = require('tape');
test('numeric short args', function (t) {
t.plan(2);
t.deepEqual(parse([ '-n123' ]), { n: 123, _: [] });
t.deepEqual(
parse([ '-123', '456' ]),
{ 1: true, 2: true, 3: 456, _: [] }
);
});
test('short', function (t) {
t.deepEqual(
parse([ '-b' ]),
{ b : true, _ : [] },
'short boolean'
);
t.deepEqual(
parse([ 'foo', 'bar', 'baz' ]),
{ _ : [ 'foo', 'bar', 'baz' ] },
'bare'
);
t.deepEqual(
parse([ '-cats' ]),
{ c : true, a : true, t : true, s : true, _ : [] },
'group'
);
t.deepEqual(
parse([ '-cats', 'meow' ]),
{ c : true, a : true, t : true, s : 'meow', _ : [] },
'short group next'
);
t.deepEqual(
parse([ '-h', 'localhost' ]),
{ h : 'localhost', _ : [] },
'short capture'
);
t.deepEqual(
parse([ '-h', 'localhost', '-p', '555' ]),
{ h : 'localhost', p : 555, _ : [] },
'short captures'
);
t.end();
});
test('mixed short bool and capture', function (t) {
t.same(
parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]),
{
f : true, p : 555, h : 'localhost',
_ : [ 'script.js' ]
}
);
t.end();
});
test('short and long', function (t) {
t.deepEqual(
parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]),
{
f : true, p : 555, h : 'localhost',
_ : [ 'script.js' ]
}
);
t.end();
});
@@ -0,0 +1,8 @@
var parse = require('../');
var test = require('tape');
test('whitespace should be whitespace' , function (t) {
t.plan(1);
var x = parse([ '-x', '\t' ]).x;
t.equal(x, '\t');
});
@@ -0,0 +1,27 @@
Copyright (c) Isaac Z. Schlueter ("Author")
All rights reserved.
The BSD License
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,24 @@
files = semver.browser.js \
semver.min.js \
semver.browser.js.gz \
semver.min.js.gz
all: $(files)
clean:
rm -f $(files)
semver.browser.js: head.js semver.js foot.js
( cat head.js; \
cat semver.js | \
egrep -v '^ *\/\* nomin \*\/' | \
perl -pi -e 's/debug\([^\)]+\)//g'; \
cat foot.js ) > semver.browser.js
semver.min.js: semver.browser.js
uglifyjs -m <semver.browser.js >semver.min.js
%.gz: %
gzip --stdout -9 <$< >$@
.PHONY: all clean
@@ -0,0 +1,158 @@
semver(1) -- The semantic versioner for npm
===========================================
## Usage
$ npm install semver
semver.valid('1.2.3') // '1.2.3'
semver.valid('a.b.c') // null
semver.clean(' =v1.2.3 ') // '1.2.3'
semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true
semver.gt('1.2.3', '9.8.7') // false
semver.lt('1.2.3', '9.8.7') // true
As a command-line utility:
$ semver -h
Usage: semver <version> [<version> [...]] [-r <range> | -i <inc> | -d <dec>]
Test if version(s) satisfy the supplied range(s), and sort them.
Multiple versions or ranges may be supplied, unless increment
or decrement options are specified. In that case, only a single
version may be used, and it is incremented by the specified level
Program exits successfully if any valid version satisfies
all supplied ranges, and prints all satisfying versions.
If no versions are valid, or ranges are not satisfied,
then exits failure.
Versions are printed in ascending order, so supplying
multiple versions to the utility will just sort them.
## Versions
A "version" is described by the `v2.0.0` specification found at
<http://semver.org/>.
A leading `"="` or `"v"` character is stripped off and ignored.
## Ranges
The following range styles are supported:
* `1.2.3` A specific version. When nothing else will do. Must be a full
version number, with major, minor, and patch versions specified.
Note that build metadata is still ignored, so `1.2.3+build2012` will
satisfy this range.
* `>1.2.3` Greater than a specific version.
* `<1.2.3` Less than a specific version. If there is no prerelease
tag on the version range, then no prerelease version will be allowed
either, even though these are technically "less than".
* `>=1.2.3` Greater than or equal to. Note that prerelease versions
are NOT equal to their "normal" equivalents, so `1.2.3-beta` will
not satisfy this range, but `2.3.0-beta` will.
* `<=1.2.3` Less than or equal to. In this case, prerelease versions
ARE allowed, so `1.2.3-beta` would satisfy.
* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4`
* `~1.2.3` := `>=1.2.3-0 <1.3.0-0` "Reasonably close to `1.2.3`". When
using tilde operators, prerelease versions are supported as well,
but a prerelease of the next significant digit will NOT be
satisfactory, so `1.3.0-beta` will not satisfy `~1.2.3`.
* `^1.2.3` := `>=1.2.3-0 <2.0.0-0` "Compatible with `1.2.3`". When
using caret operators, anything from the specified version (including
prerelease) will be supported up to, but not including, the next
major version (or its prereleases). `1.5.1` will satisfy `^1.2.3`,
while `1.2.2` and `2.0.0-beta` will not.
* `^0.1.3` := `>=0.1.3-0 <0.2.0-0` "Compatible with `0.1.3`". `0.x.x` versions are
special: the first non-zero component indicates potentially breaking changes,
meaning the caret operator matches any version with the same first non-zero
component starting at the specified version.
* `^0.0.2` := `=0.0.2` "Only the version `0.0.2` is considered compatible"
* `~1.2` := `>=1.2.0-0 <1.3.0-0` "Any version starting with `1.2`"
* `^1.2` := `>=1.2.0-0 <2.0.0-0` "Any version compatible with `1.2`"
* `1.2.x` := `>=1.2.0-0 <1.3.0-0` "Any version starting with `1.2`"
* `1.2.*` Same as `1.2.x`.
* `1.2` Same as `1.2.x`.
* `~1` := `>=1.0.0-0 <2.0.0-0` "Any version starting with `1`"
* `^1` := `>=1.0.0-0 <2.0.0-0` "Any version compatible with `1`"
* `1.x` := `>=1.0.0-0 <2.0.0-0` "Any version starting with `1`"
* `1.*` Same as `1.x`.
* `1` Same as `1.x`.
* `*` Any version whatsoever.
* `x` Same as `*`.
* `""` (just an empty string) Same as `*`.
Ranges can be joined with either a space (which implies "and") or a
`||` (which implies "or").
## Functions
All methods and classes take a final `loose` boolean argument that, if
true, will be more forgiving about not-quite-valid semver strings.
The resulting output will always be 100% strict, of course.
Strict-mode Comparators and Ranges will be strict about the SemVer
strings that they parse.
* `valid(v)`: Return the parsed version, or null if it's not valid.
* `inc(v, release)`: Return the version incremented by the release
type (`major`, `premajor`, `minor`, `preminor`, `patch`,
`prepatch`, or `prerelease`), or null if it's not valid
* `premajor` in one call will bump the version up to the next major
version and down to a prerelease of that major version.
`preminor`, and `prepatch` work the same way.
* If called from a non-prerelease version, the `prerelease` will work the
same as `prepatch`. It increments the patch version, then makes a
prerelease. If the input version is already a prerelease it simply
increments it.
### Comparison
* `gt(v1, v2)`: `v1 > v2`
* `gte(v1, v2)`: `v1 >= v2`
* `lt(v1, v2)`: `v1 < v2`
* `lte(v1, v2)`: `v1 <= v2`
* `eq(v1, v2)`: `v1 == v2` This is true if they're logically equivalent,
even if they're not the exact same string. You already know how to
compare strings.
* `neq(v1, v2)`: `v1 != v2` The opposite of `eq`.
* `cmp(v1, comparator, v2)`: Pass in a comparison string, and it'll call
the corresponding function above. `"==="` and `"!=="` do simple
string comparison, but are included for completeness. Throws if an
invalid comparison string is provided.
* `compare(v1, v2)`: Return `0` if `v1 == v2`, or `1` if `v1` is greater, or `-1` if
`v2` is greater. Sorts in ascending order if passed to `Array.sort()`.
* `rcompare(v1, v2)`: The reverse of compare. Sorts an array of versions
in descending order when passed to `Array.sort()`.
### Ranges
* `validRange(range)`: Return the valid range or null if it's not valid
* `satisfies(version, range)`: Return true if the version satisfies the
range.
* `maxSatisfying(versions, range)`: Return the highest version in the list
that satisfies the range, or `null` if none of them do.
* `gtr(version, range)`: Return `true` if version is greater than all the
versions possible in the range.
* `ltr(version, range)`: Return `true` if version is less than all the
versions possible in the range.
* `outside(version, range, hilo)`: Return true if the version is outside
the bounds of the range in either the high or low direction. The
`hilo` argument must be either the string `'>'` or `'<'`. (This is
the function called by `gtr` and `ltr`.)
Note that, since ranges may be non-contiguous, a version might not be
greater than a range, less than a range, *or* satisfy a range! For
example, the range `1.2 <1.2.9 || >2.0.0` would have a hole from `1.2.9`
until `2.0.0`, so the version `1.2.10` would not be greater than the
range (because `2.0.1` satisfies, which is higher), nor less than the
range (since `1.2.8` satisfies, which is lower), and it also does not
satisfy the range.
If you want to know if a version satisfies or does not satisfy a
range, use the `satisfies(version, range)` function.
@@ -0,0 +1,125 @@
#!/usr/bin/env node
// Standalone semver comparison program.
// Exits successfully and prints matching version(s) if
// any supplied version is valid and passes all tests.
var argv = process.argv.slice(2)
, versions = []
, range = []
, gt = []
, lt = []
, eq = []
, inc = null
, version = require("../package.json").version
, loose = false
, semver = require("../semver")
, reverse = false
main()
function main () {
if (!argv.length) return help()
while (argv.length) {
var a = argv.shift()
var i = a.indexOf('=')
if (i !== -1) {
a = a.slice(0, i)
argv.unshift(a.slice(i + 1))
}
switch (a) {
case "-rv": case "-rev": case "--rev": case "--reverse":
reverse = true
break
case "-l": case "--loose":
loose = true
break
case "-v": case "--version":
versions.push(argv.shift())
break
case "-i": case "--inc": case "--increment":
switch (argv[0]) {
case "major": case "minor": case "patch": case "prerelease":
case "premajor": case "preminor": case "prepatch":
inc = argv.shift()
break
default:
inc = "patch"
break
}
break
case "-r": case "--range":
range.push(argv.shift())
break
case "-h": case "--help": case "-?":
return help()
default:
versions.push(a)
break
}
}
versions = versions.filter(function (v) {
return semver.valid(v, loose)
})
if (!versions.length) return fail()
if (inc && (versions.length !== 1 || range.length))
return failInc()
for (var i = 0, l = range.length; i < l ; i ++) {
versions = versions.filter(function (v) {
return semver.satisfies(v, range[i], loose)
})
if (!versions.length) return fail()
}
return success(versions)
}
function failInc () {
console.error("--inc can only be used on a single version with no range")
fail()
}
function fail () { process.exit(1) }
function success () {
var compare = reverse ? "rcompare" : "compare"
versions.sort(function (a, b) {
return semver[compare](a, b, loose)
}).map(function (v) {
return semver.clean(v, loose)
}).map(function (v) {
return inc ? semver.inc(v, inc, loose) : v
}).forEach(function (v,i,_) { console.log(v) })
}
function help () {
console.log(["SemVer " + version
,""
,"A JavaScript implementation of the http://semver.org/ specification"
,"Copyright Isaac Z. Schlueter"
,""
,"Usage: semver [options] <version> [<version> [...]]"
,"Prints valid versions sorted by SemVer precedence"
,""
,"Options:"
,"-r --range <range>"
," Print versions that match the specified range."
,""
,"-i --increment [<level>]"
," Increment a version by the specified level. Level can"
," be one of: major, minor, patch, premajor, preminor,"
," prepatch, or prerelease. Default level is 'patch'."
," Only one version may be specified."
,""
,"-l --loose"
," Interpret versions and ranges loosely"
,""
,"Program exits successfully if any valid version satisfies"
,"all supplied ranges, and prints all satisfying versions."
,""
,"If no satisfying versions are found, then exits failure."
,""
,"Versions are printed in ascending order, so supplying"
,"multiple versions to the utility will just sort them."
].join("\n"))
}
@@ -0,0 +1,6 @@
})(
typeof exports === 'object' ? exports :
typeof define === 'function' && define.amd ? {} :
semver = {}
);
@@ -0,0 +1,2 @@
;(function(exports) {
@@ -0,0 +1,50 @@
{
"name": "semver",
"version": "2.3.2",
"description": "The semantic version parser used by npm.",
"main": "semver.js",
"browser": "semver.browser.js",
"min": "semver.min.js",
"scripts": {
"test": "tap test/*.js",
"prepublish": "make"
},
"devDependencies": {
"tap": "0.x >=0.0.4",
"uglify-js": "~2.3.6"
},
"license": "BSD",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/node-semver.git"
},
"bin": {
"semver": "./bin/semver"
},
"gitHead": "87bcf749b18fd0ce32b1808f60a98eacecd84689",
"bugs": {
"url": "https://github.com/isaacs/node-semver/issues"
},
"homepage": "https://github.com/isaacs/node-semver",
"_id": "semver@2.3.2",
"_shasum": "b9848f25d6cf36333073ec9ef8856d42f1233e52",
"_from": "semver@>=2.3.0 <3.0.0",
"_npmVersion": "1.5.0-alpha-4",
"_npmUser": {
"name": "isaacs",
"email": "i@izs.me"
},
"maintainers": [
{
"name": "isaacs",
"email": "i@izs.me"
}
],
"dist": {
"shasum": "b9848f25d6cf36333073ec9ef8856d42f1233e52",
"tarball": "http://registry.npmjs.org/semver/-/semver-2.3.2.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/semver/-/semver-2.3.2.tgz",
"readme": "ERROR: No README data found!"
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,15 @@
var tap = require('tap');
var test = tap.test;
test('amd', function(t) {
global.define = define;
define.amd = true;
var defined = null;
function define(stuff) {
defined = stuff;
}
var fromRequire = require('../');
t.ok(defined, 'amd function called');
t.equal(fromRequire, defined, 'amd stuff same as require stuff');
t.end();
});
@@ -0,0 +1,173 @@
var tap = require('tap');
var test = tap.test;
var semver = require('../semver.js');
var gtr = semver.gtr;
test('\ngtr tests', function(t) {
// [range, version, loose]
// Version should be greater than range
[
['~1.2.2', '1.3.0'],
['~0.6.1-1', '0.7.1-1'],
['1.0.0 - 2.0.0', '2.0.1'],
['1.0.0', '1.0.1-beta1'],
['1.0.0', '2.0.0'],
['<=2.0.0', '2.1.1'],
['<=2.0.0', '3.2.9'],
['<2.0.0', '2.0.0'],
['0.1.20 || 1.2.4', '1.2.5'],
['2.x.x', '3.0.0'],
['1.2.x', '1.3.0'],
['1.2.x || 2.x', '3.0.0'],
['2.*.*', '5.0.1'],
['1.2.*', '1.3.3'],
['1.2.* || 2.*', '4.0.0'],
['2', '3.0.0'],
['2.3', '2.4.2'],
['~2.4', '2.5.0'], // >=2.4.0 <2.5.0
['~2.4', '2.5.5'],
['~>3.2.1', '3.3.0'], // >=3.2.1 <3.3.0
['~1', '2.2.3'], // >=1.0.0 <2.0.0
['~>1', '2.2.4'],
['~> 1', '3.2.3'],
['~1.0', '1.1.2'], // >=1.0.0 <1.1.0
['~ 1.0', '1.1.0'],
['<1.2', '1.2.0'],
['< 1.2', '1.2.1'],
['1', '2.0.0beta', true],
['~v0.5.4-pre', '0.6.0'],
['~v0.5.4-pre', '0.6.1-pre'],
['=0.7.x', '0.8.0'],
['=0.7.x', '0.8.0-asdf'],
['<=0.7.x', '0.7.0'],
['~1.2.2', '1.3.0'],
['1.0.0 - 2.0.0', '2.2.3'],
['1.0.0', '1.0.1'],
['<=2.0.0', '3.0.0'],
['<=2.0.0', '2.9999.9999'],
['<=2.0.0', '2.2.9'],
['<2.0.0', '2.9999.9999'],
['<2.0.0', '2.2.9'],
['2.x.x', '3.1.3'],
['1.2.x', '1.3.3'],
['1.2.x || 2.x', '3.1.3'],
['2.*.*', '3.1.3'],
['1.2.*', '1.3.3'],
['1.2.* || 2.*', '3.1.3'],
['2', '3.1.2'],
['2.3', '2.4.1'],
['~2.4', '2.5.0'], // >=2.4.0 <2.5.0
['~>3.2.1', '3.3.2'], // >=3.2.1 <3.3.0
['~1', '2.2.3'], // >=1.0.0 <2.0.0
['~>1', '2.2.3'],
['~1.0', '1.1.0'], // >=1.0.0 <1.1.0
['<1', '1.0.0'],
['1', '2.0.0beta', true],
['<1', '1.0.0beta', true],
['< 1', '1.0.0beta', true],
['=0.7.x', '0.8.2'],
['<=0.7.x', '0.7.2']
].forEach(function(tuple) {
var range = tuple[0];
var version = tuple[1];
var loose = tuple[2] || false;
var msg = 'gtr(' + version + ', ' + range + ', ' + loose + ')';
t.ok(gtr(version, range, loose), msg);
});
t.end();
});
test('\nnegative gtr tests', function(t) {
// [range, version, loose]
// Version should NOT be greater than range
[
['~0.6.1-1', '0.6.1-1'],
['1.0.0 - 2.0.0', '1.2.3'],
['1.0.0 - 2.0.0', '0.9.9'],
['1.0.0', '1.0.0'],
['>=*', '0.2.4'],
['', '1.0.0', true],
['*', '1.2.3'],
['*', 'v1.2.3-foo'],
['>=1.0.0', '1.0.0'],
['>=1.0.0', '1.0.1'],
['>=1.0.0', '1.1.0'],
['>1.0.0', '1.0.1'],
['>1.0.0', '1.1.0'],
['<=2.0.0', '2.0.0'],
['<=2.0.0', '1.9999.9999'],
['<=2.0.0', '0.2.9'],
['<2.0.0', '1.9999.9999'],
['<2.0.0', '0.2.9'],
['>= 1.0.0', '1.0.0'],
['>= 1.0.0', '1.0.1'],
['>= 1.0.0', '1.1.0'],
['> 1.0.0', '1.0.1'],
['> 1.0.0', '1.1.0'],
['<= 2.0.0', '2.0.0'],
['<= 2.0.0', '1.9999.9999'],
['<= 2.0.0', '0.2.9'],
['< 2.0.0', '1.9999.9999'],
['<\t2.0.0', '0.2.9'],
['>=0.1.97', 'v0.1.97'],
['>=0.1.97', '0.1.97'],
['0.1.20 || 1.2.4', '1.2.4'],
['0.1.20 || >1.2.4', '1.2.4'],
['0.1.20 || 1.2.4', '1.2.3'],
['0.1.20 || 1.2.4', '0.1.20'],
['>=0.2.3 || <0.0.1', '0.0.0'],
['>=0.2.3 || <0.0.1', '0.2.3'],
['>=0.2.3 || <0.0.1', '0.2.4'],
['||', '1.3.4'],
['2.x.x', '2.1.3'],
['1.2.x', '1.2.3'],
['1.2.x || 2.x', '2.1.3'],
['1.2.x || 2.x', '1.2.3'],
['x', '1.2.3'],
['2.*.*', '2.1.3'],
['1.2.*', '1.2.3'],
['1.2.* || 2.*', '2.1.3'],
['1.2.* || 2.*', '1.2.3'],
['1.2.* || 2.*', '1.2.3'],
['*', '1.2.3'],
['2', '2.1.2'],
['2.3', '2.3.1'],
['~2.4', '2.4.0'], // >=2.4.0 <2.5.0
['~2.4', '2.4.5'],
['~>3.2.1', '3.2.2'], // >=3.2.1 <3.3.0
['~1', '1.2.3'], // >=1.0.0 <2.0.0
['~>1', '1.2.3'],
['~> 1', '1.2.3'],
['~1.0', '1.0.2'], // >=1.0.0 <1.1.0
['~ 1.0', '1.0.2'],
['>=1', '1.0.0'],
['>= 1', '1.0.0'],
['<1.2', '1.1.1'],
['< 1.2', '1.1.1'],
['1', '1.0.0beta', true],
['~v0.5.4-pre', '0.5.5'],
['~v0.5.4-pre', '0.5.4'],
['=0.7.x', '0.7.2'],
['>=0.7.x', '0.7.2'],
['=0.7.x', '0.7.0-asdf'],
['>=0.7.x', '0.7.0-asdf'],
['<=0.7.x', '0.6.2'],
['>0.2.3 >0.2.4 <=0.2.5', '0.2.5'],
['>=0.2.3 <=0.2.4', '0.2.4'],
['1.0.0 - 2.0.0', '2.0.0'],
['^1', '0.0.0-0'],
['^3.0.0', '2.0.0'],
['^1.0.0 || ~2.0.1', '2.0.0'],
['^0.1.0 || ~3.0.1 || 5.0.0', '3.2.0'],
['^0.1.0 || ~3.0.1 || 5.0.0', '1.0.0beta', true],
['^0.1.0 || ~3.0.1 || 5.0.0', '5.0.0-0', true],
['^0.1.0 || ~3.0.1 || >4 <=5.0.0', '3.5.0']
].forEach(function(tuple) {
var range = tuple[0];
var version = tuple[1];
var loose = tuple[2] || false;
var msg = '!gtr(' + version + ', ' + range + ', ' + loose + ')';
t.notOk(gtr(version, range, loose), msg);
});
t.end();
});
@@ -0,0 +1,588 @@
'use strict';
var tap = require('tap');
var test = tap.test;
var semver = require('../semver.js');
var eq = semver.eq;
var gt = semver.gt;
var lt = semver.lt;
var neq = semver.neq;
var cmp = semver.cmp;
var gte = semver.gte;
var lte = semver.lte;
var satisfies = semver.satisfies;
var validRange = semver.validRange;
var inc = semver.inc;
var replaceStars = semver.replaceStars;
var toComparators = semver.toComparators;
var SemVer = semver.SemVer;
var Range = semver.Range;
test('\ncomparison tests', function(t) {
// [version1, version2]
// version1 should be greater than version2
[['0.0.0', '0.0.0-foo'],
['0.0.1', '0.0.0'],
['1.0.0', '0.9.9'],
['0.10.0', '0.9.0'],
['0.99.0', '0.10.0'],
['2.0.0', '1.2.3'],
['v0.0.0', '0.0.0-foo', true],
['v0.0.1', '0.0.0', true],
['v1.0.0', '0.9.9', true],
['v0.10.0', '0.9.0', true],
['v0.99.0', '0.10.0', true],
['v2.0.0', '1.2.3', true],
['0.0.0', 'v0.0.0-foo', true],
['0.0.1', 'v0.0.0', true],
['1.0.0', 'v0.9.9', true],
['0.10.0', 'v0.9.0', true],
['0.99.0', 'v0.10.0', true],
['2.0.0', 'v1.2.3', true],
['1.2.3', '1.2.3-asdf'],
['1.2.3', '1.2.3-4'],
['1.2.3', '1.2.3-4-foo'],
['1.2.3-5-foo', '1.2.3-5'],
['1.2.3-5', '1.2.3-4'],
['1.2.3-5-foo', '1.2.3-5-Foo'],
['3.0.0', '2.7.2+asdf'],
['1.2.3-a.10', '1.2.3-a.5'],
['1.2.3-a.b', '1.2.3-a.5'],
['1.2.3-a.b', '1.2.3-a'],
['1.2.3-a.b.c.10.d.5', '1.2.3-a.b.c.5.d.100']
].forEach(function(v) {
var v0 = v[0];
var v1 = v[1];
var loose = v[2];
t.ok(gt(v0, v1, loose), "gt('" + v0 + "', '" + v1 + "')");
t.ok(lt(v1, v0, loose), "lt('" + v1 + "', '" + v0 + "')");
t.ok(!gt(v1, v0, loose), "!gt('" + v1 + "', '" + v0 + "')");
t.ok(!lt(v0, v1, loose), "!lt('" + v0 + "', '" + v1 + "')");
t.ok(eq(v0, v0, loose), "eq('" + v0 + "', '" + v0 + "')");
t.ok(eq(v1, v1, loose), "eq('" + v1 + "', '" + v1 + "')");
t.ok(neq(v0, v1, loose), "neq('" + v0 + "', '" + v1 + "')");
t.ok(cmp(v1, '==', v1, loose), "cmp('" + v1 + "' == '" + v1 + "')");
t.ok(cmp(v0, '>=', v1, loose), "cmp('" + v0 + "' >= '" + v1 + "')");
t.ok(cmp(v1, '<=', v0, loose), "cmp('" + v1 + "' <= '" + v0 + "')");
t.ok(cmp(v0, '!=', v1, loose), "cmp('" + v0 + "' != '" + v1 + "')");
});
t.end();
});
test('\nequality tests', function(t) {
// [version1, version2]
// version1 should be equivalent to version2
[['1.2.3', 'v1.2.3', true],
['1.2.3', '=1.2.3', true],
['1.2.3', 'v 1.2.3', true],
['1.2.3', '= 1.2.3', true],
['1.2.3', ' v1.2.3', true],
['1.2.3', ' =1.2.3', true],
['1.2.3', ' v 1.2.3', true],
['1.2.3', ' = 1.2.3', true],
['1.2.3-0', 'v1.2.3-0', true],
['1.2.3-0', '=1.2.3-0', true],
['1.2.3-0', 'v 1.2.3-0', true],
['1.2.3-0', '= 1.2.3-0', true],
['1.2.3-0', ' v1.2.3-0', true],
['1.2.3-0', ' =1.2.3-0', true],
['1.2.3-0', ' v 1.2.3-0', true],
['1.2.3-0', ' = 1.2.3-0', true],
['1.2.3-1', 'v1.2.3-1', true],
['1.2.3-1', '=1.2.3-1', true],
['1.2.3-1', 'v 1.2.3-1', true],
['1.2.3-1', '= 1.2.3-1', true],
['1.2.3-1', ' v1.2.3-1', true],
['1.2.3-1', ' =1.2.3-1', true],
['1.2.3-1', ' v 1.2.3-1', true],
['1.2.3-1', ' = 1.2.3-1', true],
['1.2.3-beta', 'v1.2.3-beta', true],
['1.2.3-beta', '=1.2.3-beta', true],
['1.2.3-beta', 'v 1.2.3-beta', true],
['1.2.3-beta', '= 1.2.3-beta', true],
['1.2.3-beta', ' v1.2.3-beta', true],
['1.2.3-beta', ' =1.2.3-beta', true],
['1.2.3-beta', ' v 1.2.3-beta', true],
['1.2.3-beta', ' = 1.2.3-beta', true],
['1.2.3-beta+build', ' = 1.2.3-beta+otherbuild', true],
['1.2.3+build', ' = 1.2.3+otherbuild', true],
['1.2.3-beta+build', '1.2.3-beta+otherbuild'],
['1.2.3+build', '1.2.3+otherbuild'],
[' v1.2.3+build', '1.2.3+otherbuild']
].forEach(function(v) {
var v0 = v[0];
var v1 = v[1];
var loose = v[2];
t.ok(eq(v0, v1, loose), "eq('" + v0 + "', '" + v1 + "')");
t.ok(!neq(v0, v1, loose), "!neq('" + v0 + "', '" + v1 + "')");
t.ok(cmp(v0, '==', v1, loose), 'cmp(' + v0 + '==' + v1 + ')');
t.ok(!cmp(v0, '!=', v1, loose), '!cmp(' + v0 + '!=' + v1 + ')');
t.ok(!cmp(v0, '===', v1, loose), '!cmp(' + v0 + '===' + v1 + ')');
t.ok(cmp(v0, '!==', v1, loose), 'cmp(' + v0 + '!==' + v1 + ')');
t.ok(!gt(v0, v1, loose), "!gt('" + v0 + "', '" + v1 + "')");
t.ok(gte(v0, v1, loose), "gte('" + v0 + "', '" + v1 + "')");
t.ok(!lt(v0, v1, loose), "!lt('" + v0 + "', '" + v1 + "')");
t.ok(lte(v0, v1, loose), "lte('" + v0 + "', '" + v1 + "')");
});
t.end();
});
test('\nrange tests', function(t) {
// [range, version]
// version should be included by range
[['1.0.0 - 2.0.0', '1.2.3'],
['1.0.0', '1.0.0'],
['>=*', '0.2.4'],
['', '1.0.0'],
['*', '1.2.3'],
['*', 'v1.2.3-foo', true],
['>=1.0.0', '1.0.0'],
['>=1.0.0', '1.0.1'],
['>=1.0.0', '1.1.0'],
['>1.0.0', '1.0.1'],
['>1.0.0', '1.1.0'],
['<=2.0.0', '2.0.0'],
['<=2.0.0', '1.9999.9999'],
['<=2.0.0', '0.2.9'],
['<2.0.0', '1.9999.9999'],
['<2.0.0', '0.2.9'],
['>= 1.0.0', '1.0.0'],
['>= 1.0.0', '1.0.1'],
['>= 1.0.0', '1.1.0'],
['> 1.0.0', '1.0.1'],
['> 1.0.0', '1.1.0'],
['<= 2.0.0', '2.0.0'],
['<= 2.0.0', '1.9999.9999'],
['<= 2.0.0', '0.2.9'],
['< 2.0.0', '1.9999.9999'],
['<\t2.0.0', '0.2.9'],
['>=0.1.97', 'v0.1.97', true],
['>=0.1.97', '0.1.97'],
['0.1.20 || 1.2.4', '1.2.4'],
['>=0.2.3 || <0.0.1', '0.0.0'],
['>=0.2.3 || <0.0.1', '0.2.3'],
['>=0.2.3 || <0.0.1', '0.2.4'],
['||', '1.3.4'],
['2.x.x', '2.1.3'],
['1.2.x', '1.2.3'],
['1.2.x || 2.x', '2.1.3'],
['1.2.x || 2.x', '1.2.3'],
['x', '1.2.3'],
['2.*.*', '2.1.3'],
['1.2.*', '1.2.3'],
['1.2.* || 2.*', '2.1.3'],
['1.2.* || 2.*', '1.2.3'],
['*', '1.2.3'],
['2', '2.1.2'],
['2.3', '2.3.1'],
['~2.4', '2.4.0'], // >=2.4.0 <2.5.0
['~2.4', '2.4.5'],
['~>3.2.1', '3.2.2'], // >=3.2.1 <3.3.0,
['~1', '1.2.3'], // >=1.0.0 <2.0.0
['~>1', '1.2.3'],
['~> 1', '1.2.3'],
['~1.0', '1.0.2'], // >=1.0.0 <1.1.0,
['~ 1.0', '1.0.2'],
['~ 1.0.3', '1.0.12'],
['>=1', '1.0.0'],
['>= 1', '1.0.0'],
['<1.2', '1.1.1'],
['< 1.2', '1.1.1'],
['1', '1.0.0beta', true],
['~v0.5.4-pre', '0.5.5'],
['~v0.5.4-pre', '0.5.4'],
['=0.7.x', '0.7.2'],
['>=0.7.x', '0.7.2'],
['=0.7.x', '0.7.0-asdf'],
['>=0.7.x', '0.7.0-asdf'],
['<=0.7.x', '0.6.2'],
['~1.2.1 >=1.2.3', '1.2.3'],
['~1.2.1 =1.2.3', '1.2.3'],
['~1.2.1 1.2.3', '1.2.3'],
['~1.2.1 >=1.2.3 1.2.3', '1.2.3'],
['~1.2.1 1.2.3 >=1.2.3', '1.2.3'],
['~1.2.1 1.2.3', '1.2.3'],
['>=1.2.1 1.2.3', '1.2.3'],
['1.2.3 >=1.2.1', '1.2.3'],
['>=1.2.3 >=1.2.1', '1.2.3'],
['>=1.2.1 >=1.2.3', '1.2.3'],
['<=1.2.3', '1.2.3-beta'],
['>1.2', '1.3.0-beta'],
['>=1.2', '1.2.8'],
['^1.2.3', '1.8.1'],
['^1.2.3', '1.2.3-beta'],
['^0.1.2', '0.1.2'],
['^0.1', '0.1.2'],
['^1.2', '1.4.2'],
['^1.2 ^1', '1.4.2'],
['^1.2', '1.2.0-pre'],
['^1.2.3', '1.2.3-pre']
].forEach(function(v) {
var range = v[0];
var ver = v[1];
var loose = v[2];
t.ok(satisfies(ver, range, loose), range + ' satisfied by ' + ver);
});
t.end();
});
test('\nnegative range tests', function(t) {
// [range, version]
// version should not be included by range
[['1.0.0 - 2.0.0', '2.2.3'],
['1.0.0', '1.0.1'],
['>=1.0.0', '0.0.0'],
['>=1.0.0', '0.0.1'],
['>=1.0.0', '0.1.0'],
['>1.0.0', '0.0.1'],
['>1.0.0', '0.1.0'],
['<=2.0.0', '3.0.0'],
['<=2.0.0', '2.9999.9999'],
['<=2.0.0', '2.2.9'],
['<2.0.0', '2.9999.9999'],
['<2.0.0', '2.2.9'],
['>=0.1.97', 'v0.1.93', true],
['>=0.1.97', '0.1.93'],
['0.1.20 || 1.2.4', '1.2.3'],
['>=0.2.3 || <0.0.1', '0.0.3'],
['>=0.2.3 || <0.0.1', '0.2.2'],
['2.x.x', '1.1.3'],
['2.x.x', '3.1.3'],
['1.2.x', '1.3.3'],
['1.2.x || 2.x', '3.1.3'],
['1.2.x || 2.x', '1.1.3'],
['2.*.*', '1.1.3'],
['2.*.*', '3.1.3'],
['1.2.*', '1.3.3'],
['1.2.* || 2.*', '3.1.3'],
['1.2.* || 2.*', '1.1.3'],
['2', '1.1.2'],
['2.3', '2.4.1'],
['~2.4', '2.5.0'], // >=2.4.0 <2.5.0
['~2.4', '2.3.9'],
['~>3.2.1', '3.3.2'], // >=3.2.1 <3.3.0
['~>3.2.1', '3.2.0'], // >=3.2.1 <3.3.0
['~1', '0.2.3'], // >=1.0.0 <2.0.0
['~>1', '2.2.3'],
['~1.0', '1.1.0'], // >=1.0.0 <1.1.0
['<1', '1.0.0'],
['>=1.2', '1.1.1'],
['1', '2.0.0beta', true],
['~v0.5.4-beta', '0.5.4-alpha'],
['<1', '1.0.0beta', true],
['< 1', '1.0.0beta', true],
['=0.7.x', '0.8.2'],
['>=0.7.x', '0.6.2'],
['<=0.7.x', '0.7.2'],
['<1.2.3', '1.2.3-beta'],
['=1.2.3', '1.2.3-beta'],
['>1.2', '1.2.8'],
['^1.2.3', '2.0.0-alpha'],
['^1.2.3', '1.2.2'],
['^1.2', '1.1.9'],
// invalid ranges never satisfied!
['blerg', '1.2.3'],
['git+https://user:password0123@github.com/foo', '123.0.0', true],
['^1.2.3', '2.0.0-pre']
].forEach(function(v) {
var range = v[0];
var ver = v[1];
var loose = v[2];
var found = satisfies(ver, range, loose);
t.ok(!found, ver + ' not satisfied by ' + range);
});
t.end();
});
test('\nincrement versions test', function(t) {
// [version, inc, result]
// inc(version, inc) -> result
[['1.2.3', 'major', '2.0.0'],
['1.2.3', 'minor', '1.3.0'],
['1.2.3', 'patch', '1.2.4'],
['1.2.3tag', 'major', '2.0.0', true],
['1.2.3-tag', 'major', '2.0.0'],
['1.2.3', 'fake', null],
['1.2.0-0', 'patch', '1.2.0'],
['fake', 'major', null],
['1.2.3-4', 'major', '2.0.0'],
['1.2.3-4', 'minor', '1.3.0'],
['1.2.3-4', 'patch', '1.2.3'],
['1.2.3-alpha.0.beta', 'major', '2.0.0'],
['1.2.3-alpha.0.beta', 'minor', '1.3.0'],
['1.2.3-alpha.0.beta', 'patch', '1.2.3'],
['1.2.4', 'prerelease', '1.2.5-0'],
['1.2.3-0', 'prerelease', '1.2.3-1'],
['1.2.3-alpha.0', 'prerelease', '1.2.3-alpha.1'],
['1.2.3-alpha.1', 'prerelease', '1.2.3-alpha.2'],
['1.2.3-alpha.2', 'prerelease', '1.2.3-alpha.3'],
['1.2.3-alpha.0.beta', 'prerelease', '1.2.3-alpha.1.beta'],
['1.2.3-alpha.1.beta', 'prerelease', '1.2.3-alpha.2.beta'],
['1.2.3-alpha.2.beta', 'prerelease', '1.2.3-alpha.3.beta'],
['1.2.3-alpha.10.0.beta', 'prerelease', '1.2.3-alpha.10.1.beta'],
['1.2.3-alpha.10.1.beta', 'prerelease', '1.2.3-alpha.10.2.beta'],
['1.2.3-alpha.10.2.beta', 'prerelease', '1.2.3-alpha.10.3.beta'],
['1.2.3-alpha.10.beta.0', 'prerelease', '1.2.3-alpha.10.beta.1'],
['1.2.3-alpha.10.beta.1', 'prerelease', '1.2.3-alpha.10.beta.2'],
['1.2.3-alpha.10.beta.2', 'prerelease', '1.2.3-alpha.10.beta.3'],
['1.2.3-alpha.9.beta', 'prerelease', '1.2.3-alpha.10.beta'],
['1.2.3-alpha.10.beta', 'prerelease', '1.2.3-alpha.11.beta'],
['1.2.3-alpha.11.beta', 'prerelease', '1.2.3-alpha.12.beta'],
['1.2.0', 'prepatch', '1.2.1-0'],
['1.2.0-1', 'prepatch', '1.2.1-0'],
['1.2.0', 'preminor', '1.3.0-0'],
['1.2.0-1', 'preminor', '1.3.0-0'],
['1.2.0', 'premajor', '2.0.0-0'],
['1.2.0-1', 'premajor', '2.0.0-0']
].forEach(function(v) {
var pre = v[0];
var what = v[1];
var wanted = v[2];
var loose = v[3];
var found = inc(pre, what, loose);
t.equal(found, wanted, 'inc(' + pre + ', ' + what + ') === ' + wanted);
});
t.end();
});
test('\nvalid range test', function(t) {
// [range, result]
// validRange(range) -> result
// translate ranges into their canonical form
[['1.0.0 - 2.0.0', '>=1.0.0 <=2.0.0'],
['1.0.0', '1.0.0'],
['>=*', '>=0.0.0-0'],
['', '*'],
['*', '*'],
['*', '*'],
['>=1.0.0', '>=1.0.0'],
['>1.0.0', '>1.0.0'],
['<=2.0.0', '<=2.0.0'],
['1', '>=1.0.0-0 <2.0.0-0'],
['<=2.0.0', '<=2.0.0'],
['<=2.0.0', '<=2.0.0'],
['<2.0.0', '<2.0.0-0'],
['<2.0.0', '<2.0.0-0'],
['>= 1.0.0', '>=1.0.0'],
['>= 1.0.0', '>=1.0.0'],
['>= 1.0.0', '>=1.0.0'],
['> 1.0.0', '>1.0.0'],
['> 1.0.0', '>1.0.0'],
['<= 2.0.0', '<=2.0.0'],
['<= 2.0.0', '<=2.0.0'],
['<= 2.0.0', '<=2.0.0'],
['< 2.0.0', '<2.0.0-0'],
['< 2.0.0', '<2.0.0-0'],
['>=0.1.97', '>=0.1.97'],
['>=0.1.97', '>=0.1.97'],
['0.1.20 || 1.2.4', '0.1.20||1.2.4'],
['>=0.2.3 || <0.0.1', '>=0.2.3||<0.0.1-0'],
['>=0.2.3 || <0.0.1', '>=0.2.3||<0.0.1-0'],
['>=0.2.3 || <0.0.1', '>=0.2.3||<0.0.1-0'],
['||', '||'],
['2.x.x', '>=2.0.0-0 <3.0.0-0'],
['1.2.x', '>=1.2.0-0 <1.3.0-0'],
['1.2.x || 2.x', '>=1.2.0-0 <1.3.0-0||>=2.0.0-0 <3.0.0-0'],
['1.2.x || 2.x', '>=1.2.0-0 <1.3.0-0||>=2.0.0-0 <3.0.0-0'],
['x', '*'],
['2.*.*', '>=2.0.0-0 <3.0.0-0'],
['1.2.*', '>=1.2.0-0 <1.3.0-0'],
['1.2.* || 2.*', '>=1.2.0-0 <1.3.0-0||>=2.0.0-0 <3.0.0-0'],
['*', '*'],
['2', '>=2.0.0-0 <3.0.0-0'],
['2.3', '>=2.3.0-0 <2.4.0-0'],
['~2.4', '>=2.4.0-0 <2.5.0-0'],
['~2.4', '>=2.4.0-0 <2.5.0-0'],
['~>3.2.1', '>=3.2.1-0 <3.3.0-0'],
['~1', '>=1.0.0-0 <2.0.0-0'],
['~>1', '>=1.0.0-0 <2.0.0-0'],
['~> 1', '>=1.0.0-0 <2.0.0-0'],
['~1.0', '>=1.0.0-0 <1.1.0-0'],
['~ 1.0', '>=1.0.0-0 <1.1.0-0'],
['^0', '>=0.0.0-0 <1.0.0-0'],
['^ 1', '>=1.0.0-0 <2.0.0-0'],
['^0.1', '>=0.1.0-0 <0.2.0-0'],
['^1.0', '>=1.0.0-0 <2.0.0-0'],
['^1.2', '>=1.2.0-0 <2.0.0-0'],
['^0.0.1', '0.0.1'],
['^0.0.1-beta', '0.0.1-beta'],
['^0.1.2', '>=0.1.2-0 <0.2.0-0'],
['^1.2.3', '>=1.2.3-0 <2.0.0-0'],
['^1.2.3-beta.4', '>=1.2.3-beta.4 <2.0.0-0'],
['<1', '<1.0.0-0'],
['< 1', '<1.0.0-0'],
['>=1', '>=1.0.0-0'],
['>= 1', '>=1.0.0-0'],
['<1.2', '<1.2.0-0'],
['< 1.2', '<1.2.0-0'],
['1', '>=1.0.0-0 <2.0.0-0'],
['>01.02.03', '>1.2.3', true],
['>01.02.03', null],
['~1.2.3beta', '>=1.2.3-beta <1.3.0-0', true],
['~1.2.3beta', null],
['^ 1.2 ^ 1', '>=1.2.0-0 <2.0.0-0 >=1.0.0-0 <2.0.0-0']
].forEach(function(v) {
var pre = v[0];
var wanted = v[1];
var loose = v[2];
var found = validRange(pre, loose);
t.equal(found, wanted, 'validRange(' + pre + ') === ' + wanted);
});
t.end();
});
test('\ncomparators test', function(t) {
// [range, comparators]
// turn range into a set of individual comparators
[['1.0.0 - 2.0.0', [['>=1.0.0', '<=2.0.0']]],
['1.0.0', [['1.0.0']]],
['>=*', [['>=0.0.0-0']]],
['', [['']]],
['*', [['']]],
['*', [['']]],
['>=1.0.0', [['>=1.0.0']]],
['>=1.0.0', [['>=1.0.0']]],
['>=1.0.0', [['>=1.0.0']]],
['>1.0.0', [['>1.0.0']]],
['>1.0.0', [['>1.0.0']]],
['<=2.0.0', [['<=2.0.0']]],
['1', [['>=1.0.0-0', '<2.0.0-0']]],
['<=2.0.0', [['<=2.0.0']]],
['<=2.0.0', [['<=2.0.0']]],
['<2.0.0', [['<2.0.0-0']]],
['<2.0.0', [['<2.0.0-0']]],
['>= 1.0.0', [['>=1.0.0']]],
['>= 1.0.0', [['>=1.0.0']]],
['>= 1.0.0', [['>=1.0.0']]],
['> 1.0.0', [['>1.0.0']]],
['> 1.0.0', [['>1.0.0']]],
['<= 2.0.0', [['<=2.0.0']]],
['<= 2.0.0', [['<=2.0.0']]],
['<= 2.0.0', [['<=2.0.0']]],
['< 2.0.0', [['<2.0.0-0']]],
['<\t2.0.0', [['<2.0.0-0']]],
['>=0.1.97', [['>=0.1.97']]],
['>=0.1.97', [['>=0.1.97']]],
['0.1.20 || 1.2.4', [['0.1.20'], ['1.2.4']]],
['>=0.2.3 || <0.0.1', [['>=0.2.3'], ['<0.0.1-0']]],
['>=0.2.3 || <0.0.1', [['>=0.2.3'], ['<0.0.1-0']]],
['>=0.2.3 || <0.0.1', [['>=0.2.3'], ['<0.0.1-0']]],
['||', [[''], ['']]],
['2.x.x', [['>=2.0.0-0', '<3.0.0-0']]],
['1.2.x', [['>=1.2.0-0', '<1.3.0-0']]],
['1.2.x || 2.x', [['>=1.2.0-0', '<1.3.0-0'], ['>=2.0.0-0', '<3.0.0-0']]],
['1.2.x || 2.x', [['>=1.2.0-0', '<1.3.0-0'], ['>=2.0.0-0', '<3.0.0-0']]],
['x', [['']]],
['2.*.*', [['>=2.0.0-0', '<3.0.0-0']]],
['1.2.*', [['>=1.2.0-0', '<1.3.0-0']]],
['1.2.* || 2.*', [['>=1.2.0-0', '<1.3.0-0'], ['>=2.0.0-0', '<3.0.0-0']]],
['1.2.* || 2.*', [['>=1.2.0-0', '<1.3.0-0'], ['>=2.0.0-0', '<3.0.0-0']]],
['*', [['']]],
['2', [['>=2.0.0-0', '<3.0.0-0']]],
['2.3', [['>=2.3.0-0', '<2.4.0-0']]],
['~2.4', [['>=2.4.0-0', '<2.5.0-0']]],
['~2.4', [['>=2.4.0-0', '<2.5.0-0']]],
['~>3.2.1', [['>=3.2.1-0', '<3.3.0-0']]],
['~1', [['>=1.0.0-0', '<2.0.0-0']]],
['~>1', [['>=1.0.0-0', '<2.0.0-0']]],
['~> 1', [['>=1.0.0-0', '<2.0.0-0']]],
['~1.0', [['>=1.0.0-0', '<1.1.0-0']]],
['~ 1.0', [['>=1.0.0-0', '<1.1.0-0']]],
['~ 1.0.3', [['>=1.0.3-0', '<1.1.0-0']]],
['~> 1.0.3', [['>=1.0.3-0', '<1.1.0-0']]],
['<1', [['<1.0.0-0']]],
['< 1', [['<1.0.0-0']]],
['>=1', [['>=1.0.0-0']]],
['>= 1', [['>=1.0.0-0']]],
['<1.2', [['<1.2.0-0']]],
['< 1.2', [['<1.2.0-0']]],
['1', [['>=1.0.0-0', '<2.0.0-0']]],
['1 2', [['>=1.0.0-0', '<2.0.0-0', '>=2.0.0-0', '<3.0.0-0']]],
['1.2 - 3.4.5', [['>=1.2.0-0', '<=3.4.5']]],
['1.2.3 - 3.4', [['>=1.2.3', '<3.5.0-0']]]
].forEach(function(v) {
var pre = v[0];
var wanted = v[1];
var found = toComparators(v[0]);
var jw = JSON.stringify(wanted);
t.equivalent(found, wanted, 'toComparators(' + pre + ') === ' + jw);
});
t.end();
});
test('\ninvalid version numbers', function(t) {
['1.2.3.4',
'NOT VALID',
1.2,
null,
'Infinity.NaN.Infinity'
].forEach(function(v) {
t.throws(function() {
new SemVer(v);
}, {name:'TypeError', message:'Invalid Version: ' + v});
});
t.end();
});
test('\nstrict vs loose version numbers', function(t) {
[['=1.2.3', '1.2.3'],
['01.02.03', '1.2.3'],
['1.2.3-beta.01', '1.2.3-beta.1'],
[' =1.2.3', '1.2.3'],
['1.2.3foo', '1.2.3-foo']
].forEach(function(v) {
var loose = v[0];
var strict = v[1];
t.throws(function() {
new SemVer(loose);
});
var lv = new SemVer(loose, true);
t.equal(lv.version, strict);
t.ok(eq(loose, strict, true));
t.throws(function() {
eq(loose, strict);
});
t.throws(function() {
new SemVer(strict).compare(loose);
});
});
t.end();
});
test('\nstrict vs loose ranges', function(t) {
[['>=01.02.03', '>=1.2.3'],
['~1.02.03beta', '>=1.2.3-beta <1.3.0-0']
].forEach(function(v) {
var loose = v[0];
var comps = v[1];
t.throws(function() {
new Range(loose);
});
t.equal(new Range(loose, true).range, comps);
});
t.end();
});
test('\nmax satisfying', function(t) {
[[['1.2.3', '1.2.4'], '1.2', '1.2.4'],
[['1.2.4', '1.2.3'], '1.2', '1.2.4'],
[['1.2.3', '1.2.4', '1.2.5', '1.2.6'], '~1.2.3', '1.2.6'],
[['1.1.0', '1.2.0', '1.2.1', '1.3.0', '2.0.0b1', '2.0.0b2', '2.0.0b3', '2.0.0', '2.1.0'], '~2.0.0', '2.0.0', true]
].forEach(function(v) {
var versions = v[0];
var range = v[1];
var expect = v[2];
var loose = v[3];
var actual = semver.maxSatisfying(versions, range, loose);
t.equal(actual, expect);
});
t.end();
});
@@ -0,0 +1,175 @@
var tap = require('tap');
var test = tap.test;
var semver = require('../semver.js');
var ltr = semver.ltr;
test('\nltr tests', function(t) {
// [range, version, loose]
// Version should be less than range
[
['~1.2.2', '1.2.1'],
['~0.6.1-1', '0.6.1-0'],
['1.0.0 - 2.0.0', '0.0.1'],
['1.0.0-beta.2', '1.0.0-beta.1'],
['1.0.0', '0.0.0'],
['>=2.0.0', '1.1.1'],
['>=2.0.0', '1.2.9'],
['>2.0.0', '2.0.0'],
['0.1.20 || 1.2.4', '0.1.5'],
['2.x.x', '1.0.0'],
['1.2.x', '1.1.0'],
['1.2.x || 2.x', '1.0.0'],
['2.*.*', '1.0.1'],
['1.2.*', '1.1.3'],
['1.2.* || 2.*', '1.1.9999'],
['2', '1.0.0'],
['2.3', '2.2.2'],
['~2.4', '2.3.0'], // >=2.4.0 <2.5.0
['~2.4', '2.3.5'],
['~>3.2.1', '3.2.0'], // >=3.2.1 <3.3.0
['~1', '0.2.3'], // >=1.0.0 <2.0.0
['~>1', '0.2.4'],
['~> 1', '0.2.3'],
['~1.0', '0.1.2'], // >=1.0.0 <1.1.0
['~ 1.0', '0.1.0'],
['>1.2', '1.2.0'],
['> 1.2', '1.2.1'],
['1', '0.0.0beta', true],
['~v0.5.4-pre', '0.5.4-alpha'],
['~v0.5.4-pre', '0.5.4-alpha'],
['=0.7.x', '0.6.0'],
['=0.7.x', '0.6.0-asdf'],
['>=0.7.x', '0.6.0'],
['~1.2.2', '1.2.1'],
['1.0.0 - 2.0.0', '0.2.3'],
['1.0.0', '0.0.1'],
['>=2.0.0', '1.0.0'],
['>=2.0.0', '1.9999.9999'],
['>=2.0.0', '1.2.9'],
['>2.0.0', '2.0.0'],
['>2.0.0', '1.2.9'],
['2.x.x', '1.1.3'],
['1.2.x', '1.1.3'],
['1.2.x || 2.x', '1.1.3'],
['2.*.*', '1.1.3'],
['1.2.*', '1.1.3'],
['1.2.* || 2.*', '1.1.3'],
['2', '1.9999.9999'],
['2.3', '2.2.1'],
['~2.4', '2.3.0'], // >=2.4.0 <2.5.0
['~>3.2.1', '2.3.2'], // >=3.2.1 <3.3.0
['~1', '0.2.3'], // >=1.0.0 <2.0.0
['~>1', '0.2.3'],
['~1.0', '0.0.0'], // >=1.0.0 <1.1.0
['>1', '1.0.0'],
['2', '1.0.0beta', true],
['>1', '1.0.0beta', true],
['> 1', '1.0.0beta', true],
['=0.7.x', '0.6.2'],
['>=0.7.x', '0.6.2']
].forEach(function(tuple) {
var range = tuple[0];
var version = tuple[1];
var loose = tuple[2] || false;
var msg = 'ltr(' + version + ', ' + range + ', ' + loose + ')';
t.ok(ltr(version, range, loose), msg);
});
t.end();
});
test('\nnegative ltr tests', function(t) {
// [range, version, loose]
// Version should NOT be greater than range
[
['~ 1.0', '1.1.0'],
['~0.6.1-1', '0.6.1-1'],
['1.0.0 - 2.0.0', '1.2.3'],
['1.0.0 - 2.0.0', '2.9.9'],
['1.0.0', '1.0.0'],
['>=*', '0.2.4'],
['', '1.0.0', true],
['*', '1.2.3'],
['*', 'v1.2.3-foo'],
['>=1.0.0', '1.0.0'],
['>=1.0.0', '1.0.1'],
['>=1.0.0', '1.1.0'],
['>1.0.0', '1.0.1'],
['>1.0.0', '1.1.0'],
['<=2.0.0', '2.0.0'],
['<=2.0.0', '1.9999.9999'],
['<=2.0.0', '0.2.9'],
['<2.0.0', '1.9999.9999'],
['<2.0.0', '0.2.9'],
['>= 1.0.0', '1.0.0'],
['>= 1.0.0', '1.0.1'],
['>= 1.0.0', '1.1.0'],
['> 1.0.0', '1.0.1'],
['> 1.0.0', '1.1.0'],
['<= 2.0.0', '2.0.0'],
['<= 2.0.0', '1.9999.9999'],
['<= 2.0.0', '0.2.9'],
['< 2.0.0', '1.9999.9999'],
['<\t2.0.0', '0.2.9'],
['>=0.1.97', 'v0.1.97'],
['>=0.1.97', '0.1.97'],
['0.1.20 || 1.2.4', '1.2.4'],
['0.1.20 || >1.2.4', '1.2.4'],
['0.1.20 || 1.2.4', '1.2.3'],
['0.1.20 || 1.2.4', '0.1.20'],
['>=0.2.3 || <0.0.1', '0.0.0'],
['>=0.2.3 || <0.0.1', '0.2.3'],
['>=0.2.3 || <0.0.1', '0.2.4'],
['||', '1.3.4'],
['2.x.x', '2.1.3'],
['1.2.x', '1.2.3'],
['1.2.x || 2.x', '2.1.3'],
['1.2.x || 2.x', '1.2.3'],
['x', '1.2.3'],
['2.*.*', '2.1.3'],
['1.2.*', '1.2.3'],
['1.2.* || 2.*', '2.1.3'],
['1.2.* || 2.*', '1.2.3'],
['1.2.* || 2.*', '1.2.3'],
['*', '1.2.3'],
['2', '2.1.2'],
['2.3', '2.3.1'],
['~2.4', '2.4.0'], // >=2.4.0 <2.5.0
['~2.4', '2.4.5'],
['~>3.2.1', '3.2.2'], // >=3.2.1 <3.3.0
['~1', '1.2.3'], // >=1.0.0 <2.0.0
['~>1', '1.2.3'],
['~> 1', '1.2.3'],
['~1.0', '1.0.2'], // >=1.0.0 <1.1.0
['~ 1.0', '1.0.2'],
['>=1', '1.0.0'],
['>= 1', '1.0.0'],
['<1.2', '1.1.1'],
['< 1.2', '1.1.1'],
['1', '1.0.0beta', true],
['~v0.5.4-pre', '0.5.5'],
['~v0.5.4-pre', '0.5.4'],
['=0.7.x', '0.7.2'],
['>=0.7.x', '0.7.2'],
['=0.7.x', '0.7.0-asdf'],
['>=0.7.x', '0.7.0-asdf'],
['<=0.7.x', '0.6.2'],
['>0.2.3 >0.2.4 <=0.2.5', '0.2.5'],
['>=0.2.3 <=0.2.4', '0.2.4'],
['1.0.0 - 2.0.0', '2.0.0'],
['^1', '1.0.0-0'],
['^3.0.0', '4.0.0'],
['^1.0.0 || ~2.0.1', '2.0.0'],
['^0.1.0 || ~3.0.1 || 5.0.0', '3.2.0'],
['^0.1.0 || ~3.0.1 || 5.0.0', '1.0.0beta', true],
['^0.1.0 || ~3.0.1 || 5.0.0', '5.0.0-0', true],
['^0.1.0 || ~3.0.1 || >4 <=5.0.0', '3.5.0'],
['=0.1.0', '1.0.0']
].forEach(function(tuple) {
var range = tuple[0];
var version = tuple[1];
var loose = tuple[2] || false;
var msg = '!ltr(' + version + ', ' + range + ', ' + loose + ')';
t.notOk(ltr(version, range, loose), msg);
});
t.end();
});
@@ -0,0 +1,19 @@
var tap = require('tap');
var test = tap.test;
test('no module system', function(t) {
var fs = require('fs');
var vm = require('vm');
var head = fs.readFileSync(require.resolve('../head.js'), 'utf8');
var src = fs.readFileSync(require.resolve('../'), 'utf8');
var foot = fs.readFileSync(require.resolve('../foot.js'), 'utf8');
vm.runInThisContext(head + src + foot, 'semver.js');
// just some basic poking to see if it did some stuff
t.type(global.semver, 'object');
t.type(global.semver.SemVer, 'function');
t.type(global.semver.Range, 'function');
t.ok(global.semver.satisfies('1.2.3', '1.2'));
t.end();
});
@@ -0,0 +1,73 @@
{
"name": "bin-version-check",
"version": "0.1.0",
"description": "Check whether a binary version satisfies a semver range",
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/sindresorhus/bin-version-check"
},
"bin": {
"bin-version-check": "cli.js"
},
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "http://sindresorhus.com"
},
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"test": "mocha"
},
"files": [
"index.js",
"cli.js"
],
"keywords": [
"cli",
"bin",
"binary",
"executable",
"version",
"semver",
"semantic",
"range",
"satisfy",
"check",
"validate"
],
"dependencies": {
"bin-version": "^0.1.0",
"minimist": "^0.1.0",
"semver": "^2.3.0"
},
"devDependencies": {
"mocha": "*"
},
"bugs": {
"url": "https://github.com/sindresorhus/bin-version-check/issues"
},
"homepage": "https://github.com/sindresorhus/bin-version-check",
"_id": "bin-version-check@0.1.0",
"_shasum": "dc9d366ea3f96fa05932ee8881a73776c8fee0e1",
"_from": "bin-version-check@>=0.1.0 <0.2.0",
"_npmVersion": "1.4.9",
"_npmUser": {
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
},
"maintainers": [
{
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
}
],
"dist": {
"shasum": "dc9d366ea3f96fa05932ee8881a73776c8fee0e1",
"tarball": "http://registry.npmjs.org/bin-version-check/-/bin-version-check-0.1.0.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-0.1.0.tgz"
}
@@ -0,0 +1,58 @@
# bin-version-check [![Build Status](https://travis-ci.org/sindresorhus/bin-version-check.svg?branch=master)](https://travis-ci.org/sindresorhus/bin-version-check)
> Check whether a binary version satisfies a [semver range](https://github.com/isaacs/node-semver#ranges)
Useful when you have a thing that only works with specific versions of a binary.
## Install
```sh
$ npm install --save bin-version-check
```
## Usage
```sh
$ curl --version
curl 7.30.0 (x86_64-apple-darwin13.0)
```
```js
var binVersionCheck = require('bin-version-check');
binVersionCheck('curl', '>=8', function (err) {
if (err) {
throw err;
//=> InvalidBinVersion: curl 7.30.0 does not satisfy the version requirement of >=8
}
});
```
## CLI
```sh
$ npm install --global bin-version-check
```
```
$ bin-version-check --help
Usage
$ bin-version-check <binary> <semver-range>
Example
$ curl --version
curl 7.30.0 (x86_64-apple-darwin13.0)
$ bin-version-check curl '>=8'
curl 7.30.0 does not satisfy the version requirement of >=8
Exits with code 0 if the semver range is satisfied and 1 if not
```
## License
MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,36 @@
'use strict';
module.exports = function (options, excludes) {
var args = [];
Object.keys(options).forEach(function (key) {
var flag;
var val = options[key];
if (Array.isArray(excludes) && excludes.indexOf(key) !== -1) {
return;
}
flag = key.replace(/[A-Z]/g, '-$&').toLowerCase();
if (val === true) {
args.push('--' + flag);
}
if (typeof val === 'string') {
args.push('--' + flag, val);
}
if (typeof val === 'number' && isNaN(val) === false) {
args.push('--' + flag, '' + val);
}
if (Array.isArray(val)) {
val.forEach(function (arrVal) {
args.push('--' + flag, arrVal);
});
}
});
return args;
};
@@ -0,0 +1,61 @@
{
"name": "dargs",
"version": "0.1.0",
"description": "Converts an object of options into an array of command-line arguments. Useful when calling command-line tools.",
"keywords": [
"options",
"arguments",
"args",
"flags",
"cli"
],
"homepage": "https://github.com/sindresorhus/dargs",
"bugs": "https://github.com/sindresorhus/dargs/issues",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "http://sindresorhus.com"
},
"main": "dargs.js",
"repository": {
"type": "git",
"url": "git://github.com/sindresorhus/dargs.git"
},
"scripts": {
"test": "mocha"
},
"devDependencies": {
"mocha": "~1.9.0"
},
"engines": {
"node": ">=0.8.0"
},
"licenses": [
{
"type": "MIT"
}
],
"files": [
"dargs.js"
],
"_id": "dargs@0.1.0",
"dist": {
"shasum": "2364ad9f441f976dcd5fe9961e21715665a5e3c3",
"tarball": "http://registry.npmjs.org/dargs/-/dargs-0.1.0.tgz"
},
"_from": "dargs@>=0.1.0 <0.2.0",
"_npmVersion": "1.2.18",
"_npmUser": {
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
},
"maintainers": [
{
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
}
],
"directories": {},
"_shasum": "2364ad9f441f976dcd5fe9961e21715665a5e3c3",
"_resolved": "https://registry.npmjs.org/dargs/-/dargs-0.1.0.tgz"
}
@@ -0,0 +1,57 @@
# dargs [![Build Status](https://secure.travis-ci.org/sindresorhus/dargs.png?branch=master)](http://travis-ci.org/sindresorhus/dargs)
> Converts an object of options into an array of command-line arguments
## Getting started
Install: `npm install --save dargs`
#### Example
```js
var dargs = require('dargs');
var options = {
foo: 'bar',
hello: true, // results in only the key being used
cake: false, // ignored
camelCase: 5, // camelCase is slugged to `camel-case`
multiple: ['value', 'value2'], // converted to multiple arguments
sad: ':('
};
var excludes = ['sad'];
console.log(dargs(options, excludes));
/*
[
'--foo', 'bar',
'--hello',
'--camel-case', '5',
'--multiple', 'value',
'--multiple', 'value2'
]
*/
```
## Documentation
### options
Object of options to convert to command-line arguments.
### excludes
Array of keys to exclude.
## License
MIT License • © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1 @@
node_modules/
@@ -0,0 +1,5 @@
language: node_js
node_js:
- "0.6"
- "0.8"
- "0.10"
@@ -0,0 +1,162 @@
# Tmp
A simple temporary file and directory creator for [node.js.][1]
[![Build Status](https://secure.travis-ci.org/raszi/node-tmp.png?branch=master)](http://travis-ci.org/raszi/node-tmp)
## About
The main difference between bruce's [node-temp][2] is that mine more
aggressively checks for the existence of the newly created temporary file and
creates the new file with `O_EXCL` instead of simple `O_CREAT | O_RDRW`, so it
is safer.
The API is slightly different as well, Tmp does not yet provide synchronous
calls and all the parameters are optional.
You can set whether you want to remove the temporary file on process exit or
not, and the destination directory can also be set.
## How to install
```bash
npm install tmp
```
## Usage
### File creation
Simple temporary file creation, the file will be unlinked on process exit.
```javascript
var tmp = require('tmp');
tmp.file(function _tempFileCreated(err, path, fd) {
if (err) throw err;
console.log("File: ", path);
console.log("Filedescriptor: ", fd);
});
```
### Directory creation
Simple temporary directory creation, it will be removed on process exit.
If the directory still contains items on process exit, then it won't be removed.
```javascript
var tmp = require('tmp');
tmp.dir(function _tempDirCreated(err, path) {
if (err) throw err;
console.log("Dir: ", path);
});
```
If you want to cleanup the directory even when there are entries in it, then
you can pass the `unsafeCleanup` option when creating it.
### Filename generation
It is possible with this library to generate a unique filename in the specified
directory.
```javascript
var tmp = require('tmp');
tmp.tmpName(function _tempNameGenerated(err, path) {
if (err) throw err;
console.log("Created temporary filename: ", path);
});
```
## Advanced usage
### File creation
Creates a file with mode `0644`, prefix will be `prefix-` and postfix will be `.txt`.
```javascript
var tmp = require('tmp');
tmp.file({ mode: 0644, prefix: 'prefix-', postfix: '.txt' }, function _tempFileCreated(err, path, fd) {
if (err) throw err;
console.log("File: ", path);
console.log("Filedescriptor: ", fd);
});
```
### Directory creation
Creates a directory with mode `0755`, prefix will be `myTmpDir_`.
```javascript
var tmp = require('tmp');
tmp.dir({ mode: 0750, prefix: 'myTmpDir_' }, function _tempDirCreated(err, path) {
if (err) throw err;
console.log("Dir: ", path);
});
```
### mkstemps like
Creates a new temporary directory with mode `0700` and filename like `/tmp/tmp-nk2J1u`.
```javascript
var tmp = require('tmp');
tmp.dir({ template: '/tmp/tmp-XXXXXX' }, function _tempDirCreated(err, path) {
if (err) throw err;
console.log("Dir: ", path);
});
```
### Filename generation
The `tmpName()` function accepts the `prefix`, `postfix`, `dir`, etc. parameters also:
```javascript
var tmp = require('tmp');
tmp.tmpName({ template: '/tmp/tmp-XXXXXX' }, function _tempNameGenerated(err, path) {
if (err) throw err;
console.log("Created temporary filename: ", path);
});
```
## Graceful cleanup
One may want to cleanup the temporary files even when an uncaught exception
occurs. To enforce this, you can call the `setGracefulCleanup()` method:
```javascript
var tmp = require('tmp');
tmp.setGracefulCleanup();
```
## Options
All options are optional :)
* `mode`: the file mode to create with, it fallbacks to `0600` on file creation and `0700` on directory creation
* `prefix`: the optional prefix, fallbacks to `tmp-` if not provided
* `postfix`: the optional postfix, fallbacks to `.tmp` on file creation
* `template`: [`mkstemps`][3] like filename template, no default
* `dir`: the optional temporary directory, fallbacks to system default (guesses from environment)
* `tries`: how many times should the function try to get a unique filename before giving up, default `3`
* `keep`: signals that the temporary file or directory should not be deleted on exit, default is `false`, means delete
* `unsafeCleanup`: recursively removes the created temporary directory, even when it's not empty. default is `false`
[1]: http://nodejs.org/
[2]: https://github.com/bruce/node-temp
[3]: http://www.kernel.org/doc/man-pages/online/pages/man3/mkstemp.3.html
@@ -0,0 +1,13 @@
var domain = require('domain');
//throw new Error('bazz');
var d = domain.create();
d.on('error', function ( e ) {
console.log('error!!!', e);
});
d.run(function () {
console.log('hey');
throw new Error('bazz');
});
@@ -0,0 +1,280 @@
/*!
* Tmp
*
* Copyright (c) 2011-2013 KARASZI Istvan <github@spam.raszi.hu>
*
* MIT Licensed
*/
/**
* Module dependencies.
*/
var
fs = require('fs'),
path = require('path'),
os = require('os'),
exists = fs.exists || path.exists,
tmpDir = os.tmpDir || _getTMPDir,
_c = require('constants');
/**
* The working inner variables.
*/
var
// store the actual TMP directory
_TMP = tmpDir(),
// the random characters to choose from
randomChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz",
randomCharsLength = randomChars.length,
// this will hold the objects need to be removed on exit
_removeObjects = [],
_gracefulCleanup = false,
_uncaughtException = false;
/**
* Gets the temp directory.
*
* @return {String}
* @api private
*/
function _getTMPDir() {
var tmpNames = [ 'TMPDIR', 'TMP', 'TEMP' ];
for (var i = 0, length = tmpNames.length; i < length; i++) {
if (_isUndefined(process.env[tmpNames[i]])) continue;
return process.env[tmpNames[i]];
}
// fallback to the default
return '/tmp';
}
/**
* Checks whether the `obj` parameter is defined or not.
*
* @param {Object} obj
* @return {Boolean}
* @api private
*/
function _isUndefined(obj) {
return typeof obj === 'undefined';
}
/**
* Parses the function arguments.
*
* This function helps to have optional arguments.
*
* @param {Object} options
* @param {Function} callback
* @api private
*/
function _parseArguments(options, callback) {
if (!callback || typeof callback != "function") {
callback = options;
options = {};
}
return [ options, callback ];
}
/**
* Gets a temporary file name.
*
* @param {Object} opts
* @param {Function} cb
* @api private
*/
function _getTmpName(options, callback) {
var
args = _parseArguments(options, callback),
opts = args[0],
cb = args[1],
template = opts.template,
templateDefined = !_isUndefined(template),
tries = opts.tries || 3;
if (isNaN(tries) || tries < 0)
return cb(new Error('Invalid tries'));
if (templateDefined && !template.match(/XXXXXX/))
return cb(new Error('Invalid template provided'));
function _getName() {
// prefix and postfix
if (!templateDefined) {
var name = [
(_isUndefined(opts.prefix)) ? 'tmp-' : opts.prefix,
process.pid,
(Math.random() * 0x1000000000).toString(36),
opts.postfix
].join('');
return path.join(opts.dir || _TMP, name);
}
// mkstemps like template
var chars = [];
for (var i = 0; i < 6; i++) {
chars.push(randomChars.substr(Math.floor(Math.random() * randomCharsLength), 1));
}
return template.replace(/XXXXXX/, chars.join(''));
}
(function _getUniqueName() {
var name = _getName();
// check whether the path exists then retry if needed
exists(name, function _pathExists(pathExists) {
if (pathExists) {
if (tries-- > 0) return _getUniqueName();
return cb(new Error('Could not get a unique tmp filename, max tries reached'));
}
cb(null, name);
});
}());
}
/**
* Creates and opens a temporary file.
*
* @param {Object} options
* @param {Function} callback
* @api public
*/
function _createTmpFile(options, callback) {
var
args = _parseArguments(options, callback),
opts = args[0],
cb = args[1];
opts.postfix = (_isUndefined(opts.postfix)) ? '.tmp' : opts.postfix;
// gets a temporary filename
_getTmpName(opts, function _tmpNameCreated(err, name) {
if (err) return cb(err);
// create and open the file
fs.open(name, _c.O_CREAT | _c.O_EXCL | _c.O_RDWR, opts.mode || 0600, function _fileCreated(err, fd) {
if (err) return cb(err);
if (!opts.keep) _removeObjects.unshift([ fs.unlinkSync, name ]);
cb(null, name, fd);
});
});
}
/**
* Removes files and folders in a directory recursively.
*
* @param {String} path
*/
function _rmdirRecursiveSync(dir) {
var files = fs.readdirSync(dir);
for (var i = 0, length = files.length; i < length; i++) {
var file = path.join(dir, files[i]);
// lstat so we don't recurse into symlinked directories.
var stat = fs.lstatSync(file);
if (stat.isDirectory()) {
_rmdirRecursiveSync(file);
} else {
fs.unlinkSync(file);
}
}
fs.rmdirSync(dir);
}
/**
* Creates a temporary directory.
*
* @param {Object} options
* @param {Function} callback
* @api public
*/
function _createTmpDir(options, callback) {
var
args = _parseArguments(options, callback),
opts = args[0],
cb = args[1];
// gets a temporary filename
_getTmpName(opts, function _tmpNameCreated(err, name) {
if (err) return cb(err);
// create the directory
fs.mkdir(name, opts.mode || 0700, function _dirCreated(err) {
if (err) return cb(err);
if (!opts.keep) {
if (opts.unsafeCleanup) {
_removeObjects.unshift([ _rmdirRecursiveSync, name ]);
} else {
_removeObjects.unshift([ fs.rmdirSync, name ]);
}
}
cb(null, name);
});
});
}
/**
* The garbage collector.
*
* @api private
*/
function _garbageCollector() {
if (_uncaughtException && !_gracefulCleanup) {
return;
}
for (var i = 0, length = _removeObjects.length; i < length; i++) {
try {
_removeObjects[i][0].call(null, _removeObjects[i][1]);
} catch (e) {
// already removed?
}
}
}
function _setGracefulCleanup() {
_gracefulCleanup = true;
}
var version = process.versions.node.split('.').map(function (value) {
return parseInt(value, 10);
});
if (version[0] === 0 && (version[1] < 9 || version[1] === 9 && version[2] < 5)) {
process.addListener('uncaughtException', function _uncaughtExceptionThrown( err ) {
_uncaughtException = true;
_garbageCollector();
throw err;
});
}
process.addListener('exit', function _exit(code) {
if (code) _uncaughtException = true;
_garbageCollector();
});
// exporting all the needed methods
module.exports.tmpdir = _TMP;
module.exports.dir = _createTmpDir;
module.exports.file = _createTmpFile;
module.exports.tmpName = _getTmpName;
module.exports.setGracefulCleanup = _setGracefulCleanup;
@@ -0,0 +1,65 @@
{
"name": "tmp",
"version": "0.0.23",
"description": "Temporary file and directory creator",
"author": {
"name": "KARASZI István",
"email": "github@spam.raszi.hu",
"url": "http://raszi.hu/"
},
"homepage": "http://github.com/raszi/node-tmp",
"keywords": [
"temporary",
"tmp",
"temp",
"tempdir",
"tempfile",
"tmpdir",
"tmpfile"
],
"licenses": [
{
"type": "MIT",
"url": "http://opensource.org/licenses/MIT"
}
],
"repository": {
"type": "git",
"url": "git://github.com/raszi/node-tmp.git"
},
"bugs": {
"url": "http://github.com/raszi/node-tmp/issues"
},
"main": "lib/tmp.js",
"scripts": {
"test": "vows test/*-test.js"
},
"engines": {
"node": ">=0.4.0"
},
"dependencies": {},
"devDependencies": {
"vows": "~0.7.0"
},
"_id": "tmp@0.0.23",
"dist": {
"shasum": "de874aa5e974a85f0a32cdfdbd74663cb3bd9c74",
"tarball": "http://registry.npmjs.org/tmp/-/tmp-0.0.23.tgz"
},
"_from": "tmp@0.0.23",
"_npmVersion": "1.3.8",
"_npmUser": {
"name": "raszi",
"email": "npm@spam.raszi.hu"
},
"maintainers": [
{
"name": "raszi",
"email": "npm@spam.raszi.hu"
}
],
"directories": {},
"_shasum": "de874aa5e974a85f0a32cdfdbd74663cb3bd9c74",
"_resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.23.tgz",
"readme": "ERROR: No README data found!"
}
@@ -0,0 +1,9 @@
#!/bin/bash
#node06
for node in node08 node; do
command -v ${node} > /dev/null 2>&1 || continue
echo "Testing with $(${node} --version)..."
${node} node_modules/vows/bin/vows test/*test.js
done
@@ -0,0 +1,6 @@
process.on('uncaughtException', function ( err ) {
console.log('blah');
throw err;
});
throw "on purpose"
@@ -0,0 +1,74 @@
var
assert = require('assert'),
path = require('path'),
exec = require('child_process').exec;
function _spawnTestWithError(testFile, params, cb) {
_spawnTest(true, testFile, params, cb);
}
function _spawnTestWithoutError(testFile, params, cb) {
_spawnTest(false, testFile, params, cb);
}
function _spawnTest(passError, testFile, params, cb) {
var
filename,
node_path = process.argv[0],
command = [ node_path, path.join(__dirname, testFile) ].concat(params).join(' ');
exec(command, function _execDone(err, stdout, stderr) {
if (passError) {
if (err) {
return cb(err);
} else if (stderr.length > 0) {
return cb(stderr.toString());
}
}
return cb(null, stdout.toString());
});
}
function _testStat(stat, mode) {
assert.equal(stat.uid, process.getuid(), 'should have the same UID');
assert.equal(stat.gid, process.getgid(), 'should have the same GUID');
assert.equal(stat.mode, mode);
}
function _testPrefix(prefix) {
return function _testPrefixGenerated(err, name, fd) {
assert.equal(path.basename(name).slice(0, prefix.length), prefix, 'should have the provided prefix');
};
}
function _testPostfix(postfix) {
return function _testPostfixGenerated(err, name, fd) {
assert.equal(name.slice(name.length - postfix.length, name.length), postfix, 'should have the provided postfix');
};
}
function _testKeep(type, keep, cb) {
_spawnTestWithError('keep.js', [ type, keep ], cb);
}
function _testGraceful(type, graceful, cb) {
_spawnTestWithoutError('graceful.js', [ type, graceful ], cb);
}
function _assertName(err, name) {
assert.isString(name);
assert.isNotZero(name.length);
}
function _testUnsafeCleanup(unsafe, cb) {
_spawnTestWithoutError('unsafe.js', [ 'dir', unsafe ], cb);
}
module.exports.testStat = _testStat;
module.exports.testPrefix = _testPrefix;
module.exports.testPostfix = _testPostfix;
module.exports.testKeep = _testKeep;
module.exports.testGraceful = _testGraceful;
module.exports.assertName = _assertName;
module.exports.testUnsafeCleanup = _testUnsafeCleanup;
@@ -0,0 +1,183 @@
var
vows = require('vows'),
assert = require('assert'),
path = require('path'),
fs = require('fs'),
existsSync = fs.existsSync || path.existsSync,
tmp = require('../lib/tmp.js'),
Test = require('./base.js');
function _testDir(mode) {
return function _testDirGenerated(err, name) {
assert.ok(existsSync(name), 'should exist');
var stat = fs.statSync(name);
assert.ok(stat.isDirectory(), 'should be a directory');
Test.testStat(stat, mode);
};
}
vows.describe('Directory creation').addBatch({
'when using without parameters': {
topic: function () {
tmp.dir(this.callback);
},
'should be a directory': _testDir(040700),
'should have the default prefix': Test.testPrefix('tmp-')
},
'when using with prefix': {
topic: function () {
tmp.dir({ prefix: 'something' }, this.callback);
},
'should not return with an error': assert.isNull,
'should return with a name': Test.assertName,
'should be a directory': _testDir(040700),
'should have the provided prefix': Test.testPrefix('something')
},
'when using with postfix': {
topic: function () {
tmp.dir({ postfix: '.txt' }, this.callback);
},
'should not return with an error': assert.isNull,
'should return with a name': Test.assertName,
'should be a directory': _testDir(040700),
'should have the provided postfix': Test.testPostfix('.txt')
},
'when using template': {
topic: function () {
tmp.dir({ template: path.join(tmp.tmpdir, 'clike-XXXXXX-postfix') }, this.callback);
},
'should not return with error': assert.isNull,
'should return with a name': Test.assertName,
'should be a file': _testDir(040700),
'should have the provided prefix': Test.testPrefix('clike-'),
'should have the provided postfix': Test.testPostfix('-postfix')
},
'when using multiple options': {
topic: function () {
tmp.dir({ prefix: 'foo', postfix: 'bar', mode: 0750 }, this.callback);
},
'should not return with an error': assert.isNull,
'should return with a name': Test.assertName,
'should be a directory': _testDir(040750),
'should have the provided prefix': Test.testPrefix('foo'),
'should have the provided postfix': Test.testPostfix('bar')
},
'when using multiple options and mode': {
topic: function () {
tmp.dir({ prefix: 'complicated', postfix: 'options', mode: 0755 }, this.callback);
},
'should not return with an error': assert.isNull,
'should return with a name': Test.assertName,
'should be a directory': _testDir(040755),
'should have the provided prefix': Test.testPrefix('complicated'),
'should have the provided postfix': Test.testPostfix('options')
},
'no tries': {
topic: function () {
tmp.dir({ tries: -1 }, this.callback);
},
'should return with an error': assert.isObject
},
'keep testing': {
topic: function () {
Test.testKeep('dir', '1', this.callback);
},
'should not return with an error': assert.isNull,
'should return with a name': Test.assertName,
'should be a dir': function (err, name) {
_testDir(040700)(err, name);
fs.rmdirSync(name);
}
},
'unlink testing': {
topic: function () {
Test.testKeep('dir', '0', this.callback);
},
'should not return with error': assert.isNull,
'should return with a name': Test.assertName,
'should not exist': function (err, name) {
assert.ok(!existsSync(name), "Directory should be removed");
}
},
'non graceful testing': {
topic: function () {
Test.testGraceful('dir', '0', this.callback);
},
'should not return with error': assert.isNull,
'should return with a name': Test.assertName,
'should be a dir': function (err, name) {
_testDir(040700)(err, name);
fs.rmdirSync(name);
}
},
'graceful testing': {
topic: function () {
Test.testGraceful('dir', '1', this.callback);
},
'should not return with an error': assert.isNull,
'should return with a name': Test.assertName,
'should not exist': function (err, name) {
assert.ok(!existsSync(name), "Directory should be removed");
}
},
'unsafeCleanup === true': {
topic: function () {
Test.testUnsafeCleanup('1', this.callback);
},
'should not return with an error': assert.isNull,
'should return with a name': Test.assertName,
'should not exist': function (err, name) {
assert.ok(!existsSync(name), "Directory should be removed");
},
'should remove symlinked dir': function(err, name) {
assert.ok(
!existsSync(name + '/symlinkme-target'),
'should remove target'
);
},
'should not remove contents of symlink dir': function(err, name) {
assert.ok(
existsSync(__dirname + '/symlinkme/file.js'),
'should not remove symlinked directory\'s content'
);
}
},
'unsafeCleanup === false': {
topic: function () {
Test.testUnsafeCleanup('0', this.callback);
},
'should not return with an error': assert.isNull,
'should return with a name': Test.assertName,
'should be a directory': _testDir(040700)
}
}).exportTo(module);
@@ -0,0 +1,165 @@
var
vows = require('vows'),
assert = require('assert'),
path = require('path'),
fs = require('fs'),
existsSync = fs.existsSync || path.existsSync,
tmp = require('../lib/tmp.js'),
Test = require('./base.js');
function _testFile(mode, fdTest) {
return function _testFileGenerated(err, name, fd) {
assert.ok(existsSync(name), 'should exist');
var stat = fs.statSync(name);
assert.equal(stat.size, 0, 'should have zero size');
assert.ok(stat.isFile(), 'should be a file');
Test.testStat(stat, mode);
// check with fstat as well (fd checking)
if (fdTest) {
var fstat = fs.fstatSync(fd);
assert.deepEqual(fstat, stat, 'fstat results should be the same');
var data = new Buffer('something');
assert.equal(fs.writeSync(fd, data, 0, data.length, 0), data.length, 'should be writable');
assert.ok(!fs.closeSync(fd), 'should not return with error');
}
};
}
vows.describe('File creation').addBatch({
'when using without parameters': {
topic: function () {
tmp.file(this.callback);
},
'should not return with an error': assert.isNull,
'should return with a name': Test.assertName,
'should be a file': _testFile(0100600, true),
'should have the default prefix': Test.testPrefix('tmp-'),
'should have the default postfix': Test.testPostfix('.tmp')
},
'when using with prefix': {
topic: function () {
tmp.file({ prefix: 'something' }, this.callback);
},
'should not return with an error': assert.isNull,
'should return with a name': Test.assertName,
'should be a file': _testFile(0100600, true),
'should have the provided prefix': Test.testPrefix('something')
},
'when using with postfix': {
topic: function () {
tmp.file({ postfix: '.txt' }, this.callback);
},
'should not return with an error': assert.isNull,
'should return with a name': Test.assertName,
'should be a file': _testFile(0100600, true),
'should have the provided postfix': Test.testPostfix('.txt')
},
'when using template': {
topic: function () {
tmp.file({ template: path.join(tmp.tmpdir, 'clike-XXXXXX-postfix') }, this.callback);
},
'should not return with an error': assert.isNull,
'should return with a name': Test.assertName,
'should be a file': _testFile(0100600, true),
'should have the provided prefix': Test.testPrefix('clike-'),
'should have the provided postfix': Test.testPostfix('-postfix')
},
'when using multiple options': {
topic: function () {
tmp.file({ prefix: 'foo', postfix: 'bar', mode: 0640 }, this.callback);
},
'should not return with an error': assert.isNull,
'should return with a name': Test.assertName,
'should be a file': _testFile(0100640, true),
'should have the provided prefix': Test.testPrefix('foo'),
'should have the provided postfix': Test.testPostfix('bar')
},
'when using multiple options and mode': {
topic: function () {
tmp.file({ prefix: 'complicated', postfix: 'options', mode: 0644 }, this.callback);
},
'should not return with an error': assert.isNull,
'should return with a name': Test.assertName,
'should be a file': _testFile(0100644, true),
'should have the provided prefix': Test.testPrefix('complicated'),
'should have the provided postfix': Test.testPostfix('options')
},
'no tries': {
topic: function () {
tmp.file({ tries: -1 }, this.callback);
},
'should not be created': assert.isObject
},
'keep testing': {
topic: function () {
Test.testKeep('file', '1', this.callback);
},
'should not return with an error': assert.isNull,
'should return with a name': Test.assertName,
'should be a file': function (err, name) {
_testFile(0100600, false)(err, name, null);
fs.unlinkSync(name);
}
},
'unlink testing': {
topic: function () {
Test.testKeep('file', '0', this.callback);
},
'should not return with an error': assert.isNull,
'should return with a name': Test.assertName,
'should not exist': function (err, name) {
assert.ok(!existsSync(name), "File should be removed");
}
},
'non graceful testing': {
topic: function () {
Test.testGraceful('file', '0', this.callback);
},
'should not return with error': assert.isNull,
'should return with a name': Test.assertName,
'should be a file': function (err, name) {
_testFile(0100600, false)(err, name, null);
fs.unlinkSync(name);
}
},
'graceful testing': {
topic: function () {
Test.testGraceful('file', '1', this.callback);
},
'should not return with an error': assert.isNull,
'should return with a name': Test.assertName,
'should not exist': function (err, name) {
assert.ok(!existsSync(name), "File should be removed");
}
}
}).exportTo(module);
@@ -0,0 +1,15 @@
var
tmp = require('../lib/tmp'),
spawn = require('./spawn');
var graceful = spawn.arg;
if (graceful) {
tmp.setGracefulCleanup();
}
spawn.tmpFunction(function (err, name) {
spawn.out(name, function () {
throw new Error("Thrown on purpose");
});
});
@@ -0,0 +1,11 @@
var spawn = require('./spawn');
var keep = spawn.arg;
spawn.tmpFunction({ keep: keep }, function (err, name) {
if (err) {
spawn.err(err, spawn.exit);
} else {
spawn.out(name, spawn.exit);
}
});
@@ -0,0 +1,82 @@
var
vows = require('vows'),
assert = require('assert'),
path = require('path'),
tmp = require('../lib/tmp.js'),
Test = require('./base.js');
vows.describe('Name creation').addBatch({
'when using without parameters': {
topic: function () {
tmp.tmpName(this.callback);
},
'should not return with error': assert.isNull,
'should have the default prefix': Test.testPrefix('tmp-')
},
'when using with prefix': {
topic: function () {
tmp.tmpName({ prefix: 'something' }, this.callback);
},
'should not return with error': assert.isNull,
'should have the provided prefix': Test.testPrefix('something')
},
'when using with postfix': {
topic: function () {
tmp.tmpName({ postfix: '.txt' }, this.callback);
},
'should not return with error': assert.isNull,
'should have the provided postfix': Test.testPostfix('.txt')
},
'when using template': {
topic: function () {
tmp.tmpName({ template: path.join(tmp.tmpdir, 'clike-XXXXXX-postfix') }, this.callback);
},
'should not return with error': assert.isNull,
'should have the provided prefix': Test.testPrefix('clike-'),
'should have the provided postfix': Test.testPostfix('-postfix'),
'should have template filled': function (err, name) {
assert.isTrue(/[a-zA-Z0-9]{6}/.test(name));
}
},
'when using multiple options': {
topic: function () {
tmp.tmpName({ prefix: 'foo', postfix: 'bar', tries: 5 }, this.callback);
},
'should not return with error': assert.isNull,
'should have the provided prefix': Test.testPrefix('foo'),
'should have the provided postfix': Test.testPostfix('bar')
},
'no tries': {
topic: function () {
tmp.tmpName({ tries: -1 }, this.callback);
},
'should fail': function (err, name) {
assert.isObject(err);
}
},
'tries not numeric': {
topic: function () {
tmp.tmpName({ tries: 'hello'}, this.callback);
},
'should fail': function (err, name) {
assert.isObject(err);
}
}
}).exportTo(module);
@@ -0,0 +1,32 @@
var
fs = require('fs'),
tmp = require('../lib/tmp');
function _writeSync(stream, str, cb) {
var flushed = stream.write(str);
if (flushed) {
return cb(null);
}
stream.once('drain', function _flushed() {
cb(null);
});
}
module.exports.out = function (str, cb) {
_writeSync(process.stdout, str, cb);
};
module.exports.err = function (str, cb) {
_writeSync(process.stderr, str, cb);
};
module.exports.exit = function () {
process.exit(0);
};
var type = process.argv[2];
module.exports.tmpFunction = (type == 'file') ? tmp.file : tmp.dir;
var arg = (process.argv[3] && parseInt(process.argv[3], 10) === 1) ? true : false;
module.exports.arg = arg;
@@ -0,0 +1,30 @@
var
fs = require('fs'),
join = require('path').join,
spawn = require('./spawn');
var unsafe = spawn.arg;
spawn.tmpFunction({ unsafeCleanup: unsafe }, function (err, name) {
if (err) {
spawn.err(err, spawn.exit);
return;
}
try {
// file that should be removed
var fd = fs.openSync(join(name, 'should-be-removed.file'), 'w');
fs.closeSync(fd);
// in tree source
var symlinkSource = join(__dirname, 'symlinkme');
// testing target
var symlinkTarget = join(name, 'symlinkme-target');
// symlink that should be removed but the contents should be preserved.
fs.symlinkSync(symlinkSource, symlinkTarget, 'dir');
spawn.out(name, spawn.exit);
} catch (e) {
spawn.err(e.toString(), spawn.exit);
}
});
@@ -0,0 +1,99 @@
{
"name": "grunt-contrib-compass",
"description": "Compile Sass to CSS using Compass",
"version": "0.9.0",
"author": {
"name": "Grunt Team",
"url": "http://gruntjs.com/"
},
"repository": {
"type": "git",
"url": "git://github.com/gruntjs/grunt-contrib-compass"
},
"licenses": [
{
"type": "MIT",
"url": "https://github.com/gruntjs/grunt-contrib-compass/blob/master/LICENSE-MIT"
}
],
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"test": "grunt test"
},
"dependencies": {
"async": "^0.8.0",
"bin-version-check": "^0.1.0",
"dargs": "^0.1.0",
"tmp": "0.0.23"
},
"devDependencies": {
"grunt": "^0.4.5",
"grunt-contrib-clean": "^0.5.0",
"grunt-contrib-internal": "^0.4.2",
"grunt-contrib-jshint": "^0.10.0",
"grunt-contrib-nodeunit": "^0.4.0"
},
"peerDependencies": {
"grunt": "^0.4.0"
},
"keywords": [
"gruntplugin",
"compass",
"scss",
"sass",
"css",
"compile",
"preprocessor",
"style"
],
"files": [
"tasks",
"LICENSE-MIT"
],
"bugs": {
"url": "https://github.com/gruntjs/grunt-contrib-compass/issues"
},
"homepage": "https://github.com/gruntjs/grunt-contrib-compass",
"_id": "grunt-contrib-compass@0.9.0",
"_shasum": "01a00947a65a58512bfd32289935fe37b79ffa61",
"_from": "grunt-contrib-compass@0.9.0",
"_npmVersion": "1.4.9",
"_npmUser": {
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
},
"maintainers": [
{
"name": "tkellen",
"email": "tyler@sleekcode.net"
},
{
"name": "cowboy",
"email": "cowboy@rj3.net"
},
{
"name": "shama",
"email": "kyle@dontkry.com"
},
{
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
},
{
"name": "vladikoff",
"email": "vlad@vladikoff.com"
},
{
"name": "jmeas",
"email": "jellyes2@gmail.com"
}
],
"dist": {
"shasum": "01a00947a65a58512bfd32289935fe37b79ffa61",
"tarball": "http://registry.npmjs.org/grunt-contrib-compass/-/grunt-contrib-compass-0.9.0.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/grunt-contrib-compass/-/grunt-contrib-compass-0.9.0.tgz"
}
@@ -0,0 +1,83 @@
/*
* grunt-contrib-compass
* http://gruntjs.com/
*
* Copyright (c) 2014 Sindre Sorhus, contributors
* Licensed under the MIT license.
*/
'use strict';
var binVersionCheck = require('bin-version-check');
module.exports = function (grunt) {
var compass = require('./lib/compass').init(grunt);
function compile(args, cb) {
var child = grunt.util.spawn({
cmd: args.shift(),
args: args
}, function (err, result, code) {
if (code === 127) {
grunt.warn(
'You need to have Ruby and Compass installed ' +
'and in your system PATH for this task to work. ' +
'More info: https://github.com/gruntjs/grunt-contrib-compass'
);
}
// `compass compile` exits with 1 and outputs "Nothing to compile"
// on stderr when it has nothing to compile.
// https://github.com/chriseppstein/compass/issues/993
// Don't fail the task in this situation.
if (code === 1 && !/Nothing to compile|Compass can't find any Sass files to compile/g.test(result.stderr)) {
grunt.warn('↑');
}
cb();
});
if (child) {
child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);
}
}
grunt.registerMultiTask('compass', 'Compile Sass to CSS using Compass', function () {
var options = this.options();
var cb = this.async();
// display compilation time
if (!options.clean) {
options.time = true;
}
// create a function to retroactively add a banner to the top of the
// generated files, if specified
var bannerCallback = compass.buildBannerCallback(grunt, options);
// create a temporary config file if there are 'raw' options or
// settings not supported as CLI arguments
var configContext = compass.buildConfigContext(options);
// get the array of arguments for the compass command
var args = compass.buildArgsArray(options);
configContext(function (err, path) {
if (err) {
grunt.warn(err);
}
if (path) {
args.push('--config', path);
}
binVersionCheck(args[0], '>=0.12.2', function (err) {
if (err) {
grunt.warn(err);
}
compile(args, function () {
bannerCallback();
cb();
});
});
});
});
};
@@ -0,0 +1,211 @@
exports.init = function (grunt) {
'use strict';
var fs = require('fs');
var tmp = require('tmp');
var dargs = require('dargs');
var path = require('path');
var async = require('async');
var exports = {};
function camelCaseToUnderscore(str) {
return str
.replace(/([a-z])([A-Z])/g, '$1_$2')
.toLowerCase();
}
// Extracts the options that cannot be used as CLI parameter but only
// as 'raw' arguments.
// Returns an object: {raw: str, options: []} with the raw string to be
// used to generate a config and the list of used options.
exports.extractRawOptions = function extractRawOptions(options) {
var raw = options.raw || '';
var supportedOptions = [
'http_path',
'css_path',
'http_stylesheets_path',
'sass_path',
'images_path',
'http_images_path',
'generated_images_dir',
'generated_images_path',
'http_generated_images_path',
'javascripts_path',
'http_javascripts_path',
'fonts_path',
'http_fonts_path',
'http_fonts_dir',
'extensions_dir',
'extension_path',
'cache_dir'
];
var usedOptions = Object.keys(options).filter(function (option) {
var underscoredOption = camelCaseToUnderscore(option);
if (supportedOptions.indexOf(underscoredOption) >= 0) {
// naively escape double-quotes in the value
var value = options[option].replace(/"/g, '\\"');
raw += underscoredOption + ' = "' + value + '"\n';
delete options[option];
return true;
} else if (underscoredOption === 'asset_cache_buster') {
// Special handling for asset_cache_buster as it doesn't take
// a string as argument, but either an inline-ruby block (which we don't
// support) or a `:none` symbol to disable it.
if (options[option] === false) {
raw += underscoredOption + ' :none' + '\n';
}
delete options[option];
return true;
} else if (underscoredOption === 'sprite_load_path') {
// Special handling for sprite_load_path as it doesn't take
// a string as argument, but an array or a string.
// Append the load paths in ruby via <<
// http://compass-style.org/blog/2012/02/01/compass-0-12-is-released/
var loadPath = options[option];
if (loadPath) {
loadPath = Array.isArray(loadPath) ? loadPath : [loadPath];
loadPath.forEach(function (path) {
// naively escape double-quotes in the value
path = path.replace(/"/g, '\\"');
raw += underscoredOption + ' << "' + path + '"\n';
});
}
delete options[option];
return true;
}
});
return {raw: raw, options: usedOptions};
};
// Create a function to add a banner, if requested through the options.
exports.buildBannerCallback = function (grunt, options) {
if (!options.specify || !options.banner) {
if (options.banner && !options.specify) {
grunt.warn('You can only use the `banner` option in combination with `specify.`');
}
// Return a no-op if specify or banner aren't set.
return function () {};
}
var srcFiles = grunt.file.expand({
filter: function (filePath) {
return path.basename(filePath)[0] !== '_';
}
}, options.specify);
var banner = options.banner;
delete options.banner;
var destFiles = srcFiles.map(function (filename) {
return filename.replace(options.sassDir, options.cssDir).replace(/\.(css\.)?(scss|sass)$/i, '.css');
});
return function () {
grunt.log.verbose.writeln('Writing CSS banners.');
async.map(destFiles, function (filename) {
grunt.log.verbose.writeln('Writing CSS banner for ' + filename);
var content = grunt.file.read(filename);
grunt.file.write(filename, banner + grunt.util.linefeed + content);
});
};
};
// Create a config file on the fly if there are arguments not supported as
// CLI, returns a function that runs within the temprorary context.
exports.buildConfigContext = function (options) {
var rawOptions = exports.extractRawOptions(options);
if (options.raw && options.config) {
grunt.warn('The options `raw` and `config` are mutually exclusive');
}
if (rawOptions.options.length > 0 && options.config) {
grunt.warn('The option `config` cannot be combined with ' +
'these options: ' + rawOptions.options.join(', ') + '.');
}
return function configContext(cb) {
if (rawOptions.raw) {
tmp.file(function (err, path, fd) {
if (err) {
return cb(err);
}
// Dynamically create config.rb as a tmp file for the `raw` content
fs.writeSync(fd, new Buffer(rawOptions.raw), 0, rawOptions.raw.length);
cb(null, path);
});
} else {
cb(null, null);
}
};
};
// build the array of arguments to build the compass command
exports.buildArgsArray = function (options) {
var args = ['compile'];
if (options.clean) {
args = ['clean'];
} else if (options.watch) {
args = ['watch'];
}
var basePath = options.basePath;
if (process.platform === 'win32') {
args.unshift('compass.bat');
} else {
args.unshift('compass');
}
if (options.bundleExec) {
args.unshift('bundle', 'exec');
}
if (options.basePath) {
args.push(options.basePath);
}
if (options.specify) {
var files = grunt.file.expand({
filter: function (filePath) {
return path.basename(filePath)[0] !== '_';
}
}, options.specify);
if (files.length > 0) {
[].push.apply(args, files);
} else {
return grunt.log.writeln('`specify` option used, but no files were found.');
}
}
// add converted options
[].push.apply(args, dargs(options, [
'raw',
'clean',
'bundleExec',
'basePath',
'specify',
'watch'
]));
// Compass doesn't have a long flag for this option:
// https://github.com/chriseppstein/compass/issues/1055
if (options.importPath) {
args = args.map(function (el) {
return el.replace('--import-path', '-I');
});
}
if (grunt.option('no-color')) {
args.push('--boring');
}
return args;
};
return exports;
};